diff --git a/blocks/AUTHORS b/blocks/AUTHORS new file mode 100644 index 0000000..5c8aa19 --- /dev/null +++ b/blocks/AUTHORS @@ -0,0 +1,3 @@ +Max <> +Mike Ossman <> +Steve Glass diff --git a/blocks/COPYING b/blocks/COPYING new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/blocks/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. 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 +them 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 prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. 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. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey 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; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If 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 convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU 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 that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + 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. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +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. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + 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 +state 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) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program 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, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU 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 Lesser General +Public License instead of this License. But first, please read +. diff --git a/blocks/ChangeLog b/blocks/ChangeLog new file mode 100644 index 0000000..02bdaf2 --- /dev/null +++ b/blocks/ChangeLog @@ -0,0 +1,23 @@ +# +# Copyright 2008 Steve Glass +# +# This file is part of OP25 +# +# OP25 is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# OP25 is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +# License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OP25; see the file COPYING. If not, write to the Free +# Software Foundation, Inc., 51 Franklin Street, Boston, MA +# 02110-1301, USA. + +For the complete project change log, please see +http://www.sedition.org.au/op25/timeline + diff --git a/blocks/INSTALL b/blocks/INSTALL new file mode 100644 index 0000000..7d1c323 --- /dev/null +++ b/blocks/INSTALL @@ -0,0 +1,365 @@ +Installation Instructions +************************* + +Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, +2006, 2007, 2008, 2009 Free Software Foundation, Inc. + + Copying and distribution of this file, with or without modification, +are permitted in any medium without royalty provided the copyright +notice and this notice are preserved. This file is offered as-is, +without warranty of any kind. + +Basic Installation +================== + + Briefly, the shell commands `./configure; make; make install' should +configure, build, and install this package. The following +more-detailed instructions are generic; see the `README' file for +instructions specific to this package. Some packages provide this +`INSTALL' file but do not implement all of the features documented +below. The lack of an optional feature in a given package is not +necessarily a bug. More recommendations for GNU packages can be found +in *note Makefile Conventions: (standards)Makefile Conventions. + + 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 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. + + Running `configure' might take a while. 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, generally using the just-built uninstalled binaries. + + 4. Type `make install' to install the programs and any data files and + documentation. When installing into a prefix owned by root, it is + recommended that the package be configured and built as a regular + user, and only the `make install' phase executed with root + privileges. + + 5. Optionally, type `make installcheck' to repeat any self-tests, but + this time using the binaries in their final installed location. + This target does not install anything. Running this target as a + regular user, particularly if the prior `make install' required + root privileges, verifies that the installation completed + correctly. + + 6. 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. + + 7. Often, you can also type `make uninstall' to remove the installed + files again. In practice, not all packages have tested that + uninstallation works correctly, even though it is required by the + GNU Coding Standards. + + 8. Some packages, particularly those that use Automake, provide `make + distcheck', which can by used by developers to test that all other + targets like `make install' and `make uninstall' work correctly. + This target is generally not run by end users. + +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=c99 CFLAGS=-g 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 can use 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 `..'. This +is known as a "VPATH" build. + + With a non-GNU `make', it is safer 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. + + On MacOS X 10.5 and later systems, you can create libraries and +executables that work on multiple system types--known as "fat" or +"universal" binaries--by specifying multiple `-arch' options to the +compiler but only a single `-arch' option to the preprocessor. Like +this: + + ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ + CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ + CPP="gcc -E" CXXCPP="g++ -E" + + This is not guaranteed to produce working output in all cases, you +may have to build one architecture at a time and combine the results +using the `lipo' tool if you have problems. + +Installation Names +================== + + By default, `make install' installs the package's commands under +`/usr/local/bin', include files under `/usr/local/include', etc. You +can specify an installation prefix other than `/usr/local' by giving +`configure' the option `--prefix=PREFIX', where PREFIX must be an +absolute file name. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +pass the option `--exec-prefix=PREFIX' to `configure', the package uses +PREFIX as the prefix for installing programs and libraries. +Documentation and other data files still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=DIR' 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. In general, the +default for these options is expressed in terms of `${prefix}', so that +specifying just `--prefix' will affect all of the other directory +specifications that were not explicitly provided. + + The most portable way to affect installation locations is to pass the +correct locations to `configure'; however, many packages provide one or +both of the following shortcuts of passing variable assignments to the +`make install' command line to change installation locations without +having to reconfigure or recompile. + + The first method involves providing an override variable for each +affected directory. For example, `make install +prefix=/alternate/directory' will choose an alternate location for all +directory configuration variables that were expressed in terms of +`${prefix}'. Any directories that were specified during `configure', +but not in terms of `${prefix}', must each be overridden at install +time for the entire installation to be relocated. The approach of +makefile variable overrides for each directory variable is required by +the GNU Coding Standards, and ideally causes no recompilation. +However, some platforms have known limitations with the semantics of +shared libraries that end up requiring recompilation when using this +method, particularly noticeable in packages that use GNU Libtool. + + The second method involves providing the `DESTDIR' variable. For +example, `make install DESTDIR=/alternate/directory' will prepend +`/alternate/directory' before all installation names. The approach of +`DESTDIR' overrides is not required by the GNU Coding Standards, and +does not work on platforms that have drive letters. On the other hand, +it does better at avoiding recompilation issues, and works well even +when some directory options were not specified in terms of `${prefix}' +at `configure' time. + +Optional Features +================= + + 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'. + + 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. + + Some packages offer the ability to configure how verbose the +execution of `make' will be. For these packages, running `./configure +--enable-silent-rules' sets the default to minimal output, which can be +overridden with `make V=1'; while running `./configure +--disable-silent-rules' sets the default to verbose, which can be +overridden with `make V=0'. + +Particular systems +================== + + On HP-UX, the default C compiler is not ANSI C compatible. If GNU +CC is not installed, it is recommended to use the following options in +order to use an ANSI C compiler: + + ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" + +and if that doesn't work, install pre-built binaries of GCC for HP-UX. + + On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot +parse its `' header file. The option `-nodtk' can be used as +a workaround. If GNU CC is not installed, it is therefore recommended +to try + + ./configure CC="cc" + +and if that doesn't work, try + + ./configure CC="cc -nodtk" + + On Solaris, don't put `/usr/ucb' early in your `PATH'. This +directory contains several dysfunctional programs; working variants of +these programs are available in `/usr/bin'. So, if you need `/usr/ucb' +in your `PATH', put it _after_ `/usr/bin'. + + On Haiku, software installed for all users goes in `/boot/common', +not `/usr/local'. It is recommended to use the following options: + + ./configure --prefix=/boot/common + +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 option `--target=TYPE' 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 + +causes the specified `gcc' to be used as the C compiler (unless it is +overridden in the site shell script). + +Unfortunately, this technique does not work for `CONFIG_SHELL' due to +an Autoconf bug. Until the bug is fixed you can use this workaround: + + CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash + +`configure' Invocation +====================== + + `configure' recognizes the following options to control how it +operates. + +`--help' +`-h' + Print a summary of all of the options to `configure', and exit. + +`--help=short' +`--help=recursive' + Print a summary of the options unique to this package's + `configure', and exit. The `short' variant lists options used + only in the top level, while the `recursive' variant lists options + also present in any nested packages. + +`--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. + +`--prefix=DIR' + Use DIR as the installation prefix. *note Installation Names:: + for more details, including other options available for fine-tuning + the installation locations. + +`--no-create' +`-n' + Run the configure checks, but stop before creating any output + files. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. + diff --git a/blocks/Makefile.am b/blocks/Makefile.am new file mode 100644 index 0000000..3ec820f --- /dev/null +++ b/blocks/Makefile.am @@ -0,0 +1,29 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of OP25 +# +# OP25 is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# OP25 is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OP25; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +include $(top_srcdir)/Makefile.common + +EXTRA_DIST = configure config.h.in +SUBDIRS = config src +DIST_SUBDIRS = config src + +pkgconfigdir = $(libdir)/pkgconfig +pkgconfig_DATA = diff --git a/blocks/Makefile.common b/blocks/Makefile.common new file mode 100644 index 0000000..cfa5b18 --- /dev/null +++ b/blocks/Makefile.common @@ -0,0 +1,43 @@ +# -*- Makefile -*- +# +# Copyright 2004,2006 Free Software Foundation, Inc. +# +# This file is part of OP25 +# +# OP25 is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# OP25 is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +# License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OP25; see the file COPYING. If not, write to the Free +# Software Foundation, Inc., 51 Franklin Street, Boston, MA +# 02110-1301, 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) + +# Don't assume that make predefines $(RM), because BSD make does +# not. We define it now in configure.ac using AM_PATH_PROG, but now +# here have to add a -f to be like GNU make. +RM=$(RM_PROG) -f diff --git a/blocks/NEWS b/blocks/NEWS new file mode 100644 index 0000000..e69de29 diff --git a/blocks/README b/blocks/README new file mode 100644 index 0000000..fd1a5fe --- /dev/null +++ b/blocks/README @@ -0,0 +1,2 @@ +This package implements signal processing blocks to support the +reception and transmission APCO Project 25 using GNU Radio. diff --git a/blocks/bootstrap b/blocks/bootstrap new file mode 100755 index 0000000..dabd4d2 --- /dev/null +++ b/blocks/bootstrap @@ -0,0 +1,29 @@ +#!/bin/sh + +# Copyright 2001,2005 Free Software Foundation, Inc. +# +# This file is part of OP25 +# +# OP25 is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# OP25 is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +# License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OP25; see the file COPYING. If not, write to the Free +# Software Foundation, Inc., 51 Franklin Street, Boston, MA +# 02110-1301, USA. + + +rm -fr config.cache autom4te*.cache + +aclocal -I config +autoconf +autoheader +libtoolize --automake +automake --add-missing -c -f diff --git a/blocks/config/Makefile.am b/blocks/config/Makefile.am new file mode 100644 index 0000000..408faa3 --- /dev/null +++ b/blocks/config/Makefile.am @@ -0,0 +1,65 @@ +# +# Copyright 2001 Free Software Foundation, Inc. +# +# This file is part of OP25 +# +# OP25 is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# OP25 is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +# License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OP25; see the file COPYING. If not, write to the Free +# Software Foundation, Inc., 51 Franklin Street, Boston, MA +# 02110-1301, 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_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/blocks/config/acx_pthread.m4 b/blocks/config/acx_pthread.m4 new file mode 100644 index 0000000..d318ab0 --- /dev/null +++ b/blocks/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/blocks/config/bnv_have_qt.m4 b/blocks/config/bnv_have_qt.m4 new file mode 100644 index 0000000..1469bfb --- /dev/null +++ b/blocks/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/blocks/config/cppunit.m4 b/blocks/config/cppunit.m4 new file mode 100644 index 0000000..0991d51 --- /dev/null +++ b/blocks/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/blocks/config/gr_boost.m4 b/blocks/config/gr_boost.m4 new file mode 100644 index 0000000..07bec50 --- /dev/null +++ b/blocks/config/gr_boost.m4 @@ -0,0 +1,111 @@ +dnl +dnl Copyright 2004,2005 Free Software Foundation, Inc. +dnl +dnl This file is part of OP25 +dnl +dnl OP25 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 3, or (at your option) +dnl any later version. +dnl +dnl OP25 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 OP25; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 51 Franklin Street, +dnl Boston, MA 02110-1301, 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/blocks/config/gr_check_createfilemapping.m4 b/blocks/config/gr_check_createfilemapping.m4 new file mode 100644 index 0000000..5a5ab4f --- /dev/null +++ b/blocks/config/gr_check_createfilemapping.m4 @@ -0,0 +1,52 @@ +dnl +dnl Copyright 2005 Free Software Foundation, Inc. +dnl +dnl This file is part of OP25 +dnl +dnl OP25 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 3, or (at your option) +dnl any later version. +dnl +dnl OP25 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 OP25; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 51 Franklin Street, +dnl Boston, MA 02110-1301, 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/blocks/config/gr_check_mc4020.m4 b/blocks/config/gr_check_mc4020.m4 new file mode 100644 index 0000000..9325a85 --- /dev/null +++ b/blocks/config/gr_check_mc4020.m4 @@ -0,0 +1,37 @@ +dnl +dnl Copyright 2003 Free Software Foundation, Inc. +dnl +dnl This file is part of OP25 +dnl +dnl OP25 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 3, or (at your option) +dnl any later version. +dnl +dnl OP25 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 OP25; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 51 Franklin Street, +dnl Boston, MA 02110-1301, 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/blocks/config/gr_check_shm_open.m4 b/blocks/config/gr_check_shm_open.m4 new file mode 100644 index 0000000..560a75a --- /dev/null +++ b/blocks/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 OP25 +dnl +dnl OP25 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 3, or (at your option) +dnl any later version. +dnl +dnl OP25 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 OP25; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 51 Franklin Street, +dnl Boston, MA 02110-1301, 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/blocks/config/gr_check_usrp.m4 b/blocks/config/gr_check_usrp.m4 new file mode 100644 index 0000000..92aad06 --- /dev/null +++ b/blocks/config/gr_check_usrp.m4 @@ -0,0 +1,32 @@ +dnl +dnl Copyright 2003 Free Software Foundation, Inc. +dnl +dnl This file is part of OP25 +dnl +dnl OP25 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 3, or (at your option) +dnl any later version. +dnl +dnl OP25 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 OP25; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 51 Franklin Street, +dnl Boston, MA 02110-1301, 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/blocks/config/gr_doxygen.m4 b/blocks/config/gr_doxygen.m4 new file mode 100644 index 0000000..7dd7427 --- /dev/null +++ b/blocks/config/gr_doxygen.m4 @@ -0,0 +1,59 @@ +dnl +dnl Copyright 2003,2005 Free Software Foundation, Inc. +dnl +dnl This file is part of OP25 +dnl +dnl OP25 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 3, or (at your option) +dnl any later version. +dnl +dnl OP25 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 OP25; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 51 Franklin Street, +dnl Boston, MA 02110-1301, 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/blocks/config/gr_gprof.m4 b/blocks/config/gr_gprof.m4 new file mode 100644 index 0000000..eebb4f6 --- /dev/null +++ b/blocks/config/gr_gprof.m4 @@ -0,0 +1,72 @@ +dnl +dnl Copyright 2002 Free Software Foundation, Inc. +dnl +dnl This file is part of OP25 +dnl +dnl OP25 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 3, or (at your option) +dnl any later version. +dnl +dnl OP25 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 OP25; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 51 Franklin Street, +dnl Boston, MA 02110-1301, 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/blocks/config/gr_libgnuradio_core_extra_ldflags.m4 b/blocks/config/gr_libgnuradio_core_extra_ldflags.m4 new file mode 100644 index 0000000..ed0c685 --- /dev/null +++ b/blocks/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 OP25 +# +# OP25 is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# OP25 is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OP25; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, 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/blocks/config/gr_no_undefined.m4 b/blocks/config/gr_no_undefined.m4 new file mode 100644 index 0000000..63a4a5d --- /dev/null +++ b/blocks/config/gr_no_undefined.m4 @@ -0,0 +1,44 @@ +dnl +dnl Copyright 2005 Free Software Foundation, Inc. +dnl +dnl This file is part of OP25 +dnl +dnl OP25 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 3, or (at your option) +dnl any later version. +dnl +dnl OP25 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 OP25; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 51 Franklin Street, +dnl Boston, MA 02110-1301, 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/blocks/config/gr_omnithread.m4 b/blocks/config/gr_omnithread.m4 new file mode 100644 index 0000000..dc27545 --- /dev/null +++ b/blocks/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 3, 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, Boston, MA +# 02110-1301, 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([OP25 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/blocks/config/gr_pwin32.m4 b/blocks/config/gr_pwin32.m4 new file mode 100644 index 0000000..59ba0f1 --- /dev/null +++ b/blocks/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 OP25 +# +# OP25 is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# OP25 is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OP25; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, 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/blocks/config/gr_python.m4 b/blocks/config/gr_python.m4 new file mode 100644 index 0000000..c6e85cf --- /dev/null +++ b/blocks/config/gr_python.m4 @@ -0,0 +1,111 @@ +dnl +dnl Copyright 2003,2004,2005 Free Software Foundation, Inc. +dnl +dnl This file is part of OP25 +dnl +dnl OP25 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 3, or (at your option) +dnl any later version. +dnl +dnl OP25 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 OP25; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 51 Franklin Street, +dnl Boston, MA 02110-1301, 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]) + + # For Fedora Core 5 and 6, see ticket:39 in Trac + if test -f '/etc/redhat-release'; then + if (echo $pyexecdir | grep -q lib64); then + pythondir="$pyexecdir" + fi + fi + + # 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 + pythondir=`echo $pythondir |sed 's,\\\\,/,g'` + pkgpythondir=`echo $pkgpythondir |sed 's,\\\\,/,g'` + pyexecdir=`echo $pyexecdir |sed 's,\\\\,/,g'` + pkgpyexecdir=`echo $pkgpyexecdir |sed 's,\\\\,/,g'` + ;; + esac + + AC_SUBST([PYTHON_LDFLAGS]) +]) diff --git a/blocks/config/gr_require_mc4020.m4 b/blocks/config/gr_require_mc4020.m4 new file mode 100644 index 0000000..d7be0f4 --- /dev/null +++ b/blocks/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 OP25 +dnl +dnl OP25 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 3, or (at your option) +dnl any later version. +dnl +dnl OP25 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 OP25; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 51 Franklin Street, +dnl Boston, MA 02110-1301, 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/blocks/config/gr_scripting.m4 b/blocks/config/gr_scripting.m4 new file mode 100644 index 0000000..dbf7aff --- /dev/null +++ b/blocks/config/gr_scripting.m4 @@ -0,0 +1,30 @@ +dnl +dnl Copyright 2003 Free Software Foundation, Inc. +dnl +dnl This file is part of OP25 +dnl +dnl OP25 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 3, or (at your option) +dnl any later version. +dnl +dnl OP25 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 OP25; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 51 Franklin Street, +dnl Boston, MA 02110-1301, 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/blocks/config/gr_set_md_cpu.m4 b/blocks/config/gr_set_md_cpu.m4 new file mode 100644 index 0000000..7f255d4 --- /dev/null +++ b/blocks/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 OP25 +dnl +dnl OP25 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 3, or (at your option) +dnl any later version. +dnl +dnl OP25 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 OP25; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 51 Franklin Street, +dnl Boston, MA 02110-1301, 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/blocks/config/gr_swig.m4 b/blocks/config/gr_swig.m4 new file mode 100644 index 0000000..0dcf671 --- /dev/null +++ b/blocks/config/gr_swig.m4 @@ -0,0 +1,85 @@ +dnl +dnl Copyright 2003 Free Software Foundation, Inc. +dnl +dnl This file is part of OP25 +dnl +dnl OP25 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 3, or (at your option) +dnl any later version. +dnl +dnl OP25 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 OP25; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 51 Franklin Street, +dnl Boston, MA 02110-1301, 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/blocks/config/gr_sysv_shm.m4 b/blocks/config/gr_sysv_shm.m4 new file mode 100644 index 0000000..db5c835 --- /dev/null +++ b/blocks/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 3, 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, Boston, MA +# 02110-1301, 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/blocks/config/gr_x86_64.m4 b/blocks/config/gr_x86_64.m4 new file mode 100644 index 0000000..64d480e --- /dev/null +++ b/blocks/config/gr_x86_64.m4 @@ -0,0 +1,39 @@ +dnl +dnl Copyright 2005 Free Software Foundation, Inc. +dnl +dnl This file is part of OP25 +dnl +dnl OP25 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 3, or (at your option) +dnl any later version. +dnl +dnl OP25 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 OP25; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 51 Franklin Street, +dnl Boston, MA 02110-1301, 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/blocks/config/lf_cc.m4 b/blocks/config/lf_cc.m4 new file mode 100644 index 0000000..b9d1c9c --- /dev/null +++ b/blocks/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 3 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., 51 Franklin Street, Boston, MA 02110-1301, 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/blocks/config/lf_cxx.m4 b/blocks/config/lf_cxx.m4 new file mode 100644 index 0000000..c581c9b --- /dev/null +++ b/blocks/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 3 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., 51 Franklin Street, Boston, MA 02110-1301, 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/blocks/config/lf_warnings.m4 b/blocks/config/lf_warnings.m4 new file mode 100644 index 0000000..4e2ca91 --- /dev/null +++ b/blocks/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 3 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., 51 Franklin Street, Boston, MA 02110-1301, 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/blocks/config/lf_x11.m4 b/blocks/config/lf_x11.m4 new file mode 100644 index 0000000..460cd60 --- /dev/null +++ b/blocks/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 3 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., 51 Franklin Street, Boston, MA 02110-1301, 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/blocks/config/mkstemp.m4 b/blocks/config/mkstemp.m4 new file mode 100644 index 0000000..4af0f0a --- /dev/null +++ b/blocks/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/blocks/config/onceonly.m4 b/blocks/config/onceonly.m4 new file mode 100644 index 0000000..f6fec37 --- /dev/null +++ b/blocks/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/blocks/config/pkg.m4 b/blocks/config/pkg.m4 new file mode 100644 index 0000000..770f062 --- /dev/null +++ b/blocks/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/blocks/config/usrp_fusb_tech.m4 b/blocks/config/usrp_fusb_tech.m4 new file mode 100644 index 0000000..bd9a276 --- /dev/null +++ b/blocks/config/usrp_fusb_tech.m4 @@ -0,0 +1,56 @@ +dnl +dnl Copyright 2003 Free Software Foundation, Inc. +dnl +dnl This file is part of OP25 +dnl +dnl OP25 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 3, or (at your option) +dnl any later version. +dnl +dnl OP25 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 OP25; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 51 Franklin Street, +dnl Boston, MA 02110-1301, 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/blocks/config/usrp_libusb.m4 b/blocks/config/usrp_libusb.m4 new file mode 100644 index 0000000..9fe4753 --- /dev/null +++ b/blocks/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 3, 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, Boston, MA +# 02110-1301, 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/blocks/config/usrp_sdcc.m4 b/blocks/config/usrp_sdcc.m4 new file mode 100644 index 0000000..37ce7c3 --- /dev/null +++ b/blocks/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 3, 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, Boston, MA +# 02110-1301, 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/blocks/configure.ac b/blocks/configure.ac new file mode 100644 index 0000000..a8d25de --- /dev/null +++ b/blocks/configure.ac @@ -0,0 +1,104 @@ +dnl +dnl Copyright 2004,2005 Free Software Foundation, Inc. +dnl +dnl This file is part of OP25 +dnl +dnl OP25 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 3, or (at your option) +dnl any later version. +dnl +dnl OP25 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 OP25; see the file COPYING. If not, write to +dnl the Free Software Foundation, Inc., 51 Franklin Street, +dnl Boston, MA 02110-1301, USA. +dnl + +AC_INIT +AC_PREREQ(2.57) +AC_CONFIG_SRCDIR([src/lib/op25.i]) +AM_CONFIG_HEADER(config.h) +AC_CANONICAL_TARGET([]) +AM_INIT_AUTOMAKE(op25,0.0.1) + +GR_X86_64 +dnl LF_CONFIGURE_CC +LF_CONFIGURE_CXX +LF_SET_WARNINGS +GR_SET_GPROF +GR_SET_PROF +AM_PROG_AS +AC_PROG_LN_S +AC_PROG_MAKE_SET +AC_PROG_INSTALL +AC_PATH_PROG([RM_PROG], [rm]) + +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_LIB([pcap], [pcap_open_live, pcap_open_dead, pcap_close, pcap_next, pcap_next_ex, pcap_datalink, pcap_inject, pcap_dump, pcap_geterr], , AC_MSG_ERROR([libpcap library not found.])) + +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 \ + 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/blocks/src/Makefile.am b/blocks/src/Makefile.am new file mode 100644 index 0000000..52d7757 --- /dev/null +++ b/blocks/src/Makefile.am @@ -0,0 +1,22 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of OP25 +# +# OP25 is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# OP25 is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +# License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OP25; see the file COPYING. If not, write to the Free +# Software Foundation, Inc., 51 Franklin Street, Boston, MA +# 02110-1301, USA. +# + +SUBDIRS = lib python diff --git a/blocks/src/lib/Makefile.am b/blocks/src/lib/Makefile.am new file mode 100644 index 0000000..0799bff --- /dev/null +++ b/blocks/src/lib/Makefile.am @@ -0,0 +1,116 @@ +# +# Copyright 2004,2005,2006,2008 Free Software Foundation, Inc. +# +# This file is part of OP25 +# +# OP25 is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# OP25 is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +# License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OP25; see the file COPYING. If not, write to the Free +# Software Foundation, Inc., 51 Franklin Street, Boston, MA +# 02110-1301, USA. +# + +include $(top_srcdir)/Makefile.common + +# Install this stuff so that it ends up as the op25.decoder_ff +# module. This usually ends up at: +# ${prefix}/lib/python${python_version}/site-packages/gnuradio + +ourpythondir = $(grpythondir) +ourlibdir = $(grpyexecdir) + +AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) $(PYTHON_CPPFLAGS) $(WITH_INCLUDES) + +SWIGPYTHONARGS = $(SWIGPYTHONFLAGS) $(SWIGGRFLAGS) $(WITH_SWIG_INCLUDES) \ + $(WITH_INCLUDES) + +ALL_IFILES = \ + $(LOCAL_IFILES) \ + $(NON_LOCAL_IFILES) + +NON_LOCAL_IFILES = \ + $(GNURADIO_CORE_INCLUDEDIR)/swig/gnuradio.i + +LOCAL_IFILES = \ + $(top_srcdir)/src/lib/op25.i + +# These files are built by SWIG. The first is the C++ glue. +# The second is the python wrapper that loads the _op25 shared library +# and knows how to call our extensions. + +BUILT_SOURCES = \ + op25.cc \ + op25.py + +# This gets op25.py installed in the right place +ourpython_PYTHON = \ + op25.py + +ourlib_LTLIBRARIES = _op25.la + +# These are the source files that go into the shared library +_op25_la_SOURCES = \ + abstract_data_unit.cc \ + data_unit.cc \ + hdu.cc \ + ldu1.cc \ + ldu2.cc \ + pdu.cc \ + tdu.cc \ + tsbk.cc \ + data_unit_handler.cc \ + logfile_du_handler.cc \ + p25cai_du_handler.cc \ + snapshot_du_handler.cc \ + imbe_decoder.cc \ + imbe_decoder_factory.cc \ + dummy_imbe_decoder.cc \ + offline_imbe_decoder.cc \ + voice_data_unit.cc \ + voice_du_handler.cc \ + op25.cc \ + op25_decoder_bf.cc \ + op25_fsk4_demod_ff.cc \ + op25_fsk4_slicer_fb.cc \ + op25_pcap_source_b.cc \ + software_imbe_decoder.cc \ + vc55_imbe_decoder.cc \ + value_string.cc \ + pickle.cc + +# magic flags +_op25_la_LDFLAGS = $(NO_UNDEFINED) -module -avoid-version + +# link the library against some comon swig runtime code and the +# c++ standard library +_op25_la_LIBADD = \ + $(PYTHON_LDFLAGS) \ + -lstdc++ \ + -litpp + +op25.cc op25.py: $(LOCAL_IFILES) $(ALL_IFILES) + $(SWIG) $(SWIGPYTHONARGS) -module op25 -o op25.cc $(LOCAL_IFILES) + +# These headers get installed in ${prefix}/include/gnuradio +grinclude_HEADERS = \ + op25_decoder_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/blocks/src/lib/abstract_data_unit.cc b/blocks/src/lib/abstract_data_unit.cc new file mode 100644 index 0000000..fa00cce --- /dev/null +++ b/blocks/src/lib/abstract_data_unit.cc @@ -0,0 +1,181 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2008 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +abstract_data_unit::~abstract_data_unit() +{ +} + +void +abstract_data_unit::correct_errors() +{ + if(is_complete()) { + do_correct_errors(d_frame_body); + } else { + ostringstream msg; + msg << "cannot correct errors - frame is not complete" << endl; + msg << "(size now: " << frame_size() << ", expected size: " << frame_size_max() << ")" << endl; + msg << "func: " << __PRETTY_FUNCTION__ << endl; + msg << "file: " << __FILE__ << endl; + msg << "line: " << __LINE__ << endl; + throw logic_error(msg.str()); + } +} + +void +abstract_data_unit::decode_audio(imbe_decoder& imbe) +{ + if(is_complete()) { + do_decode_audio(d_frame_body, imbe); + } else { + ostringstream msg; + msg << "cannot decode audio - frame is not complete" << endl; + msg << "(size now: " << frame_size() << ", expected size: " << frame_size_max() << ")" << endl; + msg << "func: " << __PRETTY_FUNCTION__ << endl; + msg << "file: " << __FILE__ << endl; + msg << "line: " << __LINE__ << endl; + throw logic_error(msg.str()); + } +} + +size_t +abstract_data_unit::decode_frame(size_t msg_sz, uint8_t *msg) +{ + return decode_frame(d_frame_body, msg_sz, msg); +} + +size_t +abstract_data_unit::decode_frame(const_bit_vector& frame_body, size_t msg_sz, uint8_t *msg) +{ + size_t n = 0; + if(is_complete()) { + if(size() <= msg_sz) { + n = extract(frame_body, 0, static_cast(frame_body.size()), msg); + } else { + ostringstream msg; + msg << "cannot decode frame body "; + msg << "(msg size: " << msg_sz << ", actual size: " << size() << ")" << endl; + msg << "func: " << __PRETTY_FUNCTION__ << endl; + msg << "file: " << __FILE__ << endl; + msg << "line: " << __LINE__ << endl; + throw length_error(msg.str()); + } + } else { + ostringstream msg; + msg << "cannot decode frame - frame is not complete" << endl; + msg << "(size now: " << frame_size() << ", expected size: " << frame_size_max() << ")" << endl; + msg << "func: " << __PRETTY_FUNCTION__ << endl; + msg << "file: " << __FILE__ << endl; + msg << "line: " << __LINE__ << endl; + throw logic_error(msg.str()); + } + return n; + +} + +void +abstract_data_unit::extend(dibit d) +{ + if(frame_size() < frame_size_max()) { + d_frame_body.push_back(d & 0x2); + d_frame_body.push_back(d & 0x1); + } else { + ostringstream msg; + msg << "cannot extend frame " << endl; + msg << "(size now: " << frame_size() << ", expected size: " << frame_size_max() << ")" << endl; + msg << "func: " << __PRETTY_FUNCTION__ << endl; + msg << "file: " << __FILE__ << endl; + msg << "line: " << __LINE__ << endl; + throw length_error(msg.str()); + } +} + +bool +abstract_data_unit::is_complete() const +{ + return frame_size() >= frame_size_max(); +} + +uint16_t +abstract_data_unit::size() const +{ + return (7 + frame_size_max()) >> 3; +} + +std::string +abstract_data_unit::snapshot() const +{ + string empty; + return empty; +} + +void +abstract_data_unit::dump(ostream& os) const +{ + uint32_t nbits = d_frame_body.size(); + os << setw(4) << nbits << " "; + for(size_t i = 48; i < nbits; ++i) { + os << (d_frame_body[i] ? "#" : "-"); + } + os << endl; +} + +abstract_data_unit::abstract_data_unit(const_bit_queue& frame_body) : + d_frame_body(frame_body.size()) +{ + copy(frame_body.begin(), frame_body.end(), d_frame_body.begin()); +} + +void +abstract_data_unit::do_correct_errors(bit_vector& frame_body) +{ +} + +void +abstract_data_unit::do_decode_audio(const_bit_vector& frame_body, imbe_decoder& imbe) +{ +} + +const_bit_vector& +abstract_data_unit::frame_body() const +{ + return d_frame_body; +} + +uint16_t +abstract_data_unit::frame_size() const +{ + return d_frame_body.size(); +} diff --git a/blocks/src/lib/abstract_data_unit.h b/blocks/src/lib/abstract_data_unit.h new file mode 100644 index 0000000..2a84506 --- /dev/null +++ b/blocks/src/lib/abstract_data_unit.h @@ -0,0 +1,191 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2008 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. + */ + +#ifndef INCLUDED_ABSTRACT_DATA_UNIT_H +#define INCLUDED_ABSTRACT_DATA_UNIT_H + +#include +#include +#include +#include + +#include +#include + +typedef std::vector bit_vector; +typedef const std::vector const_bit_vector; + +/** + * Abstract P25 data unit. + */ +class abstract_data_unit : public data_unit +{ + +public: + + /** + * abstract data_unit virtual destructor. + */ + virtual ~abstract_data_unit(); + + /** + * Apply error correction to this data_unit. + * + * \precondition is_complete() == true. + */ + virtual void correct_errors(); + + /** + * Decode compressed audio using the supplied imbe_decoder. + * + * \precondition is_complete() == true. + * \param imbe The imbe_decoder to use to generate the audio. + */ + virtual void decode_audio(imbe_decoder& imbe); + + /** + * Decode the frame into an octet vector. + * + * \precondition is_complete() == true. + * \param msg_sz The size of the message buffer. + * \param msg A pointer to the message buffer. + * \return The number of octets written to msg. + */ + virtual size_t decode_frame(size_t msg_sz, uint8_t *msg); + + /** + * Dump this data unit in human readable format to stream s. + * + * \param s The stream to write on + */ + virtual void dump(std::ostream& os) const; + + /** + * Extends this data_unit with the specified dibit. If this + * data_unit is already complete a range_error is thrown. + * + * \precondition is_complete() == false. + * \param d The dibit to extend the frame with. + * \throws range_error When the frame already is at its maximum size. + * \return true when the frame is complete otherwise false. + */ + virtual void extend(dibit d); + + /** + * Tests whether this data unit has enough data to begin decoding. + * + * \return true when this data_unit is complete; otherwise returns + * false. + */ + virtual bool is_complete() const; + + /** + * Returns the size (in octets) of this data_unit. + * + * \return The size (in octets) of this data_unit. + */ + virtual uint16_t size() const; + + /** + * Return a snapshot of the key fields from this frame in a manner + * suitable for display by the UI. The string is encoded as a + * pickled Python dictionary. + * + * \precondition is_complete() == true. + * \return A string containing the fields to display. + */ + virtual std::string snapshot() const; + +protected: + + /** + * abstract_data_unit constructor. + * + * \param frame_body A const_bit_queue representing the frame body. + */ + abstract_data_unit(const_bit_queue& frame_body); + + /** + * Applies error correction code to the specified bit_vector. + * + * \param frame_body The bit vector to decode. + */ + virtual void do_correct_errors(bit_vector& frame_body); + + /** + * Decode compressed audio using the supplied imbe_decoder. + * + * \precondition is_complete() == true. + * \param frame_body The const_bit_vector to decode. + * \param imbe The imbe_decoder to use. + */ + virtual void do_decode_audio(const_bit_vector& frame_body, imbe_decoder& imbe); + + /** + * Decode frame_body and write the decoded frame contents to msg. + * + * \param frame_body The bit vector to decode. + * \param msg_sz The size of the message buffer. + * \param msg A pointer to where the data unit content will be written. + * \return The number of octets written to msg. + */ + virtual size_t decode_frame(const_bit_vector& frame_body, size_t msg_sz, uint8_t *msg); + + /** + * Returns a string describing the Data Unit ID (DUID). + * + * \return A string identifying the DUID. + */ + virtual std::string duid_str() const = 0; + + /** + * Return a reference to the frame body. + */ + const_bit_vector& frame_body() const; + + /** + * Returns the expected size (in bits) of this data_unit. For + * variable-length data this should return UINT16_MAX until the + * actual length of this frame is known. + * + * \return The expected size (in bits) of this data_unit when encoded. + */ + virtual uint16_t frame_size_max() const = 0; + + /** + * Returns the current size (in bits) of this data_unit. + * + * \return The current size (in bits) of this data_unit. + */ + virtual uint16_t frame_size() const; + +private: + + /** + * A bit vector containing the frame body. + */ + bit_vector d_frame_body; + +}; + +#endif /* INCLUDED_ABSTRACT_DATA_UNIT_H */ diff --git a/blocks/src/lib/data_unit.cc b/blocks/src/lib/data_unit.cc new file mode 100644 index 0000000..9e118c8 --- /dev/null +++ b/blocks/src/lib/data_unit.cc @@ -0,0 +1,73 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2008 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +data_unit_sptr +data_unit::make_data_unit(const_bit_queue& frame_body) +{ + data_unit_sptr d; + uint8_t duid = extract(frame_body, 60, 64); + switch(duid) { + case 0x0: + d = data_unit_sptr(new hdu(frame_body)); + break; + case 0x3: + d = data_unit_sptr(new tdu(frame_body, false)); + break; + case 0x5: + d = data_unit_sptr(new ldu1(frame_body)); + break; + case 0x7: + d = data_unit_sptr(new tsbk(frame_body)); + break; + case 0xa: + d = data_unit_sptr(new ldu2(frame_body)); + break; + case 0x9: // VSELP "voice PDU" + case 0xc: + d = data_unit_sptr(new pdu(frame_body)); + break; + case 0xf: + d = data_unit_sptr(new tdu(frame_body, true)); + break; + }; + return d; +} + +data_unit::~data_unit() +{ +} + +data_unit::data_unit() +{ +} diff --git a/blocks/src/lib/data_unit.h b/blocks/src/lib/data_unit.h new file mode 100644 index 0000000..ff40378 --- /dev/null +++ b/blocks/src/lib/data_unit.h @@ -0,0 +1,142 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2008 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. + */ + +#ifndef INCLUDED_DATA_UNIT_H +#define INCLUDED_DATA_UNIT_H + +#include +#include +#include +#include +#include +#include + +typedef std::deque bit_queue; +typedef const std::deque const_bit_queue; + +typedef uint8_t dibit; + +typedef std::deque float_queue; + +typedef boost::shared_ptr data_unit_sptr; + +/** + * A P25 data unit. + */ +class data_unit : public boost::noncopyable +{ +public: + + /** + * data_unit (virtual) constructor. Returns a pointer to an + * appropriate data_unit instance given the initial frame_body. + * \param fs The frame sync value for this data_unit. + * \param nid The network ID for this data_unit. + * \return A (possibly null-valued) pointer to the data_unit. + */ + static data_unit_sptr make_data_unit(const_bit_queue& frame_body); + + /** + * data_unit (virtual) destructor. + */ + virtual ~data_unit(); + + /** + * Apply error correction to this data_unit. + * + * \precondition is_complete() == true. + */ + virtual void correct_errors() = 0; + + /** + * Decode compressed audio using the supplied imbe_decoder and + * writes output to audio. + * + * \precondition is_complete() == true. + * \param imbe The imbe_decoder to use to generate the audio. + */ + virtual void decode_audio(imbe_decoder& imbe) = 0; + + /** + * Decode the frame into an octet vector. + * + * \precondition is_complete() == true. + * \param msg_sz The size of the message buffer. + * \param msg A pointer to the message buffer. + * \return The number of octets written to msg. + */ + virtual size_t decode_frame(size_t msg_sz, uint8_t *msg) = 0; + + /** + * Dump this data unit in human readable format to stream s. + * + * \param s The stream to write on + */ + virtual void dump(std::ostream& os) const = 0; + + /** + * Extends this data_unit with the specified dibit. If this + * data_unit is already complete a range_error is thrown. + * + * \precondition is_complete() == false. + * \param d The dibit to extend the frame with. + * \throws range_error When the frame already is at its maximum size. + * \return true when the frame is complete otherwise false. + */ + virtual void extend(dibit d) = 0; + + /** + * Tests whether this data unit is complete. + * + * \return true when this data_unit is complete; otherwise returns + * false. + * \ see extend() + */ + virtual bool is_complete() const = 0; + + /** + * Returns the size (in octets) of the data_unit. + * + * \return The actual size (in octets) of this data_unit. + */ + virtual uint16_t size() const = 0; + + /** + * Return a snapshot of the key fields from this frame in a manner + * suitable for display by the UI. The string is encoded using the + * Python pickle format allowing for different fields to be + * returned. + * + * \return A string containing the fields to display. + */ + virtual std::string snapshot() const = 0; + +protected: + + /** + * data_unit default constructor. + */ + data_unit(); +}; + +#endif /* INCLUDED_DATA_UNIT_H */ diff --git a/blocks/src/lib/data_unit_handler.cc b/blocks/src/lib/data_unit_handler.cc new file mode 100644 index 0000000..3d1316c --- /dev/null +++ b/blocks/src/lib/data_unit_handler.cc @@ -0,0 +1,19 @@ +#include "data_unit_handler.h" + +data_unit_handler::~data_unit_handler() +{ +} + +void +data_unit_handler::handle(data_unit_sptr du) +{ + if(d_next) { + d_next->handle(du); + } +} + +data_unit_handler::data_unit_handler(data_unit_handler_sptr next) : + d_next(next) +{ +} + diff --git a/blocks/src/lib/data_unit_handler.h b/blocks/src/lib/data_unit_handler.h new file mode 100644 index 0000000..308b6be --- /dev/null +++ b/blocks/src/lib/data_unit_handler.h @@ -0,0 +1,71 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2008 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. +*/ + +#ifndef INCLUDED_DATA_UNIT_HANDLER_H +#define INCLUDED_DATA_UNIT_HANDLER_H + +#include +#include +#include + +typedef boost::shared_ptr data_unit_handler_sptr; + +/** + * P25 data_unit_handler interface. + */ +class data_unit_handler : public boost::noncopyable +{ + +public: + + /** + * data_unit_handler virtual destructor. + */ + virtual ~data_unit_handler(); + + /** + * Handle a received P25 frame. + * + * \param du A non-null data_unit_sptr to handle. + */ + virtual void handle(data_unit_sptr du) = 0; + +protected: + + /** + * data_unit_handler default constructor. + * + * \param next The next data_unit_handler in this chain. + */ + data_unit_handler(data_unit_handler_sptr next); + +private: + + /** + * The next data_unit_handler in this chain. + */ + data_unit_handler_sptr d_next; + +}; + +#endif /* INCLUDED_DATA_UNIT_HANDLER_H */ diff --git a/blocks/src/lib/dummy_imbe_decoder.cc b/blocks/src/lib/dummy_imbe_decoder.cc new file mode 100644 index 0000000..eae8dd3 --- /dev/null +++ b/blocks/src/lib/dummy_imbe_decoder.cc @@ -0,0 +1,37 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2008 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. + */ + +#include + +dummy_imbe_decoder::dummy_imbe_decoder() +{ +} + +dummy_imbe_decoder::~dummy_imbe_decoder() +{ +} + +void +dummy_imbe_decoder::decode(const voice_codeword& cw) +{ +} diff --git a/blocks/src/lib/dummy_imbe_decoder.h b/blocks/src/lib/dummy_imbe_decoder.h new file mode 100644 index 0000000..60b0e27 --- /dev/null +++ b/blocks/src/lib/dummy_imbe_decoder.h @@ -0,0 +1,55 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2008 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. + */ + +#ifndef INCLUDED_DUMMY_IMBE_DECODER_H +#define INCLUDED_DUMMY_IMBE_DECODER_H + +#include + +/** + * dummy_imbe_decoder is the imbe_decoder of last resort. It consumes + * the voice_codeeword and does nothing. + */ +class dummy_imbe_decoder : public imbe_decoder { +public: + + /** + * dummy_imbe_decoder default constructor. + */ + dummy_imbe_decoder(); + + /** + * dummy_imbe_decoder (virtual) destructor. + */ + virtual ~dummy_imbe_decoder(); + + /** + * Ignores in_out and generates no audio. + * + * \param cw IMBE codewords and parity. + */ + virtual void decode(const voice_codeword& cw); + +}; + +#endif /* INCLUDED_DUMMY_IMBE_DECODER_H */ diff --git a/blocks/src/lib/hdu.cc b/blocks/src/lib/hdu.cc new file mode 100644 index 0000000..ce2df0c --- /dev/null +++ b/blocks/src/lib/hdu.cc @@ -0,0 +1,224 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2008 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. + */ + +#include +#include +#include +#include +#include +#include + +using namespace std; + +hdu::hdu(const_bit_queue& frame_body) : + abstract_data_unit(frame_body) +{ +} + +hdu::~hdu() +{ +} + +string +hdu::duid_str() const +{ + return string("HDU"); +} + +std::string +hdu::snapshot() const +{ + pickle p; + p.add("duid", duid_str()); + p.add("nac", nac_str()); + p.add("mfid", mfid_str()); + p.add("algid", algid_str()); + p.add("kid", kid_str()); + p.add("mi", mi_str()); + p.add("tgid", tgid_str()); + return p.to_string(); +} + +void +hdu::do_correct_errors(bit_vector& frame) +{ + apply_golay_correction(frame); + apply_rs_correction(frame); +} + +void +hdu::apply_golay_correction(bit_vector& frame) +{ + static const size_t NOF_GOLAY_CODEWORDS = 36, GOLAY_CODEWORD_SZ = 18; + static const size_t GOLAY_CODEWORDS[NOF_GOLAY_CODEWORDS][GOLAY_CODEWORD_SZ] = { + { 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131 }, + { 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 144, 145, 146, 147, 148, 149, 150, 151 }, + { 152, 153, 154, 155, 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168, 169 }, + { 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187 }, + { 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205 }, + { 206, 207, 208, 209, 210, 211, 212, 213, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225 }, + { 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243 }, + { 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 256, 257, 258, 259, 260, 261 }, + { 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279 }, + { 280, 281, 282, 283, 284, 285, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299 }, + { 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317 }, + { 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335 }, + { 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353 }, + { 354, 355, 356, 357, 360, 361, 362, 363, 364, 365, 366, 367, 368, 369, 370, 371, 372, 373 }, + { 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391 }, + { 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409 }, + { 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, 422, 423, 424, 425, 426, 427 }, + { 428, 429, 432, 433, 434, 435, 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447 }, + { 448, 449, 450, 451, 452, 453, 454, 455, 456, 457, 458, 459, 460, 461, 462, 463, 464, 465 }, + { 466, 467, 468, 469, 470, 471, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 482, 483 }, + { 484, 485, 486, 487, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501 }, + { 504, 505, 506, 507, 508, 509, 510, 511, 512, 513, 514, 515, 516, 517, 518, 519, 520, 521 }, + { 522, 523, 524, 525, 526, 527, 528, 529, 530, 531, 532, 533, 534, 535, 536, 537, 538, 539 }, + { 540, 541, 542, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 557 }, + { 558, 559, 560, 561, 562, 563, 564, 565, 566, 567, 568, 569, 570, 571, 572, 573, 576, 577 }, + { 578, 579, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 594, 595 }, + { 596, 597, 598, 599, 600, 601, 602, 603, 604, 605, 606, 607, 608, 609, 610, 611, 612, 613 }, + { 614, 615, 616, 617, 618, 619, 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631 }, + { 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 648, 649, 650, 651 }, + { 652, 653, 654, 655, 656, 657, 658, 659, 660, 661, 662, 663, 664, 665, 666, 667, 668, 669 }, + { 670, 671, 672, 673, 674, 675, 676, 677, 678, 679, 680, 681, 682, 683, 684, 685, 686, 687 }, + { 688, 689, 690, 691, 692, 693, 694, 695, 696, 697, 698, 699, 700, 701, 702, 703, 704, 705 }, + { 706, 707, 708, 709, 710, 711, 712, 713, 714, 715, 716, 717, 720, 721, 722, 723, 724, 725 }, + { 726, 727, 728, 729, 730, 731, 732, 733, 734, 735, 736, 737, 738, 739, 740, 741, 742, 743 }, + { 744, 745, 746, 747, 748, 749, 750, 751, 752, 753, 754, 755, 756, 757, 758, 759, 760, 761 }, + { 762, 763, 764, 765, 766, 767, 768, 769, 770, 771, 772, 773, 774, 775, 776, 777, 778, 779 } + }; + for(size_t i = 0; i < NOF_GOLAY_CODEWORDS; ++i) { + uint32_t cw = extract(frame, GOLAY_CODEWORDS[i], GOLAY_CODEWORD_SZ); +// uint32_t d = golay_decode(cw); +// uint32 cw = golay_encode(cw); +// yank_back(d, PAD_SZ, frame, GOLAY_CODEWORDS[i], GOLAY_DATA_SZ); + } +} + +void +hdu::apply_rs_correction(bit_vector& frame) +{ +#if 0 + static itpp::Reed_Solomon rs(6, 8, true); + + const size_t rs_codeword[][6] = { + }; + const size_t nof_codeword_bits = sizeof(codeword_bits) / sizeof(codeword_bits[0]); + +#endif +} + +uint16_t +hdu::frame_size_max() const +{ + return 792; +} + +string +hdu::algid_str() const +{ + const size_t ALGID_BITS[] = { + 356, 357, 360, 361, 374, 375, 376, 377 + }; + const size_t ALGID_BITS_SZ = sizeof(ALGID_BITS) / sizeof(ALGID_BITS[0]); + uint8_t algid = extract(frame_body(), ALGID_BITS, ALGID_BITS_SZ); + return lookup(algid, ALGIDS, ALGIDS_SZ); +} + +string +hdu::kid_str() const +{ + const size_t KID_BITS[] = { + 378, 379, 392, 393, 394, 395, 396, 397, + 410, 411, 412, 413, 414, 415, 428, 429 + }; + const size_t KID_BITS_SZ = sizeof(KID_BITS) / sizeof(KID_BITS[0]); + uint16_t kid = extract(frame_body(), KID_BITS, KID_BITS_SZ); + ostringstream os; + os << hex << showbase << setfill('0') << setw(4) << kid; + return os.str(); +} + +std::string +hdu::mi_str() const +{ + const size_t MI_BITS[] = { + 114, 115, 116, 117, 118, 119, 132, 133, + 134, 135, 136, 137, 152, 153, 154, 155, + 156, 157, 170, 171, 172, 173, 174, 175, + 188, 189, 190, 191, 192, 193, 206, 207, + 208, 209, 210, 211, 226, 227, 228, 229, + 230, 231, 244, 245, 246, 247, 248, 249, + 262, 263, 264, 265, 266, 267, 280, 281, + 282, 283, 284, 285, 300, 301, 302, 303, + 304, 305, 318, 319, 320, 321, 322, 323, + }; + const size_t MI_BITS_SZ = sizeof(MI_BITS) / sizeof(MI_BITS[0]); + + uint8_t mi[9]; + extract(frame_body(), MI_BITS, MI_BITS_SZ, mi); + ostringstream os; + os << "0x"; + for(size_t i = 0; i < (sizeof(mi) / sizeof(mi[0])); ++i) { + uint16_t octet = mi[i]; + os << hex << setfill('0') << setw(2) << octet; + } + return os.str(); +} + +string +hdu::mfid_str() const +{ + const size_t MFID_BITS[] = { + 336, 337, 338, 339, 340, 341, 354, 355 + }; + const size_t MFID_BITS_SZ = sizeof(MFID_BITS) / sizeof(MFID_BITS_SZ); + uint8_t mfid = extract(frame_body(), MFID_BITS, MFID_BITS_SZ); + return lookup(mfid, MFIDS, MFIDS_SZ); +} + +string +hdu::nac_str() const +{ + const size_t NAC_BITS[] = { + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59 + }; + const size_t NAC_BITS_SZ = sizeof(NAC_BITS) / sizeof(NAC_BITS[0]); + uint32_t nac = extract(frame_body(), NAC_BITS, NAC_BITS_SZ); + return lookup(nac, NACS, NACS_SZ); +} + +string +hdu::tgid_str() const +{ + const size_t TGID_BITS[] = { + 432, 433, 434, 435, 448, 449, 450, 451, + 452, 453, 466, 467, 468, 469, 470, 471 + }; + const size_t TGID_BITS_SZ = sizeof(TGID_BITS) / sizeof(TGID_BITS[0]); + const uint16_t tgid = extract(frame_body(), TGID_BITS, TGID_BITS_SZ); + ostringstream os; + os << hex << showbase << setfill('0') << setw(4) << tgid; + return os.str(); +} diff --git a/blocks/src/lib/hdu.h b/blocks/src/lib/hdu.h new file mode 100644 index 0000000..0877199 --- /dev/null +++ b/blocks/src/lib/hdu.h @@ -0,0 +1,144 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2008 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. +*/ + +#ifndef INCLUDED_HDU_H +#define INCLUDED_HDU_H + +#include + +/** + * P25 header data unit (HDU). + */ +class hdu : public abstract_data_unit +{ + +public: + + /** + * hdu constructor. + * + * \param frame_body A const_bit_queue representing the frame body. + */ + hdu(const_bit_queue& frame_body); + + /** + * hdu virtual destructor. + */ + virtual ~hdu(); + + /** + * Returns a string describing the Data Unit ID (DUID). + */ + std::string duid_str() const; + + /** + * Return a snapshot of the key fields from this frame in a manner + * suitable for display by the UI. The string is encoded as a + * pickled Python dictionary. + * + * \return A string containing the fields to display. + */ + virtual std::string snapshot() const; + +protected: + + /** + * Applies error correction code to the specified bit_vector. + * + * \param frame_body The bit vector to decode. + * \return + */ + virtual void do_correct_errors(bit_vector& frame_body); + + /** + * Apply Golay error correction code to the specified bit_vector. + * + * \param frame_body The bit vector to decode. + * \return + */ + virtual void apply_golay_correction(bit_vector& frame_body); + + /** + * Apply Reed-Solomon error correction code to the specified + * bit_vector. + * + * \param frame_body The bit vector to decode. + * \return + */ + virtual void apply_rs_correction(bit_vector& frame_body); + + /** + * Returns the expected size (in bits) of this data unit in + * bits. For variable-length data this should return UINT16_MAX + * until the actual length of this frame is known. + * + * \return The expected size (in bits) of this data_unit when encoded. + */ + virtual uint16_t frame_size_max() const; + +private: + + /** + * Return a string describing the encryption algorithm ID (ALGID). + * + * \return A string identifying the ALGID. + */ + std::string algid_str() const; + + /** + * Returns a string describing the key id (KID). + * + * \return A string identifying the KID. + */ + virtual std::string kid_str() const; + + /** + * Returns a string describing the manufacturer ID (MFID). + * + * \return A string identifying the MFID + */ + virtual std::string mfid_str() const; + + /** + * Returns a string describing the message indicator (MI). + * + * \return A string identifying the MI. + */ + virtual std::string mi_str() const; + + /** + * Returns a string describing the Network Access Code (NAC). + * + * \return A string identifying the NAC. + */ + virtual std::string nac_str() const; + + /** + * Returns a string describing the talk group id (TGID). + * + * \return A string identifying the TGID. + */ + virtual std::string tgid_str() const; +}; + +#endif /* INCLUDED_HDU_H */ diff --git a/blocks/src/lib/imbe_decoder.cc b/blocks/src/lib/imbe_decoder.cc new file mode 100644 index 0000000..b07b3ed --- /dev/null +++ b/blocks/src/lib/imbe_decoder.cc @@ -0,0 +1,16 @@ +#include + +imbe_decoder::~imbe_decoder() +{ +} + +imbe_decoder::imbe_decoder() : + d_audio() +{ +} + +audio_samples* +imbe_decoder::audio() +{ + return &d_audio; +} diff --git a/blocks/src/lib/imbe_decoder.h b/blocks/src/lib/imbe_decoder.h new file mode 100644 index 0000000..e7645f0 --- /dev/null +++ b/blocks/src/lib/imbe_decoder.h @@ -0,0 +1,90 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2008 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. + */ + +#ifndef INCLUDED_IMBE_DECODER_H +#define INCLUDED_IMBE_DECODER_H + +#include +#include +#include +#include + +typedef std::deque audio_samples; +typedef std::vector voice_codeword; + +typedef boost::shared_ptr imbe_decoder_sptr; + +/** + * imbe_decoder is the interface to the various mechanisms for + * translating P25 voice codewords into audio samples. + */ +class imbe_decoder : public boost::noncopyable { +public: + + /** + * imbe_decoder (virtual) constructor. The exact subclass + * instantiated depends on some yet-to-be-decided magic. + * + * \return A shared_ptr to an imbe_decoder. + */ + static imbe_decoder_sptr make(); + + /** + * imbe_decoder (virtual) destructor. + */ + virtual ~imbe_decoder(); + + /** + * Decode the compressed IMBE audio. + * + * \param cw IMBE codeword (including parity check bits). + */ + virtual void decode(const voice_codeword& cw) = 0; + + /** + * Returns the audio_samples samples. These are mono samples at + * 8KS/s represented as a float in the range -1.0 .. +1.0. + * + * \return A non-null pointer to a deque of audio samples. + */ + audio_samples *audio(); + +protected: + + /** + * Construct an instance of imbe_decoder. Access is protected + * because this is an abstract class and users should call + * make_imbe_decoder to construct concrete instances. + */ + imbe_decoder(); + +private: + + /** + * The audio samples produced by the IMBE decoder. + */ + audio_samples d_audio; + +}; + +#endif /* INCLUDED_IMBE_DECODER_H */ diff --git a/blocks/src/lib/imbe_decoder_factory.cc b/blocks/src/lib/imbe_decoder_factory.cc new file mode 100644 index 0000000..a6238b2 --- /dev/null +++ b/blocks/src/lib/imbe_decoder_factory.cc @@ -0,0 +1,29 @@ +#include +#include +#include +#include +#include + +#include +#include + +imbe_decoder_sptr +imbe_decoder::make() +{ + imbe_decoder_sptr imbe; + const char *imbe_type = getenv("IMBE"); + if(imbe_type) { + if(strcasecmp(imbe_type, "offline") == 0) { + imbe = imbe_decoder_sptr(new offline_imbe_decoder()); + } else if(strcasecmp(imbe_type, "soft") == 0) { + imbe = imbe_decoder_sptr(new software_imbe_decoder()); + } else if(strcasecmp(imbe_type, "vc55") == 0) { + imbe = imbe_decoder_sptr(new vc55_imbe_decoder()); + } else { + imbe = imbe_decoder_sptr(new dummy_imbe_decoder()); + } + } else { + imbe = imbe_decoder_sptr(new software_imbe_decoder()); + } + return imbe; +} diff --git a/blocks/src/lib/ldu1.cc b/blocks/src/lib/ldu1.cc new file mode 100644 index 0000000..19f9c2f --- /dev/null +++ b/blocks/src/lib/ldu1.cc @@ -0,0 +1,41 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2008 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. + */ + +#include + +using std::string; + +ldu1::ldu1(const_bit_queue& frame_body) : + voice_data_unit(frame_body) +{ +} + +ldu1::~ldu1() +{ +} + +string +ldu1::duid_str() const +{ + return string("LDU1"); +} diff --git a/blocks/src/lib/ldu1.h b/blocks/src/lib/ldu1.h new file mode 100644 index 0000000..b9feee8 --- /dev/null +++ b/blocks/src/lib/ldu1.h @@ -0,0 +1,55 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2008 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. + */ + +#ifndef INCLUDED_LDU1_H +#define INCLUDED_LDU1_H + +#include + +/** + * P25 Logical Data Unit 1. + */ +class ldu1 : public voice_data_unit +{ +public: + + /** + * ldu1 constuctor + * + * \param frame_body A const_bit_queue representing the frame body. + */ + ldu1(const_bit_queue& frame_body); + + /** + * ldu1 (virtual) destuctor + */ + virtual ~ldu1(); + + /** + * Returns a string describing the Data Unit ID (DUID). + */ + std::string duid_str() const; + +}; + +#endif /* INCLUDED_LDU1_H */ diff --git a/blocks/src/lib/ldu2.cc b/blocks/src/lib/ldu2.cc new file mode 100644 index 0000000..8638275 --- /dev/null +++ b/blocks/src/lib/ldu2.cc @@ -0,0 +1,41 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2008 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. + */ + +#include + +using std::string; + +ldu2::ldu2(const_bit_queue& frame_body) : + voice_data_unit(frame_body) +{ +} + +ldu2::~ldu2() +{ +} + +string +ldu2::duid_str() const +{ + return string("LDU2"); +} diff --git a/blocks/src/lib/ldu2.h b/blocks/src/lib/ldu2.h new file mode 100644 index 0000000..508482d --- /dev/null +++ b/blocks/src/lib/ldu2.h @@ -0,0 +1,54 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2008 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. + */ + +#ifndef INCLUDED_LDU2_H +#define INCLUDED_LDU2_H + +#include + +/** + * P25 Logical Data Unit 2. + */ +class ldu2 : public voice_data_unit +{ +public: + + /** + * ldu2 constructor. + * + * \param frame_body A const_bit_queue representing the frame body. + */ + ldu2(const_bit_queue& frame_body); + + /** + * ldu2 (virtual) destructor. + */ + virtual ~ldu2(); + + /** + * Returns a string describing the Data Unit ID (DUID). + */ + std::string duid_str() const; +}; + +#endif /* INCLUDED_LDU2_H */ diff --git a/blocks/src/lib/logfile_du_handler.cc b/blocks/src/lib/logfile_du_handler.cc new file mode 100644 index 0000000..36aa9dc --- /dev/null +++ b/blocks/src/lib/logfile_du_handler.cc @@ -0,0 +1,47 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2008 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. + */ + +#include +#include +#include + +using namespace std; + +logfile_du_handler::logfile_du_handler(data_unit_handler_sptr next, const char *filename) : + data_unit_handler(next), + d_log(filename) +{ +} + +logfile_du_handler::~logfile_du_handler() +{ + d_log.flush(); + d_log.close(); +} + +void +logfile_du_handler::handle(data_unit_sptr du) +{ + du->dump(d_log); + data_unit_handler::handle(du); +} diff --git a/blocks/src/lib/logfile_du_handler.h b/blocks/src/lib/logfile_du_handler.h new file mode 100644 index 0000000..f06b0f8 --- /dev/null +++ b/blocks/src/lib/logfile_du_handler.h @@ -0,0 +1,68 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2008 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. +*/ + +#ifndef INCLUDED_LOGFILE_DU_HANDLER_H +#define INCLUDED_LOGFILE_DU_HANDLER_H + +#include +#include +#include + +/** + * logfile_data_unit_handler writes frames to a log file for later inspection. + */ +class logfile_du_handler : public data_unit_handler +{ + +public: + + /** + * logfile_du_handler constructor. + * + * \param next The next data_unit_handler in the chain. + * \param filename The path to the log file. + */ + logfile_du_handler(data_unit_handler_sptr next, const char *filename); + + /** + * logfile_du_handler virtual destructor. + */ + virtual ~logfile_du_handler(); + + /** + * Handle a received P25 frame. + * + * \param next The next data_unit_handler in this chain. + */ + virtual void handle(data_unit_sptr du); + +private: + + /** + * The file to which decoded frames are written. + */ + std::ofstream d_log; + +}; + +#endif /* INCLUDED_LOGFILE_DU_HANDLER_H */ diff --git a/blocks/src/lib/offline_imbe_decoder.cc b/blocks/src/lib/offline_imbe_decoder.cc new file mode 100644 index 0000000..617df66 --- /dev/null +++ b/blocks/src/lib/offline_imbe_decoder.cc @@ -0,0 +1,63 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2008 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. + */ + +#include +#include +#include +#include + +using namespace std; + +offline_imbe_decoder::offline_imbe_decoder() +{ + const char *dev = getenv("IMBE_FILE"); + if(!dev) { + const char *default_filename = "imbe.dat"; + dev = default_filename; + } + d_fp = fopen(dev, "w"); + if(NULL == d_fp) { + perror("fopen(dev, \"w\");"); // a warning, not an error + } +} + +offline_imbe_decoder::~offline_imbe_decoder() +{ + if(d_fp) { + fclose(d_fp); + } +} + +void +offline_imbe_decoder::decode(const voice_codeword& cw) +{ + if(d_fp) { + uint8_t codewords[18]; + extract(cw, 0, 144, codewords); + if(0 == fwrite(codewords, sizeof(codewords), 1, d_fp)) { + perror("fwrite(codewords, sizeof(codewords), 1, d_fp)"); + fclose(d_fp); + d_fp = NULL; + } + } +} diff --git a/blocks/src/lib/offline_imbe_decoder.h b/blocks/src/lib/offline_imbe_decoder.h new file mode 100644 index 0000000..9e45aad --- /dev/null +++ b/blocks/src/lib/offline_imbe_decoder.h @@ -0,0 +1,64 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2008 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. + */ + +#ifndef INCLUDED_OFFLINE_IMBE_DECODER_H +#define INCLUDED_OFFLINE_IMBE_DECODER_H + +#include + +#include + +/** + * offline_imbe_decoder dumps voice codewords to file for offline decoding. + * + */ +class offline_imbe_decoder : public imbe_decoder { +public: + + /** + * offline_imbe_decoder default constructor. + */ + offline_imbe_decoder(); + + /** + * offline_imbe_decoder (virtual) destructor. + */ + virtual ~offline_imbe_decoder(); + + /** + * Dump voice_codeword in_out to file. + * + * \param cw IMBE codewords and parity. + */ + virtual void decode(const voice_codeword& cw); + +private: + + /** + * The output file. + */ + FILE *d_fp; + +}; + +#endif /* INCLUDED_OFFLINE_IMBE_DECODER_H */ diff --git a/blocks/src/lib/op25.i b/blocks/src/lib/op25.i new file mode 100644 index 0000000..b92d10b --- /dev/null +++ b/blocks/src/lib/op25.i @@ -0,0 +1,109 @@ +/* -*- C++ -*- */ + +%feature("autodoc", "1"); + +%include "exception.i" +%import "gnuradio.i" + +%{ +#include "gnuradio_swig_bug_workaround.h" +#include "op25_fsk4_demod_ff.h" +#include "op25_fsk4_slicer_fb.h" +#include "op25_decoder_bf.h" +#include "op25_pcap_source_b.h" +%} + +// ---------------------------------------------------------------- + +/* + * This does some behind-the-scenes magic so we can + * access fsk4_square_ff from python as fsk4.square_ff + */ +GR_SWIG_BLOCK_MAGIC(op25, fsk4_demod_ff); + +/* + * Publicly-accesible default constuctor function for op25_fsk4_demod_bf. + */ +op25_fsk4_demod_ff_sptr op25_make_fsk4_demod_ff(gr_msg_queue_sptr queue, float sample_rate, float symbol_rate); + +class op25_fsk4_demod_ff : public gr_block +{ +private: + op25_fsk4_demod_ff(gr_msg_queue_sptr queue, float sample_rate, float symbol_rate); +}; + +// ---------------------------------------------------------------- + +/* + * This does some behind-the-scenes magic so we can invoke + * op25_make_slicer_fb from python as op25.slicer_fbf. + */ +GR_SWIG_BLOCK_MAGIC(op25, fsk4_slicer_fb); + +/* + * Publicly-accesible default constuctor function for op25_decoder_bf. + */ +op25_fsk4_slicer_fb_sptr op25_make_fsk4_slicer_fb(const std::vector &slice_levels); + +/* + * The op25_fsk4_slicer block. Takes a series of float samples and + * partitions them into dibit symbols according to the slices_levels + * provided to the constructor. + */ +class op25_fsk4_slicer_fb : public gr_sync_block +{ +private: + op25_fsk4_slicer_fb (const std::vector &slice_levels); +}; + +// ---------------------------------------------------------------- + +/* + * This does some behind-the-scenes magic so we can invoke + * op25_make_decoder_bsf from python as op25.decoder_bf. + */ +GR_SWIG_BLOCK_MAGIC(op25, decoder_bf); + +/* + * Publicly-accesible default constuctor function for op25_decoder_bf. + */ +op25_decoder_bf_sptr op25_make_decoder_bf(); + +/** + * The op25_decoder_bf block. Accepts a stream of dibit symbols and + * produces an 8KS/s audio stream. + */ +class op25_decoder_bf : public gr_block +{ +private: + op25_decoder_bf(); +public: + const char *destination() const; + gr_msg_queue_sptr get_msgq() const; + void set_msgq(gr_msg_queue_sptr msgq); +}; + +// ---------------------------------------------------------------- + +/* + * This does some behind-the-scenes magic so we can invoke + * op25_make_pcap_source_b from python as op25.pcap_source_b. + */ +GR_SWIG_BLOCK_MAGIC(op25, pcap_source_b); + +/* + * Publicly-accesible constuctor function for op25_pcap_source. + */ +op25_pcap_source_b_sptr op25_make_pcap_source_b(const char *path, float delay); + +/* + * The op25_pcap_source block. Reads symbols from a tcpdump-formatted + * file and produces a stream of symbols of the appropriate size. + */ +class op25_pcap_source_b : public gr_sync_block +{ +private: + op25_pcap_source_b(const char *path, float delay); +}; + +// ---------------------------------------------------------------- diff --git a/blocks/src/lib/op25_decoder_bf.cc b/blocks/src/lib/op25_decoder_bf.cc new file mode 100644 index 0000000..ae68638 --- /dev/null +++ b/blocks/src/lib/op25_decoder_bf.cc @@ -0,0 +1,221 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2008-2011 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +op25_decoder_bf_sptr +op25_make_decoder_bf() +{ + return op25_decoder_bf_sptr(new op25_decoder_bf); +} + +op25_decoder_bf::~op25_decoder_bf() +{ +} + +gr_msg_queue_sptr +op25_decoder_bf::get_msgq() const +{ + return d_snapshot_du_handler->get_msgq(); +} + +void + +op25_decoder_bf::set_msgq(gr_msg_queue_sptr msgq) +{ + d_snapshot_du_handler->set_msgq(msgq); +} + +void +op25_decoder_bf::forecast(int nof_outputs, gr_vector_int &nof_inputs_reqd) +{ + /* This block consumes 4800 symbols/s and produces 8000 + * samples/s. That's a work rate of 3/5 or 0.6. If no audio output + * is available we'll produce silence. + */ + const size_t nof_inputs = nof_inputs_reqd.size(); + const int nof_samples_reqd = .6 * nof_outputs; + fill(&nof_inputs_reqd[0], &nof_inputs_reqd[nof_inputs], nof_samples_reqd); +} + +int +op25_decoder_bf::general_work(int nof_output_items, gr_vector_int& nof_input_items, gr_vector_const_void_star& input_items, gr_vector_void_star& output_items) +{ + try { + + // process input + const uint8_t *in = reinterpret_cast(input_items[0]); + for(int i = 0; i < nof_input_items[0]; ++i) { + dibit d = in[i] & 0x3; + receive_symbol(d); + } + consume_each(nof_input_items[0]); + + // produce audio + audio_samples *samples = d_imbe->audio(); + float *out = reinterpret_cast(output_items[0]); + const int n = min(static_cast(samples->size()), nof_output_items); + if(0 < n) { + copy(samples->begin(), samples->begin() + n, out); + samples->erase(samples->begin(), samples->begin() + n); + } + if(n < nof_output_items) { + fill(out + n, out + nof_output_items, 0.0); + } + return nof_output_items; + + } catch(const std::exception& x) { + cerr << x.what() << endl; + exit(1); + } catch(...) { + cerr << "unhandled exception" << endl; + exit(2); } +} + +const char* +op25_decoder_bf::destination() const +{ + return d_p25cai_du_handler->destination(); +} + +op25_decoder_bf::op25_decoder_bf() : + gr_block("decoder_bf", gr_make_io_signature(1, 1, sizeof(uint8_t)), gr_make_io_signature(0, 1, sizeof(float))), + d_data_unit(), + d_data_unit_handler(), + d_frame_hdr(), + d_imbe(imbe_decoder::make()), + d_state(SYNCHRONIZING), + d_p25cai_du_handler(NULL) +{ + d_p25cai_du_handler = new p25cai_du_handler(d_data_unit_handler, "224.0.0.1", 23456); + d_data_unit_handler = data_unit_handler_sptr(d_p25cai_du_handler); + d_snapshot_du_handler = new snapshot_du_handler(d_data_unit_handler); + d_data_unit_handler = data_unit_handler_sptr(d_snapshot_du_handler); + d_data_unit_handler = data_unit_handler_sptr(new voice_du_handler(d_data_unit_handler, d_imbe)); +} + +bool +op25_decoder_bf::correlated() +{ + static const bool FS[] = { + 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 1, 1, 0, 1, 0, 1, + 1, 1, 1, 1, 0, 1, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1 + }; + static const size_t FS_SZ = sizeof(FS)/sizeof(FS[0]); + + uint8_t errs = 0; + for(size_t i = 0; i < FS_SZ; ++i) { + if(d_frame_hdr[i] ^ FS[i]) { + ++errs; + } + } + return (errs <= 4); +} + +data_unit_sptr +op25_decoder_bf::identified() +{ + static const size_t NID[] = { + 63, 62, 61, 60, 59, 58, 57, 56, + 55, 54, 53, 52, 51, 50, 49, 48, + 112, 111, 110, 109, 108, 107, 106, 105, + 104, 103, 102, 101, 100, 99, 98, 97, + 96, 95, 94, 93, 92, 91, 90, 89, + 88, 87, 86, 85, 84, 83, 82, 81, + 80, 79, 78, 77, 76, 75, 74, 73, + 72, 69, 68, 67, 66, 65, 64, + }; + size_t NID_SZ = sizeof(NID) / sizeof(NID[0]); + + itpp::bvec b(63), zeroes(16); + itpp::BCH bch(63, 16, 11, "6 3 3 1 1 4 1 3 6 7 2 3 5 4 5 3", true); + yank(d_frame_hdr, NID, NID_SZ, b, 0); + b = bch.decode(b); + if(b != zeroes) { + b = bch.encode(b); + yank_back(b, 0, d_frame_hdr, NID, NID_SZ); + d_data_unit = data_unit::make_data_unit(d_frame_hdr); + } else { + data_unit_sptr null; + d_data_unit = null; + } + return d_data_unit; +} + +void +op25_decoder_bf::receive_symbol(dibit d) +{ + d_frame_hdr.push_back(d & 0x2); + d_frame_hdr.push_back(d & 0x1); + const size_t frame_hdr_sz = d_frame_hdr.size(); + + switch(d_state) { + case SYNCHRONIZING: + if(48 <= frame_hdr_sz) { + d_frame_hdr.erase(d_frame_hdr.begin(), d_frame_hdr.begin() + (frame_hdr_sz - 48)); + if(correlated()) { + d_state = IDENTIFYING; + } + } + break; + case IDENTIFYING: + if(114 == frame_hdr_sz) { + if(identified()) { + d_state = READING; + } else { + d_state = SYNCHRONIZING; + } + } + break; + case READING: + d_data_unit->extend(d); + if(d_data_unit->is_complete()) { + d_data_unit->correct_errors(); + d_data_unit_handler->handle(d_data_unit); + data_unit_sptr null; + d_data_unit = null; + d_state = SYNCHRONIZING; + } + break; + } +} diff --git a/blocks/src/lib/op25_decoder_bf.h b/blocks/src/lib/op25_decoder_bf.h new file mode 100644 index 0000000..421bb7d --- /dev/null +++ b/blocks/src/lib/op25_decoder_bf.h @@ -0,0 +1,169 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2008-2011 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. + */ + +#ifndef INCLUDED_OP25_DECODER_BF_H +#define INCLUDED_OP25_DECODER_BF_H + +#include +#include +#include +#include +#include +#include + +typedef boost::shared_ptr op25_decoder_bf_sptr; + +op25_decoder_bf_sptr op25_make_decoder_bf(); + +/** + * op25_decoder_bf is a GNU Radio block for decoding APCO P25 + * signals. This class expects its input to be a stream of dibit + * symbols from the demodulator and produces a mono audio + * stream. + */ +class op25_decoder_bf : public gr_block +{ +public: + + /** + * op25_decoder_bf (virtual) destructor. + */ + virtual ~op25_decoder_bf(); + + /** + * Estimate nof_input_items_reqd for a given nof_output_items. + */ + virtual void forecast(int nof_output_items, gr_vector_int &nof_input_items_reqd); + + /** + * Process symbols into frames. + */ + virtual int general_work(int nof_output_items, gr_vector_int& nof_input_items, gr_vector_const_void_star& input_items, gr_vector_void_star& output_items); + + /** + * Return a pointer to a string identifying the destination of + * the received frames. + * + * \return A pointer to a NUL-terminated character string. + */ + const char *destination() const; + + /** + * Accessor for the msgq attribute. Returns a pointer to the msgq + * if it exists. + * + * \return A (possibly NULL) gr_msg_queue_sptr pointing to the message queue. + */ + gr_msg_queue_sptr get_msgq() const; + + /** + * Accessor for the msgq attribute. Sets the msgq to point to the + * provided message queue object. + * + * \return A (possibly NULL) gr_msg_queue_sptr pointing to the message queue. + */ + void set_msgq(gr_msg_queue_sptr msgq); + +private: + + /** + * Expose class to public ctor. Create a new instance of + * op25_decoder_bf and wrap it in a shared_ptr. This is effectively + * the public constructor. + */ + friend op25_decoder_bf_sptr op25_make_decoder_bf(); + + /** + * op25_decoder_bf private constructor. + */ + op25_decoder_bf(); + + /** + * Tests whether d_frame_header correlates with the APCO P25 frame + * sync sequence. This method must only be called when the frame + * header is larger than 48 bits in length (the minimum size for + * the FS). + * + * \return true if the frame header correlates; otherwise false. + */ + bool correlated(); + + /** + * Tests whether d_frame_header identifies a known data unit and if + * so sets d_data_unit to point to an appropriate instance and + * returns a pointer to it. This method must only be called when + * the frame header is larger than 114 bits in length (the minimum + * size for a frame containing a NID). + * + * \return A data_unit_sptr pointing to an appropriate data_unit + * instance or NULL if the frame header is unrecognized. + */ + data_unit_sptr identified(); + + /** + * Handle a received symbol. + * + * \param d The symbol to process. + */ + void receive_symbol(dibit d); + +private: + + /** + * When d_state == READING the current data unit, otherwise null. + */ + data_unit_sptr d_data_unit; + + /** + * The head of a chain of data_unit_handler instances. + */ + data_unit_handler_sptr d_data_unit_handler; + + /** + * A bit_queue used to correlate the FS. + */ + bit_queue d_frame_hdr; + + /** + * The IMBE decoder to use. + */ + imbe_decoder_sptr d_imbe; + + /** + * Valid states for the decoder state model. + */ + enum { SYNCHRONIZING, IDENTIFYING, READING } d_state; + + /** + * The p25cai (TUN/TAP) data unit handler. + */ + class p25cai_du_handler *d_p25cai_du_handler; + + /** + * The snapshot data unit handler. + */ + class snapshot_du_handler *d_snapshot_du_handler; + +}; + +#endif /* INCLUDED_OP25_DECODER_BF_H */ diff --git a/blocks/src/lib/op25_decoder_ff.cc b/blocks/src/lib/op25_decoder_ff.cc new file mode 100644 index 0000000..51e6f1d --- /dev/null +++ b/blocks/src/lib/op25_decoder_ff.cc @@ -0,0 +1,230 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2008-2011 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +op25_decoder_ff_sptr +op25_make_decoder_ff() +{ + return op25_decoder_ff_sptr(new op25_decoder_ff); +} + +op25_decoder_ff::~op25_decoder_ff() +{ +} + +gr_msg_queue_sptr +op25_decoder_ff::get_msgq() const +{ + return d_snapshot_du_handler->get_msgq(); +} + +void + +op25_decoder_ff::set_msgq(gr_msg_queue_sptr msgq) +{ + d_snapshot_du_handler->set_msgq(msgq); +} + +void +op25_decoder_ff::forecast(int nof_output_items, gr_vector_int &nof_input_items_reqd) +{ + /* This block consumes 4800 symbols/s and produces 8000 + * samples/s. That's a work rate of 3/5 or 0.6. If no audio output + * is available we'll produce silence. + */ + const size_t nof_inputs = nof_input_items_reqd.size(); + const int nof_samples_reqd = .6 * nof_output_items; + fill(&nof_input_items_reqd[0], &nof_input_items_reqd[nof_inputs], nof_samples_reqd); +} + +int +op25_decoder_ff::general_work(int nof_output_items, gr_vector_int& nof_input_items, gr_vector_const_void_star& input_items, gr_vector_void_star& output_items) +{ + try { + + // process input + const float *in = reinterpret_cast(input_items[0]); + for(int i = 0; i < nof_input_items[0]; ++i) { + dibit d; + if(in[i] < -2.0) { + d = 3; + } else if(in[i] < 0.0) { + d = 2; + } else if(in[i] < 2.0) { + d = 0; + } else { + d = 1; + } + receive_symbol(d); + } + consume_each(nof_input_items[0]); + + // produce audio + audio_samples *samples = d_imbe->audio(); + float *out = reinterpret_cast(output_items[0]); + const int n = min(static_cast(samples->size()), nof_output_items); + if(0 < n) { + copy(samples->begin(), samples->begin() + n, out); + samples->erase(samples->begin(), samples->begin() + n); + } + if(n < nof_output_items) { + fill(out + n, out + nof_output_items, 0.0); + } + return nof_output_items; + + } catch(const std::exception& x) { + cerr << x.what() << endl; + exit(1); + } catch(...) { + cerr << "unhandled exception" << endl; + exit(2); } +} + +const char* +op25_decoder_ff::destination() const +{ + return d_p25cai_du_handler->destination(); +} + +op25_decoder_ff::op25_decoder_ff() : + gr_block("decoder_ff", gr_make_io_signature(1, 1, sizeof(float)), gr_make_io_signature(0, 1, sizeof(float))), + d_data_unit(), + d_data_unit_handler(), + d_frame_hdr(), + d_imbe(imbe_decoder::make()), + d_state(SYNCHRONIZING), + d_p25cai_du_handler(NULL) +{ + d_p25cai_du_handler = new p25cai_du_handler(d_data_unit_handler, "224.0.0.1", 23456); + d_data_unit_handler = data_unit_handler_sptr(d_p25cai_du_handler); + d_snapshot_du_handler = new snapshot_du_handler(d_data_unit_handler); + d_data_unit_handler = data_unit_handler_sptr(d_snapshot_du_handler); + d_data_unit_handler = data_unit_handler_sptr(new voice_du_handler(d_data_unit_handler, d_imbe)); +} + +bool +op25_decoder_ff::correlated() +{ + static const bool FS[] = { + 0, 1, 0, 1, 0, 1, 0, 1, + 0, 1, 1, 1, 0, 1, 0, 1, + 1, 1, 1, 1, 0, 1, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 0, 1, 1, 1, 0, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1 + }; + static const size_t FS_SZ = sizeof(FS)/sizeof(FS[0]); + + uint8_t errs = 0; + for(size_t i = 0; i < FS_SZ; ++i) { + if(d_frame_hdr[i] ^ FS[i]) { + ++errs; + } + } + return (errs <= 4); +} + +data_unit_sptr +op25_decoder_ff::identified() +{ + static const size_t NID[] = { + 63, 62, 61, 60, 59, 58, 57, 56, + 55, 54, 53, 52, 51, 50, 49, 48, + 112, 111, 110, 109, 108, 107, 106, 105, + 104, 103, 102, 101, 100, 99, 98, 97, + 96, 95, 94, 93, 92, 91, 90, 89, + 88, 87, 86, 85, 84, 83, 82, 81, + 80, 79, 78, 77, 76, 75, 74, 73, + 72, 69, 68, 67, 66, 65, 64, + }; + size_t NID_SZ = sizeof(NID) / sizeof(NID[0]); + + itpp::bvec b(63), zeroes(16); + itpp::BCH bch(63, 16, 11, "6 3 3 1 1 4 1 3 6 7 2 3 5 4 5 3", true); + yank(d_frame_hdr, NID, NID_SZ, b, 0); + b = bch.decode(b); + if(b != zeroes) { + b = bch.encode(b); + yank_back(b, 0, d_frame_hdr, NID, NID_SZ); + d_data_unit = data_unit::make_data_unit(d_frame_hdr); + } else { + data_unit_sptr null; + d_data_unit = null; + } + return d_data_unit; +} + +void +op25_decoder_ff::receive_symbol(dibit d) +{ + d_frame_hdr.push_back(d & 0x2); + d_frame_hdr.push_back(d & 0x1); + const size_t frame_hdr_sz = d_frame_hdr.size(); + + switch(d_state) { + case SYNCHRONIZING: + if(48 <= frame_hdr_sz) { + d_frame_hdr.erase(d_frame_hdr.begin(), d_frame_hdr.begin() + (frame_hdr_sz - 48)); + if(correlated()) { + d_state = IDENTIFYING; + } + } + break; + case IDENTIFYING: + if(114 == frame_hdr_sz) { + if(identified()) { + d_state = READING; + } else { + d_state = SYNCHRONIZING; + } + } + break; + case READING: + d_data_unit->extend(d); + if(d_data_unit->is_complete()) { + d_data_unit->correct_errors(); + d_data_unit_handler->handle(d_data_unit); + data_unit_sptr null; + d_data_unit = null; + d_state = SYNCHRONIZING; + } + break; + } +} diff --git a/blocks/src/lib/op25_decoder_ff.h b/blocks/src/lib/op25_decoder_ff.h new file mode 100644 index 0000000..43b6d62 --- /dev/null +++ b/blocks/src/lib/op25_decoder_ff.h @@ -0,0 +1,168 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2008-2011 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. + */ + +#ifndef INCLUDED_OP25_DECODER_FF_H +#define INCLUDED_OP25_DECODER_FF_H + +#include +#include +#include +#include +#include +#include + +typedef boost::shared_ptr op25_decoder_ff_sptr; + +op25_decoder_ff_sptr op25_make_decoder_ff(); + +/** + * op25_decoder_ff is a GNU Radio block for decoding APCO P25 + * signals. This class expects its input to be a stream of dibit + * symbols from the demodulator and produces a mono audio + * stream. + */ +class op25_decoder_ff : public gr_block +{ +public: + + /** + * op25_decoder_ff (virtual) destructor. + */ + virtual ~op25_decoder_ff(); + + /** + * Estimate nof_input_items_reqd for a given nof_output_items. + */ + virtual void forecast(int nof_output_items, gr_vector_int &nof_input_items_reqd); + + /** + * Process symbols into frames. + */ + virtual int general_work(int nof_output_items, gr_vector_int& nof_input_items, gr_vector_const_void_star& input_items, gr_vector_void_star& output_items); + /** + * Return a pointer to a string identifying the destination of + * the received frames. + * + * \return A pointer to a NUL-terminated character string. + */ + const char *destination() const; + + /** + * Accessor for the msgq attribute. Returns a pointer to the msgq + * if it exists. + * + * \return A (possibly NULL) gr_msg_queue_sptr pointing to the message queue. + */ + gr_msg_queue_sptr get_msgq() const; + + /** + * Accessor for the msgq attribute. Sets the msgq to point to the + * provided message queue object. + * + * \return A (possibly NULL) gr_msg_queue_sptr pointing to the message queue. + */ + void set_msgq(gr_msg_queue_sptr msgq); + +private: + + /** + * Expose class to public ctor. Create a new instance of + * op25_decoder_ff and wrap it in a shared_ptr. This is effectively + * the public constructor. + */ + friend op25_decoder_ff_sptr op25_make_decoder_ff(); + + /** + * op25_decoder_ff protected constructor. + */ + op25_decoder_ff(); + + /** + * Tests whether d_frame_header correlates with the APCO P25 frame + * sync sequence. This method must only be called when the frame + * header is larger than 48 bits in length (the minimum size for + * the FS). + * + * \return true if the frame header correlates; otherwise false. + */ + bool correlated(); + + /** + * Tests whether d_frame_header identifies a known data unit and if + * so sets d_data_unit to point to an appropriate instance and + * returns a pointer to it. This method must only be called when + * the frame header is larger than 114 bits in length (the minimum + * size for a frame containing a NID). + * + * \return A data_unit_sptr pointing to an appropriate data_unit + * instance or NULL if the frame header is unrecognized. + */ + data_unit_sptr identified(); + + /** + * Handle a received symbol. + * + * \param d The symbol to process. + */ + void receive_symbol(dibit d); + +private: + + /** + * When d_state == READING the current data unit, otherwise null. + */ + data_unit_sptr d_data_unit; + + /** + * The head of a chain of data_unit_handler instances. + */ + data_unit_handler_sptr d_data_unit_handler; + + /** + * A bit_queue used to correlate the FS. + */ + bit_queue d_frame_hdr; + + /** + * The IMBE decoder to use. + */ + imbe_decoder_sptr d_imbe; + + /** + * Valid states for the decoder state model. + */ + enum { SYNCHRONIZING, IDENTIFYING, READING } d_state; + + /** + * The p25cai (TUN/TAP) data unit handler. + */ + class p25cai_du_handler *d_p25cai_du_handler; + + /** + * The snapshot data unit handler. + */ + class snapshot_du_handler *d_snapshot_du_handler; + +}; + +#endif /* INCLUDED_OP25_DECODER_FF_H */ diff --git a/blocks/src/lib/op25_fsk4_demod_ff.cc b/blocks/src/lib/op25_fsk4_demod_ff.cc new file mode 100644 index 0000000..c816841 --- /dev/null +++ b/blocks/src/lib/op25_fsk4_demod_ff.cc @@ -0,0 +1,361 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2006, 2007 Frank (Radio Rausch) + * Copyright 2011 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +using namespace std; + +/* + * This table 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 +}; + +op25_fsk4_demod_ff::~op25_fsk4_demod_ff () +{ +} + +void +op25_fsk4_demod_ff::forecast(int nof_outputs, gr_vector_int &nof_inputs_reqd) +{ + const int nof_samples_reqd = static_cast(ceil(d_block_rate * nof_outputs)); + fill(&nof_inputs_reqd[0], &nof_inputs_reqd[nof_inputs_reqd.size()], nof_samples_reqd); +} + +int +op25_fsk4_demod_ff::general_work (int nof_outputs, gr_vector_int &nof_inputs, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) +{ + int n = 0; + + const float *in = reinterpret_cast(input_items[0]); + float *out = reinterpret_cast(output_items[0]); + + // first we run through all provided data + for(int i = 0; i < nof_outputs; i++) { + if(tracking_loop_mmse(in[i], &out[n])) { + ++n; + } + } + + // send frequency adjusment request if needed + send_frequency_correction(); + + consume_each(nof_outputs); + return n; +} + +op25_fsk4_demod_ff_sptr +op25_make_fsk4_demod_ff(gr_msg_queue_sptr queue, float sample_rate_Hz, float symbol_rate_Hz) +{ + return op25_fsk4_demod_ff_sptr(new op25_fsk4_demod_ff(queue, sample_rate_Hz, symbol_rate_Hz)); +} + +op25_fsk4_demod_ff::op25_fsk4_demod_ff (gr_msg_queue_sptr queue, float sample_rate_Hz, float symbol_rate_Hz) : + gr_block ("fsk4_demod_ff", gr_make_io_signature(1, 1, sizeof(float)), gr_make_io_signature(1, 1, sizeof(float))), + d_block_rate(sample_rate_Hz / symbol_rate_Hz), + d_history(new float[NTAPS]), + d_history_last(0), + d_queue(queue), + d_symbol_clock(0.0), + d_symbol_spread(2.0), // nominal symbol spread of 2.0 gives outputs at -3, -1, +1, +3 + d_symbol_time(symbol_rate_Hz / sample_rate_Hz) +{ + fine_frequency_correction = 0.0; + coarse_frequency_correction = 0.0; + + fill(&d_history[0], &d_history[NTAPS], 0.0); +} + +void +op25_fsk4_demod_ff::send_frequency_correction() +{ + double arg1, arg2; + + // if the queue is full, don't block, drop the data... + if(d_queue->full_p()) + return; + + const double COARSE_FREQUENCY_DEADBAND = 1.66; // gnuradio frequency adjust messages will not be emitted until we exceed this threshold + + if((coarse_frequency_correction < COARSE_FREQUENCY_DEADBAND) && (coarse_frequency_correction > -COARSE_FREQUENCY_DEADBAND)) + return; + + arg1 = coarse_frequency_correction; + arg2 = 0.0; + coarse_frequency_correction = 0.0; + + // build & send a message + gr_message_sptr msg = gr_make_message(0, arg1, arg2, 0); // vlen() * sizeof(float)); + d_queue->insert_tail(msg); + msg.reset(); +} + +bool +op25_fsk4_demod_ff::tracking_loop_mmse(float input, float *output) +{ + d_symbol_clock += d_symbol_time; + + d_history[d_history_last++] = input; + d_history_last %= NTAPS; + + if(d_symbol_clock > 1.0) { + + d_symbol_clock -= 1.0; + + // at this point we state that linear interpolation was tried + // but found to be slightly inferior. Using MMSE interpolation + // shouldn't be a terrible burden + +#if 0 + int imu = min(static_cast(floor(0.5 + (NSTEPS * (d_symbol_clock / d_symbol_time)))), NSTEPS - 1); + int imu_p1 = imu + 1; +#else + int imu = (int) floor(0.5 + (NSTEPS * ((d_symbol_clock / d_symbol_time)))); + int imu_p1 = imu + 1; + if (imu >= NSTEPS) { + imu = NSTEPS - 1; + imu_p1 = NSTEPS; + } +#endif + +#if 0 + double interp = 0.0; + double interp_p1 = 0.0; + for(size_t i = 0, j = d_history_last; i < NTAPS; ++i) { + interp += TAPS[imu][i] * d_history[j]; + interp_p1 += TAPS[imu_p1][i] * d_history[j]; + j = (j + 1) % NTAPS; + } +#else + size_t j = d_history_last; + double interp = 0.0; + double interp_p1 = 0.0; + for(int i=0; i +#include + +#include + +typedef boost::shared_ptr op25_fsk4_demod_ff_sptr; + +op25_fsk4_demod_ff_sptr op25_make_fsk4_demod_ff(gr_msg_queue_sptr queue, float sample_rate, float symbol_rate); + +/** + * op25_fsk4_demod_ff is a GNU Radio block for demodulating APCO P25 + * CF4M signals. This class expects its input to consist of a 4 level + * FSK modulated baseband signal. It produces a stream of symbols. + * + * All inputs are post FM demodulator and symbol shaping filter data + * is normalized before being sent to this block so these parameters + * should not need adjusting even when working on different signals. + * + * Nominal levels are -3, -1, +1, and +3. + */ +class op25_fsk4_demod_ff : public gr_block +{ +public: + + /** + * op25_fsk4_demod_ff (virtual) destructor. + */ + virtual ~op25_fsk4_demod_ff(); + + /** + * Estimate nof_input_items_reqd for a given nof_output_items. + */ + virtual void forecast(int noutput_items, gr_vector_int &inputs_required); + + /** + * Process baseband into symbols. + */ + 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); + +private: + + /** + * Expose class to public ctor. Create a new instance of + * op25_fsk4_demod_ff and wrap it in a shared_ptr. This is + * effectively the public constructor. + */ + friend op25_fsk4_demod_ff_sptr op25_make_fsk4_demod_ff(gr_msg_queue_sptr queue, float sample_rate, float symbol_rate); + + /** + * op25_fsk4_demod_ff private constructor. + */ + op25_fsk4_demod_ff(gr_msg_queue_sptr queue, float sample_rate, float symbol_rate); + + /** + * Called when we want the input frequency to be adjusted. + */ + void send_frequency_correction(); + + /** + * Tracking loop. + */ + bool tracking_loop_mmse(float input, float *output); + +private: + + const float d_block_rate; + + boost::scoped_array d_history; + + size_t d_history_last; + + gr_msg_queue_sptr d_queue; + + double d_symbol_clock; + + double d_symbol_spread; + + const float d_symbol_time; + + double fine_frequency_correction; + + double coarse_frequency_correction; + +}; + +#endif /* INCLUDED_OP25_FSK4_DEMOD_FF_H */ diff --git a/blocks/src/lib/op25_fsk4_slicer_fb.cc b/blocks/src/lib/op25_fsk4_slicer_fb.cc new file mode 100644 index 0000000..4fa9b03 --- /dev/null +++ b/blocks/src/lib/op25_fsk4_slicer_fb.cc @@ -0,0 +1,123 @@ +/* -*- Mode: C++ -*- */ + +/* + * Copyright 2010, KA1RBI + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, 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 +#include + +/* + * Create a new instance of op25_fsk4_slicer_fb and return + * a boost shared_ptr. This is effectively the public constructor. + */ +op25_fsk4_slicer_fb_sptr +op25_make_fsk4_slicer_fb(const std::vector &slice_levels) +{ + return op25_fsk4_slicer_fb_sptr(new op25_fsk4_slicer_fb (slice_levels)); +} + +/* + * 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 + */ +op25_fsk4_slicer_fb::op25_fsk4_slicer_fb(const std::vector &slice_levels) + : gr_sync_block("fsk4_slicer_fb", + gr_make_io_signature(MIN_IN, MAX_IN, sizeof(float)), + gr_make_io_signature(MIN_OUT, MAX_OUT, sizeof(unsigned char))) +{ + d_slice_levels[0] = slice_levels[0]; + d_slice_levels[1] = slice_levels[1]; + d_slice_levels[2] = slice_levels[2]; + d_slice_levels[3] = slice_levels[3]; +} + +/* + * Our virtual destructor. + */ +op25_fsk4_slicer_fb::~op25_fsk4_slicer_fb() +{ + // nothing else required in this example +} + +int +op25_fsk4_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++){ +#if 0 + if(in[i] < -2.0) { + out[i] = 3; + } else if(in[i] < 0.0) { + out[i] = 2; + } else if(in[i] < 2.0) { + out[i] = 0; + } else { + out[i] = 1; + } +#endif + uint8_t dibit; + float sym = in[i]; + if(d_slice_levels[3] < 0) { + dibit = 1; + if(d_slice_levels[3] <= sym && sym < d_slice_levels[0]) + dibit = 3; + } else { + dibit = 3; + if(d_slice_levels[2] <= sym && sym < d_slice_levels[3]) + dibit = 1; + } + if(d_slice_levels[0] <= sym && sym < d_slice_levels[1]) + dibit = 2; + if(d_slice_levels[1] <= sym && sym < d_slice_levels[2]) + dibit = 0; + out[i] = dibit; + } + + // Tell runtime system how many output items we produced. + return noutput_items; +} diff --git a/blocks/src/lib/op25_fsk4_slicer_fb.h b/blocks/src/lib/op25_fsk4_slicer_fb.h new file mode 100644 index 0000000..aa7a92b --- /dev/null +++ b/blocks/src/lib/op25_fsk4_slicer_fb.h @@ -0,0 +1,81 @@ +/* -*- c++ -*- */ + +/* + * Copyright 2010 KA1RBI + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef INCLUDED_OP25_FSK4_SLICER_FB_H +#define INCLUDED_OP25_FSK4_SLICER_FB_H + +#include + +/** + * 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 op25_fsk4_slicer_fb_sptr; + +/** + * Return a shared_ptr to a new instance of op25_fsk4_slicer_fb. To + * avoid accidental use of raw pointers, op25_fsk4_slicer_fb's + * constructor is private. op25_make_fsk4_slicer_fb is the public + * interface for creating new instances. + */ +op25_fsk4_slicer_fb_sptr op25_make_fsk4_slicer_fb (const std::vector &slice_levels); + +/** + * Produce a stream of dibits, given a stream of floats in [-3,-1,1,3]. + * \ingroup block + * + * This uses the preferred technique: subclassing gr_sync_block. + */ +class op25_fsk4_slicer_fb : public gr_sync_block +{ + +public: + + virtual ~op25_fsk4_slicer_fb (); + + virtual int work (int noutput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + +private: + + /** + * The friend declaration allows op25_make_fsk4_slicer_fb to access + * the private constructor. + */ + friend op25_fsk4_slicer_fb_sptr op25_make_fsk4_slicer_fb (const std::vector &slice_levels); + + op25_fsk4_slicer_fb (const std::vector &slice_levels); + + float d_slice_levels[4]; + +}; + +#endif /* INCLUDED_OP25_FSK4_SLICER_FB_H */ diff --git a/blocks/src/lib/op25_golay.h b/blocks/src/lib/op25_golay.h new file mode 100644 index 0000000..36a2aab --- /dev/null +++ b/blocks/src/lib/op25_golay.h @@ -0,0 +1,206 @@ +#ifndef INCLUDED_OP25_GOLAY_H +#define INCLUDED_OP25_GOLAY_H + +#include +#include + +static inline uint32_t +golay_24_encode(uint32_t code_word_in) +{ + static const uint32_t encoding[12] = { + 040006165, + 020003073, + 010007550, + 04003664, + 02001732, + 01006631, + 0403315, + 0201547, + 0106706, + 045227, + 024476, + 014353 + }; + + uint32_t code_word_out = 0; + for(uint16_t i = 0; i < 12; i++) { + uint32_t temp_word = code_word_in & (1 << (11 - i)); + if(temp_word >= 1) { + code_word_out = code_word_out ^ encoding[i]; + } + } + return(code_word_out); +} + +/* APCO Golay(23,11,7) ecoder. + * + * \param val The 12-bit value to encode. + * \return The encoded codeword. + */ + +static inline uint32_t +golay_23_encode(uint32_t code_word_in) +{ + return golay_24_encode(code_word_in) >> 1; +} + +static inline uint32_t +golay_23_syndrome(uint32_t pattern) +{ + uint32_t aux = 0x400000; + while(pattern & 0xFFFFF800) { + while((aux & pattern) == 0) { + aux >>= 1; + } + pattern ^= (aux >> 11) * 0xC75; + } + return pattern; +} +/* APCO Golay(23,11,7) decoder. + * + * \param cw The 23-bit codeword to decode. + * \return The number of errors detected. + */ + +static inline size_t +golay_23_decode(uint32_t& cw) +{ + static const uint32_t decoding[2048] = { + 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 147459, + 1, 2, 2, 3, 2, 3, 3, 4268035, 2, 3, 3, 1574915, 3, 2097155, 294915, 4099, + 1, 2, 2, 3, 2, 3, 3, 147459, 2, 3, 3, 147459, 3, 147459, 147459, 147458, + 2, 3, 3, 32771, 3, 2051, 3149827, 786435, 3, 274435, 4194307, 2162691, 589827, 5275651, 10243, 147459, + 1, 2, 2, 3, 2, 3, 3, 2621443, 2, 3, 3, 8195, 3, 1118211, 294915, 4196355, + 2, 3, 3, 135171, 3, 2051, 294915, 1064963, 3, 4210691, 294915, 2162691, 294915, 663555, 294914, 294915, + 2, 3, 3, 5505027, 3, 2051, 65539, 45059, 3, 557059, 6147, 2162691, 6299651, 262147, 1572867, 147459, + 3, 2051, 548867, 2162691, 2051, 2050, 4325379, 2051, 1179651, 2162691, 2162691, 2162690, 20483, 2051, 294915, 2162691, + 1, 2, 2, 3, 2, 3, 3, 2621443, 2, 3, 3, 327683, 3, 43011, 5242883, 4099, + 2, 3, 3, 32771, 3, 1441795, 18435, 4099, 3, 4210691, 2236419, 4099, 589827, 4099, 4099, 4098, + 2, 3, 3, 32771, 3, 4198403, 270339, 1116163, 3, 3145731, 6147, 4726787, 589827, 262147, 2129923, 147459, + 3, 32771, 32771, 32770, 589827, 2121731, 4325379, 32771, 589827, 133123, 1327107, 32771, 589826, 589827, 589827, 4099, + 2, 3, 3, 2621443, 3, 2621443, 2621443, 2621442, 3, 4210691, 6147, 1212419, 131075, 262147, 90115, 2621443, + 3, 4210691, 1114115, 272387, 12291, 98307, 4325379, 2621443, 4210691, 4210690, 524291, 4210691, 3147779, 4210691, 294915, 4099, + 3, 204803, 6147, 16387, 1097731, 262147, 4325379, 2621443, 6147, 262147, 6146, 6147, 262147, 262146, 6147, 262147, + 2359299, 1576963, 4325379, 32771, 4325379, 2051, 4325378, 4325379, 40963, 4210691, 6147, 2162691, 589827, 262147, 4325379, 1056771, + 1, 2, 2, 3, 2, 3, 3, 268291, 2, 3, 3, 8195, 3, 2097155, 5242883, 622595, + 2, 3, 3, 32771, 3, 2097155, 655363, 1064963, 3, 2097155, 86019, 4587523, 2097155, 2097154, 10243, 2097155, + 2, 3, 3, 32771, 3, 1581059, 65539, 6291459, 3, 4261891, 2883587, 1052675, 36867, 262147, 10243, 147459, + 3, 32771, 32771, 32770, 4472835, 200707, 10243, 32771, 1179651, 540675, 10243, 32771, 10243, 2097155, 10242, 10243, + 2, 3, 3, 8195, 3, 4358147, 65539, 1064963, 3, 8195, 8195, 8194, 542723, 262147, 2232323, 8195, + 3, 851971, 6293507, 1064963, 12291, 1064963, 1064963, 1064962, 1179651, 38915, 524291, 8195, 4259843, 2097155, 294915, 1064963, + 3, 2117635, 65539, 657411, 65539, 262147, 65538, 65539, 1179651, 262147, 4243459, 8195, 262147, 262146, 65539, 262147, + 1179651, 4202499, 266243, 32771, 2654211, 2051, 65539, 1064963, 1179650, 1179651, 1179651, 2162691, 1179651, 262147, 10243, 4722691, + 2, 3, 3, 32771, 3, 81923, 5242883, 139267, 3, 659459, 5242883, 2115587, 5242883, 262147, 5242882, 5242883, + 3, 32771, 32771, 32770, 12291, 4720643, 2424835, 32771, 264195, 1122307, 524291, 32771, 180227, 2097155, 5242883, 4099, + 3, 32771, 32771, 32770, 2230275, 262147, 544771, 32771, 24579, 262147, 196611, 32771, 262147, 262146, 5242883, 262147, + 32771, 32770, 32770, 32769, 1048579, 32771, 32771, 32770, 6295555, 32771, 32771, 32770, 589827, 262147, 10243, 32771, + 3, 1050627, 409603, 4263939, 12291, 262147, 34819, 2621443, 2195459, 262147, 524291, 8195, 262147, 262146, 5242883, 262147, + 12291, 2228227, 524291, 32771, 12290, 12291, 12291, 1064963, 524291, 4210691, 524290, 524291, 12291, 262147, 524291, 198659, + 4718595, 262147, 3153923, 32771, 262147, 262146, 65539, 262147, 262147, 262146, 6147, 262147, 262146, 262145, 262147, 262146, + 83971, 32771, 32771, 32770, 12291, 262147, 4325379, 32771, 1179651, 262147, 524291, 32771, 262147, 262146, 2113539, 262147, + 1, 2, 2, 3, 2, 3, 3, 1081347, 2, 3, 3, 327683, 3, 2097155, 536579, 4196355, + 2, 3, 3, 135171, 3, 2097155, 18435, 786435, 3, 2097155, 4194307, 57347, 2097155, 2097154, 1245187, 2097155, + 2, 3, 3, 2107395, 3, 4198403, 65539, 786435, 3, 557059, 4194307, 1052675, 1312771, 73731, 2129923, 147459, + 3, 1130499, 4194307, 786435, 172035, 786435, 786435, 786434, 4194307, 133123, 4194306, 4194307, 20483, 2097155, 4194307, 786435, + 2, 3, 3, 135171, 3, 286723, 65539, 4196355, 3, 557059, 3162115, 4196355, 131075, 4196355, 4196355, 4196354, + 3, 135171, 135171, 135170, 5767171, 98307, 2105347, 135171, 75779, 1310723, 524291, 135171, 20483, 2097155, 294915, 4196355, + 3, 557059, 65539, 16387, 65539, 3276803, 65538, 65539, 557059, 557058, 401411, 557059, 20483, 557059, 65539, 4196355, + 2359299, 4202499, 1083395, 135171, 20483, 2051, 65539, 786435, 20483, 557059, 4194307, 2162691, 20482, 20483, 20483, 1056771, + 2, 3, 3, 327683, 3, 4198403, 18435, 139267, 3, 327683, 327683, 327682, 131075, 1589251, 2129923, 327683, + 3, 532483, 18435, 7340035, 18435, 98307, 18434, 18435, 1085443, 133123, 524291, 327683, 4464643, 2097155, 18435, 4099, + 3, 4198403, 1703939, 16387, 4198403, 4198402, 2129923, 4198403, 24579, 133123, 2129923, 327683, 2129923, 4198403, 2129922, 2129923, + 2359299, 133123, 77827, 32771, 1048579, 4198403, 18435, 786435, 133123, 133122, 4194307, 133123, 589827, 133123, 2129923, 1056771, + 3, 1050627, 4235267, 16387, 131075, 98307, 1314819, 2621443, 131075, 2109443, 524291, 327683, 131074, 131075, 131075, 4196355, + 2359299, 98307, 524291, 135171, 98307, 98306, 18435, 98307, 524291, 4210691, 524290, 524291, 131075, 98307, 524291, 1056771, + 2359299, 16387, 16387, 16386, 534531, 4198403, 65539, 16387, 5308419, 557059, 6147, 16387, 131075, 262147, 2129923, 1056771, + 2359298, 2359299, 2359299, 16387, 2359299, 98307, 4325379, 1056771, 2359299, 133123, 524291, 1056771, 20483, 1056771, 1056771, 1056770, + 2, 3, 3, 4734979, 3, 2097155, 65539, 139267, 3, 2097155, 165891, 1052675, 2097155, 2097154, 278531, 2097155, + 3, 2097155, 1318915, 67587, 2097155, 2097154, 4231171, 2097155, 2097155, 2097154, 524291, 2097155, 2097154, 2097153, 2097155, 2097154, + 3, 393219, 65539, 1052675, 65539, 51203, 65538, 65539, 24579, 1052675, 1052675, 1052674, 4849667, 2097155, 65539, 1052675, + 530435, 4202499, 2244611, 32771, 1048579, 2097155, 65539, 786435, 360451, 2097155, 4194307, 1052675, 2097155, 2097154, 10243, 2097155, + 3, 1050627, 65539, 2392067, 65539, 528387, 65538, 65539, 4460547, 212995, 524291, 8195, 1089539, 2097155, 65539, 4196355, + 49155, 4202499, 524291, 135171, 395267, 2097155, 65539, 1064963, 524291, 2097155, 524290, 524291, 2097155, 2097154, 524291, 2097155, + 65539, 4202499, 65538, 65539, 65538, 65539, 65537, 65538, 2099203, 557059, 65539, 1052675, 65539, 262147, 65538, 65539, + 4202499, 4202498, 65539, 4202499, 65539, 4202499, 65538, 65539, 1179651, 4202499, 524291, 280579, 20483, 2097155, 65539, 163843, + 3, 1050627, 2101251, 139267, 819203, 139267, 139267, 139266, 24579, 4227075, 524291, 327683, 71683, 2097155, 5242883, 139267, + 4390915, 282627, 524291, 32771, 1048579, 2097155, 18435, 139267, 524291, 2097155, 524290, 524291, 2097155, 2097154, 524291, 2097155, + 24579, 2686979, 4458499, 32771, 1048579, 4198403, 65539, 139267, 24578, 24579, 24579, 1052675, 24579, 262147, 2129923, 526339, + 1048579, 32771, 32771, 32770, 1048578, 1048579, 1048579, 32771, 24579, 133123, 524291, 32771, 1048579, 2097155, 397315, 4276227, + 1050627, 1050626, 524291, 1050627, 6307843, 1050627, 65539, 139267, 524291, 1050627, 524290, 524291, 131075, 262147, 524291, 53251, + 524291, 1050627, 524290, 524291, 12291, 98307, 524291, 4456451, 524290, 524291, 524289, 524290, 524291, 2097155, 524290, 524291, + 167939, 1050627, 65539, 16387, 65539, 262147, 65538, 65539, 24579, 262147, 524291, 6422531, 262147, 262146, 65539, 262147, + 2359299, 4202499, 524291, 32771, 1048579, 671747, 65539, 2103299, 524291, 69635, 524290, 524291, 4229123, 262147, 524291, 1056771, + 1, 2, 2, 3, 2, 3, 3, 1081347, 2, 3, 3, 8195, 3, 4980739, 2164739, 4099, + 2, 3, 3, 2375683, 3, 2051, 655363, 4099, 3, 229379, 4194307, 4099, 1073155, 4099, 4099, 4098, + 2, 3, 3, 593923, 3, 2051, 270339, 6291459, 3, 3145731, 4194307, 296963, 36867, 73731, 1572867, 147459, + 3, 2051, 4194307, 1187843, 2051, 2050, 114691, 2051, 4194307, 540675, 4194306, 4194307, 2490371, 2051, 4194307, 4099, + 2, 3, 3, 8195, 3, 2051, 4214787, 458755, 3, 8195, 8195, 8194, 131075, 2146307, 1572867, 8195, + 3, 2051, 1114115, 4751363, 2051, 2050, 2105347, 2051, 2625539, 1310723, 149507, 8195, 4259843, 2051, 294915, 4099, + 3, 2051, 2260995, 16387, 2051, 2050, 1572867, 2051, 344067, 4329475, 1572867, 8195, 1572867, 2051, 1572866, 1572867, + 2051, 2050, 266243, 2051, 2050, 2049, 2051, 2050, 40963, 2051, 4194307, 2162691, 2051, 2050, 1572867, 2051, + 2, 3, 3, 4327427, 3, 81923, 270339, 4099, 3, 3145731, 573443, 4099, 131075, 4099, 4099, 4098, + 3, 532483, 1114115, 4099, 6324227, 4099, 4099, 4098, 264195, 4099, 4099, 4098, 4099, 4098, 4098, 4097, + 3, 3145731, 270339, 16387, 270339, 688131, 270338, 270339, 3145731, 3145730, 196611, 3145731, 4212739, 3145731, 270339, 4099, + 151555, 4521987, 2623491, 32771, 1048579, 2051, 270339, 4099, 40963, 3145731, 4194307, 4099, 589827, 4099, 4099, 4098, + 3, 299011, 1114115, 16387, 131075, 5251075, 34819, 2621443, 131075, 591875, 6553603, 8195, 131074, 131075, 131075, 4099, + 1114115, 2228227, 1114114, 1114115, 802819, 2051, 1114115, 4099, 40963, 4210691, 1114115, 4099, 131075, 4099, 4099, 4098, + 4718595, 16387, 16387, 16386, 2166787, 2051, 270339, 16387, 40963, 3145731, 6147, 16387, 131075, 262147, 1572867, 4292611, + 40963, 2051, 1114115, 16387, 2051, 2050, 4325379, 2051, 40962, 40963, 40963, 917507, 40963, 2051, 2113539, 4099, + 2, 3, 3, 8195, 3, 81923, 655363, 6291459, 3, 8195, 8195, 8194, 36867, 1181699, 278531, 8195, + 3, 5246979, 655363, 67587, 655363, 303107, 655362, 655363, 264195, 540675, 3178499, 8195, 4259843, 2097155, 655363, 4099, + 3, 393219, 1067011, 6291459, 36867, 6291459, 6291459, 6291458, 36867, 540675, 196611, 8195, 36866, 36867, 36867, 6291459, + 2170883, 540675, 266243, 32771, 1048579, 2051, 655363, 6291459, 540675, 540674, 4194307, 540675, 36867, 540675, 10243, 1376259, + 3, 8195, 8195, 8194, 3407875, 528387, 34819, 8195, 8195, 8194, 8194, 8193, 4259843, 8195, 8195, 8194, + 49155, 2228227, 266243, 8195, 4259843, 2051, 655363, 1064963, 4259843, 8195, 8195, 8194, 4259842, 4259843, 4259843, 8195, + 4718595, 1146883, 266243, 8195, 155651, 2051, 65539, 6291459, 2099203, 8195, 8195, 8194, 36867, 262147, 1572867, 8195, + 266243, 2051, 266242, 266243, 2051, 2050, 266243, 2051, 1179651, 540675, 266243, 8195, 4259843, 2051, 2113539, 163843, + 3, 81923, 2101251, 1835011, 81923, 81922, 34819, 81923, 264195, 4227075, 196611, 8195, 2629635, 81923, 5242883, 4099, + 264195, 2228227, 4218883, 32771, 1048579, 81923, 655363, 4099, 264194, 264195, 264195, 4099, 264195, 4099, 4099, 4098, + 4718595, 14339, 196611, 32771, 1048579, 81923, 270339, 6291459, 196611, 3145731, 196610, 196611, 36867, 262147, 196611, 526339, + 1048579, 32771, 32771, 32770, 1048578, 1048579, 1048579, 32771, 264195, 540675, 196611, 32771, 1048579, 4333571, 2113539, 4099, + 4718595, 2228227, 34819, 8195, 34819, 81923, 34818, 34819, 1069059, 8195, 8195, 8194, 131075, 262147, 34819, 8195, + 2228227, 2228226, 1114115, 2228227, 12291, 2228227, 34819, 4456451, 264195, 2228227, 524291, 8195, 4259843, 1605635, 2113539, 4099, + 4718594, 4718595, 4718595, 16387, 4718595, 262147, 34819, 1183747, 4718595, 262147, 196611, 8195, 262147, 262146, 2113539, 262147, + 4718595, 2228227, 266243, 32771, 1048579, 2051, 2113539, 598019, 40963, 69635, 2113539, 5244931, 2113539, 262147, 2113538, 2113539, + 2, 3, 3, 1081347, 3, 1081347, 1081347, 1081346, 3, 22531, 4194307, 2752515, 131075, 73731, 278531, 1081347, + 3, 532483, 4194307, 67587, 331779, 4341763, 2105347, 1081347, 4194307, 1310723, 4194306, 4194307, 559107, 2097155, 4194307, 4099, + 3, 393219, 4194307, 16387, 2637827, 73731, 137219, 1081347, 4194307, 73731, 4194306, 4194307, 73731, 73730, 4194307, 73731, + 4194307, 2134019, 4194306, 4194307, 1048579, 2051, 4194307, 786435, 4194306, 4194307, 4194305, 4194306, 4194307, 73731, 4194306, 4194307, + 3, 6356995, 788483, 16387, 131075, 528387, 2105347, 1081347, 131075, 1310723, 102403, 8195, 131074, 131075, 131075, 4196355, + 49155, 1310723, 2105347, 135171, 2105347, 2051, 2105346, 2105347, 1310723, 1310722, 4194307, 1310723, 131075, 1310723, 2105347, 606211, + 1060867, 16387, 16387, 16386, 4489219, 2051, 65539, 16387, 2099203, 557059, 4194307, 16387, 131075, 73731, 1572867, 2363395, + 720899, 2051, 4194307, 16387, 2051, 2050, 2105347, 2051, 4194307, 1310723, 4194306, 4194307, 20483, 2051, 4194307, 163843, + 3, 532483, 2101251, 16387, 131075, 2361347, 4784131, 1081347, 131075, 4227075, 1058819, 327683, 131074, 131075, 131075, 4099, + 532483, 532482, 425987, 532483, 1048579, 532483, 18435, 4099, 2179075, 532483, 4194307, 4099, 131075, 4099, 4099, 4098, + 100355, 16387, 16387, 16386, 1048579, 4198403, 270339, 16387, 790531, 3145731, 4194307, 16387, 131075, 73731, 2129923, 526339, + 1048579, 532483, 4194307, 16387, 1048578, 1048579, 1048579, 2293763, 4194307, 133123, 4194306, 4194307, 1048579, 311299, 4194307, 4099, + 131075, 16387, 16387, 16386, 131074, 131075, 131075, 16387, 131074, 131075, 131075, 16387, 131073, 131074, 131074, 131075, + 4200451, 532483, 1114115, 16387, 131075, 98307, 2105347, 4456451, 131075, 1310723, 524291, 2131971, 131074, 131075, 131075, 4099, + 16387, 16386, 16386, 16385, 131075, 16387, 16387, 16386, 131075, 16387, 16387, 16386, 131074, 131075, 131075, 16387, + 2359299, 16387, 16387, 16386, 1048579, 2051, 561155, 16387, 40963, 69635, 4194307, 16387, 131075, 6815747, 329731, 1056771, + 3, 393219, 2101251, 67587, 4204547, 528387, 278531, 1081347, 1638403, 4227075, 278531, 8195, 278531, 2097155, 278530, 278531, + 49155, 67587, 67587, 67586, 1048579, 2097155, 655363, 67587, 143363, 2097155, 4194307, 67587, 2097155, 2097154, 278531, 2097155, + 393219, 393218, 565251, 393219, 1048579, 393219, 65539, 6291459, 2099203, 393219, 4194307, 1052675, 36867, 73731, 278531, 526339, + 1048579, 393219, 4194307, 67587, 1048578, 1048579, 1048579, 28675, 4194307, 540675, 4194306, 4194307, 1048579, 2097155, 4194307, 163843, + 49155, 528387, 5373955, 8195, 528387, 528386, 65539, 528387, 2099203, 8195, 8195, 8194, 131075, 528387, 278531, 8195, + 49154, 49155, 49155, 67587, 49155, 528387, 2105347, 4456451, 49155, 1310723, 524291, 8195, 4259843, 2097155, 1054723, 163843, + 2099203, 393219, 65539, 16387, 65539, 528387, 65538, 65539, 2099202, 2099203, 2099203, 8195, 2099203, 5259267, 65539, 163843, + 49155, 4202499, 266243, 3670019, 1048579, 2051, 65539, 163843, 2099203, 69635, 4194307, 163843, 794627, 163843, 163843, 163842, + 2101251, 4227075, 2101250, 2101251, 1048579, 81923, 2101251, 139267, 4227075, 4227074, 2101251, 4227075, 131075, 4227075, 278531, 526339, + 1048579, 532483, 2101251, 67587, 1048578, 1048579, 1048579, 4456451, 264195, 4227075, 524291, 1196035, 1048579, 2097155, 106499, 4099, + 1048579, 393219, 2101251, 16387, 1048578, 1048579, 1048579, 526339, 24579, 4227075, 196611, 526339, 1048579, 526339, 526339, 526338, + 1048578, 1048579, 1048579, 32771, 1048577, 1048578, 1048578, 1048579, 1048579, 69635, 4194307, 2367491, 1048578, 1048579, 1048579, 526339, + 335875, 1050627, 2101251, 16387, 131075, 528387, 34819, 4456451, 131075, 4227075, 524291, 8195, 131074, 131075, 131075, 3211267, + 49155, 2228227, 524291, 4456451, 1048579, 4456451, 4456451, 4456450, 524291, 69635, 524290, 524291, 131075, 26627, 524291, 4456451, + 4718595, 16387, 16387, 16386, 1048579, 2138115, 65539, 16387, 2099203, 69635, 1343491, 16387, 131075, 262147, 4206595, 526339, + 1048579, 69635, 141315, 16387, 1048578, 1048579, 1048579, 4456451, 69635, 69634, 524291, 69635, 1048579, 69635, 2113539, 163843 + }; + + cw &= 0x007fffff; + unsigned int correction = decoding[golay_23_syndrome(cw)]; + cw ^= correction; + cw >>= 11; + return correction & 3; +} + +#endif /* INCLUDED_OP25_GOLAY_H */ diff --git a/blocks/src/lib/op25_hamming.h b/blocks/src/lib/op25_hamming.h new file mode 100644 index 0000000..0ab3c7a --- /dev/null +++ b/blocks/src/lib/op25_hamming.h @@ -0,0 +1,186 @@ +#ifndef INCLUDED_OP25_HAMMING_H +#define INCLUDED_OP25_HAMMING_H + +#include +#include + +/* + * APCO Hamming(15,11,3) ecoder. + * + * \param val The 11-bit value to encode. + * \return The encoded codeword. + */ +static inline uint16_t +hamming_15_encode(uint16_t code_word_in) +{ + static long int encoding[11] = { + 0x400f, 0x200e, 0x100d, 0x080c, 0x040b, 0x020a, 0x0109, + 0x0087, 0x0046, 0x0025, 0x0013 + }; + + uint16_t code_word_out = 0u; + for(uint8_t i = 0; i < 11; ++i) { + if(code_word_in & (1u << (10 - i))) { + code_word_out ^= encoding[i]; + } + } + return code_word_out; +} + +/* + * APCO Hamming(15,11,3) decoder. + * + * \param cw The 15-bit codeword to decode. + * \return The number of errors detected. + */ +static inline size_t +hamming_15_decode(uint16_t& cw) +{ + static const int encoding[2048] = { + 0, 3, 5, 6, 6, 5, 3, 0, 7, 4, 2, 1, 1, 2, 4, 7, + 9, 10, 12, 15, 15, 12, 10, 9, 14, 13, 11, 8, 8, 11, 13, 14, + 10, 9, 15, 12, 12, 15, 9, 10, 13, 14, 8, 11, 11, 8, 14, 13, + 3, 0, 6, 5, 5, 6, 0, 3, 4, 7, 1, 2, 2, 1, 7, 4, + 11, 8, 14, 13, 13, 14, 8, 11, 12, 15, 9, 10, 10, 9, 15, 12, + 2, 1, 7, 4, 4, 7, 1, 2, 5, 6, 0, 3, 3, 0, 6, 5, + 1, 2, 4, 7, 7, 4, 2, 1, 6, 5, 3, 0, 0, 3, 5, 6, + 8, 11, 13, 14, 14, 13, 11, 8, 15, 12, 10, 9, 9, 10, 12, 15, + 12, 15, 9, 10, 10, 9, 15, 12, 11, 8, 14, 13, 13, 14, 8, 11, + 5, 6, 0, 3, 3, 0, 6, 5, 2, 1, 7, 4, 4, 7, 1, 2, + 6, 5, 3, 0, 0, 3, 5, 6, 1, 2, 4, 7, 7, 4, 2, 1, + 15, 12, 10, 9, 9, 10, 12, 15, 8, 11, 13, 14, 14, 13, 11, 8, + 7, 4, 2, 1, 1, 2, 4, 7, 0, 3, 5, 6, 6, 5, 3, 0, + 14, 13, 11, 8, 8, 11, 13, 14, 9, 10, 12, 15, 15, 12, 10, 9, + 13, 14, 8, 11, 11, 8, 14, 13, 10, 9, 15, 12, 12, 15, 9, 10, + 4, 7, 1, 2, 2, 1, 7, 4, 3, 0, 6, 5, 5, 6, 0, 3, + 13, 14, 8, 11, 11, 8, 14, 13, 10, 9, 15, 12, 12, 15, 9, 10, + 4, 7, 1, 2, 2, 1, 7, 4, 3, 0, 6, 5, 5, 6, 0, 3, + 7, 4, 2, 1, 1, 2, 4, 7, 0, 3, 5, 6, 6, 5, 3, 0, + 14, 13, 11, 8, 8, 11, 13, 14, 9, 10, 12, 15, 15, 12, 10, 9, + 6, 5, 3, 0, 0, 3, 5, 6, 1, 2, 4, 7, 7, 4, 2, 1, + 15, 12, 10, 9, 9, 10, 12, 15, 8, 11, 13, 14, 14, 13, 11, 8, + 12, 15, 9, 10, 10, 9, 15, 12, 11, 8, 14, 13, 13, 14, 8, 11, + 5, 6, 0, 3, 3, 0, 6, 5, 2, 1, 7, 4, 4, 7, 1, 2, + 1, 2, 4, 7, 7, 4, 2, 1, 6, 5, 3, 0, 0, 3, 5, 6, + 8, 11, 13, 14, 14, 13, 11, 8, 15, 12, 10, 9, 9, 10, 12, 15, + 11, 8, 14, 13, 13, 14, 8, 11, 12, 15, 9, 10, 10, 9, 15, 12, + 2, 1, 7, 4, 4, 7, 1, 2, 5, 6, 0, 3, 3, 0, 6, 5, + 10, 9, 15, 12, 12, 15, 9, 10, 13, 14, 8, 11, 11, 8, 14, 13, + 3, 0, 6, 5, 5, 6, 0, 3, 4, 7, 1, 2, 2, 1, 7, 4, + 0, 3, 5, 6, 6, 5, 3, 0, 7, 4, 2, 1, 1, 2, 4, 7, + 9, 10, 12, 15, 15, 12, 10, 9, 14, 13, 11, 8, 8, 11, 13, 14, + 14, 13, 11, 8, 8, 11, 13, 14, 9, 10, 12, 15, 15, 12, 10, 9, + 7, 4, 2, 1, 1, 2, 4, 7, 0, 3, 5, 6, 6, 5, 3, 0, + 4, 7, 1, 2, 2, 1, 7, 4, 3, 0, 6, 5, 5, 6, 0, 3, + 13, 14, 8, 11, 11, 8, 14, 13, 10, 9, 15, 12, 12, 15, 9, 10, + 5, 6, 0, 3, 3, 0, 6, 5, 2, 1, 7, 4, 4, 7, 1, 2, + 12, 15, 9, 10, 10, 9, 15, 12, 11, 8, 14, 13, 13, 14, 8, 11, + 15, 12, 10, 9, 9, 10, 12, 15, 8, 11, 13, 14, 14, 13, 11, 8, + 6, 5, 3, 0, 0, 3, 5, 6, 1, 2, 4, 7, 7, 4, 2, 1, + 2, 1, 7, 4, 4, 7, 1, 2, 5, 6, 0, 3, 3, 0, 6, 5, + 11, 8, 14, 13, 13, 14, 8, 11, 12, 15, 9, 10, 10, 9, 15, 12, + 8, 11, 13, 14, 14, 13, 11, 8, 15, 12, 10, 9, 9, 10, 12, 15, + 1, 2, 4, 7, 7, 4, 2, 1, 6, 5, 3, 0, 0, 3, 5, 6, + 9, 10, 12, 15, 15, 12, 10, 9, 14, 13, 11, 8, 8, 11, 13, 14, + 0, 3, 5, 6, 6, 5, 3, 0, 7, 4, 2, 1, 1, 2, 4, 7, + 3, 0, 6, 5, 5, 6, 0, 3, 4, 7, 1, 2, 2, 1, 7, 4, + 10, 9, 15, 12, 12, 15, 9, 10, 13, 14, 8, 11, 11, 8, 14, 13, + 3, 0, 6, 5, 5, 6, 0, 3, 4, 7, 1, 2, 2, 1, 7, 4, + 10, 9, 15, 12, 12, 15, 9, 10, 13, 14, 8, 11, 11, 8, 14, 13, + 9, 10, 12, 15, 15, 12, 10, 9, 14, 13, 11, 8, 8, 11, 13, 14, + 0, 3, 5, 6, 6, 5, 3, 0, 7, 4, 2, 1, 1, 2, 4, 7, + 8, 11, 13, 14, 14, 13, 11, 8, 15, 12, 10, 9, 9, 10, 12, 15, + 1, 2, 4, 7, 7, 4, 2, 1, 6, 5, 3, 0, 0, 3, 5, 6, + 2, 1, 7, 4, 4, 7, 1, 2, 5, 6, 0, 3, 3, 0, 6, 5, + 11, 8, 14, 13, 13, 14, 8, 11, 12, 15, 9, 10, 10, 9, 15, 12, + 15, 12, 10, 9, 9, 10, 12, 15, 8, 11, 13, 14, 14, 13, 11, 8, + 6, 5, 3, 0, 0, 3, 5, 6, 1, 2, 4, 7, 7, 4, 2, 1, + 5, 6, 0, 3, 3, 0, 6, 5, 2, 1, 7, 4, 4, 7, 1, 2, + 12, 15, 9, 10, 10, 9, 15, 12, 11, 8, 14, 13, 13, 14, 8, 11, + 4, 7, 1, 2, 2, 1, 7, 4, 3, 0, 6, 5, 5, 6, 0, 3, + 13, 14, 8, 11, 11, 8, 14, 13, 10, 9, 15, 12, 12, 15, 9, 10, + 14, 13, 11, 8, 8, 11, 13, 14, 9, 10, 12, 15, 15, 12, 10, 9, + 7, 4, 2, 1, 1, 2, 4, 7, 0, 3, 5, 6, 6, 5, 3, 0, + 15, 12, 10, 9, 9, 10, 12, 15, 8, 11, 13, 14, 14, 13, 11, 8, + 6, 5, 3, 0, 0, 3, 5, 6, 1, 2, 4, 7, 7, 4, 2, 1, + 5, 6, 0, 3, 3, 0, 6, 5, 2, 1, 7, 4, 4, 7, 1, 2, + 12, 15, 9, 10, 10, 9, 15, 12, 11, 8, 14, 13, 13, 14, 8, 11, + 4, 7, 1, 2, 2, 1, 7, 4, 3, 0, 6, 5, 5, 6, 0, 3, + 13, 14, 8, 11, 11, 8, 14, 13, 10, 9, 15, 12, 12, 15, 9, 10, + 14, 13, 11, 8, 8, 11, 13, 14, 9, 10, 12, 15, 15, 12, 10, 9, + 7, 4, 2, 1, 1, 2, 4, 7, 0, 3, 5, 6, 6, 5, 3, 0, + 3, 0, 6, 5, 5, 6, 0, 3, 4, 7, 1, 2, 2, 1, 7, 4, + 10, 9, 15, 12, 12, 15, 9, 10, 13, 14, 8, 11, 11, 8, 14, 13, + 9, 10, 12, 15, 15, 12, 10, 9, 14, 13, 11, 8, 8, 11, 13, 14, + 0, 3, 5, 6, 6, 5, 3, 0, 7, 4, 2, 1, 1, 2, 4, 7, + 8, 11, 13, 14, 14, 13, 11, 8, 15, 12, 10, 9, 9, 10, 12, 15, + 1, 2, 4, 7, 7, 4, 2, 1, 6, 5, 3, 0, 0, 3, 5, 6, + 2, 1, 7, 4, 4, 7, 1, 2, 5, 6, 0, 3, 3, 0, 6, 5, + 11, 8, 14, 13, 13, 14, 8, 11, 12, 15, 9, 10, 10, 9, 15, 12, + 2, 1, 7, 4, 4, 7, 1, 2, 5, 6, 0, 3, 3, 0, 6, 5, + 11, 8, 14, 13, 13, 14, 8, 11, 12, 15, 9, 10, 10, 9, 15, 12, + 8, 11, 13, 14, 14, 13, 11, 8, 15, 12, 10, 9, 9, 10, 12, 15, + 1, 2, 4, 7, 7, 4, 2, 1, 6, 5, 3, 0, 0, 3, 5, 6, + 9, 10, 12, 15, 15, 12, 10, 9, 14, 13, 11, 8, 8, 11, 13, 14, + 0, 3, 5, 6, 6, 5, 3, 0, 7, 4, 2, 1, 1, 2, 4, 7, + 3, 0, 6, 5, 5, 6, 0, 3, 4, 7, 1, 2, 2, 1, 7, 4, + 10, 9, 15, 12, 12, 15, 9, 10, 13, 14, 8, 11, 11, 8, 14, 13, + 14, 13, 11, 8, 8, 11, 13, 14, 9, 10, 12, 15, 15, 12, 10, 9, + 7, 4, 2, 1, 1, 2, 4, 7, 0, 3, 5, 6, 6, 5, 3, 0, + 4, 7, 1, 2, 2, 1, 7, 4, 3, 0, 6, 5, 5, 6, 0, 3, + 13, 14, 8, 11, 11, 8, 14, 13, 10, 9, 15, 12, 12, 15, 9, 10, + 5, 6, 0, 3, 3, 0, 6, 5, 2, 1, 7, 4, 4, 7, 1, 2, + 12, 15, 9, 10, 10, 9, 15, 12, 11, 8, 14, 13, 13, 14, 8, 11, + 15, 12, 10, 9, 9, 10, 12, 15, 8, 11, 13, 14, 14, 13, 11, 8, + 6, 5, 3, 0, 0, 3, 5, 6, 1, 2, 4, 7, 7, 4, 2, 1, + 1, 2, 4, 7, 7, 4, 2, 1, 6, 5, 3, 0, 0, 3, 5, 6, + 8, 11, 13, 14, 14, 13, 11, 8, 15, 12, 10, 9, 9, 10, 12, 15, + 11, 8, 14, 13, 13, 14, 8, 11, 12, 15, 9, 10, 10, 9, 15, 12, + 2, 1, 7, 4, 4, 7, 1, 2, 5, 6, 0, 3, 3, 0, 6, 5, + 10, 9, 15, 12, 12, 15, 9, 10, 13, 14, 8, 11, 11, 8, 14, 13, + 3, 0, 6, 5, 5, 6, 0, 3, 4, 7, 1, 2, 2, 1, 7, 4, + 0, 3, 5, 6, 6, 5, 3, 0, 7, 4, 2, 1, 1, 2, 4, 7, + 9, 10, 12, 15, 15, 12, 10, 9, 14, 13, 11, 8, 8, 11, 13, 14, + 13, 14, 8, 11, 11, 8, 14, 13, 10, 9, 15, 12, 12, 15, 9, 10, + 4, 7, 1, 2, 2, 1, 7, 4, 3, 0, 6, 5, 5, 6, 0, 3, + 7, 4, 2, 1, 1, 2, 4, 7, 0, 3, 5, 6, 6, 5, 3, 0, + 14, 13, 11, 8, 8, 11, 13, 14, 9, 10, 12, 15, 15, 12, 10, 9, + 6, 5, 3, 0, 0, 3, 5, 6, 1, 2, 4, 7, 7, 4, 2, 1, + 15, 12, 10, 9, 9, 10, 12, 15, 8, 11, 13, 14, 14, 13, 11, 8, + 12, 15, 9, 10, 10, 9, 15, 12, 11, 8, 14, 13, 13, 14, 8, 11, + 5, 6, 0, 3, 3, 0, 6, 5, 2, 1, 7, 4, 4, 7, 1, 2, + 12, 15, 9, 10, 10, 9, 15, 12, 11, 8, 14, 13, 13, 14, 8, 11, + 5, 6, 0, 3, 3, 0, 6, 5, 2, 1, 7, 4, 4, 7, 1, 2, + 6, 5, 3, 0, 0, 3, 5, 6, 1, 2, 4, 7, 7, 4, 2, 1, + 15, 12, 10, 9, 9, 10, 12, 15, 8, 11, 13, 14, 14, 13, 11, 8, + 7, 4, 2, 1, 1, 2, 4, 7, 0, 3, 5, 6, 6, 5, 3, 0, + 14, 13, 11, 8, 8, 11, 13, 14, 9, 10, 12, 15, 15, 12, 10, 9, + 13, 14, 8, 11, 11, 8, 14, 13, 10, 9, 15, 12, 12, 15, 9, 10, + 4, 7, 1, 2, 2, 1, 7, 4, 3, 0, 6, 5, 5, 6, 0, 3, + 0, 3, 5, 6, 6, 5, 3, 0, 7, 4, 2, 1, 1, 2, 4, 7, + 9, 10, 12, 15, 15, 12, 10, 9, 14, 13, 11, 8, 8, 11, 13, 14, + 10, 9, 15, 12, 12, 15, 9, 10, 13, 14, 8, 11, 11, 8, 14, 13, + 3, 0, 6, 5, 5, 6, 0, 3, 4, 7, 1, 2, 2, 1, 7, 4, + 11, 8, 14, 13, 13, 14, 8, 11, 12, 15, 9, 10, 10, 9, 15, 12, + 2, 1, 7, 4, 4, 7, 1, 2, 5, 6, 0, 3, 3, 0, 6, 5, + 1, 2, 4, 7, 7, 4, 2, 1, 6, 5, 3, 0, 0, 3, 5, 6, + 8, 11, 13, 14, 14, 13, 11, 8, 15, 12, 10, 9, 9, 10, 12, 15 + }; + + static const int decoding[16] = { + 0, 0, 0, 1, 0, 2, 4, 8, 0, 16, 32, 64, 128, 256, 512, 1024 + }; + + size_t errs = 0; + uint16_t par = cw & 0xf; + cw &= 0xffff; + cw >>= 4; + uint16_t correction = decoding[encoding[cw] ^ par]; + if(correction) { + cw ^= correction; + ++errs; + } + return errs; +} + +#endif /* INCLUDED_OP25_HAMMING_H */ diff --git a/blocks/src/lib/op25_imbe_frame.h b/blocks/src/lib/op25_imbe_frame.h new file mode 100644 index 0000000..702ec2f --- /dev/null +++ b/blocks/src/lib/op25_imbe_frame.h @@ -0,0 +1,427 @@ +#ifndef INCLUDED_IMBE_FRAME_H +#define INCLUDED_IMBE_FRAME_H + +#include +#include +#include +#include +#include +#include + +typedef std::vector voice_codeword; +typedef const std::vector const_bit_vector; +typedef std::vector bit_vector; + +static const size_t nof_voice_codewords = 9, voice_codeword_sz = 144; + +static const uint16_t imbe_ldu_NID_bits[] = { + 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, + 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 72, 73, + 74, 75, 76, 77, 78, 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 }; + +static const uint16_t imbe_ldu_status_bits[] = { + 70, 71, 142, 143, 214, 215, 286, 287, 358, 359, 430, 431, + 502, 503, 574, 575, 646, 647, 718, 719, 790, 791, 862, 863, + 934, 935, 1006, 1007, 1078, 1079, 1150, 1151, 1222, 1223, 1294, 1295, + 1366, 1367, 1438, 1439, 1510, 1511, 1582, 1583, 1654, 1655, 1726, 1727 }; + +static const uint16_t imbe_ldu_lcf_bits[] = { + 410, 411, 412, 413, 414, 415, 420, 421, + 422, 423, 424, 425, 432, 433, 434, 435, + 436, 437, 442, 443, 444, 445, 446, 447, + 600, 601, 602, 603, 604, 605, 610, 611, + 612, 613, 614, 615, 620, 621, 622, 623, + 624, 625, 630, 631, 632, 633, 634, 635, + 788, 789, 792, 793, 794, 795, 800, 801, + 802, 803, 804, 805, 810, 811, 812, 813, + 814, 815, 820, 821, 822, 823, 824, 825 }; + +// FIXME: separate these into their respective fields +static const uint16_t imbe_ldu_ls_data_bits[] = { + 410, 411, 412, 413, 414, 415, 416, 417, 418, 419, 420, 421, + 422, 423, 424, 425, 426, 427, 428, 429, 432, 433, 434, 435, + 436, 437, 438, 439, 440, 441, 442, 443, 444, 445, 446, 447, + 448, 449, 450, 451, 600, 601, 602, 603, 604, 605, 606, 607, + 608, 609, 610, 611, 612, 613, 614, 615, 616, 617, 618, 619, + 620, 621, 622, 623, 624, 625, 626, 627, 628, 629, 630, 631, + 632, 633, 634, 635, 636, 637, 638, 639, 788, 789, 792, 793, + 794, 795, 796, 797, 798, 799, 800, 801, 802, 803, 804, 805, + 806, 807, 808, 809, 810, 811, 812, 813, 814, 815, 816, 817, + 818, 819, 820, 821, 822, 823, 824, 825, 826, 827, 828, 829, + 978, 979, 980, 981, 982, 983, 984, 985, 986, 987, 988, 989, + 990, 991, 992, 993, 994, 995, 996, 997, 998, 999, 1000, 1001, + 1002, 1003, 1004, 1005, 1008, 1009, 1010, 1011, 1012, 1013, 1014, 1015, + 1016, 1017, 1018, 1019, 1168, 1169, 1170, 1171, 1172, 1173, 1174, 1175, + 1176, 1177, 1178, 1179, 1180, 1181, 1182, 1183, 1184, 1185, 1186, 1187, + 1188, 1189, 1190, 1191, 1192, 1193, 1194, 1195, 1196, 1197, 1198, 1199, + 1200, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1356, 1357, 1358, 1359, + 1360, 1361, 1362, 1363, 1364, 1365, 1368, 1369, 1370, 1371, 1372, 1373, + 1374, 1375, 1376, 1377, 1378, 1379, 1380, 1381, 1382, 1383, 1384, 1385, + 1386, 1387, 1388, 1389, 1390, 1391, 1392, 1393, 1394, 1395, 1396, 1397, + 1546, 1547, 1548, 1549, 1550, 1551, 1552, 1553, 1554, 1555, 1556, 1557, + 1558, 1559, 1560, 1561, 1562, 1563, 1564, 1565, 1566, 1567, 1568, 1569, + 1570, 1571, 1572, 1573, 1574, 1575, 1576, 1577 }; + +static const uint16_t voice_codeword_bits[nof_voice_codewords][voice_codeword_sz] = { + + { 114, 121, 126, 133, 138, 147, 152, 159, 164, 171, 176, 183, + 188, 195, 200, 207, 212, 221, 226, 233, 238, 245, 250, 257, + 115, 120, 127, 132, 139, 146, 153, 158, 165, 170, 177, 182, + 189, 194, 201, 206, 213, 220, 227, 232, 239, 244, 251, 256, + 116, 123, 128, 135, 140, 149, 154, 161, 166, 173, 178, 185, + 190, 197, 202, 209, 216, 223, 228, 235, 240, 247, 252, 259, + 117, 122, 129, 134, 141, 148, 155, 160, 167, 172, 179, 184, + 191, 196, 203, 208, 217, 222, 229, 234, 241, 246, 253, 258, + 118, 125, 130, 137, 144, 151, 156, 163, 168, 175, 180, 187, + 192, 199, 204, 211, 218, 225, 230, 237, 242, 249, 254, 261, + 119, 124, 131, 136, 145, 150, 157, 162, 169, 174, 181, 186, + 193, 198, 205, 210, 219, 224, 231, 236, 243, 248, 255, 260 }, + + { 262, 269, 274, 281, 288, 295, 300, 307, 312, 319, 324, 331, + 336, 343, 348, 355, 362, 369, 374, 381, 386, 393, 398, 405, + 263, 268, 275, 280, 289, 294, 301, 306, 313, 318, 325, 330, + 337, 342, 349, 354, 363, 368, 375, 380, 387, 392, 399, 404, + 264, 271, 276, 283, 290, 297, 302, 309, 314, 321, 326, 333, + 338, 345, 350, 357, 364, 371, 376, 383, 388, 395, 400, 407, + 265, 270, 277, 282, 291, 296, 303, 308, 315, 320, 327, 332, + 339, 344, 351, 356, 365, 370, 377, 382, 389, 394, 401, 406, + 266, 273, 278, 285, 292, 299, 304, 311, 316, 323, 328, 335, + 340, 347, 352, 361, 366, 373, 378, 385, 390, 397, 402, 409, + 267, 272, 279, 284, 293, 298, 305, 310, 317, 322, 329, 334, + 341, 346, 353, 360, 367, 372, 379, 384, 391, 396, 403, 408 }, + + { 452, 459, 464, 471, 476, 483, 488, 495, 500, 509, 514, 521, + 526, 533, 538, 545, 550, 557, 562, 569, 576, 583, 588, 595, + 453, 458, 465, 470, 477, 482, 489, 494, 501, 508, 515, 520, + 527, 532, 539, 544, 551, 556, 563, 568, 577, 582, 589, 594, + 454, 461, 466, 473, 478, 485, 490, 497, 504, 511, 516, 523, + 528, 535, 540, 547, 552, 559, 564, 571, 578, 585, 590, 597, + 455, 460, 467, 472, 479, 484, 491, 496, 505, 510, 517, 522, + 529, 534, 541, 546, 553, 558, 565, 570, 579, 584, 591, 596, + 456, 463, 468, 475, 480, 487, 492, 499, 506, 513, 518, 525, + 530, 537, 542, 549, 554, 561, 566, 573, 580, 587, 592, 599, + 457, 462, 469, 474, 481, 486, 493, 498, 507, 512, 519, 524, + 531, 536, 543, 548, 555, 560, 567, 572, 581, 586, 593, 598 }, + + { 640, 649, 654, 661, 666, 673, 678, 685, 690, 697, 702, 709, + 714, 723, 728, 735, 740, 747, 752, 759, 764, 771, 776, 783, + 641, 648, 655, 660, 667, 672, 679, 684, 691, 696, 703, 708, + 715, 722, 729, 734, 741, 746, 753, 758, 765, 770, 777, 782, + 642, 651, 656, 663, 668, 675, 680, 687, 692, 699, 704, 711, + 716, 725, 730, 737, 742, 749, 754, 761, 766, 773, 778, 785, + 643, 650, 657, 662, 669, 674, 681, 686, 693, 698, 705, 710, + 717, 724, 731, 736, 743, 748, 755, 760, 767, 772, 779, 784, + 644, 653, 658, 665, 670, 677, 682, 689, 694, 701, 706, 713, + 720, 727, 732, 739, 744, 751, 756, 763, 768, 775, 780, 787, + 645, 652, 659, 664, 671, 676, 683, 688, 695, 700, 707, 712, + 721, 726, 733, 738, 745, 750, 757, 762, 769, 774, 781, 786 }, + + { 830, 837, 842, 849, 854, 861, 868, 875, 880, 887, 892, 899, + 904, 911, 916, 923, 928, 937, 942, 949, 954, 961, 966, 973, + 831, 836, 843, 848, 855, 860, 869, 874, 881, 886, 893, 898, + 905, 910, 917, 922, 929, 936, 943, 948, 955, 960, 967, 972, + 832, 839, 844, 851, 856, 865, 870, 877, 882, 889, 894, 901, + 906, 913, 918, 925, 930, 939, 944, 951, 956, 963, 968, 975, + 833, 838, 845, 850, 857, 864, 871, 876, 883, 888, 895, 900, + 907, 912, 919, 924, 931, 938, 945, 950, 957, 962, 969, 974, + 834, 841, 846, 853, 858, 867, 872, 879, 884, 891, 896, 903, + 908, 915, 920, 927, 932, 941, 946, 953, 958, 965, 970, 977, + 835, 840, 847, 852, 859, 866, 873, 878, 885, 890, 897, 902, + 909, 914, 921, 926, 933, 940, 947, 952, 959, 964, 971, 976 }, + + { 1020, 1027, 1032, 1039, 1044, 1051, 1056, 1063, 1068, 1075, 1082, 1089, + 1094, 1101, 1106, 1113, 1118, 1125, 1130, 1137, 1142, 1149, 1156, 1163, + 1021, 1026, 1033, 1038, 1045, 1050, 1057, 1062, 1069, 1074, 1083, 1088, + 1095, 1100, 1107, 1112, 1119, 1124, 1131, 1136, 1143, 1148, 1157, 1162, + 1022, 1029, 1034, 1041, 1046, 1053, 1058, 1065, 1070, 1077, 1084, 1091, + 1096, 1103, 1108, 1115, 1120, 1127, 1132, 1139, 1144, 1153, 1158, 1165, + 1023, 1028, 1035, 1040, 1047, 1052, 1059, 1064, 1071, 1076, 1085, 1090, + 1097, 1102, 1109, 1114, 1121, 1126, 1133, 1138, 1145, 1152, 1159, 1164, + 1024, 1031, 1036, 1043, 1048, 1055, 1060, 1067, 1072, 1081, 1086, 1093, + 1098, 1105, 1110, 1117, 1122, 1129, 1134, 1141, 1146, 1155, 1160, 1167, + 1025, 1030, 1037, 1042, 1049, 1054, 1061, 1066, 1073, 1080, 1087, 1092, + 1099, 1104, 1111, 1116, 1123, 1128, 1135, 1140, 1147, 1154, 1161, 1166 }, + + { 1208, 1215, 1220, 1229, 1234, 1241, 1246, 1253, 1258, 1265, 1270, 1277, + 1282, 1289, 1296, 1303, 1308, 1315, 1320, 1327, 1332, 1339, 1344, 1351, + 1209, 1214, 1221, 1228, 1235, 1240, 1247, 1252, 1259, 1264, 1271, 1276, + 1283, 1288, 1297, 1302, 1309, 1314, 1321, 1326, 1333, 1338, 1345, 1350, + 1210, 1217, 1224, 1231, 1236, 1243, 1248, 1255, 1260, 1267, 1272, 1279, + 1284, 1291, 1298, 1305, 1310, 1317, 1322, 1329, 1334, 1341, 1346, 1353, + 1211, 1216, 1225, 1230, 1237, 1242, 1249, 1254, 1261, 1266, 1273, 1278, + 1285, 1290, 1299, 1304, 1311, 1316, 1323, 1328, 1335, 1340, 1347, 1352, + 1212, 1219, 1226, 1233, 1238, 1245, 1250, 1257, 1262, 1269, 1274, 1281, + 1286, 1293, 1300, 1307, 1312, 1319, 1324, 1331, 1336, 1343, 1348, 1355, + 1213, 1218, 1227, 1232, 1239, 1244, 1251, 1256, 1263, 1268, 1275, 1280, + 1287, 1292, 1301, 1306, 1313, 1318, 1325, 1330, 1337, 1342, 1349, 1354 }, + + { 1398, 1405, 1410, 1417, 1422, 1429, 1434, 1443, 1448, 1455, 1460, 1467, + 1472, 1479, 1484, 1491, 1496, 1503, 1508, 1517, 1522, 1529, 1534, 1541, + 1399, 1404, 1411, 1416, 1423, 1428, 1435, 1442, 1449, 1454, 1461, 1466, + 1473, 1478, 1485, 1490, 1497, 1502, 1509, 1516, 1523, 1528, 1535, 1540, + 1400, 1407, 1412, 1419, 1424, 1431, 1436, 1445, 1450, 1457, 1462, 1469, + 1474, 1481, 1486, 1493, 1498, 1505, 1512, 1519, 1524, 1531, 1536, 1543, + 1401, 1406, 1413, 1418, 1425, 1430, 1437, 1444, 1451, 1456, 1463, 1468, + 1475, 1480, 1487, 1492, 1499, 1504, 1513, 1518, 1525, 1530, 1537, 1542, + 1402, 1409, 1414, 1421, 1426, 1433, 1440, 1447, 1452, 1459, 1464, 1471, + 1476, 1483, 1488, 1495, 1500, 1507, 1514, 1521, 1526, 1533, 1538, 1545, + 1403, 1408, 1415, 1420, 1427, 1432, 1441, 1446, 1453, 1458, 1465, 1470, + 1477, 1482, 1489, 1494, 1501, 1506, 1515, 1520, 1527, 1532, 1539, 1544 }, + + { 1578, 1587, 1592, 1599, 1604, 1611, 1616, 1623, 1628, 1635, 1640, 1647, + 1652, 1661, 1666, 1673, 1678, 1685, 1690, 1697, 1702, 1709, 1714, 1721, + 1579, 1586, 1593, 1598, 1605, 1610, 1617, 1622, 1629, 1634, 1641, 1646, + 1653, 1660, 1667, 1672, 1679, 1684, 1691, 1696, 1703, 1708, 1715, 1720, + 1580, 1589, 1594, 1601, 1606, 1613, 1618, 1625, 1630, 1637, 1642, 1649, + 1656, 1663, 1668, 1675, 1680, 1687, 1692, 1699, 1704, 1711, 1716, 1723, + 1581, 1588, 1595, 1600, 1607, 1612, 1619, 1624, 1631, 1636, 1643, 1648, + 1657, 1662, 1669, 1674, 1681, 1686, 1693, 1698, 1705, 1710, 1717, 1722, + 1584, 1591, 1596, 1603, 1608, 1615, 1620, 1627, 1632, 1639, 1644, 1651, + 1658, 1665, 1670, 1677, 1682, 1689, 1694, 1701, 1706, 1713, 1718, 1725, + 1585, 1590, 1597, 1602, 1609, 1614, 1621, 1626, 1633, 1638, 1645, 1650, + 1659, 1664, 1671, 1676, 1683, 1688, 1695, 1700, 1707, 1712, 1719, 1724 }, + + }; + +#if DEBUG +/* + * Convert bit vector to hex dump format and print + */ +static inline void +dump_cw(const voice_codeword& cw, int len, FILE* fp) // len in bytes +{ + int i, j; + for (i = 0; i < len; i++){ + int p = 0; + for (j = 0; j < 8; j++){ + p = (p << 1) + cw[ i*8 + j ]; + } + fprintf(fp, "%02x ", p); + if (!((i+1) % 16)) + fprintf(fp, "\n"); + } + fprintf(fp, "\n"); +} +#endif + +static inline void +imbe_store_bits(voice_codeword& cw, int s, int l, uint32_t v) +{ + for (int i = l-1; i >= s; i--) { + cw[i] = v & 1; + v >>= 1; + } +} + +static inline uint32_t +pngen15(uint32_t& Pr) +{ + int n = 0; + for(int i = 14; i >= 0; --i) { + Pr = (173 * Pr + 13849) & 0xffffu; + if(Pr & 32768) { + n += (1 << i); + } + } + return n; +} + +static inline uint32_t +pngen23(uint32_t& Pr) +{ + int n = 0; + for(int i = 22; i >= 0; --i) { + Pr = (173 * Pr + 13849) & 0xffffu; + if(Pr & 32768) { + n += (1 << i); + } + } + return n; +} + +/* APCO IMBE header decoder. + * + * extracts 88 bits of IMBE parameters given an input 144-bit frame + * + * \param cw Codeword containing bits to be decoded + * \param u0-u7 Result output vectors + */ + +static inline void +imbe_header_decode(const voice_codeword& cw, uint32_t& u0, uint32_t& u1, uint32_t& u2, uint32_t& u3, uint32_t& u4, uint32_t& u5, uint32_t& u6, uint32_t& u7, uint32_t& E0, uint32_t& ET) +{ + ET = 0; + + size_t errs = 0; + uint32_t v0 = extract(cw, 0, 23); + errs = golay_23_decode(v0); + u0 = v0; + E0 = ET; + + uint32_t pn = u0 << 4; + uint32_t m1 = pngen23(pn); + uint32_t v1 = extract(cw, 23, 46) ^ m1; + errs += golay_23_decode(v1); + u1 = v1; + + uint32_t m2 = pngen23(pn); + uint32_t v2 = extract(cw, 46, 69) ^ m2; + errs += golay_23_decode(v2); + u2 = v2; + + uint32_t m3 = pngen23(pn); + uint32_t v3 = extract(cw, 69, 92) ^ m3; + errs += golay_23_decode(v3); + u3 = v3; + + uint32_t m4 = pngen15(pn); + uint16_t v4 = extract(cw, 92, 107) ^ m4; + errs += hamming_15_decode(v4); + u4 = v4; + + uint32_t m5 = pngen15(pn); + uint16_t v5 = extract(cw, 107, 122) ^ m5; + errs += hamming_15_decode(v5); + u5 = v5; + + uint32_t m6 = pngen15(pn); + uint16_t v6 = extract(cw, 122, 137) ^ m6; + errs += hamming_15_decode(v6); + u6 = v6; + + u7 = extract(cw, 137, 144); + u7 <<= 1; /* so that bit0 is free (see note about BOT bit */ +} + +/* APCO IMBE header encoder. + * + * given 88 bits of IMBE parameters, construct output 144-bit IMBE codeword + * + * \param cw Codeword into which 144 bits of results are placed + * \param u0-u7 input parameters + */ + +static inline void +imbe_header_encode(voice_codeword& cw, uint32_t u0, uint32_t u1, uint32_t u2, uint32_t u3, uint32_t u4, uint32_t u5, uint32_t u6, uint32_t u7) +{ + // given input 88-bit IMBE frame (in u0-u7), + // add golay / hamming bits to produce a 144-bit frame. + uint32_t c0, c1, c2, c3, c4, c5, c6, c7; + + uint32_t pn = u0 << 4; + + c0 = golay_23_encode(u0); + imbe_store_bits(cw, 0, 23, c0); + + uint32_t m1 = pngen23(pn); + c1 = golay_23_encode(u1) ^ m1; + imbe_store_bits(cw, 23, 46, c1); + + uint32_t m2 = pngen23(pn); + c2 = golay_23_encode(u2) ^ m2; + imbe_store_bits(cw, 46, 69, c2); + + uint32_t m3 = pngen23(pn); + c3 = golay_23_encode(u3) ^ m3; + imbe_store_bits(cw, 69, 92, c3); + + uint32_t m4 = pngen15(pn); + c4 = hamming_15_encode(u4) ^ m4; + imbe_store_bits(cw, 92, 107, c4); + + uint32_t m5 = pngen15(pn); + c5 = hamming_15_encode(u5) ^ m5; + imbe_store_bits(cw, 107, 122, c5); + + uint32_t m6 = pngen15(pn); + c6 = hamming_15_encode(u6) ^ m6; + imbe_store_bits(cw, 122, 137, c6); + + c7 = u7; + imbe_store_bits(cw, 137, 144, c7 >> 1); +} + +static inline void +imbe_deinterleave (const_bit_vector& frame_body, voice_codeword& cw, uint32_t frame_nr) +{ + for(size_t j = 0; j < voice_codeword_sz; ++j) { + cw[j] = frame_body[voice_codeword_bits[frame_nr][j]]; + } +} + + +static inline void +imbe_interleave(bit_vector& frame_body, const voice_codeword& cw, uint32_t frame_nr) +{ + for(size_t j = 0; j < voice_codeword_sz; ++j) { + frame_body[voice_codeword_bits[frame_nr][j]] = cw[j]; + } +} + +static inline void +imbe_frame_unpack(uint8_t *A, uint32_t& u0, uint32_t& u1, uint32_t& u2, uint32_t& u3, uint32_t& u4, uint32_t& u5, uint32_t& u6, uint32_t& u7, uint32_t& E0, uint32_t& ET) +{ + E0 = A[0]; + ET = A[1]; + u0 = A[4] + (E0 & 240) * 16; + u1 = A[5] + (E0 & 15) * 256; + u2 = A[6] + (ET & 240) * 16; + u3 = A[7] + (ET & 15) * 256; + E0 = A[2]; + ET = A[3]; + u4 = A[8] + (E0 & 224) * 8; + u5 = A[9] + (E0 & 28) * 64; + u6 = A[10] + (ET & 128) * 2 + (E0 & 3) * 512; + u7 = ET & 127; + E0 = A[11]; + if(E0 & 192) exit(4); + ET = E0 & 3; + E0 = (E0 & 84) / 4; +} + +/* + * Given a 144-bit IMBE frame(cw), + * 1. Decode frame to error-corrected 88-bit format + * 2. Re-encode frame into 144-bit format with refreshed Hamming/Golay encoding + * 3. FIXME: track decoding error rates and stats + */ +static inline void +imbe_regenerate_frame(bit_vector& cw) { + unsigned int u0 = 0; + unsigned int u1,u2,u3,u4,u5,u6,u7; + unsigned int E0 = 0; + unsigned int ET = 0; + + // PN/Hamming/Golay - etc. + imbe_header_decode(cw, u0, u1, u2, u3, u4, u5, u6, u7, E0, ET) ; +#if DEBUG + printf("u_0: %x\r\nu_1: %x\r\nu_2: %x\r\nu_3: %x\r\nu_4: %x\r\nu_5: %x\r\nu_6: %x\r\nu_7: %x\r\n\r\n", u0, u1, u2, u3, u4, u5, u6, u7>>1); +#endif + imbe_header_encode(cw, u0, u1, u2, u3, u4, u5, u6, u7); +} + +/* + * process voice units (ldu1 or ldu2) + * perform error correction for each of the nine embedded 144-bit frames + * by regenerating the error-correction coding bits + */ +static inline void +imbe_regenerate_voice_unit(bit_vector& frame_body) { + voice_codeword cw(voice_codeword_sz); +#if DEBUG + dump_cw(frame_body, 216, stderr); +#endif + for(size_t i = 0; i < nof_voice_codewords; ++i) { + imbe_deinterleave(frame_body, cw, i); + imbe_regenerate_frame(cw); + imbe_interleave(frame_body, cw, i); + } +#if DEBUG + dump_cw(frame_body, 216, stderr); +#endif +} + +#endif /* INCLUDED_IMBE_FRAME_H */ diff --git a/blocks/src/lib/op25_p25_frame.h b/blocks/src/lib/op25_p25_frame.h new file mode 100644 index 0000000..f60b2c8 --- /dev/null +++ b/blocks/src/lib/op25_p25_frame.h @@ -0,0 +1,38 @@ +#ifndef INCLUDED_OP25_P25_FRAME_H +#define INCLUDED_OP25_P25_FRAME_H 1 + +static const size_t P25_VOICE_FRAME_SIZE = 1728; +static const size_t P25_HEADER_SYMBOLS = 24 + 32 + 1; +static const size_t P25_HEADER_BITS = P25_HEADER_SYMBOLS * 2; + +static const uint64_t P25_FRAME_SYNC_MAGIC = 0x5575F5FF77FFLL; +static const uint64_t P25_FRAME_SYNC_REV_P = 0x5575F5FF77FFLL ^ 0xAAAAAAAAAAAALL; +static const uint64_t P25_FRAME_SYNC_MASK = 0xFFFFFFFFFFFFLL; + +/* Given a 64-bit frame header word and a frame body which is to be initialized + * 1. Place flags at beginning of frame body + * 2. Store 64-bit frame header word + * 3. FIXME Place first status symbol + */ +static inline void +p25_setup_frame_header(bit_vector& frame_body, uint64_t hw) { + uint64_t acc = P25_FRAME_SYNC_MAGIC; + for (int i=47; i>=0; i--) { + frame_body[ i ] = acc & 1; + acc >>= 1; + } + acc = hw; + for (int i=113; i>=72; i--) { + frame_body[ i ] = acc & 1; + acc >>= 1; + } + // FIXME: insert proper status dibit bits at 70, 71 + frame_body[70] = 1; + frame_body[71] = 0; + for (int i=69; i>=48; i--) { + frame_body[ i ] = acc & 1; + acc >>= 1; + } +} + +#endif /* INCLUDED_OP25_P25_FRAME_H */ diff --git a/blocks/src/lib/op25_pcap_source_b.cc b/blocks/src/lib/op25_pcap_source_b.cc new file mode 100644 index 0000000..234de64 --- /dev/null +++ b/blocks/src/lib/op25_pcap_source_b.cc @@ -0,0 +1,114 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2010,2011 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. + */ + +#define __STDC_CONSTANT_MACROS + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define PCAP_DONT_INCLUDE_PCAP_BPF_H +#include + +using namespace std; + +op25_pcap_source_b_sptr +op25_make_pcap_source_b(const char *path, float delay) +{ + return op25_pcap_source_b_sptr(new op25_pcap_source_b(path, delay)); +} + +op25_pcap_source_b::~op25_pcap_source_b() +{ +} + +int +op25_pcap_source_b::work(int nof_output_items, gr_vector_const_void_star& input_items, gr_vector_void_star& output_items) +{ + try { + const size_t OCTETS_AVAIL = octets_.size(); + uint8_t *out = reinterpret_cast(output_items[0]); + const int OCTETS_REQD = static_cast(nof_output_items); + for(int i = 0; i < OCTETS_REQD; ++i) { + out[i] = octets_[loc_++]; + loc_ %= OCTETS_AVAIL; + } + return OCTETS_REQD; + } catch(const std::exception& x) { + cerr << x.what() << endl; + exit(EXIT_FAILURE); + } catch(...) { + cerr << "unhandled exception" << endl; + exit(EXIT_FAILURE); + } + +} + +op25_pcap_source_b::op25_pcap_source_b(const char *path, float delay) : + gr_sync_block ("pcap_source_b", + gr_make_io_signature (0, 0, 0), + gr_make_io_signature (1, 1, sizeof(uint8_t))), + loc_(0), + octets_(/* delay * 1200, 0 */) +{ + char err[PCAP_ERRBUF_SIZE]; + pcap_t *pcap = pcap_open_offline(path, err); + if(pcap) { + struct pcap_pkthdr hdr; + for(const uint8_t *octets; octets = pcap_next(pcap, &hdr);) { + const size_t ETHERNET_SZ = 14; + const size_t IP_SZ = 20; + const size_t UDP_SZ = 8; + const size_t P25CAI_OFS = ETHERNET_SZ + IP_SZ + UDP_SZ; + if(P25CAI_OFS < hdr.caplen) { + const size_t FRAME_SZ = hdr.caplen - P25CAI_OFS; +#if 0 + // push some zero octets to separate frames + const size_t SILENCE_OCTETS = 48; + octets_.resize(octets_.size() + SILENCE_OCTETS, 0); +#endif + // push octets from frame payload into local buffer + octets_.reserve(octets_.size() + hdr.caplen - P25CAI_OFS); + for(size_t i = 0; i < FRAME_SZ; ++i) { + octets_.push_back(octets[P25CAI_OFS + i]); + } + } + } + pcap_close(pcap); + } else { + cerr << "error: failed to open " << path; + cerr << " (" << err << ")" << endl; + exit(EXIT_FAILURE); + } +} diff --git a/blocks/src/lib/op25_pcap_source_b.h b/blocks/src/lib/op25_pcap_source_b.h new file mode 100644 index 0000000..0ab6618 --- /dev/null +++ b/blocks/src/lib/op25_pcap_source_b.h @@ -0,0 +1,89 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2010-2011 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. + */ + +#ifndef INCLUDED_OP25_PCAP_SOURCE_B_H +#define INCLUDED_OP25_PCAP_SOURCE_B_H + +#include +#include +#include +#include +#include + +typedef boost::shared_ptr op25_pcap_source_b_sptr; + +op25_pcap_source_b_sptr op25_make_pcap_source_b(const char *path, float delay); + +/** + * op25_pcap_source_b is a GNU Radio block for reading from a + * tcpdump-formatted capture file and producing a stream of octets. + */ +class op25_pcap_source_b : public gr_sync_block +{ +public: + + /** + * op25_pcap_source_b (virtual) destructor. + */ + virtual ~op25_pcap_source_b(); + + /** + * Process symbols into frames. + */ + virtual int work(int nof_output_items, gr_vector_const_void_star& input_items, gr_vector_void_star& output_items); + +private: + + /** + * Expose class to public ctor. Create a new instance of + * op25_pcap_source_b and wrap it in a shared_ptr. This is + * effectively the public constructor. + * + * \param path The path to the tcpdump-formatted input file. + * \param delay The number of seconds to delay before sending the first frame. + */ + friend op25_pcap_source_b_sptr op25_make_pcap_source_b(const char *path, float delay); + + /** + * op25_pcap_source_b protected constructor. + * + * \param path The path to the tcpdump-formatted input file. + * \param delay The number of seconds to delay before sending the first frame. + */ + op25_pcap_source_b(const char *path, float delay); + +private: + + /** + * The next octet to be read from the input file. + */ + size_t loc_; + + /** + * Symbols from the input file. + */ + std::vector octets_; + +}; + +#endif /* INCLUDED_OP25_PCAP_SOURCE_B_H */ diff --git a/blocks/src/lib/op25_yank.h b/blocks/src/lib/op25_yank.h new file mode 100644 index 0000000..621c316 --- /dev/null +++ b/blocks/src/lib/op25_yank.h @@ -0,0 +1,114 @@ +#ifndef INCLUDED_SWAB_H +#define INCLUDED_SWAB_H + +/** + * Yank in[bits[0]..bits[bits_sz]) to out[where,where+bits_sz). + * + * \param in A const reference to the source. + * \param bits An array specifying the ordinals of the bits to copy. + * \param bits_sz The size of the bits array. + * \param out A reference to the destination. + * \param where The offset of the first bit to write. + */ +template +void yank(const X& in, const size_t bits[], size_t bits_sz, Y& out, size_t where) +{ + for(size_t i = 0; i < bits_sz; ++i) { + out[where+i] = in[bits[i]]; + } +} + +/** + * Yank back from in[where,where+bits_sz) to out[bits[0]..bits[bits_sz]). + * + * \param in A const reference to the source. + * \param where The offset of the first bit to read. + * \param out A reference to the destination. + * \param bits An array specifying the ordinals of the bits to copy. + * \param bits_sz The size of the bits array. + */ +template +void yank_back(const X& in, size_t where, Y& out, const size_t bits[], size_t bits_sz) +{ + for(size_t i = 0; i < bits_sz; ++i) { + out[bits[i]] = in[where+i]; + } +} + +/** + * Extract a bit_vector in[begin,end) to an octet buffer. + * + * \param in A const reference to the source. + * \param begin The offset of the first bit to extract (the MSB). + * \param end The offset of the end bit. + * \param out Address of the octet buffer to write into. + * \return The number of octers written. + */ +template +size_t extract(const X& in, int begin, int end, uint8_t *out) +{ + const size_t out_sz = (7 + end - begin) / 8; + std::fill(out, out + out_sz, 0); + for(int i = begin, j = 0; i < end; ++i, ++j) { + out[j / 8] |= (in[i] ? 1 << (7 - (j % 8)) : 0); + } + return out_sz; +} + +/** + * Extract a bit_vector in[bits[0)..bits[bits_sz)) to an octet buffer. + * + * \param in A const reference to the source. + * \param bits An array specifying the ordinals of the bits to extract. + * \param bits_sz The size of the bits array. + * \param out Address of the octet buffer to write into. + * \return The number of octers written. + */ +template +size_t extract(const X& in, const size_t bits[], size_t bits_sz, uint8_t *out) +{ + const size_t out_sz = (7 + bits_sz) / 8; + std::fill(out, out + out_sz, 0); + for(size_t i = 0; i < bits_sz; ++i) { + out[i / 8] ^= in[bits[i]] << (7 - (i % 8)); + } + return out_sz; +} + +/** + * Extract value of bits from in[bits[0..bits_sz)). + * + * \param in The input const_bit_vector. + * \param begin The offset of the first bit to extract (the MSB). + * \param end The offset of the end bit. + * \return A uint64_t containing the value + */ +template +uint64_t extract(const X& in, int begin, int end) +{ + uint64_t x = 0LL; + for(int i = begin; i < end; ++i) { + x = (x << 1) | (in[i] ? 1 : 0); + } + return x; +} + +/** + * Extract value of bits from in[bits[0..bits_sz)). + * + * \param in A const reference to the source. + * \param bits An array specifying the ordinals of the bits to extract. + * \param bits_sz The size of the bits array. + * \return A uint64_t containing the value + */ +template +uint64_t extract(const X& in, const size_t bits[], size_t bits_sz) +{ + uint64_t x = 0LL; + for(size_t i = 0; i < bits_sz; ++i) { + x = (x << 1) | (in[bits[i]] ? 1 : 0); + } + return x; +} + +#endif // INCLUDED_SWAB_H diff --git a/blocks/src/lib/p25cai_du_handler.cc b/blocks/src/lib/p25cai_du_handler.cc new file mode 100644 index 0000000..7628042 --- /dev/null +++ b/blocks/src/lib/p25cai_du_handler.cc @@ -0,0 +1,87 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2008-2011 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +p25cai_du_handler::p25cai_du_handler(data_unit_handler_sptr next, const char *addr, int port) : + data_unit_handler(next), + d_cai(-1), + d_address("Unavailable") +{ + struct sockaddr_in sin; + sin.sin_family = AF_INET; + sin.sin_port = htons(port); + inet_aton(addr, &sin.sin_addr); + d_cai = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if(-1 != d_cai) { + if(-1 != connect(d_cai, (struct sockaddr*) &sin, sizeof(sin))) { + ostringstream address; + address << addr << ":" << port; + d_address = address.str(); + } else { + printf("error %d: %s\n", errno, strerror(errno)); + perror("connect(d_tap, (struct sockaddr*) &sin, sizeof(sin))"); + close(d_cai); + d_cai = -1; + } + } else { + perror("socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)"); + d_cai = -1; + } +} + +p25cai_du_handler::~p25cai_du_handler() +{ + if(-1 != d_cai) { + close(d_cai); + } +} + +const char* +p25cai_du_handler::destination() const +{ + return d_address.c_str(); +} + +void +p25cai_du_handler::handle(data_unit_sptr du) +{ + if(-1 != d_cai) { + const size_t CAI_SZ = du->size(); + uint8_t cai[CAI_SZ]; + du->decode_frame(CAI_SZ, cai); + write(d_cai, cai, CAI_SZ); + } + data_unit_handler::handle(du); +} diff --git a/blocks/src/lib/p25cai_du_handler.h b/blocks/src/lib/p25cai_du_handler.h new file mode 100644 index 0000000..4a601bb --- /dev/null +++ b/blocks/src/lib/p25cai_du_handler.h @@ -0,0 +1,84 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2008-2011 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. +*/ + +#ifndef INCLUDED_P25CAI_DU_HANDLER_H +#define INCLUDED_P25CAI_DU_HANDLER_H + +#include +#include + +/** + * This data_unit_handler forwards received frames using p25cai - a + * straighforward encapsulation of the P25 CAI in a UDP datagram. This + * format is understood by Wireshark and replaces the use of TUN/TAP + * which require root privileges and are not present by default on + * some platforms. + */ +class p25cai_du_handler : public data_unit_handler +{ + +public: + + /** + * p25cai_du_handler constructor. + * + * \param next The next data_unit_handler. + * \param addr The address of the receiver. + * \param port The port number of the receiver. + */ + p25cai_du_handler(data_unit_handler_sptr next, const char *addr, int port); + + /** + * p25cai_du_handler virtual destructor. + */ + virtual ~p25cai_du_handler(); + + /** + * Handle a received P25 frame. + * + * \param du A non-null data_unit_sptr to handle. + */ + virtual void handle(data_unit_sptr du); + + /** + * Return a pointer to a string identifying the destination address. + * + * \return A pointer to a NUL-terminated character string. + */ + const char *destination() const; + +private: + + /** + * file descriptor for the UDP socket. + */ + int32_t d_cai; + + /** + * A string identifying the address of the receiver. + */ + std::string d_address; + +}; + +#endif /* INCLUDED_P25CAI_DU_HANDLER_H */ diff --git a/blocks/src/lib/pdu.cc b/blocks/src/lib/pdu.cc new file mode 100644 index 0000000..5b479af --- /dev/null +++ b/blocks/src/lib/pdu.cc @@ -0,0 +1,67 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2008 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. + */ + +#include + +using std::string; + +pdu::pdu(const_bit_queue& frame_body) : + abstract_data_unit(frame_body) +{ +} +pdu::~pdu() +{ +} + +string +pdu::duid_str() const +{ + return string("PDU"); +} + +void +pdu::do_correct_errors(bit_vector& frame_body) +{ +} + +uint16_t +pdu::frame_size_max() const +{ +#if 1 + const size_t HEADER_BLOCK_SIZE = 720; + return HEADER_BLOCK_SIZE; +#else + const size_t MIN_HEADER_BLOCK_SZ = 312; + // after HEADER_BLOCK_SIZE bits have been read we can then use the + // header contents to decide on frame_size_max + + size_t n = MIN_HEADER_BLOCK_SZ; + if(n < ) { + static const size_t BITS[] = {}; + static const size_t BITS_SZ = sizeof(BITS) / sizeof(BITS[0]); + n = extract(); + } + return n; + +#endif +} diff --git a/blocks/src/lib/pdu.h b/blocks/src/lib/pdu.h new file mode 100644 index 0000000..87ad58e --- /dev/null +++ b/blocks/src/lib/pdu.h @@ -0,0 +1,74 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2008 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. + */ + +#ifndef INCLUDED_PDU_H +#define INCLUDED_PDU_H + +#include + +/** + * P25 packet data unit (PDU). + */ +class pdu : public abstract_data_unit +{ +public: + + /** + * P25 packet data unit (PDU) constructor. + * + * \param frame_body A const_bit_queue representing the frame body. + */ + pdu(const_bit_queue& frame_body); + + /** + * pdu (virtual) destructor. + */ + virtual ~pdu(); + + /** + * Returns a string describing the Data Unit ID (DUID). + */ + std::string duid_str() const; + +protected: + + /** + * Applies error correction code to the specified bit_vector. + * + * \param frame_body The bit vector to decode. + * \return + */ + virtual void do_correct_errors(bit_vector& frame_body); + + /** + * Returns the expected size (in bits) of this data unit in + * bits. For variable-length data this should return UINT16_MAX + * until the actual length of this frame is known. + * + * \return The expected size (in bits) of this data_unit when encoded. + */ + virtual uint16_t frame_size_max() const; + +}; + +#endif /* INCLUDED_PDU_H */ diff --git a/blocks/src/lib/pickle.cc b/blocks/src/lib/pickle.cc new file mode 100644 index 0000000..e50aafe --- /dev/null +++ b/blocks/src/lib/pickle.cc @@ -0,0 +1,59 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2008 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. +*/ + +#include + +#include +#include + +using namespace std; + +pickle::pickle() +{ +} + +pickle::~pickle() +{ +} + +void +pickle::add(string key, string value) +{ + map_[key] = value; +} + +string +pickle::to_string() const +{ + size_t n = 1; + ostringstream os; + os << "(dp" << n++ << endl; + for(stringmap::const_iterator i(map_.begin()); i != map_.end(); ++i) { + os << "S'" << i->first << "'" << endl; + os << "p" << n++ << endl; + os << "S'" << i->second << "'" << endl; + os << "p" << n++ << endl << "s"; + } + os << "." << endl; + return os.str(); +} diff --git a/blocks/src/lib/pickle.h b/blocks/src/lib/pickle.h new file mode 100644 index 0000000..048a635 --- /dev/null +++ b/blocks/src/lib/pickle.h @@ -0,0 +1,69 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2008 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. +*/ + +#ifndef INCLUDED_PICKLE_H +#define INCLUDED_PICKLE_H + +#include + +#include + +/** + * A pickled Python dictionary. Used to pass stuff to the UI. + */ +class pickle +{ + +public: + + /** + * pickle constructor. + * + * \param frame_body A const_bit_queue representing the frame body. + */ + pickle(); + + /** + * pickle virtual destructor. + */ + ~pickle(); + + /** + * Add a key/value pair to the pickled dictionary + */ + void add(std::string key, std::string value); + + /** + * Returns a string describing the Data Unit ID (DUID). + */ + std::string to_string() const; + +private: + + typedef std::map stringmap; + + stringmap map_; + +}; + +#endif /* INCLUDED_PICKLE_H */ diff --git a/blocks/src/lib/snapshot_du_handler.cc b/blocks/src/lib/snapshot_du_handler.cc new file mode 100644 index 0000000..222f5ed --- /dev/null +++ b/blocks/src/lib/snapshot_du_handler.cc @@ -0,0 +1,66 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2008 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. + */ + +#include +#include +#include + +using std::string; + +snapshot_du_handler::snapshot_du_handler(data_unit_handler_sptr next) : + data_unit_handler(next), + d_data_units(0) +{ +} + +snapshot_du_handler::~snapshot_du_handler() +{ +} + +void +snapshot_du_handler::handle(data_unit_sptr du) +{ + if(d_msgq) { + string snapshot(du->snapshot()); + if(snapshot.size() > 0) { + const size_t snapshot_sz = snapshot.size() + 1; + gr_message_sptr msg = gr_make_message(/*type*/0, /*arg1*/++d_data_units, /*arg2*/0, snapshot_sz); + char *snapshot_data = reinterpret_cast(msg->msg()); + memcpy(snapshot_data, snapshot.c_str(), snapshot_sz); + d_msgq->handle(msg); + } + } + data_unit_handler::handle(du); +} + +gr_msg_queue_sptr +snapshot_du_handler::get_msgq() const +{ + return d_msgq; +} + +void +snapshot_du_handler::set_msgq(gr_msg_queue_sptr msgq) +{ + d_msgq = msgq; +} diff --git a/blocks/src/lib/snapshot_du_handler.h b/blocks/src/lib/snapshot_du_handler.h new file mode 100644 index 0000000..3f92120 --- /dev/null +++ b/blocks/src/lib/snapshot_du_handler.h @@ -0,0 +1,94 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2008 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. +*/ + +#ifndef INCLUDED_SNAPSHOT_DU_HANDLER_H +#define INCLUDED_SNAPSHOT_DU_HANDLER_H + +#include +#include +#include + +/** + * snapshot_du_handler. Writes traffic snapshots to a msg_queue based + * on the HDU frame contents. The format used is that of a pickled + * python dictionary allowing the other end of the queue to pick only + * those fields of interest and ignore the rest. + */ +class snapshot_du_handler : public data_unit_handler +{ + +public: + + /** + * snapshot_du_handler constructor. + * + * \param next The next data_unit_handler in the chain. + * \param msgq A non-null msg_queue_sptr to the msg_queue to use. + */ + snapshot_du_handler(data_unit_handler_sptr next); + + /** + * snapshot_du_handler virtual destructor. + */ + virtual ~snapshot_du_handler(); + + /** + * Handle a received P25 frame. + * + * \param du A non-null data_unit_sptr to handle. + */ + virtual void handle(data_unit_sptr du); + + /** + * Accessor for the msgq attribute. Returns a pointer to the msgq + * if it exists. + * + * \return A (possibly NULL) gr_msg_queue_sptr pointing to the message queue. + */ + gr_msg_queue_sptr get_msgq() const; + + /** + * Accessor for the msgq attribute. Sets the msgq to point to the + * provided message queue object. + * + * \return A (possibly NULL) gr_msg_queue_sptr pointing to the message queue. + */ + void set_msgq(gr_msg_queue_sptr msgq); + +private: + + /** + * Count of the data units seen so far. + */ + uint32_t d_data_units; + + /** + * The msg_queue to which decoded frames are written. + */ + gr_msg_queue_sptr d_msgq; + +}; + + + +#endif /* INCLUDED_SNAPSHOT_DU_HANDLER_H */ diff --git a/blocks/src/lib/software_imbe_decoder.cc b/blocks/src/lib/software_imbe_decoder.cc new file mode 100644 index 0000000..1801027 --- /dev/null +++ b/blocks/src/lib/software_imbe_decoder.cc @@ -0,0 +1,1433 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2008-2009 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or(at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static const int BMTn[3600] = { + 3, 3, 4, 5, 6, 7, 8, 3, 4, 5, 6, 7, 8, 9, 3, 4, + 5, 6, 7, 8, 9, 10, 3, 4, 5, 6, 7, 8, 9, 10, 3, 4, + 5, 6, 7, 8, 9, 10, 3, 1, 1, 1, 2, 2, 4, 5, 6, 7, + 8, 9, 10, 3, 4, 5, 6, 7, 8, 9, 10, 3, 4, 5, 6, 7, + 8, 9, 10, 3, 4, 5, 6, 7, 8, 9, 10, 3, 4, 8, 3, 4, + 5, 6, 7, 8, 3, 4, 5, 6, 7, 8, 9, 3, 4, 5, 6, 7, + 8, 9, 10, 3, 4, 5, 6, 7, 8, 9, 10, 11, 3, 4, 5, 6, + 7, 8, 1, 1, 1, 1, 2, 2, 9, 10, 11, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 3, 4, 5, 6, 7, 8, 9, 10, 11, 3, 4, 5, + 6, 7, 8, 9, 10, 11, 8, 3, 4, 5, 8, 3, 4, 5, 6, 7, + 8, 9, 3, 4, 5, 6, 7, 8, 9, 10, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 1, 1, + 1, 2, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 3, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 3, 8, 3, 4, 5, 6, 7, 8, 9, 3, 4, 5, 6, 7, 8, + 9, 10, 3, 4, 5, 6, 7, 8, 9, 10, 11, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 3, 4, 5, 1, 1, 1, 1, 2, 2, 6, 7, + 8, 9, 10, 11, 12, 13, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 3, 4, 5, 8, + 9, 3, 4, 5, 6, 7, 8, 9, 10, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 3, 4, 5, 6, + 7, 8, 9, 1, 1, 1, 1, 1, 2, 2, 10, 11, 12, 13, 14, 3, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 3, 8, 9, 3, 4, 5, 6, 7, 8, + 9, 3, 4, 5, 6, 7, 8, 9, 10, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 14, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 1, + 1, 1, 1, 2, 2, 13, 14, 15, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 3, 9, 3, 4, 5, 6, 8, 9, 3, 4, 5, 6, 7, 8, + 9, 10, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 1, 1, 1, 1, 1, 2, 2, + 16, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 3, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 3, 4, 5, + 8, 9, 3, 4, 5, 6, 7, 8, 9, 10, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 3, 4, 1, 1, 1, 1, 1, 1, 2, 2, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 16, 17, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 3, 4, 3, 4, 5, 6, 7, 8, + 9, 10, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 3, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17, 3, 4, 5, 6, 1, + 1, 1, 1, 1, 1, 2, 2, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 3, 3, 4, 5, 6, 7, 8, 10, 11, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 16, 3, 4, 5, 6, 7, 8, 1, 1, 1, 1, 1, 1, + 2, 2, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 3, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 3, 3, + 4, 5, 8, 10, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 3, 4, 5, + 6, 7, 8, 9, 10, 1, 1, 1, 1, 1, 1, 1, 2, 2, 11, 12, + 13, 14, 15, 16, 17, 18, 19, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 3, 3, 4, 5, 8, 10, 3, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 16, 19, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 1, 1, 1, 1, 1, 1, 1, 2, 2, 12, 13, 14, 15, 16, 17, 19, + 20, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 3, 4, 5, 10, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, 20, + 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1, 1, 1, 1, 1, + 1, 1, 2, 2, 14, 15, 16, 17, 18, 20, 21, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 3, + 4, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 15, 18, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, + 17, 18, 19, 21, 22, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 3, 3, 4, 5, 6, 7, + 8, 10, 11, 13, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 16, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, + 18, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 19, 20, 22, 23, 3, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 3, 3, 4, 5, 6, 7, 8, 11, 3, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 1, 1, 1, 1, + 1, 1, 1, 1, 2, 2, 21, 23, 24, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 3, 3, 4, 5, 6, 8, 11, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 17, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 20, 21, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 23, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 3, 3, 4, 5, 8, + 11, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 17, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 21, + 24, 25, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 3, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 3, 3, 4, 5, 8, 11, 3, 4, 5, 6, + 7, 8, 9, 11, 12, 14, 17, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 21, 22, 25, 26, 3, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 2, 2, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, + 28, 3, 4, 5, 8, 11, 3, 4, 5, 6, 7, 8, 9, 11, 12, 14, + 18, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 22, 23, 26, 3, 4, 5, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 2, 2, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 3, 4, 5, 11, + 3, 4, 5, 6, 7, 8, 9, 11, 12, 15, 19, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 23, 27, 3, + 4, 5, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 7, + 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 3, 4, 5, 3, 4, 5, 6, 7, 8, + 9, 12, 13, 16, 20, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 20, 21, 24, 28, 3, 4, 5, 6, 7, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, + 30, 31, 3, 4, 3, 4, 5, 6, 7, 8, 9, 12, 13, 16, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 21, + 24, 28, 3, 4, 5, 6, 7, 8, 9, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 2, 2, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 3, 4, 3, + 4, 5, 6, 7, 8, 9, 12, 13, 16, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 20, 21, 24, 29, 3, 4, 5, + 6, 7, 8, 9, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, + 2, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, 3, 3, 4, 5, 6, 7, 8, 9, + 12, 13, 16, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 20, 21, 25, 30, 3, 4, 5, 6, 7, 8, 9, 10, 11, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 32, 33, 34, 3, 3, 4, 5, 6, 7, 8, 12, 16, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 21, 22, 26, 31, + 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 2, 2, 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 3, 3, + 4, 5, 6, 7, 8, 12, 17, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 22, 23, 27, 32, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 2, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 32, 33, 34, 35, 3, 3, 4, 5, 6, 7, 8, + 13, 18, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 15, 16, 18, + 19, 23, 24, 28, 33, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, + 33, 34, 35, 36, 3, 3, 4, 5, 6, 8, 13, 18, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 23, 28, 33, 3, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 2, 2, 15, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 33, 34, 35, 36, 37, 3, + 3, 4, 5, 6, 8, 13, 18, 3, 4, 5, 6, 7, 8, 9, 10, 11, + 13, 14, 15, 16, 18, 19, 23, 28, 34, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 2, 2, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, + 28, 29, 30, 31, 32, 34, 35, 36, 37, 38, 3, 3, 4, 5, 6, 8, + 13, 18, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 15, 16, 18, + 19, 23, 24, 29, 35, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 29, 30, 31, 32, + 33, 35, 36, 37, 38, 3, 3, 4, 5, 6, 8, 13, 18, 3, 4, 5, + 6, 7, 8, 9, 10, 11, 13, 14, 15, 18, 19, 24, 25, 30, 36, 3, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 16, 17, 18, 19, 20, 21, + 22, 23, 24, 25, 26, 27, 28, 30, 31, 32, 33, 34, 36, 37, 38, 39, + 3, 3, 4, 5, 8, 13, 19, 3, 4, 5, 6, 7, 8, 9, 10, 13, + 14, 15, 16, 19, 20, 25, 26, 31, 37, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 2, 2, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, + 28, 29, 31, 32, 33, 34, 35, 37, 38, 39, 40, 3, 3, 4, 5, 8, + 14, 3, 4, 5, 6, 7, 8, 9, 10, 11, 14, 15, 16, 17, 20, 21, + 26, 27, 32, 38, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 32, 33, + 34, 35, 38, 39, 40, 41, 3, 3, 4, 5, 8, 14, 3, 4, 5, 6, + 7, 8, 9, 10, 11, 14, 15, 16, 17, 20, 21, 26, 32, 38, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 18, 19, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 29, 30, 32, 33, 34, 35, 38, 39, 40, 41, + 42, 3, 3, 4, 5, 8, 14, 3, 4, 5, 6, 7, 8, 9, 10, 14, + 15, 16, 17, 20, 21, 26, 32, 39, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 2, 2, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 32, 33, 34, 35, 36, 39, 40, 41, 42, 43, 3, 3, 4, 5, + 8, 14, 3, 4, 5, 6, 7, 8, 9, 10, 14, 15, 16, 20, 21, 26, + 27, 33, 40, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, + 2, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 33, 34, 35, + 36, 37, 40, 41, 42, 43, 44, 3, 4, 5, 8, 14, 3, 4, 5, 6, + 7, 8, 9, 10, 14, 15, 16, 20, 21, 27, 28, 34, 41, 3, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 20, 21, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 31, 34, 35, 36, 37, 38, 41, 42, 43, + 44, 45, 3, 4, 5, 8, 14, 3, 4, 5, 6, 7, 8, 9, 10, 14, + 15, 16, 21, 22, 28, 29, 35, 42, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 2, 2, 20, 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 32, 35, 36, 37, 38, 39, 42, 43, 44, 45, 3, 4, 5, + 8, 15, 3, 4, 5, 6, 7, 8, 9, 10, 15, 16, 17, 22, 23, 29, + 30, 36, 43, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, + 36, 37, 38, 39, 43, 44, 45, 46, 3, 4, 5, 8, 15, 3, 4, 5, + 6, 7, 8, 9, 10, 15, 16, 17, 22, 23, 29, 30, 36, 43, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 20, 21, 22, + 23, 24, 25, 26, 27, 29, 30, 31, 32, 33, 36, 37, 38, 39, 43, 44, + 45, 46, 47, 3, 4, 5, 8, 15, 3, 4, 5, 6, 7, 8, 9, 10, + 15, 16, 17, 22, 23, 29, 30, 36, 44, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 2, 2, 20, 21, 22, 23, 24, 25, 26, 27, + 29, 30, 31, 32, 33, 36, 37, 38, 39, 40, 44, 45, 46, 47, 3, 4, + 5, 8, 15, 3, 4, 5, 6, 7, 8, 9, 10, 15, 16, 22, 23, 29, + 30, 37, 45, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 2, 21, 22, 23, 24, 25, 26, 27, 29, 30, 31, 32, 33, 37, + 38, 39, 40, 41, 45, 46, 47, 48, 49, 3, 4, 8, 15, 3, 4, 5, + 6, 7, 8, 9, 15, 16, 17, 22, 23, 30, 31, 38, 46, 3, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 22, 23, + 24, 25, 26, 27, 28, 30, 31, 32, 33, 34, 38, 39, 40, 41, 42, 46, + 47, 48, 49, 50, 3, 4, 8, 15, 3, 4, 5, 6, 7, 8, 9, 15, + 16, 17, 23, 24, 31, 32, 39, 47, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 2, 2, 22, 23, 24, 25, 26, 27, 28, + 29, 31, 32, 33, 34, 35, 39, 40, 41, 42, 43, 47, 48, 49, 50, 3, + 4, 8, 16, 3, 4, 5, 6, 7, 8, 9, 10, 16, 17, 18, 24, 25, + 32, 33, 40, 48, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 16, 17, 18, 19, 20, 21, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 2, 2, 22, 24, 25, 26, 27, 28, 29, 30, 32, 33, 34, 35, + 36, 40, 41, 42, 43, 44, 48, 49, 50, 51, 3, 4, 8, 16, 3, 4, + 5, 6, 7, 8, 9, 10, 16, 17, 18, 24, 25, 32, 33, 40, 48, 3, + 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 18, 19, 20, + 21, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 22, + 24, 25, 26, 27, 28, 29, 30, 32, 33, 34, 35, 36, 40, 41, 42, 43, + 48, 49, 50, 51, 52, 3, 4, 8, 16, 3, 4, 5, 6, 7, 8, 9, + 10, 16, 17, 18, 24, 25, 32, 33, 40, 49, 3, 4, 5, 6, 7, 8, + 9, 10, 11, 12, 13, 14, 16, 17, 18, 19, 20, 21, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 22, 24, 25, 26, 27, 28, + 29, 30, 32, 33, 34, 35, 36, 40, 41, 42, 43, 44, 49, 50, 51, 52 +}; + +static const int BMTb[3600] = { + 512, 256, 256, 256, 256, 256, 256, 128, 128, 128, 128, 128, 128, 128, 64, 64, + 64, 64, 64, 64, 64, 64, 32, 32, 32, 32, 32, 32, 32, 32, 16, 16, + 16, 16, 16, 16, 16, 16, 8, 4, 2, 1, 4, 2, 8, 8, 8, 8, + 8, 8, 8, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, + 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 256, 256, 256, 128, 128, + 128, 128, 128, 128, 64, 64, 64, 64, 64, 64, 64, 32, 32, 32, 32, 32, + 32, 32, 32, 16, 16, 16, 16, 16, 16, 16, 16, 16, 8, 8, 8, 8, + 8, 8, 8, 4, 2, 1, 4, 2, 8, 8, 8, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 256, 128, 128, 128, 128, 64, 64, 64, 64, 64, + 64, 64, 32, 32, 32, 32, 32, 32, 32, 32, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 4, 2, + 1, 4, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 128, 128, 64, 64, 64, 64, 64, 64, 64, 32, 32, 32, 32, 32, 32, + 32, 32, 16, 16, 16, 16, 16, 16, 16, 16, 16, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 4, 4, 4, 8, 4, 2, 1, 4, 2, 4, 4, + 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 64, 64, 64, 64, + 64, 32, 32, 32, 32, 32, 32, 32, 32, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, + 4, 4, 4, 16, 8, 4, 2, 1, 4, 2, 4, 4, 4, 4, 4, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 64, 64, 64, 32, 32, 32, 32, 32, 32, + 32, 16, 16, 16, 16, 16, 16, 16, 16, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 16, 8, + 4, 2, 1, 4, 2, 4, 4, 4, 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, 64, 64, 32, 32, 32, 32, 32, 32, 16, 16, 16, 16, 16, 16, + 16, 16, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 16, 8, 4, 2, 1, 4, 2, + 4, 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, 32, 32, 32, + 32, 32, 16, 16, 16, 16, 16, 16, 16, 16, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 2, 2, 32, 16, 8, 4, 2, 1, 4, 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, 32, 32, 16, 16, 16, 16, 16, 16, + 16, 16, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 32, + 16, 8, 4, 2, 1, 4, 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, 32, 16, 16, 16, 16, 16, 16, 16, 16, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 32, 16, 8, 4, 2, 1, + 4, 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, 32, 16, + 16, 16, 16, 16, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, + 2, 2, 2, 2, 2, 64, 32, 16, 8, 4, 2, 1, 4, 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, 32, 16, 16, 16, 16, 16, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 64, 32, 16, 8, 4, 2, 1, 4, 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, 16, 16, 16, 16, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 64, 32, 16, 8, 4, + 2, 1, 4, 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, 16, + 16, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 128, 64, 32, 16, 8, 4, 2, 1, 4, 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, 16, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 128, 64, 32, 16, 8, 4, 2, 1, 4, 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, 16, 8, 8, 8, 8, 8, 8, 8, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 128, 64, 32, 16, + 8, 4, 2, 1, 4, 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, + 16, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 256, 128, 64, 32, 16, 8, 4, 2, 1, + 4, 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, 16, 8, 8, 8, 8, + 8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 256, 128, 64, 32, 16, 8, 4, 2, 1, 4, 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, 16, 8, 8, 8, 8, 8, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 256, 128, 64, + 32, 16, 8, 4, 2, 1, 4, 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, 8, 8, 8, 8, 8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 1, 1, 1, 512, 256, 128, 64, 32, 16, 8, 4, + 2, 1, 4, 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, 8, 8, 8, 8, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, + 1, 1, 1, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1, 4, 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, 8, 8, 8, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 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, 512, 256, + 128, 64, 32, 16, 8, 4, 2, 1, 4, 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, 8, 8, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 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, 1024, 512, 256, 128, 64, 32, 16, + 8, 4, 2, 1, 4, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 8, 8, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 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, 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1, 4, + 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 8, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 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, 1024, + 512, 256, 128, 64, 32, 16, 8, 4, 2, 1, 4, 2, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 8, 4, 4, 4, 4, 4, 4, 4, 4, 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, 2048, 1024, 512, 256, 128, 64, + 32, 16, 8, 4, 2, 1, 4, 2, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 8, 4, + 4, 4, 4, 4, 4, 4, 4, 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, 2048, 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, + 1, 4, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 8, 4, 4, 4, 4, 4, 4, + 4, 4, 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, + 2048, 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1, 4, 2, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 8, 4, 4, 4, 4, 4, 4, 4, 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, 2048, 1024, 512, 256, 128, + 64, 32, 16, 8, 4, 2, 1, 4, 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 8, + 4, 4, 4, 4, 4, 4, 4, 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, 2048, 1024, 512, 256, 128, 64, 32, 16, 8, 4, + 2, 1, 4, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 8, 4, 4, 4, 4, 4, + 4, 4, 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, 2048, 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1, 4, 2, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 8, 4, 4, 4, 4, 4, 4, 4, 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, 2048, 1024, 512, 256, + 128, 64, 32, 16, 8, 4, 2, 1, 4, 2, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 8, 4, 4, 4, 4, 4, 4, 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, 2048, 1024, 512, 256, 128, 64, 32, 16, 8, + 4, 2, 1, 4, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 8, 4, 4, 4, 4, + 4, 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, 2048, 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1, 4, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 8, 4, 4, 4, 4, 4, 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, 2048, 1024, 512, + 256, 128, 64, 32, 16, 8, 4, 2, 1, 4, 2, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 8, 4, 4, 4, 4, 4, 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, 2048, 1024, 512, 256, 128, 64, 32, 16, + 8, 4, 2, 1, 4, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 8, 4, 4, 4, + 4, 4, 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, 2048, 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1, 4, + 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 4, 4, 4, 4, 4, 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, 2048, 1024, + 512, 256, 128, 64, 32, 16, 8, 4, 2, 1, 4, 2, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 4, 4, 4, 4, 4, 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, 2048, 1024, 512, 256, 128, 64, 32, + 16, 8, 4, 2, 1, 4, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 4, + 4, 4, 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, 2048, 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1, + 4, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 4, 4, 4, 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, 2048, + 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1, 4, 2, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 4, 4, 4, 4, 4, 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, 2048, 1024, 512, 256, 128, 64, + 32, 16, 8, 4, 2, 1, 4, 2, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, + 4, 4, 4, 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, 2048, 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, + 1, 4, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 4, 4, 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, + 2048, 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1, 4, 2, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 4, 4, 4, 4, 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, 2048, 1024, 512, 256, 128, + 64, 32, 16, 8, 4, 2, 1, 4, 2, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, + 4, 4, 4, 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, 2048, 1024, 512, 256, 128, 64, 32, 16, 8, 4, + 2, 1, 4, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 4, 4, 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, 2048, 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1, 4, 2, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 4, 4, 4, 4, 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, 2048, 1024, 512, 256, + 128, 64, 32, 16, 8, 4, 2, 1, 4, 2, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 +}; + +static const int BitCount[1512] = { + 10, 9, 9, 9, 9, 9, 8, 7, 9, 9, 8, 8, 8, 9, 7, 6, + 5, 8, 8, 8, 7, 7, 9, 7, 6, 5, 4, 8, 7, 7, 7, 7, + 8, 7, 6, 5, 4, 3, 7, 7, 7, 6, 6, 7, 7, 6, 5, 4, + 3, 3, 7, 6, 6, 6, 6, 7, 7, 5, 4, 4, 3, 4, 3, 7, + 6, 6, 6, 5, 6, 7, 5, 4, 4, 3, 3, 3, 3, 6, 6, 6, + 5, 5, 6, 6, 5, 4, 4, 3, 3, 3, 3, 2, 6, 6, 5, 5, + 5, 5, 5, 5, 4, 4, 4, 3, 3, 2, 3, 2, 6, 5, 5, 5, + 5, 5, 4, 5, 5, 4, 3, 3, 3, 3, 2, 2, 2, 6, 5, 5, + 4, 4, 5, 4, 5, 4, 4, 3, 3, 3, 3, 2, 3, 2, 1, 6, + 5, 5, 4, 4, 5, 4, 5, 4, 4, 3, 3, 2, 3, 2, 1, 3, + 2, 1, 5, 5, 5, 4, 4, 4, 4, 5, 4, 4, 3, 3, 2, 2, + 3, 2, 1, 3, 2, 1, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, + 3, 2, 3, 2, 2, 3, 2, 1, 2, 2, 1, 5, 4, 4, 4, 4, + 4, 3, 4, 4, 3, 4, 3, 2, 3, 2, 2, 2, 2, 1, 2, 2, + 1, 5, 4, 4, 4, 4, 4, 3, 3, 4, 3, 3, 3, 3, 2, 3, + 2, 1, 2, 2, 1, 2, 2, 1, 5, 4, 4, 4, 3, 4, 3, 3, + 4, 3, 3, 3, 3, 2, 3, 2, 1, 2, 2, 1, 2, 1, 1, 1, + 5, 4, 4, 3, 3, 4, 3, 3, 4, 3, 3, 3, 2, 2, 3, 2, + 1, 2, 2, 1, 1, 2, 2, 1, 1, 5, 4, 4, 3, 3, 4, 3, + 2, 4, 3, 2, 3, 2, 2, 3, 2, 2, 1, 2, 2, 1, 1, 2, + 2, 1, 1, 4, 4, 4, 3, 3, 4, 3, 2, 4, 3, 2, 3, 2, + 2, 2, 3, 2, 1, 1, 2, 2, 1, 1, 2, 1, 1, 1, 4, 4, + 4, 3, 3, 3, 3, 2, 4, 3, 2, 2, 3, 2, 2, 2, 3, 2, + 1, 1, 2, 1, 1, 1, 2, 1, 1, 1, 4, 4, 4, 3, 3, 3, + 3, 2, 2, 3, 3, 2, 2, 3, 2, 2, 1, 3, 2, 1, 1, 2, + 1, 1, 1, 2, 1, 1, 1, 4, 4, 3, 3, 3, 3, 3, 2, 2, + 3, 3, 2, 2, 3, 2, 2, 1, 2, 2, 1, 1, 2, 1, 1, 1, + 2, 1, 1, 1, 1, 4, 4, 3, 3, 3, 3, 3, 2, 2, 3, 3, + 2, 2, 3, 2, 2, 1, 2, 2, 1, 1, 2, 1, 1, 1, 1, 2, + 1, 1, 1, 0, 4, 3, 3, 3, 3, 3, 3, 2, 2, 3, 3, 2, + 2, 3, 2, 1, 1, 2, 2, 1, 1, 1, 2, 1, 1, 1, 1, 2, + 1, 1, 1, 1, 4, 3, 3, 3, 3, 3, 2, 2, 2, 3, 2, 2, + 2, 3, 2, 2, 1, 1, 2, 2, 1, 1, 1, 2, 1, 1, 1, 1, + 2, 1, 1, 1, 0, 4, 3, 3, 3, 3, 3, 2, 2, 2, 3, 2, + 2, 2, 2, 3, 2, 1, 1, 1, 2, 2, 1, 1, 1, 2, 1, 1, + 1, 0, 2, 1, 1, 1, 0, 4, 3, 3, 3, 3, 3, 2, 2, 2, + 1, 3, 2, 2, 2, 1, 3, 2, 1, 1, 1, 2, 2, 1, 1, 1, + 2, 1, 1, 1, 0, 2, 1, 1, 1, 0, 4, 3, 3, 3, 2, 3, + 2, 2, 2, 1, 3, 2, 2, 2, 2, 3, 2, 1, 1, 1, 2, 1, + 1, 1, 1, 2, 1, 1, 1, 0, 2, 1, 1, 1, 1, 0, 4, 3, + 3, 3, 2, 3, 2, 2, 2, 1, 3, 2, 2, 2, 1, 3, 2, 1, + 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 0, 2, 1, 1, + 1, 1, 0, 4, 3, 3, 3, 2, 3, 2, 2, 2, 1, 3, 2, 2, + 2, 1, 3, 2, 1, 1, 1, 2, 2, 1, 1, 1, 0, 2, 1, 1, + 1, 1, 0, 2, 1, 1, 1, 0, 0, 4, 3, 3, 3, 2, 3, 2, + 2, 2, 1, 3, 2, 2, 1, 1, 3, 2, 1, 1, 1, 1, 2, 2, + 1, 1, 1, 0, 2, 1, 1, 1, 1, 0, 2, 1, 1, 1, 0, 0, + 4, 3, 3, 2, 2, 3, 2, 2, 1, 1, 3, 2, 2, 2, 1, 1, + 3, 2, 1, 1, 1, 1, 2, 2, 1, 1, 1, 0, 2, 1, 1, 1, + 1, 0, 2, 1, 1, 1, 0, 0, 4, 3, 3, 2, 2, 3, 2, 2, + 2, 1, 1, 3, 2, 2, 2, 1, 1, 2, 2, 1, 1, 1, 1, 2, + 2, 1, 1, 1, 0, 2, 1, 1, 1, 0, 0, 2, 1, 1, 1, 0, + 0, 4, 3, 3, 2, 2, 3, 2, 2, 2, 1, 1, 3, 2, 2, 2, + 1, 1, 2, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 0, 2, 1, + 1, 1, 0, 0, 2, 1, 1, 1, 1, 0, 0, 4, 3, 3, 2, 2, + 3, 2, 2, 1, 1, 1, 3, 2, 2, 2, 1, 1, 2, 2, 1, 1, + 1, 1, 2, 1, 1, 1, 1, 0, 2, 1, 1, 1, 1, 0, 0, 2, + 1, 1, 1, 1, 0, 0, 4, 3, 3, 2, 2, 3, 2, 2, 1, 1, + 1, 3, 2, 2, 1, 1, 1, 2, 2, 1, 1, 1, 1, 2, 2, 1, + 1, 1, 0, 0, 2, 1, 1, 1, 1, 0, 0, 2, 1, 1, 1, 1, + 0, 0, 3, 3, 3, 2, 2, 3, 2, 2, 1, 1, 1, 3, 2, 2, + 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 0, + 0, 2, 1, 1, 1, 1, 0, 0, 2, 1, 1, 1, 1, 0, 0, 3, + 3, 3, 2, 2, 3, 2, 2, 1, 1, 1, 3, 2, 2, 1, 1, 1, + 1, 2, 2, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 0, 0, 2, + 1, 1, 1, 1, 0, 0, 2, 1, 1, 1, 0, 0, 0, 3, 3, 3, + 2, 2, 3, 2, 2, 1, 1, 1, 1, 3, 2, 2, 1, 1, 1, 1, + 2, 2, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 0, 0, 2, 1, + 1, 1, 0, 0, 0, 2, 1, 1, 1, 0, 0, 0, 3, 3, 3, 2, + 2, 3, 2, 2, 1, 1, 1, 1, 3, 2, 2, 1, 1, 1, 1, 2, + 2, 1, 1, 1, 1, 0, 2, 2, 1, 1, 1, 0, 0, 2, 1, 1, + 1, 0, 0, 0, 2, 1, 1, 1, 1, 0, 0, 0, 3, 3, 3, 2, + 2, 3, 2, 2, 1, 1, 1, 1, 3, 2, 2, 1, 1, 1, 1, 2, + 2, 1, 1, 1, 1, 0, 2, 2, 1, 1, 1, 0, 0, 2, 1, 1, + 1, 1, 0, 0, 0, 2, 1, 1, 1, 0, 0, 0, 0, 3, 3, 3, + 2, 2, 3, 2, 2, 1, 1, 1, 1, 3, 2, 1, 1, 1, 1, 1, + 2, 2, 1, 1, 1, 1, 0, 2, 2, 1, 1, 1, 0, 0, 0, 2, + 1, 1, 1, 1, 0, 0, 0, 2, 1, 1, 1, 1, 0, 0, 0, 3, + 3, 2, 2, 2, 3, 2, 1, 1, 1, 1, 1, 3, 2, 2, 1, 1, + 1, 1, 2, 2, 1, 1, 1, 1, 1, 0, 2, 2, 1, 1, 1, 0, + 0, 0, 2, 1, 1, 1, 1, 0, 0, 0, 2, 1, 1, 1, 1, 0, + 0, 0, 3, 3, 2, 2, 2, 3, 2, 1, 1, 1, 1, 1, 3, 2, + 2, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 0, 2, 2, + 1, 1, 1, 0, 0, 0, 2, 1, 1, 1, 1, 0, 0, 0, 2, 1, + 1, 1, 0, 0, 0, 0, 3, 3, 2, 2, 2, 3, 2, 2, 1, 1, + 1, 1, 0, 3, 2, 2, 1, 1, 1, 1, 0, 2, 2, 1, 1, 1, + 1, 1, 0, 2, 2, 1, 1, 1, 0, 0, 0, 2, 1, 1, 1, 1, + 0, 0, 0, 2, 1, 1, 1, 0, 0, 0, 0, 3, 3, 2, 2, 2, + 3, 2, 2, 1, 1, 1, 1, 0, 3, 2, 2, 1, 1, 1, 1, 0, + 2, 2, 1, 1, 1, 1, 1, 0, 2, 2, 1, 1, 1, 0, 0, 0, + 2, 1, 1, 1, 0, 0, 0, 0, 2, 1, 1, 1, 1, 0, 0, 0, + 0, 3, 3, 2, 2, 2, 3, 2, 2, 1, 1, 1, 1, 0, 3, 2, + 2, 1, 1, 1, 1, 0, 2, 2, 1, 1, 1, 1, 1, 0, 2, 2, + 1, 1, 1, 0, 0, 0, 2, 1, 1, 1, 1, 0, 0, 0, 0, 2, + 1, 1, 1, 0, 0, 0, 0, 0 +}; + +static const float StepSize[1512] = { + 0.003100, 0.004020, 0.003360, 0.002900, 0.002640, 0.006140, 0.012280, 0.024560, 0.006200, 0.004020, 0.006720, 0.005800, 0.005280, 0.006140, 0.024560, 0.046050, + 0.085960, 0.012400, 0.008040, 0.006720, 0.011600, 0.010560, 0.006140, 0.024560, 0.046050, 0.085960, 0.122800, 0.012400, 0.016080, 0.013440, 0.011600, 0.010560, + 0.012280, 0.024560, 0.046050, 0.085960, 0.122800, 0.199550, 0.024800, 0.016080, 0.013440, 0.021750, 0.019800, 0.024560, 0.024560, 0.046050, 0.085960, 0.122800, + 0.199550, 0.156650, 0.024800, 0.030150, 0.025200, 0.021750, 0.019800, 0.024560, 0.024560, 0.085960, 0.122800, 0.122800, 0.156650, 0.122800, 0.156650, 0.024800, + 0.030150, 0.025200, 0.021750, 0.036960, 0.046050, 0.024560, 0.085960, 0.122800, 0.096400, 0.199550, 0.156650, 0.199550, 0.156650, 0.046500, 0.030150, 0.025200, + 0.040600, 0.036960, 0.046050, 0.046050, 0.085960, 0.096400, 0.122800, 0.156650, 0.199550, 0.156650, 0.199550, 0.204850, 0.046500, 0.030150, 0.047040, 0.040600, + 0.036960, 0.085960, 0.085960, 0.067480, 0.122800, 0.096400, 0.122800, 0.156650, 0.199550, 0.204850, 0.199550, 0.204850, 0.046500, 0.056280, 0.047040, 0.040600, + 0.036960, 0.085960, 0.096400, 0.085960, 0.067480, 0.122800, 0.156650, 0.199550, 0.156650, 0.199550, 0.204850, 0.260950, 0.204850, 0.046500, 0.056280, 0.047040, + 0.058000, 0.052800, 0.085960, 0.096400, 0.085960, 0.096400, 0.122800, 0.156650, 0.199550, 0.156650, 0.199550, 0.204850, 0.199550, 0.204850, 0.248400, 0.046500, + 0.056280, 0.047040, 0.058000, 0.052800, 0.085960, 0.096400, 0.085960, 0.096400, 0.122800, 0.156650, 0.199550, 0.204850, 0.199550, 0.204850, 0.248400, 0.199550, + 0.204850, 0.248400, 0.086800, 0.056280, 0.047040, 0.058000, 0.052800, 0.122800, 0.096400, 0.085960, 0.096400, 0.122800, 0.156650, 0.199550, 0.204850, 0.175950, + 0.199550, 0.204850, 0.248400, 0.199550, 0.204850, 0.248400, 0.086800, 0.056280, 0.067200, 0.058000, 0.052800, 0.122800, 0.096400, 0.122800, 0.096400, 0.122800, + 0.156650, 0.175950, 0.199550, 0.204850, 0.175950, 0.199550, 0.204850, 0.248400, 0.260950, 0.204850, 0.248400, 0.086800, 0.080400, 0.067200, 0.058000, 0.052800, + 0.122800, 0.156650, 0.122800, 0.096400, 0.134550, 0.122800, 0.156650, 0.175950, 0.199550, 0.204850, 0.175950, 0.260950, 0.204850, 0.248400, 0.260950, 0.204850, + 0.248400, 0.086800, 0.080400, 0.067200, 0.058000, 0.052800, 0.122800, 0.156650, 0.134550, 0.122800, 0.156650, 0.134550, 0.199550, 0.156650, 0.175950, 0.199550, + 0.204850, 0.248400, 0.260950, 0.204850, 0.248400, 0.260950, 0.204850, 0.248400, 0.086800, 0.080400, 0.067200, 0.058000, 0.085800, 0.122800, 0.156650, 0.134550, + 0.122800, 0.156650, 0.134550, 0.199550, 0.156650, 0.175950, 0.199550, 0.204850, 0.248400, 0.260950, 0.204850, 0.248400, 0.260950, 0.289200, 0.248400, 0.228000, + 0.086800, 0.080400, 0.067200, 0.094250, 0.085800, 0.122800, 0.156650, 0.134550, 0.122800, 0.156650, 0.134550, 0.199550, 0.204850, 0.175950, 0.199550, 0.204850, + 0.248400, 0.260950, 0.204850, 0.248400, 0.228000, 0.260950, 0.204850, 0.248400, 0.228000, 0.086800, 0.080400, 0.067200, 0.094250, 0.085800, 0.122800, 0.156650, + 0.175950, 0.122800, 0.156650, 0.175950, 0.199550, 0.204850, 0.175950, 0.199550, 0.204850, 0.175950, 0.228000, 0.260950, 0.204850, 0.248400, 0.228000, 0.260950, + 0.204850, 0.248400, 0.228000, 0.124000, 0.080400, 0.067200, 0.094250, 0.085800, 0.122800, 0.156650, 0.175950, 0.122800, 0.156650, 0.175950, 0.199550, 0.204850, + 0.175950, 0.161500, 0.199550, 0.204850, 0.248400, 0.228000, 0.260950, 0.204850, 0.248400, 0.228000, 0.260950, 0.289200, 0.248400, 0.228000, 0.124000, 0.080400, + 0.067200, 0.094250, 0.085800, 0.199550, 0.156650, 0.175950, 0.122800, 0.156650, 0.175950, 0.161500, 0.199550, 0.204850, 0.175950, 0.161500, 0.199550, 0.204850, + 0.248400, 0.228000, 0.260950, 0.289200, 0.248400, 0.228000, 0.260950, 0.289200, 0.248400, 0.228000, 0.124000, 0.080400, 0.067200, 0.094250, 0.085800, 0.199550, + 0.156650, 0.175950, 0.161500, 0.199550, 0.156650, 0.175950, 0.161500, 0.199550, 0.204850, 0.175950, 0.228000, 0.199550, 0.204850, 0.248400, 0.228000, 0.260950, + 0.289200, 0.248400, 0.228000, 0.260950, 0.289200, 0.248400, 0.228000, 0.124000, 0.080400, 0.109200, 0.094250, 0.085800, 0.199550, 0.156650, 0.175950, 0.161500, + 0.199550, 0.156650, 0.175950, 0.161500, 0.199550, 0.204850, 0.175950, 0.228000, 0.260950, 0.204850, 0.248400, 0.228000, 0.260950, 0.289200, 0.248400, 0.228000, + 0.260950, 0.289200, 0.248400, 0.228000, 0.214800, 0.124000, 0.080400, 0.109200, 0.094250, 0.085800, 0.199550, 0.156650, 0.175950, 0.161500, 0.199550, 0.156650, + 0.175950, 0.161500, 0.199550, 0.204850, 0.175950, 0.228000, 0.260950, 0.204850, 0.248400, 0.228000, 0.260950, 0.289200, 0.248400, 0.228000, 0.214800, 0.260950, + 0.289200, 0.248400, 0.228000, 0.000000, 0.124000, 0.130650, 0.109200, 0.094250, 0.085800, 0.199550, 0.156650, 0.175950, 0.161500, 0.199550, 0.156650, 0.175950, + 0.161500, 0.199550, 0.204850, 0.248400, 0.228000, 0.260950, 0.204850, 0.248400, 0.228000, 0.214800, 0.260950, 0.289200, 0.248400, 0.228000, 0.214800, 0.260950, + 0.289200, 0.248400, 0.228000, 0.214800, 0.124000, 0.130650, 0.109200, 0.094250, 0.085800, 0.199550, 0.204850, 0.175950, 0.161500, 0.199550, 0.204850, 0.175950, + 0.161500, 0.199550, 0.204850, 0.175950, 0.228000, 0.214800, 0.260950, 0.204850, 0.248400, 0.228000, 0.214800, 0.260950, 0.289200, 0.248400, 0.228000, 0.214800, + 0.260950, 0.289200, 0.248400, 0.228000, 0.000000, 0.124000, 0.130650, 0.109200, 0.094250, 0.085800, 0.199550, 0.204850, 0.175950, 0.161500, 0.199550, 0.204850, + 0.175950, 0.161500, 0.152150, 0.199550, 0.204850, 0.248400, 0.228000, 0.214800, 0.260950, 0.204850, 0.248400, 0.228000, 0.214800, 0.260950, 0.289200, 0.248400, + 0.228000, 0.000000, 0.260950, 0.289200, 0.248400, 0.228000, 0.000000, 0.124000, 0.130650, 0.109200, 0.094250, 0.085800, 0.199550, 0.204850, 0.175950, 0.161500, + 0.214800, 0.199550, 0.204850, 0.175950, 0.161500, 0.214800, 0.199550, 0.204850, 0.248400, 0.228000, 0.214800, 0.260950, 0.204850, 0.248400, 0.228000, 0.214800, + 0.260950, 0.289200, 0.248400, 0.228000, 0.000000, 0.260950, 0.289200, 0.248400, 0.228000, 0.000000, 0.124000, 0.130650, 0.109200, 0.094250, 0.112200, 0.199550, + 0.204850, 0.175950, 0.161500, 0.214800, 0.199550, 0.204850, 0.175950, 0.161500, 0.152150, 0.199550, 0.204850, 0.248400, 0.228000, 0.214800, 0.260950, 0.289200, + 0.248400, 0.228000, 0.214800, 0.260950, 0.289200, 0.248400, 0.228000, 0.000000, 0.260950, 0.289200, 0.248400, 0.228000, 0.214800, 0.000000, 0.124000, 0.130650, + 0.109200, 0.094250, 0.112200, 0.199550, 0.204850, 0.175950, 0.161500, 0.214800, 0.199550, 0.204850, 0.175950, 0.161500, 0.214800, 0.199550, 0.204850, 0.248400, + 0.228000, 0.214800, 0.260950, 0.289200, 0.248400, 0.228000, 0.214800, 0.260950, 0.289200, 0.248400, 0.228000, 0.214800, 0.000000, 0.260950, 0.289200, 0.248400, + 0.228000, 0.214800, 0.000000, 0.124000, 0.130650, 0.109200, 0.094250, 0.112200, 0.199550, 0.204850, 0.175950, 0.161500, 0.214800, 0.199550, 0.204850, 0.175950, + 0.161500, 0.214800, 0.199550, 0.204850, 0.248400, 0.228000, 0.214800, 0.260950, 0.204850, 0.248400, 0.228000, 0.214800, 0.000000, 0.260950, 0.289200, 0.248400, + 0.228000, 0.214800, 0.000000, 0.260950, 0.289200, 0.248400, 0.228000, 0.000000, 0.000000, 0.124000, 0.130650, 0.109200, 0.094250, 0.112200, 0.199550, 0.204850, + 0.175950, 0.161500, 0.214800, 0.199550, 0.204850, 0.175950, 0.228000, 0.214800, 0.199550, 0.204850, 0.248400, 0.228000, 0.214800, 0.207600, 0.260950, 0.204850, + 0.248400, 0.228000, 0.214800, 0.000000, 0.260950, 0.289200, 0.248400, 0.228000, 0.214800, 0.000000, 0.260950, 0.289200, 0.248400, 0.228000, 0.000000, 0.000000, + 0.124000, 0.130650, 0.109200, 0.123250, 0.112200, 0.199550, 0.204850, 0.175950, 0.228000, 0.214800, 0.199550, 0.204850, 0.175950, 0.161500, 0.214800, 0.207600, + 0.199550, 0.204850, 0.248400, 0.228000, 0.214800, 0.207600, 0.260950, 0.204850, 0.248400, 0.228000, 0.214800, 0.000000, 0.260950, 0.289200, 0.248400, 0.228000, + 0.214800, 0.000000, 0.260950, 0.289200, 0.248400, 0.228000, 0.000000, 0.000000, 0.124000, 0.130650, 0.109200, 0.123250, 0.112200, 0.199550, 0.204850, 0.175950, + 0.161500, 0.214800, 0.207600, 0.199550, 0.204850, 0.175950, 0.161500, 0.214800, 0.207600, 0.260950, 0.204850, 0.248400, 0.228000, 0.214800, 0.207600, 0.260950, + 0.204850, 0.248400, 0.228000, 0.214800, 0.000000, 0.260950, 0.289200, 0.248400, 0.228000, 0.000000, 0.000000, 0.260950, 0.289200, 0.248400, 0.228000, 0.000000, + 0.000000, 0.124000, 0.130650, 0.109200, 0.123250, 0.112200, 0.199550, 0.204850, 0.175950, 0.161500, 0.214800, 0.207600, 0.199550, 0.204850, 0.175950, 0.161500, + 0.214800, 0.207600, 0.260950, 0.204850, 0.248400, 0.228000, 0.214800, 0.207600, 0.260950, 0.289200, 0.248400, 0.228000, 0.214800, 0.000000, 0.260950, 0.289200, + 0.248400, 0.228000, 0.000000, 0.000000, 0.260950, 0.289200, 0.248400, 0.228000, 0.214800, 0.000000, 0.000000, 0.124000, 0.130650, 0.109200, 0.123250, 0.112200, + 0.199550, 0.204850, 0.175950, 0.228000, 0.214800, 0.207600, 0.199550, 0.204850, 0.175950, 0.161500, 0.214800, 0.207600, 0.260950, 0.204850, 0.248400, 0.228000, + 0.214800, 0.207600, 0.260950, 0.289200, 0.248400, 0.228000, 0.214800, 0.000000, 0.260950, 0.289200, 0.248400, 0.228000, 0.214800, 0.000000, 0.000000, 0.260950, + 0.289200, 0.248400, 0.228000, 0.214800, 0.000000, 0.000000, 0.124000, 0.130650, 0.109200, 0.123250, 0.112200, 0.199550, 0.204850, 0.175950, 0.228000, 0.214800, + 0.207600, 0.199550, 0.204850, 0.175950, 0.228000, 0.214800, 0.207600, 0.260950, 0.204850, 0.248400, 0.228000, 0.214800, 0.207600, 0.260950, 0.204850, 0.248400, + 0.228000, 0.214800, 0.000000, 0.000000, 0.260950, 0.289200, 0.248400, 0.228000, 0.214800, 0.000000, 0.000000, 0.260950, 0.289200, 0.248400, 0.228000, 0.214800, + 0.000000, 0.000000, 0.201500, 0.130650, 0.109200, 0.123250, 0.112200, 0.199550, 0.204850, 0.175950, 0.228000, 0.214800, 0.207600, 0.199550, 0.204850, 0.175950, + 0.228000, 0.214800, 0.207600, 0.260950, 0.204850, 0.248400, 0.228000, 0.214800, 0.207600, 0.198000, 0.260950, 0.204850, 0.248400, 0.228000, 0.214800, 0.000000, + 0.000000, 0.260950, 0.289200, 0.248400, 0.228000, 0.214800, 0.000000, 0.000000, 0.260950, 0.289200, 0.248400, 0.228000, 0.214800, 0.000000, 0.000000, 0.201500, + 0.130650, 0.109200, 0.123250, 0.112200, 0.199550, 0.204850, 0.175950, 0.228000, 0.214800, 0.207600, 0.199550, 0.204850, 0.175950, 0.228000, 0.214800, 0.207600, + 0.198000, 0.260950, 0.204850, 0.248400, 0.228000, 0.214800, 0.207600, 0.198000, 0.260950, 0.204850, 0.248400, 0.228000, 0.214800, 0.000000, 0.000000, 0.260950, + 0.289200, 0.248400, 0.228000, 0.214800, 0.000000, 0.000000, 0.260950, 0.289200, 0.248400, 0.228000, 0.000000, 0.000000, 0.000000, 0.201500, 0.130650, 0.109200, + 0.123250, 0.112200, 0.199550, 0.204850, 0.175950, 0.228000, 0.214800, 0.207600, 0.198000, 0.199550, 0.204850, 0.175950, 0.228000, 0.214800, 0.207600, 0.198000, + 0.260950, 0.204850, 0.248400, 0.228000, 0.214800, 0.207600, 0.198000, 0.260950, 0.204850, 0.248400, 0.228000, 0.214800, 0.000000, 0.000000, 0.260950, 0.289200, + 0.248400, 0.228000, 0.000000, 0.000000, 0.000000, 0.260950, 0.289200, 0.248400, 0.228000, 0.000000, 0.000000, 0.000000, 0.201500, 0.130650, 0.109200, 0.123250, + 0.112200, 0.199550, 0.204850, 0.175950, 0.228000, 0.214800, 0.207600, 0.198000, 0.199550, 0.204850, 0.175950, 0.228000, 0.214800, 0.207600, 0.198000, 0.260950, + 0.204850, 0.248400, 0.228000, 0.214800, 0.207600, 0.000000, 0.260950, 0.204850, 0.248400, 0.228000, 0.214800, 0.000000, 0.000000, 0.260950, 0.289200, 0.248400, + 0.228000, 0.000000, 0.000000, 0.000000, 0.260950, 0.289200, 0.248400, 0.228000, 0.214800, 0.000000, 0.000000, 0.000000, 0.201500, 0.130650, 0.109200, 0.123250, + 0.112200, 0.199550, 0.204850, 0.175950, 0.228000, 0.214800, 0.207600, 0.198000, 0.199550, 0.204850, 0.175950, 0.228000, 0.214800, 0.207600, 0.198000, 0.260950, + 0.204850, 0.248400, 0.228000, 0.214800, 0.207600, 0.000000, 0.260950, 0.204850, 0.248400, 0.228000, 0.214800, 0.000000, 0.000000, 0.260950, 0.289200, 0.248400, + 0.228000, 0.214800, 0.000000, 0.000000, 0.000000, 0.260950, 0.289200, 0.248400, 0.228000, 0.000000, 0.000000, 0.000000, 0.000000, 0.201500, 0.130650, 0.109200, + 0.123250, 0.112200, 0.199550, 0.204850, 0.175950, 0.228000, 0.214800, 0.207600, 0.198000, 0.199550, 0.204850, 0.248400, 0.228000, 0.214800, 0.207600, 0.198000, + 0.260950, 0.204850, 0.248400, 0.228000, 0.214800, 0.207600, 0.000000, 0.260950, 0.204850, 0.248400, 0.228000, 0.214800, 0.000000, 0.000000, 0.000000, 0.260950, + 0.289200, 0.248400, 0.228000, 0.214800, 0.000000, 0.000000, 0.000000, 0.260950, 0.289200, 0.248400, 0.228000, 0.214800, 0.000000, 0.000000, 0.000000, 0.201500, + 0.130650, 0.142800, 0.123250, 0.112200, 0.199550, 0.204850, 0.248400, 0.228000, 0.214800, 0.207600, 0.198000, 0.199550, 0.204850, 0.175950, 0.228000, 0.214800, + 0.207600, 0.198000, 0.260950, 0.204850, 0.248400, 0.228000, 0.214800, 0.207600, 0.198000, 0.000000, 0.260950, 0.204850, 0.248400, 0.228000, 0.214800, 0.000000, + 0.000000, 0.000000, 0.260950, 0.289200, 0.248400, 0.228000, 0.214800, 0.000000, 0.000000, 0.000000, 0.260950, 0.289200, 0.248400, 0.228000, 0.214800, 0.000000, + 0.000000, 0.000000, 0.201500, 0.130650, 0.142800, 0.123250, 0.112200, 0.199550, 0.204850, 0.248400, 0.228000, 0.214800, 0.207600, 0.198000, 0.199550, 0.204850, + 0.175950, 0.228000, 0.214800, 0.207600, 0.198000, 0.204000, 0.260950, 0.204850, 0.248400, 0.228000, 0.214800, 0.207600, 0.198000, 0.000000, 0.260950, 0.204850, + 0.248400, 0.228000, 0.214800, 0.000000, 0.000000, 0.000000, 0.260950, 0.289200, 0.248400, 0.228000, 0.214800, 0.000000, 0.000000, 0.000000, 0.260950, 0.289200, + 0.248400, 0.228000, 0.000000, 0.000000, 0.000000, 0.000000, 0.201500, 0.130650, 0.142800, 0.123250, 0.112200, 0.199550, 0.204850, 0.175950, 0.228000, 0.214800, + 0.207600, 0.198000, 0.000000, 0.199550, 0.204850, 0.175950, 0.228000, 0.214800, 0.207600, 0.198000, 0.000000, 0.260950, 0.204850, 0.248400, 0.228000, 0.214800, + 0.207600, 0.198000, 0.000000, 0.260950, 0.204850, 0.248400, 0.228000, 0.214800, 0.000000, 0.000000, 0.000000, 0.260950, 0.289200, 0.248400, 0.228000, 0.214800, + 0.000000, 0.000000, 0.000000, 0.260950, 0.289200, 0.248400, 0.228000, 0.000000, 0.000000, 0.000000, 0.000000, 0.201500, 0.130650, 0.142800, 0.123250, 0.112200, + 0.199550, 0.204850, 0.175950, 0.228000, 0.214800, 0.207600, 0.198000, 0.000000, 0.199550, 0.204850, 0.175950, 0.228000, 0.214800, 0.207600, 0.198000, 0.000000, + 0.260950, 0.204850, 0.248400, 0.228000, 0.214800, 0.207600, 0.198000, 0.000000, 0.260950, 0.204850, 0.248400, 0.228000, 0.214800, 0.000000, 0.000000, 0.000000, + 0.260950, 0.289200, 0.248400, 0.228000, 0.000000, 0.000000, 0.000000, 0.000000, 0.260950, 0.289200, 0.248400, 0.228000, 0.214800, 0.000000, 0.000000, 0.000000, + 0.000000, 0.201500, 0.130650, 0.142800, 0.123250, 0.112200, 0.199550, 0.204850, 0.175950, 0.228000, 0.214800, 0.207600, 0.198000, 0.000000, 0.199550, 0.204850, + 0.175950, 0.228000, 0.214800, 0.207600, 0.198000, 0.000000, 0.260950, 0.204850, 0.248400, 0.228000, 0.214800, 0.207600, 0.198000, 0.000000, 0.260950, 0.204850, + 0.248400, 0.228000, 0.214800, 0.000000, 0.000000, 0.000000, 0.260950, 0.289200, 0.248400, 0.228000, 0.214800, 0.000000, 0.000000, 0.000000, 0.000000, 0.260950, + 0.289200, 0.248400, 0.228000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000 +}; + +static const float AnnexE[64] = { + -2.842205, -2.694235, -2.558260, -2.382850, -2.221042, -2.095574, -1.980845, -1.836058, -1.645556, -1.417658, -1.261301, -1.125631, -0.958207, -0.781591, -0.555837, -0.346976, + -0.147249, 0.027755, 0.211495, 0.388380, 0.552873, 0.737223, 0.932197, 1.139032, 1.320995, 1.483433, 1.648297, 1.801447, 1.942731, 2.118613, 2.321486, 2.504443, + 2.653909, 2.780654, 2.925355, 3.076390, 3.220825, 3.402869, 3.585096, 3.784606, 3.955521, 4.155636, 4.314009, 4.444150, 4.577542, 4.735552, 4.909493, 5.085264, + 5.254767, 5.411894, 5.568094, 5.738523, 5.919215, 6.087701, 6.280685, 6.464201, 6.647736, 6.834672, 7.022583, 7.211777, 7.471016, 7.738948, 8.124863, 8.695827 +}; + +static const float ws[211] = { + 0.000000, 0.020000, 0.040000, 0.060000, 0.080000, 0.100000, 0.120000, 0.140000, 0.160000, 0.180000, 0.200000, 0.220000, 0.240000, 0.260000, 0.280000, 0.300000, + 0.320000, 0.340000, 0.360000, 0.380000, 0.400000, 0.420000, 0.440000, 0.460000, 0.480000, 0.500000, 0.520000, 0.540000, 0.560000, 0.580000, 0.600000, 0.620000, + 0.640000, 0.660000, 0.680000, 0.700000, 0.720000, 0.740000, 0.760000, 0.780000, 0.800000, 0.820000, 0.840000, 0.860000, 0.880000, 0.900000, 0.920000, 0.940000, + 0.960000, 0.980000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, 1.000000, + 1.000000, 0.980000, 0.960000, 0.940000, 0.920000, 0.900000, 0.880000, 0.860000, 0.840000, 0.820000, 0.800000, 0.780000, 0.760000, 0.740000, 0.720000, 0.700000, + 0.680000, 0.660000, 0.640000, 0.620000, 0.600000, 0.580000, 0.560000, 0.540000, 0.520000, 0.500000, 0.480000, 0.460000, 0.440000, 0.420000, 0.400000, 0.380000, + 0.360000, 0.340000, 0.320000, 0.300000, 0.280000, 0.260000, 0.240000, 0.220000, 0.200000, 0.180000, 0.160000, 0.140000, 0.120000, 0.100000, 0.080000, 0.060000, + 0.040000, 0.020000, 0.000000 +}; + +static const float woaa[105] = { + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, + 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 0.000000, 1.040799, 1.083189, 1.127142, 1.172608, 1.219512, 1.267748, 1.317176, 1.367615, + 1.418842, 1.470588, 1.522534, 1.574307, 1.625488, 1.675603, 1.724138, 1.770538, 1.814224, 1.854599, 1.891074, 1.923077, 1.950078, 1.971609, 1.987282, 1.996805, + 2.000000, 1.996805, 1.987282, 1.971609, 1.950078, 1.923077, 1.891074, 1.854599, 1.814224, 1.770538, 1.724138, 1.675603, 1.625488, 1.574307, 1.522534, 1.470588, + 1.418842, 1.367615, 1.317176, 1.267748, 1.219512, 1.172608, 1.127142, 1.083189, 1.040799 +}; + +static const float PhzNz[57] = { + 0.000000, 3.002978, -0.385743, -1.804058, 0.708389, 3.080091, 0.234237, -2.601564, 2.564900, 0.101063, -0.241570, -2.283176, 0.460491, -1.611275, 2.258339, -2.055267, + 1.733923, 2.517236, -1.766211, 0.897032, -2.360999, -0.280836, -2.714514, 2.100092, 2.300326, -1.158767, -2.044268, -2.668387, -2.578737, 0.185036, 1.551429, 2.726814, + 2.655614, 3.046857, 0.834348, -0.513595, 1.466037, 0.691121, 0.127319, -2.034924, -1.070655, 0.456588, -2.278682, 1.229021, -2.139595, -0.119750, -0.301534, 0.029391, + 0.068775, 0.520336, 2.339119, -0.808328, 1.332154, 2.929768, -0.338316, 0.022767, -1.063795 +}; + +static const float Ui[129] = { + 460.246094, 90.698601, -140.362900, 3.415093, 99.369812, 445.443207, 522.042786, 252.818405, 125.521202, -119.443199, -342.607910, -393.066895, -494.564301, -284.859009, 351.480896, 660.536377, + 149.394104, -654.466980, -845.040527, -496.079102, -155.383499, 313.371399, 370.925110, -207.061905, -49.371632, 355.883392, -295.865509, -950.418823, -646.136597, 154.876801, 475.990295, 251.149902, + 275.690796, 176.195206, 39.321491, 323.984711, 3.765467, -740.295471, -684.010681, 22.967060, 532.828186, 327.829803, -17.576559, 36.373402, -144.939194, -400.725189, 59.048889, 408.261597, + -3.164414, -207.470093, -76.218567, -8.249402, 56.827209, -221.976196, -346.998199, -139.244995, -582.422485, -1028.400024, -727.781982, -406.098907, -191.811295, 41.401581, -151.480103, -641.985779, + -607.550781, -400.055786, -678.727417, -376.449890, 434.718109, 239.750504, -470.508392, -552.972717, -148.247299, 153.369507, 113.672798, 29.017599, 31.270840, -13.290440, -250.178604, -504.166809, + -8.738471, 669.869019, 43.365711, -669.164429, -29.603149, 114.396599, -495.633301, -105.838203, 90.404091, -299.971100, 154.039200, 380.408691, 111.480400, 158.179993, -205.268204, -386.008087, + -62.792370, -327.508087, -488.555298, 15.982190, 264.942902, 171.169998, 112.966904, -209.006302, -364.411591, 367.667999, 417.925293, -867.776184, -1286.915039, -779.282288, -557.706482, -184.866501, + 189.383804, 140.763107, 143.058304, 522.142395, 586.625122, -52.709290, 46.055168, 955.700806, 807.637085, -213.939499, -450.946411, 209.997101, 114.041298, -608.001221, -67.676140, 800.976929, + 918.058594 +}; + +static const float Uq[129] = { + 0.000000, 15.557470, -141.517395, 4.850000, 20.818390, -31.850750, 240.388107, 359.115509, 353.314514, -34.321480, -683.943787, -426.828705, 251.196106, 648.932800, 583.257080, -272.161804, + -696.480774, -616.009888, -730.197388, -275.599213, -71.369781, -246.298599, 353.591187, 383.542999, -457.883911, -573.009827, 123.842796, 808.834473, 590.295227, -116.924400, 4.462234, 300.142792, + -398.965790, -1374.654053, -1271.543945, -306.073090, 175.326508, 330.696106, 640.043701, 308.004608, -163.072403, 10.378300, -113.961601, -623.374390, -714.512207, -384.877991, 71.181877, 261.299896, + 129.764801, -8.331214, -68.725418, 88.997963, 276.388611, -133.622498, -673.724915, -355.871704, -137.479996, -829.466675, -936.803223, -471.582794, -615.728271, -670.887085, -713.287109, -1046.473022, + -679.554688, -198.067902, -328.069305, -487.968994, -368.145203, 482.697296, 1213.579956, 528.013977, -148.013107, 88.007896, 349.561005, 483.642792, -11.267410, -765.563721, -95.221008, 1021.109985, + 810.747620, 291.417908, 516.477783, 771.458984, 430.919586, -105.049500, -259.056702, -412.976807, -776.695312, -506.850098, -208.051407, -624.956421, -280.915710, 302.574402, -349.600403, -520.683228, + 278.127899, 446.518799, 21.136551, -178.466400, 262.635498, 683.496704, 448.290802, 360.132202, 334.482605, -306.716003, -777.159912, -433.828796, 88.513657, 278.588989, 94.746696, -541.088989, + -645.232483, 321.504211, 801.454773, 511.169189, 164.987106, -538.676819, -971.696228, -735.475586, -533.916626, -355.275909, -234.147903, -468.023285, -691.458313, -533.001770, -291.729004, -199.716904, + 0.000000 +}; + +software_imbe_decoder::software_imbe_decoder() +{ + int i,j; + //initialize + Old = 1; New = 0; + psi1 = 0.0; + for(i=0; i < 58; i++) { + for(j=0; j < 2; j++) { + log2Mu[i][j] = 0.0; + } + } + for(i=0; i < 57; i++) { + for(j=0; j < 2; j++) { + phi[i][j] = 0.0; + } + } + for(i=0; i < 256; i++) { + Olduw[i] = 0.0; + } +} + +software_imbe_decoder::~software_imbe_decoder() +{ +} + +void +software_imbe_decoder::decode(const voice_codeword& cw) +{ + // process input 144-bit IMBE frame - converts to 88-bit frame + unsigned int u0 = 0; + unsigned int u1,u2,u3,u4,u5,u6,u7; + unsigned int E0 = 0; + unsigned int ET = 0; + unsigned char O[12]; + + // PN/Hamming/Golay - etc. + imbe_header_decode(cw, u0, u1, u2, u3, u4, u5, u6, u7, E0, ET) ; + + //replace the sync bit(LSB of u7) with the BOT flag + u7 = u7 | 0x01; //ECC procedure called above always returns u7 LSB = 0 + + O[0] = (((u0 / 16) & 240) + (u1 / 256)); + O[1] = (((u2 / 16) & 240) + (u3 / 256)); + O[2] = (((u4 / 8) & 224) + ((u5 / 64) & 28) + (u6 / 512)); + O[3] = (((u6 / 2) & 128) + u7); + O[4] = (u0 & 255); + O[5] = (u1 & 255); + O[6] = (u2 & 255); + O[7] = (u3 & 255); + O[8] = (u4 & 255); + O[9] = (u5 & 255); + O[10] = (u6 & 255); + O[11] = E0 + 4 * ET; + + decode_audio(O); // process 88-bit frame +} + +void +software_imbe_decoder::adaptive_smoothing(float SE, float ER, float ET) +{ + float VM; + float YM; + int ell; + + if(ER <= .005 && ET <= 4) { + VM = 1E+38; //infinity + } else if( ER <= .0125 && ET == 0) { //(guessing typo in std) + VM = 45.255 * powf(SE, .375) / exp(277.6 * ER); + } else { + VM = 1.414 * powf(SE, .375); + } + + float AM = 0; + for(ell = 1; ell <= L; ell++) { + if(M[ell][ New] > VM) vee[ell][ New] = 1; //CAUTION: + AM = AM + M[ell][ New]; //smoothed vee(ell) replaces unsmoothed! + } + + float TM = (ER <= .005 && ET <= 6) ? 20480 : 6000 - 300 * ET; // + TM; /* ToDo: uninitialized! */ + if(TM <= AM) { + YM = TM / AM; + for(ell = 1; ell <= L; ell++) { + M[ell][ New] = M[ell][New] * YM; + } + } +} + +void +software_imbe_decoder::fft(float REX[], float IMX[]) +{ + int I; + int J; + int K; + int H; + int KpH; + int Ht2; + float tmp_f; + float l_Ui, l_Uq, Theta, Si, Sq, Ti, Xi, Tq, Xq; + + J = 64; + for(I = 1; I <= 126; I++) { +#define SWAP(x,y) tmp_f=x;x=y;y=tmp_f + if(I < J) { SWAP(REX[J], REX[I]); SWAP(IMX[J], IMX[I]); } +#undef SWAP + K = 64; + while(K <= J) { J = J - K; K = K / 2; } + J = J + K; + } + + H = 1; + for(I = 1; I <= 7; I++) { + Ht2 = H * 2; l_Ui = 1; l_Uq = 0; + Theta = M_PI / H; Si = cos(Theta); Sq = -sin(Theta); + for(J = 1; J <= H; J++) { + for(K = J - 1; K <= 127; K+=Ht2) { + KpH = K + H; + + Ti = REX[KpH] * l_Ui - IMX[KpH] * l_Uq; Xi = REX[K]; + Tq = REX[KpH] * l_Uq + IMX[KpH] * l_Ui; Xq = IMX[K]; + + REX[KpH] = Xi - Ti; REX[K] = Xi + Ti; + IMX[KpH] = Xq - Tq; IMX[K] = Xq + Tq; + } + Ti = l_Ui; + l_Ui = Ti * Si - l_Uq * Sq; + l_Uq = Ti * Sq + l_Uq * Si; + } + H = Ht2; + } + +} + +void +software_imbe_decoder::decode_audio(uint8_t *A) +{ + uint32_t u0, u1, u2, u3, u4, u5, u6, u7, E0, ET; + int K; + int en, tmp_f; + float SE = 0, ER = 0; + + imbe_frame_unpack(A, u0, u1, u2, u3, u4, u5, u6, u7, E0, ET); + + ER = .95 * ER + .000365 * ET; + if( ER > .0875) { + // Huh?! + } else if(u0 >= 3328 || E0 >= 2 || ET >=(10 + 40 * ER)) { + // Whuh?! + } else { + K = rearrange(u0, u1, u2, u3, u4, u5, u6, u7); // re-arrange the bits from u to b (ToDo: make 'b' return value ???) + decode_vuv(K); + + int Len3, Start3, Len8, Start8; + Len3 = L - 1; + Start3 =((Len3 * (Len3 - 1)) / 2) - 28; + Len8 = L - 6; + Start8 =((Len8 * (Len8 - 1)) / 2) - 3; + + decode_spectral_amplitudes(Start3, Start8); + enhance_spectral_amplitudes(SE); + adaptive_smoothing(SE, ER, ET); + + // (8000 samp/sec) * (1 sec / 50 compressed voice frames) = 160 samples/frame + + //synth: + synth_unvoiced();// ToDo: make suv return value? + synth_voiced(); // ToDo: make sv return value? + + //output: + audio_samples *samples = audio(); + for(en = 0; en <= 159; en++) { + // The unvoiced samples are loud and the voiced are low...I don't know why. + // Most of the difference is compensated by removing the 146.6433 factor + // in the synth_unvoiced procedure. The final tweak is done by raising the + // voiced samples: + float sample = suv[en] + sv[en] * 4; //balance v/uv loudness +// if(abs((int)sample) > 32767) { +// sample = 32767 * (sample < 0) ? -1 : 1; // * sgn(sample) +// } + sample /= 16384.0; /* 32768.0 - but audio amplitude is not full range of int16 */ + samples->push_back(sample); + } + } + OldL = L; + Oldw0 = w0; + tmp_f = Old; Old = New; New = tmp_f; +} + +void +software_imbe_decoder::decode_spectral_amplitudes(int Start3, int Start8) +{ + float G[7]; //Can we use C(1 to 6,1) for this? + int J[7]; + float C[7][ 11] ; + float T[57]; + + float Tmp ; + float Tk ; + float TD; + float Tp ; + + int P3, P8, eye, jay, kay, ell, em, iTk; + + P3 = Start3; P8 = Start8; + + G[1] = AnnexE[bee[2]]; + + for(eye = 2; eye <= 6; eye++) { + G[eye] = StepSize[P3] *(bee[eye + 1] - powf(2 ,(BitCount[P3] - 1)) + .5); + P3 = P3 + 1; + } + + for(eye = 1; eye <= 6; eye++) { + Tmp = G[1]; + for(em = 2; em <= 6; em++) { + Tmp = Tmp + 2 * G[em] * cos(M_PI *(em - 1) *(eye - .5) / 6); + } + //R(eye) = Tmp + C[eye][1] = Tmp; + } + + ell = 8; + for(eye = 1; eye <= 6; eye++) { + J[eye] =(L + eye - 1) / 6; //Prediction Residual Block Length + // FOR kay = 2 TO J(eye) + for(kay = 2; kay <= J[eye]; kay++) { + C[eye][ kay] = StepSize[P3] *(bee[ell] - powf(2 ,(BitCount[P3] - 1)) + .5); + P3 = P3 + 1; P8 = P8 + 1; ell = ell + 1; + } + } + + ell = 0; + for(eye = 1; eye <= 6; eye++) { + for(jay = 1; jay <= J[eye]; jay++) { + Tmp = C[eye][ 1]; + // FOR kay = 2 TO J(eye) + for(kay = 2; kay <= J[eye]; kay++) { + Tmp = Tmp + 2 * C[eye][ kay] * cos(M_PI *(kay - 1) *(jay - .5) / J[eye]); + } + ell = ell + 1; T[ell] = Tmp; + } + } + if(ell != L) exit(1); + + // ******* + // we have the residuals in T(ell); now to sum with the predictions + // ******* + + // first, set up the assumptions about the previous frame values + // Note: L means L(0); OldL means L(-1) + if(OldL == 0) { OldL = 30; for( ell = 0; ell <= 57; ell++) { log2Mu[ell][ Old] = 1; } } + for(ell = OldL + 1; ell <= L + 1; ell++) { log2Mu[ell][ Old] = log2Mu[OldL][ Old]; } + + // make the predictions and sum with T(ell) + if(L <= 15) + Tp = .4; + else if(L <= 24) + Tp = .03 * L - .05; + else + Tp = .7; + + Tmp = 0; + for(ell = 1; ell <= L; ell++) { + Tk =((float)OldL /(float)L) *(float)ell; + iTk =(int) Tk; + TD = Tk - iTk; + // temporarily use Mu(ell, New) as temp + Mu[ell][ New] = Tp *((1 - TD) * log2Mu[iTk][ Old] + TD * log2Mu[iTk + 1][ Old]); + Tmp = Tmp + Mu[ell][ New]; + } + Tmp = Tmp / L; + for(ell = 1; ell <= L; ell++) { + log2Mu[ell][ New] = T[ell] + Mu[ell][ New] - Tmp; + // Mu(ell, New) no longer temp + Mu[ell][ New] = powf(2 ,log2Mu[ell][ New]); + } +} + +void +software_imbe_decoder::decode_vuv(int K) +{ + int bee1, ell, kay; + bee1 = bee[1]; + for(ell = 1; ell <= L; ell++) { + if(ell <= 36) + kay =(ell + 2) / 3; + else + kay = 12; + + //vee(ell, New) = (bee1 \(2 ^(K - kay))) - 2 *(bee1 \(2 ^(K + 1 - kay))) + vee[ell][ New] = ((bee1 & (1 << (K - kay))) > 0) ? 1 : 0; + } +} + +void +software_imbe_decoder::enhance_spectral_amplitudes(float& SE) +{ + float RM0; + float RM1; + float Tmp; + float K1; + float K2; + float K3; + float W; + int ell; + + RM0 = 0; RM1 = 0; + for(ell = 1; ell <= L; ell++) { + Tmp = powf(Mu[ell][ New] , 2); + RM0 = RM0 + Tmp; + RM1 = RM1 + Tmp * cos(w0 * ell); + } + + K1 = .96 * M_PI /(w0 * RM0 *(powf(RM0 , 2) - powf(RM1 , 2))); + K2 = powf(RM0 , 2) + powf(RM1 , 2); + K3 = 2 * RM0 * RM1; + + Tmp = 0; + for(ell = 1; ell <= L; ell++) { + W = sqrt(Mu[ell][ New]) * powf((K1 *(K2 - K3 * cos(w0 * ell))) , .25); + if((8 * ell) <= L) + M[ell][ New] = Mu[ell][ New]; + else if(W > 1.2) + M[ell][ New] = Mu[ell][ New] * 1.2; + else if(W < .5) + M[ell][ New] = Mu[ell][ New] * .5; + else + M[ell][ New] = Mu[ell][ New] * W; + Tmp = Tmp + powf(M[ell][ New] , 2); + } + + Tmp = sqrt(RM0 / Tmp); + + for(ell = 1; ell <= L; ell++) { + M[ell][ New] = M[ell][ New] * Tmp; + } + + // update SE + SE = .95 * SE + .05 * RM0; if(SE < 10000) SE = 10000; + +} + +void +software_imbe_decoder::ifft(float FDi[], float FDq[], float TD[]) // ToDo: replace "real IFFT" with fftw3 IFFT proc! +{ + //Inverse FFT: + // transform 129-point freq domain(FDx) to 256-point time domain(TD) + + float Ai[128]; + float Aq[128]; + + int I; + int J; + int K; + int H; + float l_Ui, l_Uq, Si, Sq, Ti, Tq, Xi, Xq; + + for(I = 0; I <= 63; I++) { + J = I + 64; //64 to 127 + K = I * 2; //0 to 126(step 2) + H = 128 - K; //128 to 2(step 2) + Ai[I] = FDi[K] + FDq[K]; + Aq[I] = FDi[K + 1] + FDq[K + 1]; + Ai[J] = FDi[H] - FDq[H]; + Aq[J] = FDi[H - 1] - FDq[H - 1]; + } + + fft(Ai, Aq); + + for(I = 1; I <= 63; I++) { + J = 128 - I; //127 to 65 + K = I + 128; //129 to 191 + H = J + 128; //255 to 193 + FDi[K] = (Aq[I] + Aq[J]) / 2; + FDi[H] = FDi[K] ; //a + FDq[K] = -(Ai[I] - Ai[J]) / 2; + FDq[H] = -FDq[K] ; //b + FDi[I] = (Ai[I] + Ai[J]) / 2; + FDi[J] = FDi[I] ; //c + FDq[I] = (Aq[I] - Aq[J]) / 2; + FDq[J] = -FDq[I] ; //d + } + + // I,J=64 K,H=192 + FDi[192] = Aq[64]; //a + FDq[192] = 0 ; //b + FDi[64] = Ai[64] ; //c (new) + FDq[64] = 0 ; //d + + //I=0 J,K=128 H=256 ( Ax(128) wraps to Ax(0)) + FDi[128] = Aq[0] ; //a + FDq[128] = 0 ; //b + FDi[0] = Ai[0] ; //c (new) + FDq[0] = 0 ; //d + + l_Ui = 1; l_Uq = 0; + Si = cos(M_PI / 128); Sq = -sin(M_PI / 128); + for(I = 0; I <= 127; I++) { + J = I + 128 ; //128 TO 255 + + Ti = FDi[J] * l_Ui - FDq[J] * l_Uq; Xi = FDi[I]; + Tq = FDi[J] * l_Uq + FDq[J] * l_Ui; Xq = FDq[I]; + + + TD[I + 128] =((Xi + Ti) -(Xq + Tq)); + TD[I ] =((Xi - Ti) -(Xq - Tq)); + + Ti = l_Ui; + l_Ui = Ti * Si - l_Uq * Sq; + l_Uq = Ti * Sq + l_Uq * Si; + } +} + +uint16_t +software_imbe_decoder::rearrange(uint32_t u0, uint32_t u1, uint32_t u2, uint32_t u3, uint32_t u4, uint32_t u5, uint32_t u6, uint32_t u7) +{ + int K; + int I, ubit, Seq, col; + + bee[0] =((u0 / 16) & 0xfc) |((u7 / 2) & 3); + + w0 = 4 * M_PI /(bee[0] + 39.5); + + L =(int)(.9254 * floorf((M_PI / w0) + .25)); if(L < 9 || L > 56) exit(2); + + if( L > 36) { + K = 12; + } else { + K =((L + 2) / 3); + if(K > 12) + exit(3); + } + + for(I = 1; I <= L + 1; I++) { bee[I] = 0; } + + bee[2] =(u0 & 56) |((u7 / 8) & 1); + + + Seq =(L - 9) * 75; + + ubit = 4; + for(I = 0; I <= 2; I++) { + if( u0 & ubit) { + col = BMTn[Seq]; + bee[col] = bee[col] + BMTb[Seq]; + } + Seq = Seq + 1; + ubit = ubit / 2; + } + + ubit = 2048; + for(I = 0; I <= 11; I++) { + if(u1 & ubit){ + col = BMTn[Seq]; + bee[col] = bee[col] + BMTb[Seq]; + } + Seq = Seq + 1; ubit = ubit / 2; + } + + ubit = 2048; + for(I = 0; I <= 11; I++) { + if(u2 & ubit){ + col = BMTn[Seq]; + bee[col] = bee[col] + BMTb[Seq]; + } + Seq = Seq + 1; + ubit = ubit / 2; + } + + ubit = 2048; + for(I = 0; I <= 11; I++) { + if(u3 & ubit) { + col = BMTn[Seq]; + bee[col] = bee[col] + BMTb[Seq]; + } + Seq = Seq + 1; + ubit = ubit / 2; + } + + ubit = 1024; + for(I = 0; I <= 10; I++) { + if(u4 & ubit) { + col = BMTn[Seq]; + bee[col] = bee[col] + BMTb[Seq]; + } + Seq = Seq + 1; + ubit = ubit / 2; + } + + ubit = 1024; + for(I = 0; I <= 10; I++) { + if(u5 & ubit) { + col = BMTn[Seq]; + bee[col] = bee[col] + BMTb[Seq]; + } + Seq = Seq + 1; + ubit = ubit / 2; + } + + ubit = 1024; + for(I = 0; I <= 10; I++) { + if(u6 & ubit){ + col = BMTn[Seq]; + bee[col] = bee[col] + BMTb[Seq]; + } + Seq = Seq + 1; + ubit = ubit / 2; + } + + ubit = 64; + for(I = 4; I <= 6; I++) { + if(u7 & ubit) { + col = BMTn[Seq]; + bee[col] = bee[col] + BMTb[Seq]; + } + Seq = Seq + 1; + ubit = ubit / 2; + } + + return K; +} + +void +software_imbe_decoder::synth_unvoiced() +{ + float Uwi[256]; + float Uwq[256]; + float uw[256]; + + float Tmp; + + int ell, bl, em, al, en; + + ell = 0; bl =(int) ceilf(128 / M_PI *(ell + .5) * w0); + for(em = 0; em <= bl - 1; em++) { + Uwi[em] = 0; Uwq[em] = 0; + } + + Luv = 0; + for(ell = 1; ell <= L; ell++) { + al = bl; bl =(int) ceilf(128 / M_PI * (ell + .5) * w0); + if(vee[ell][New]) { + // FOR em = al TO bl - 1 + for(em = al; em <= bl - 1; em++) { + Uwi[em] = 0; Uwq[em] = 0; + } + } else { + Luv = Luv + 1; + //precompute Tmp = + Tmp = 0; + // FOR en = al TO bl - 1 + for(en = al; en <= bl - 1; en++) { + Tmp += powf(Ui[en], 2) + pow(Uq[en], 2); + } + Tmp = M[ell][New] / sqrt(Tmp /(bl - al)); //too loud with 146.6433 factor + //now do the rest of b.h.e. + for(em = al; em <= bl - 1; em++) { + Uwi[em] =(Ui[em]) * Tmp; + Uwq[em] =(Uq[em]) * Tmp; + } + } + } + // finally do over-freq + // FOR em = bl TO 128 + for(em = bl; em <= 128; em++) { + Uwi[em] = 0; Uwq[em] = 0; + } + + ifft(Uwi, Uwq, uw); + + // ws(n)*uw(n,-1) + ws(n-159)*uw(n-159,0) uw(-128 to 127) + //suv(n) = -------------------------------------- + // (ws(n)^2) +(ws(n-159)^2) ws(-105 to 105) + + for(en = 0; en <= 55; en++) { + suv[en] = Olduw[en+128]; + } + for(en = 56; en <= 104; en++) { + suv[en] =(ws[en+105] * Olduw[en+128] + ws[en - 55] * uw[en - 32]) * woaa[en]; + } + for(en = 105; en <= 159; en++) { + suv[en] = uw[en - 32]; + } + + for(en = -128; en <= 127; en++) { + Olduw[en+128] = uw[en+128]; + } +} + +void +software_imbe_decoder::synth_voiced() +{ + float MaxL; + float Tmp; + float Dpl; + float Dwl; + float THa; + float THb; + float MNew; + float MOld; + float Mb; + + int ell, en; + + if( L > OldL) { + MaxL = L; + } else { + MaxL = OldL; + } + + psi1 = psi1 +(Oldw0 + w0) * 80; + psi1 = remainderf(psi1, 2 * M_PI); // ToDo: decide if its 2pi or pi^2 + + for(ell = 1; ell <= L/4; ell++) { + phi[ell][ New] = psi1 * ell; + } + Tmp = Luv / L; + for(; ell <= MaxL; ell++) { + phi[ell][ New] = psi1 * ell + Tmp * PhzNz[ell]; + } + + for(en = 0; en <= 159; en++) { + sv[en] = 0; + } + + for(ell = 1; ell <= MaxL; ell++) { + + if(ell > L) { + MNew = 0; + } else { + MNew = M[ell][ New]; + } + + if(ell > OldL) { + MOld = 0; + } else { + MOld = M[ell][ Old]; + } + + if(vee[ell][ New]) { + if ( vee[ell][ Old]) { + if(ell < 8 && fabsf(w0 - Oldw0) < .1 * w0) { // (fine transition) + const double PI_SQUARED = M_PI * M_PI; + const double INV_PI_SQUARED = 1.0 / PI_SQUARED; + Dpl = phi[ell][ New] - phi[ell][ Old] -(Oldw0 + w0) * ell * 80; + Dwl = .00625 * (Dpl - PI_SQUARED * floorf((Dpl + M_PI) * INV_PI_SQUARED)); + THa = (Oldw0 * (float)ell + Dwl); + THb = (w0 - Oldw0) * ell * .003125; + Mb = .00625 *(MNew - MOld); + for(en = 0; en <= 159; en++) { + sv[en] = sv[en] +(MOld + en * Mb) * cos(phi[ell][ Old] +(THa + THb * en) * en); + } + } else { // (coarse transition) + for(en = 0; en <= 55; en++) { + sv[en] = sv[en] + ws[en+105] * MOld * cos(Oldw0 * en * ell + phi[ell] [ Old]); + } + for(en = 56; en <= 105; en++) { + sv[en] = sv[en] + ws[en+105] * MOld * cos(Oldw0 * en * ell + phi[ell][ Old]); + sv[en] = sv[en] + ws[en-55] * MNew * cos(w0 *(en - 160) * ell + phi[ell][ New]); + } + for(en = 106; en <= 159; en++) { + sv[en] = sv[en] + ws[en-55] * MNew * cos(w0 *(en - 160) * ell + phi[ell][ New]); + } + } + } else { + for(en = 56; en <= 159; en++) { + sv[en] = sv[en] + ws[en-55] * MNew * cos(w0 *(en - 160) * ell + phi[ell][ New]); + } + } + } else { + if( vee[ell][Old]) { + for(en = 0; en <= 105; en++) { + sv[en] = sv[en] + ws[en+105] * MOld * cos(Oldw0 * en * ell + phi[ell][ Old]); + } + } + } + } +} + diff --git a/blocks/src/lib/software_imbe_decoder.h b/blocks/src/lib/software_imbe_decoder.h new file mode 100644 index 0000000..4ef515f --- /dev/null +++ b/blocks/src/lib/software_imbe_decoder.h @@ -0,0 +1,101 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2008-2009 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or(at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. + */ + +#ifndef INCLUDED_SOFTWARE_IMBE_DECODER_H +#define INCLUDED_SOFTWARE_IMBE_DECODER_H + +#include + +#include + +/** + * A software implementation of the imbe_decoder interface. + */ +class software_imbe_decoder : public imbe_decoder { +public: + + /** + * Default constructor for the software_imbe_decoder. + */ + software_imbe_decoder(); + + /** + * Destructor for the software_imbe_decoder. + */ + virtual ~software_imbe_decoder(); + + /** + * Decode the compressed audio. + * + * \cw in IMBE codeword (including parity check bits). + */ + virtual void decode(const voice_codeword& cw); + +private: + + //NOTE: Single-letter variable names are upper case only; Lower + // case if needed is spelled. e.g. L, ell + + // global Seq ER ? + + int bee[58]; //Encoded Spectral Amplitudes + float M[57][2]; //Enhanced Spectral Amplitudes + float Mu[57][2]; //Unenhanced Spectral Amplitudes + int vee[57][2]; //V/UV decisions + float suv[160]; //Unvoiced samples + float sv[160]; //Voiced samples + float log2Mu[58][2]; + float Olduw[256]; + float psi1; + float phi[57][2]; + + int Old; + int New; + int L; + int OldL; + float w0; + float Oldw0; + float Luv; //number of unvoiced spectral amplitudes + + char sym_b[4096]; + char RxData[4096]; + int sym_bp; + int ErFlag; + + uint32_t pngen15(uint32_t& pn); + uint32_t pngen23(uint32_t& pn); + void decode_audio(uint8_t *); + void decode_spectral_amplitudes(int, int ); + void decode_vuv(int ); + void adaptive_smoothing(float, float, float ); + void fft(float i[], float q[]); + void enhance_spectral_amplitudes(float&); + void ifft(float i[], float q[], float[]); + uint16_t rearrange(uint32_t u0, uint32_t u1, uint32_t u2, uint32_t u3, uint32_t u4, uint32_t u5, uint32_t u6, uint32_t u7); + void synth_unvoiced(); + void synth_voiced(); + void unpack(uint8_t *buf, uint32_t& u0, uint32_t& u1, uint32_t& u2, uint32_t& u3, uint32_t& u4, uint32_t& u5, uint32_t& u6, uint32_t& u7, uint32_t& E0, uint32_t& ET); +}; + + +#endif /* INCLUDED_SOFTWARE_IMBE_DECODER_H */ diff --git a/blocks/src/lib/tdu.cc b/blocks/src/lib/tdu.cc new file mode 100644 index 0000000..e5cfdde --- /dev/null +++ b/blocks/src/lib/tdu.cc @@ -0,0 +1,84 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2008 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. + */ + +#include +#include +#include +#include + +using std::string; + +tdu::tdu(const_bit_queue& frame_body, bool has_link_control) : + abstract_data_unit(frame_body), + d_has_link_control(has_link_control) +{ +} + +tdu::~tdu() +{ +} + +string +tdu::duid_str() const +{ + return string("TDU"); +} + +void +tdu::do_correct_errors(bit_vector& frame) +{ + if(d_has_link_control) { + apply_golay_correction(frame); + apply_rs_correction(frame); + } +} + +void +tdu::apply_golay_correction(bit_vector& frame) +{ +} + +void +tdu::apply_rs_correction(bit_vector& frame) +{ +#if 0 + static itpp::Reed_Solomon rs(63, 17, true); + itpp::bvec b(70); + swab(frame, 114, 122, b, 0); + swab(frame, 122, 126, b, 8); + swab(frame, 138, 142, b, 12); + swab(frame, 144, 152, b, 16); + swab(frame, 164, 176, b, 24); + swab(frame, 188, 200, b, 36); + swab(frame, 212, 213, b, 48); + swab(frame, 216, 226, b, 50); + swab(frame, 238, 250, b, 60); + itpp::bvec bd(rs.decode(b)); +#endif +} + +uint16_t +tdu::frame_size_max() const +{ + return d_has_link_control ? 432 : 144; +} diff --git a/blocks/src/lib/tdu.h b/blocks/src/lib/tdu.h new file mode 100644 index 0000000..bb5c678 --- /dev/null +++ b/blocks/src/lib/tdu.h @@ -0,0 +1,99 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2008 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. + */ + +#ifndef INCLUDED_TDU_H +#define INCLUDED_TDU_H + +#include + +/** + * P25 terminator data unit (TDU). + */ +class tdu : public abstract_data_unit +{ +public: + + /** + * tdu constructor. + * + * \param frame_body A const_bit_queue representing the frame body. + * \param has_link_control true if frame has link control data, otherwise false. + */ + tdu(const_bit_queue& frame_body, bool has_link_control); + + /** + * tdu constructor. + */ + virtual ~tdu(); + + /** + * Returns a string describing the Data Unit ID (DUID). + */ + std::string duid_str() const; + +protected: + + /** + * Applies error correction code to the specified bit_vector. + * + * \param frame_body The bit vector to decode. + * \return + */ + virtual void do_correct_errors(bit_vector& frame_body); + + /** + * Apply Golay error correction code to the specified bit_vector. + * + * \param frame_body The bit vector to decode. + * \return + */ + virtual void apply_golay_correction(bit_vector& frame_body); + + /** + * Apply Reed-Solomon error correction code to the specified + * bit_vector. + * + * \param frame_body The bit vector to decode. + * \return + */ + virtual void apply_rs_correction(bit_vector& frame_body); + + /** + * Returns the expected size (in bits) of this data unit in + * bits. For variable-length data this should return UINT16_MAX + * until the actual length of this frame is known. + * + * \return The expected size (in bits) of this data_unit when encoded. + */ + virtual uint16_t frame_size_max() const; + +private: + + /** + * Does this TDU have a link_control field? + */ + bool d_has_link_control; + +}; + +#endif /* INCLUDED_TDU_H */ diff --git a/blocks/src/lib/tsbk.cc b/blocks/src/lib/tsbk.cc new file mode 100644 index 0000000..7320ace --- /dev/null +++ b/blocks/src/lib/tsbk.cc @@ -0,0 +1,52 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2008 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. + */ + +#include + +using namespace std; + +tsbk::tsbk(const_bit_queue& frame_body) : + abstract_data_unit(frame_body) +{ +} + +tsbk::~tsbk() +{ +} + +string +tsbk::duid_str() const +{ + return string("TSBK"); +} + +uint16_t +tsbk::frame_size_max() const +{ +#if 1 + return 720; +#else + // todo: check this out! + return 358; +#endif +} diff --git a/blocks/src/lib/tsbk.h b/blocks/src/lib/tsbk.h new file mode 100644 index 0000000..08e1001 --- /dev/null +++ b/blocks/src/lib/tsbk.h @@ -0,0 +1,66 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2008 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. +*/ + +#ifndef INCLUDED_TSBK_H +#define INCLUDED_TSBK_H + +#include + +/** + * P25 trunking signalling block (TSBK). + */ +class tsbk : public abstract_data_unit +{ + +public: + + /** + * tsbk constructor. + * + * \param frame_body A const_bit_queue representing the frame body. + */ + tsbk(const_bit_queue& frame_body); + + /** + * tsbk virtual destructor. + */ + virtual ~tsbk(); + + /** + * Returns a string describing the Data Unit ID (DUID). + */ + std::string duid_str() const; + +protected: + + /** + * Returns the expected size (in bits) of this data unit in + * bits. + * + * \return The expected size (in bits) of this data_unit when encoded. + */ + virtual uint16_t frame_size_max() const; + +}; + +#endif /* INCLUDED_TSBK_H */ diff --git a/blocks/src/lib/value_string.cc b/blocks/src/lib/value_string.cc new file mode 100644 index 0000000..fdaf7c3 --- /dev/null +++ b/blocks/src/lib/value_string.cc @@ -0,0 +1,116 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2008 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. + */ + +#include +#include +#include + +using namespace std; + +struct value_string { + uint16_t value; + const char *label; +}; + +string +lookup(uint16_t value, const value_string mappings[], size_t mappings_sz) +{ + for(size_t i = 0; i < mappings_sz; ++i) { + if(mappings[i].value == value) { + return mappings[i].label; + } + } + ostringstream os; + os << "Unknown (" << hex << showbase << value << ")"; + return os.str(); +} + +const value_string ALGIDS[] = { + /* Type I */ + { 0x00, "ACCORDION 1.3" }, + { 0x01, "BATON (Auto Even)" }, + { 0x02, "FIREFLY Type 1" }, + { 0x03, "MAYFLY Type 1" }, + { 0x04, "SAVILLE" }, + { 0x41, "BATON (Auto Odd)" }, + /* Type III */ + { 0x80, "Plain" }, + { 0x81, "DES-OFB" }, + { 0x82, "2 key Triple DES" }, + { 0x83, "3 key Triple DES" }, + { 0x84, "AES-256" }, + /* Motorola proprietary */ + { 0x9F, "Motorola DES-XL" }, + { 0xA0, "Motorola DVI-XL" }, + { 0xA1, "Motorola DVP-XL" }, + { 0xAA, "Motorola ADP" }, +}; +const size_t ALGIDS_SZ = sizeof(ALGIDS) / sizeof(ALGIDS[0]); + + +const value_string MFIDS[] = { + { 0x00, "Standard MFID (pre-2001)" }, + { 0x01, "Standard MFID (post-2001)" }, + { 0x09, "Aselsan Inc." }, + { 0x10, "Relm / BK Radio" }, + { 0x18, "EADS Public Safety Inc." }, + { 0x20, "Cycomm" }, + { 0x28, "Efratom Time and Frequency Products, Inc" }, + { 0x30, "Com-Net Ericsson" }, + { 0x34, "Etherstack" }, + { 0x38, "Datron" }, + { 0x40, "Icom" }, + { 0x48, "Garmin" }, + { 0x50, "GTE" }, + { 0x55, "IFR Systems" }, + { 0x5A, "INIT Innovations in Transportation, Inc" }, + { 0x60, "GEC-Marconi" }, + { 0x64, "Harris Corp." }, + { 0x68, "Kenwood Communications" }, + { 0x70, "Glenayre Electronics" }, + { 0x74, "Japan Radio Co." }, + { 0x78, "Kokusai" }, + { 0x7C, "Maxon" }, + { 0x80, "Midland" }, + { 0x86, "Daniels Electronics Ltd." }, + { 0x90, "Motorola" }, + { 0xA0, "Thales" }, + { 0xA4, "M/A-COM" }, + { 0xB0, "Raytheon" }, + { 0xC0, "SEA" }, + { 0xC8, "Securicor" }, + { 0xD0, "ADI" }, + { 0xD8, "Tait Electronics" }, + { 0xE0, "Teletec" }, + { 0xF0, "Transcrypt International" }, + { 0xF8, "Vertex Standard" }, + { 0xFC, "Zetron, Inc" }, +}; +const size_t MFIDS_SZ = sizeof(MFIDS) / sizeof(MFIDS[0]); + +const value_string NACS[] = { + { 0x293, "Default NAC" }, + { 0xF7E, "Receiver to open on any NAC" }, + { 0xF7F, "Repeater to receive and retransmit any NAC" }, +}; +const size_t NACS_SZ = sizeof(NACS) / sizeof(NACS[0]); diff --git a/blocks/src/lib/value_string.h b/blocks/src/lib/value_string.h new file mode 100644 index 0000000..f8c686e --- /dev/null +++ b/blocks/src/lib/value_string.h @@ -0,0 +1,49 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2008 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. +*/ + +#ifndef INCLUDED_VALUE_STRING +#define INCLUDED_VALUE_STRING + +#include +#include + +/* + * Look up a value in a value_string array. + * + */ +extern std::string lookup(uint16_t value, const class value_string mappings[], size_t mappings_sz); + +/* + * Look up tables. + */ + +extern const value_string ALGIDS[]; +extern const size_t ALGIDS_SZ; + +extern const value_string MFIDS[]; +extern const size_t MFIDS_SZ; + +extern const value_string NACS[]; +extern const size_t NACS_SZ; + +#endif // INCLUDED_VALUE_STRING diff --git a/blocks/src/lib/vc55_imbe_decoder.cc b/blocks/src/lib/vc55_imbe_decoder.cc new file mode 100644 index 0000000..6ba8663 --- /dev/null +++ b/blocks/src/lib/vc55_imbe_decoder.cc @@ -0,0 +1,87 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2008 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +vc55_imbe_decoder::vc55_imbe_decoder() +{ + const char *dev = getenv("IMBE_DEV"); + const char *default_dev = "/dev/ttyS0"; + dev = dev ? dev : default_dev; + d_fd = open(dev, O_WRONLY | O_NOCTTY); + if(-1 != d_fd) { + struct termios options; + if(-1 != tcgetattr(d_fd, &options)) { + cfsetospeed(&options, B115200); + options.c_cflag |= (CLOCAL | CREAD | CS8); + options.c_cflag &= ~(CSTOPB | PARENB | CRTSCTS | IXON); + if(-1 == tcsetattr(d_fd, TCSANOW, &options)) { + ostringstream msg; + msg << "tcsetattr(fd, TCSANOW, &options): " << strerror(errno) << endl; + msg << "func: " << __PRETTY_FUNCTION__ << endl; + msg << "file: " << __FILE__ << endl; + msg << "line: " << __LINE__ << endl; + throw runtime_error(msg.str()); + } + } + } else { + perror("open(dev, O_WRONLY | O_NOCTTY)"); // a warning, not an error + } +} + +vc55_imbe_decoder::~vc55_imbe_decoder() +{ + if(-1 != d_fd) { + close(d_fd); + } +} + +void +vc55_imbe_decoder::decode(const voice_codeword& cw) +{ + if(-1 != d_fd) { + uint8_t packet[20]; + packet[0] = 0x56; + packet[1] = 0xf0; + extract(cw, 0, 144, &packet[2]); + if(-1 == write(d_fd, packet, sizeof(packet))) { + perror("write(d_fd, packet, sizeof(packet))"); + close(d_fd); + d_fd = -1; + } + } +} diff --git a/blocks/src/lib/vc55_imbe_decoder.h b/blocks/src/lib/vc55_imbe_decoder.h new file mode 100644 index 0000000..7d0b38f --- /dev/null +++ b/blocks/src/lib/vc55_imbe_decoder.h @@ -0,0 +1,64 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2008 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. + */ + +#ifndef INCLUDED_VC55_IMBE_DECODER_H +#define INCLUDED_VC55_IMBE_DECODER_H + +#include + +/** + * vc55_imbe_decoder uses the VC55PR vocoder to decode voice. Note + * that the VC55 produces audio but this is not fed back to the flow + * graph. + * + */ +class vc55_imbe_decoder : public imbe_decoder { +public: + + /** + * vc55_imbe_decoder default constructor. + */ + vc55_imbe_decoder(); + + /** + * vc55_imbe_decoder (virtual) destructor. + */ + virtual ~vc55_imbe_decoder(); + + /** + * Passess the voice_codeword in_out to the VC55PR device. + * + * \param cw IMBE codewords and parity. + */ + virtual void decode(const voice_codeword& cw); + +private: + + /** + * File descriptor for the actual terminal device. + */ + int32_t d_fd; + +}; + +#endif /* INCLUDED_VC55_IMBE_DECODER_H */ diff --git a/blocks/src/lib/voice_data_unit.cc b/blocks/src/lib/voice_data_unit.cc new file mode 100644 index 0000000..adb20ff --- /dev/null +++ b/blocks/src/lib/voice_data_unit.cc @@ -0,0 +1,58 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2008 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. + */ + +#include +#include +#include + +using namespace std; + +voice_data_unit::~voice_data_unit() +{ +} + +voice_data_unit::voice_data_unit(const_bit_queue& frame_body) : + abstract_data_unit(frame_body) +{ +} + +void +voice_data_unit::do_correct_errors(bit_vector& frame_body) +{ +} + +void +voice_data_unit::do_decode_audio(const_bit_vector& frame_body, imbe_decoder& imbe) +{ + voice_codeword cw(voice_codeword_sz); + for(size_t i = 0; i < nof_voice_codewords; ++i) { + imbe_deinterleave(frame_body, cw, i); + imbe.decode(cw); + } +} + +uint16_t +voice_data_unit::frame_size_max() const +{ + return 1728; +} diff --git a/blocks/src/lib/voice_data_unit.h b/blocks/src/lib/voice_data_unit.h new file mode 100644 index 0000000..5f2494f --- /dev/null +++ b/blocks/src/lib/voice_data_unit.h @@ -0,0 +1,79 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2008 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. + */ + +#ifndef INCLUDED_VOICE_DATA_UNIT_H +#define INCLUDED_VOICE_DATA_UNIT_H + +#include + +/** + * P25 Logical Data Unit 1 (compressed IBME voice). + */ +class voice_data_unit : public abstract_data_unit +{ +public: + + /** + * voice_data_unit (virtual) destuctor + */ + virtual ~voice_data_unit(); + +protected: + + /** + * voice_data_unit constuctor + * + * \param frame_body A const_bit_queue representing the frame body. + */ + voice_data_unit(const_bit_queue& frame_body); + + /** + * Applies error correction code to the specified bit_vector. Not + * that this function removes the PN sequences from the source + * frame. + * + * \param frame_body The bit vector to decode. + * \return + */ + virtual void do_correct_errors(bit_vector& frame_body); + + /** + * Decode compressed audio using the supplied imbe_decoder. + * + * \param frame_body The const_bit_vector to decode. + * \param imbe The imbe_decoder to use to generate the audio. + */ + virtual void do_decode_audio(const_bit_vector& frame_body, imbe_decoder& imbe); + + /** + * Returns the expected size (in bits) of this data_unit. For + * variable-length data this should return UINT16_MAX until the + * actual length of this frame is known. + * + * \return The expected size (in bits) of this data_unit when encoded. + */ + virtual uint16_t frame_size_max() const; + +}; + +#endif /* INCLUDED_VOICE_DATA_UNIT_H */ diff --git a/blocks/src/lib/voice_du_handler.cc b/blocks/src/lib/voice_du_handler.cc new file mode 100644 index 0000000..816b1b2 --- /dev/null +++ b/blocks/src/lib/voice_du_handler.cc @@ -0,0 +1,47 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2008 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. + */ + +#include + +#include +#include + +using namespace std; + +voice_du_handler::voice_du_handler(data_unit_handler_sptr next, imbe_decoder_sptr decoder) : + data_unit_handler(next), + d_decoder(decoder) +{ +} + + +voice_du_handler::~voice_du_handler() +{ +} + +void +voice_du_handler::handle(data_unit_sptr du) +{ + du->decode_audio(*d_decoder); + data_unit_handler::handle(du); +} diff --git a/blocks/src/lib/voice_du_handler.h b/blocks/src/lib/voice_du_handler.h new file mode 100644 index 0000000..f826e50 --- /dev/null +++ b/blocks/src/lib/voice_du_handler.h @@ -0,0 +1,69 @@ +/* -*- C++ -*- */ + +/* + * Copyright 2009 Steve Glass + * + * This file is part of OP25. + * + * OP25 is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3, or (at your option) + * any later version. + * + * OP25 is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + * License for more details. + * + * You should have received a copy of the GNU General Public License + * along with OP25; see the file COPYING. If not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Boston, MA + * 02110-1301, USA. +*/ + +#ifndef INCLUDED_VOICE_DU_HANDLER_H +#define INCLUDED_VOICE_DU_HANDLER_H + +#include +#include + +#include + +/** + * voice_data_unit_handler performs IMBE decoding. + */ +class voice_du_handler : public data_unit_handler +{ + +public: + + /** + * voice_du_handler constructor. + * + * \param next The next data_unit_handler in the chain. + * \param decoder An imbe_decoder_sptr to the IMBE decoder to use. + */ + voice_du_handler(data_unit_handler_sptr next, imbe_decoder_sptr decoder); + + /** + * voice_du_handler virtual destructor. + */ + virtual ~voice_du_handler(); + + /** + * Handle a received P25 frame. + * + * \param next The next data_unit_handler in this chain. + */ + virtual void handle(data_unit_sptr du); + +private: + + /** + * The IMBE decder to use. + */ + imbe_decoder_sptr d_decoder; + +}; + +#endif /* INCLUDED_VOICE_DU_HANDLER_H */ diff --git a/blocks/src/python/Makefile.am b/blocks/src/python/Makefile.am new file mode 100644 index 0000000..2ed2678 --- /dev/null +++ b/blocks/src/python/Makefile.am @@ -0,0 +1,32 @@ +# +# Copyright 2004 Free Software Foundation, Inc. +# +# This file is part of OP25 +# +# OP25 is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# OP25 is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +# License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OP25; see the file COPYING. If not, write to the Free +# Software Foundation, Inc., 51 Franklin Street, Boston, MA +# 02110-1301, USA. +# + +include $(top_srcdir)/Makefile.common + +EXTRA_DIST = run_tests.in + + +TESTS = \ + run_tests + + +noinst_PYTHON = \ + qa_op25.py diff --git a/blocks/src/python/qa_op25.py b/blocks/src/python/qa_op25.py new file mode 100755 index 0000000..4f347c1 --- /dev/null +++ b/blocks/src/python/qa_op25.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python +# +# Copyright 2008 Steve Glass +# +# This file is part of OP25 +# +# OP25 is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# OP25 is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public +# License for more details. +# +# You should have received a copy of the GNU General Public License +# along with OP25; see the file COPYING. If not, write to the Free +# Software Foundation, Inc., 51 Franklin Street, Boston, MA +# 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +import op25 + +# import os +# +# print 'Blocked waiting for GDB attach (pid = %d)' % (os.getpid(),) +# raw_input("Press Enter to continue...") + +class qa_op25(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + def test_constructor(self): + empty_sequence = () + src = gr.vector_source_b(empty_sequence, False) + # msgq = gr.msg_queue() + p25 = op25.decoder_bf() + self.tb.connect(src, p25) + +if __name__ == '__main__': + gr_unittest.main () diff --git a/blocks/src/python/run_tests.in b/blocks/src/python/run_tests.in new file mode 100644 index 0000000..6e4b83e --- /dev/null +++ b/blocks/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