Merge branch 'deb-bin-no-ext' of https://github.com/petterreinholdtsen/gr-gsm into petterreinholdtsen-deb-bin-no-ext
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 5832d42..6e85472 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -107,6 +107,8 @@
find_package(CppUnit)
find_package(Doxygen)
find_package(Libosmocore)
+#find_package(Libosmocoding)
+find_package(Libosmocodec)
if(NOT GNURADIO_RUNTIME_FOUND)
message(FATAL_ERROR "GnuRadio Runtime required to compile gr-gsm")
@@ -120,6 +122,13 @@
if(NOT LIBOSMOCORE_FOUND)
message(FATAL_ERROR "Libosmocore required to compile gr-gsm")
endif()
+message( dupa 2!!! )
+#if(NOT LIBOSMOCODEC_FOUND)
+# message(FATAL_ERROR "Libosmocodec required to compile gr-gsm")
+#endif()
+#if(NOT LIBOSMOCODING_FOUND)
+# message(FATAL_ERROR "Libosmocoding required to compile gr-gsm")
+#endif()
########################################################################
# Setup doxygen option
diff --git a/COPYING b/COPYING
index 94a9ed0..14878e9 100644
--- a/COPYING
+++ b/COPYING
@@ -672,3 +672,738 @@
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
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
+
+
+
+
+
+ GNU AFFERO GENERAL PUBLIC LICENSE
+ Version 3, 19 November 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU Affero General Public License is a free, copyleft license for
+software and other kinds of works, specifically designed to ensure
+cooperation with the community in the case of network server software.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+our General Public Licenses are 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.
+
+ 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.
+
+ Developers that use our General Public Licenses protect your rights
+with two steps: (1) assert copyright on the software, and (2) offer
+you this License which gives you legal permission to copy, distribute
+and/or modify the software.
+
+ A secondary benefit of defending all users' freedom is that
+improvements made in alternate versions of the program, if they
+receive widespread use, become available for other developers to
+incorporate. Many developers of free software are heartened and
+encouraged by the resulting cooperation. However, in the case of
+software used on network servers, this result may fail to come about.
+The GNU General Public License permits making a modified version and
+letting the public access it on a server without ever releasing its
+source code to the public.
+
+ The GNU Affero General Public License is designed specifically to
+ensure that, in such cases, the modified source code becomes available
+to the community. It requires the operator of a network server to
+provide the source code of the modified version running there to the
+users of that server. Therefore, public use of a modified version, on
+a publicly accessible server, gives the public access to the source
+code of the modified version.
+
+ An older license, called the Affero General Public License and
+published by Affero, was designed to accomplish similar goals. This is
+a different license, not a version of the Affero GPL, but Affero has
+released a new version of the Affero GPL which permits relicensing under
+this license.
+
+ 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 Affero 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. Remote Network Interaction; Use with the GNU General Public License.
+
+ Notwithstanding any other provision of this License, if you modify the
+Program, your modified version must prominently offer all users
+interacting with it remotely through a computer network (if your version
+supports such interaction) an opportunity to receive the Corresponding
+Source of your version by providing access to the Corresponding Source
+from a network server at no charge, through some standard or customary
+means of facilitating copying of software. This Corresponding Source
+shall include the Corresponding Source for any work covered by version 3
+of the GNU General Public License that is incorporated pursuant to the
+following paragraph.
+
+ 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 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 work with which it is combined will remain governed by version
+3 of the GNU General Public License.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU Affero 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 Affero 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 Affero 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 Affero 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.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU Affero 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 Affero General Public License for more details.
+
+ You should have received a copy of the GNU Affero General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If your software can interact with users remotely through a computer
+network, you should also make sure that it provides a way for users to
+get its source. For example, if your program is a web application, its
+interface could display a "Source" link that leads users to an archive
+of the code. There are many ways you could offer source, and different
+solutions will be better for different programs; see section 13 for the
+specific requirements.
+
+ 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 AGPL, see
+<http://www.gnu.org/licenses/>.
+
+
+
+
+=========================================================================
+
+This marks the end of the AGPLv3 text. The following text is appended to the
+same file for convience but constituting a distinct document, not part of the
+actual AGPL text and not part of an attempt to create a deriviative work based
+on the AGPLv3 text.
+
+=========================================================================
+
+
+ADDITIONAL TERMS TO THE AGPLv3 LICENSE FOR OPENBTS
+
+
+Permissive Terms Supplementing the License
+
+1. Remote Interaction Through IP Networks.
+
+OpenBTS includes an implementation of the GSM network cellular air interface,
+as well as other interfaces to IP networks. The interaction of cellular
+handsets with the OpenBTS software is considered "remote network interaction"
+for the purposes of the Affero General Public License and cellular users are
+subject to the source code access requirements of Section 13 of AGPLv3 ("Remote
+Network Interaction; Use with the GNU General Public License").
+
+Remote interactions through interfaces other than the GSM air interface are, at
+your option, exempted from the requirements of Section 13 ("Remote Network
+Interaction; Use with the GNU General Public License"). This exemption of
+interfaces other than the GSM air interface from the requirements of Section 13
+is an additional permission granted to you.
+
+2. GSM "A5" cipher stream generation libraries
+
+Notwithstanding any other provision of this License, you have
+permission to link the Program with GSM "A5" cipher-stream generation
+libraries provided under any license that allows redistribution of
+those libraries in binary form, provided that the function of any such
+library is limited to the generation of cipher-steam bits.
+
+
+Non-Permissive Terms Supplementing The License
+
+1. Trademarks.
+
+"OpenBTS" is a trademark of Range Networks, Inc., registered with
+the US Patent and Trademark Office. Your use of OpenBTS software under a GPL
+license does not include the right to use the OpenBTS trademark in commerce.
+This additional non-permissive term is consistent with Section 7 of the AGPLv3
+license.
+
+END OF ADDITIONAL TERMS
+
+
+How to comply with Section 13 of the AGPLv3 license.
+
+The recommended method for compliance with Section 13 of the AGPLv3 license is
+to deliver a text message to each handset that attaches to the OpenBTS cellular
+network. At a minimum, that text message should include the string "OpenBTS
+AGPLv3" and a URL that can be used to access the OpenBTS source code. This
+message need not be delivered to handsets that are denied registration with the
+network, since those handsets have been denied service.
+
+In OpenBTS 2.6, such text messages can be delivered with the "Welcome Message"
+feature. See the OpenBTS.config.example file for more information on the use of
+this feature for AGPLv3 compliance.
+
diff --git a/README.md b/README.md
index bcd359f..86ca1e8 100644
--- a/README.md
+++ b/README.md
@@ -44,8 +44,6 @@
*Pieter Robyns* \<pieter.robyns (at) uhasselt.be\> - block reversing channel hopping
-*Steve* \<steve (at) segfault.net\> - functions for decoding control channels
-
Thanks
======
diff --git a/apps/README b/apps/README
index e811c06..e9de333 100644
--- a/apps/README
+++ b/apps/README
@@ -10,8 +10,8 @@
There are following helper programs for grgsm_decode program:
-* grgsm_capture (old name: airprobe_rtlsdr_capture.py) - program for capturing GSM signal to a file
+* grgsm_capture.py (old name: airprobe_rtlsdr_capture.py) - program for capturing GSM signal to a file
that can be later processed by grgsm_decode,
-* grgsm_channelize (old name: gsm_channelize.py) - splits wideband capture file into multiple files - each contain
+* grgsm_channelize.py (old name: gsm_channelize.py) - splits wideband capture file into multiple files - each contain
single GSM channel.
diff --git a/apps/grgsm_decode b/apps/grgsm_decode
index 2198bc4..222d67e 100755
--- a/apps/grgsm_decode
+++ b/apps/grgsm_decode
@@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @file
-# @author Roman Khassraf <rkhassraf@gmail.com>
+# @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
# @section LICENSE
#
# Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/apps/grgsm_livemon b/apps/grgsm_livemon
index cb63bdc..b77acbb 100755
--- a/apps/grgsm_livemon
+++ b/apps/grgsm_livemon
@@ -1,5 +1,25 @@
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
+# @file
+# @author (C) 2014-2016 by Piotr Krysik <ptrkrysik@gmail.com>
+# @section LICENSE
+#
+# Gr-gsm is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# Gr-gsm is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with gr-gsm; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+#
##################################################
# GNU Radio Python Flow Graph
# Title: Gr-gsm Livemon
diff --git a/apps/grgsm_scanner b/apps/grgsm_scanner
index 397d51e..c1e5638 100755
--- a/apps/grgsm_scanner
+++ b/apps/grgsm_scanner
@@ -1,8 +1,8 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @file
-# @author Piotr Krysik <ptrkrysik@gmail.com>
-# @author Roman Khassraf <rkhassraf@gmail.com>
+# @author (C) 2015 by Piotr Krysik <ptrkrysik@gmail.com>
+# @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
# @section LICENSE
#
# Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/apps/helpers/grgsm_capture b/apps/helpers/grgsm_capture
index a71c2c8..add42d3 100755
--- a/apps/helpers/grgsm_capture
+++ b/apps/helpers/grgsm_capture
@@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @file
-# @author Roman Khassraf <rkhassraf@gmail.com>
+# @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
# @section LICENSE
#
# Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/apps/helpers/grgsm_channelize b/apps/helpers/grgsm_channelize
index 146bb8f..fb30334 100755
--- a/apps/helpers/grgsm_channelize
+++ b/apps/helpers/grgsm_channelize
@@ -1,7 +1,7 @@
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
# @file
-# @author Pieter Robyns <pieter.robyns@uhasselt.be>
+# @author (C) 2015 by Pieter Robyns <pieter.robyns@uhasselt.be>
# @section LICENSE
#
# Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/cmake/Modules/FindLibosmocodec.cmake b/cmake/Modules/FindLibosmocodec.cmake
new file mode 100644
index 0000000..c28e9f9
--- /dev/null
+++ b/cmake/Modules/FindLibosmocodec.cmake
@@ -0,0 +1,32 @@
+INCLUDE(FindPkgConfig)
+pkg_check_modules(PC_libosmocodec libosmocodec)
+set(LIBOSMOCODEC_DEFINITIONS ${PC_LIBOSMOCODEC_CFLAGS_OTHER})
+
+find_path(
+ LIBOSMOCODEC_INCLUDE_DIR
+ NAMES osmocom/codec/codec.h
+ HINTS ${PC_libosmocodec_INCLUDEDIR}
+ ${PC_libosmocodec_INCLUDE_DIRS}
+ ${CMAKE_INSTALL_PREFIX}/include
+ PATHS /usr/local/include
+ /usr/include
+)
+
+find_library(
+ LIBOSMOCODEC_LIBRARY
+ NAMES libosmocodec osmocodec
+ HINTS ${PC_libosmocodec_LIBDIR}
+ ${PC_libosmocodec_LIBRARY_DIRS}
+ ${CMAKE_INSTALL_PREFIX}/lib/
+ ${CMAKE_INSTALL_PREFIX}/lib64/
+ PATHS /usr/local/lib
+ /usr/lib
+)
+
+
+set(LIBOSMOCODEC_LIBRARIES ${LIBOSMOCODEC_LIBRARY})
+set(LIBOSMOCODEC_INCLUDE_DIRS ${LIBOSMOCODEC_INCLUDE_DIR})
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(libosmocodec DEFAULT_MSG LIBOSMOCODEC_LIBRARY LIBOSMOCODEC_INCLUDE_DIR)
+mark_as_advanced(LIBOSMOCODEC_INCLUDE_DIR LIBOSMOCODEC_LIBRARY )
diff --git a/cmake/Modules/FindLibosmocoding.cmake b/cmake/Modules/FindLibosmocoding.cmake
new file mode 100644
index 0000000..b63869a
--- /dev/null
+++ b/cmake/Modules/FindLibosmocoding.cmake
@@ -0,0 +1,32 @@
+find_package(PkgConfig)
+pkg_check_modules(PC_libosmocoding libosmocoding)
+set(LIBOSMOCODING_DEFINITIONS ${PC_LIBOSMOCODING_CFLAGS_OTHER})
+
+find_path(
+ LIBOSMOCODING_INCLUDE_DIR
+ NAMES osmocom/coding/gsm0503_coding.h
+ HINTS ${PC_libosmocoding_INCLUDEDIR}
+ ${PC_libosmocoding_INCLUDE_DIRS}
+ ${CMAKE_INSTALL_PREFIX}/include
+ PATHS /usr/local/include
+ /usr/include
+)
+
+find_library(
+ LIBOSMOCODING_LIBRARY
+ NAMES libosmocoding osmocoding
+ HINTS ${PC_libosmocoding_LIBDIR}
+ ${PC_libosmocoding_LIBRARY_DIRS}
+ ${CMAKE_INSTALL_PREFIX}/lib/
+ ${CMAKE_INSTALL_PREFIX}/lib64/
+ PATHS /usr/local/lib
+ /usr/lib
+)
+
+
+set(LIBOSMOCODING_LIBRARIES ${LIBOSMOCODING_LIBRARY})
+set(LIBOSMOCODING_INCLUDE_DIRS ${LIBOSMOCODING_INCLUDE_DIR})
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(libosmocoding DEFAULT_MSG LIBOSMOCODING_LIBRARY LIBOSMOCODING_INCLUDE_DIR)
+mark_as_advanced(LIBOSMOCODING_INCLUDE_DIR LIBOSMOCODING_LIBRARY )
\ No newline at end of file
diff --git a/cmake/Modules/FindLibosmocore.cmake b/cmake/Modules/FindLibosmocore.cmake
index 9eff233..9e4f3c4 100644
--- a/cmake/Modules/FindLibosmocore.cmake
+++ b/cmake/Modules/FindLibosmocore.cmake
@@ -1,5 +1,7 @@
-find_package(PkgConfig)
+#find_package(PkgConfig)
+INCLUDE(FindPkgConfig)
pkg_check_modules(PC_libosmocore libosmocore)
+pkg_check_modules(PC_libosmogsm libosmogsm)
set(LIBOSMOCORE_DEFINITIONS ${PC_LIBOSMOCORE_CFLAGS_OTHER})
find_path(
diff --git a/cmake/Modules/FindSWIG.cmake b/cmake/Modules/FindSWIG.cmake
index 156bd5e..e10080d 100644
--- a/cmake/Modules/FindSWIG.cmake
+++ b/cmake/Modules/FindSWIG.cmake
@@ -139,3 +139,4 @@
message(FATAL_ERROR "SWIG is required, but was not found.")
endif()
endif()
+
diff --git a/debian/build-package b/debian/build-package
index 269590b..2d928de 100755
--- a/debian/build-package
+++ b/debian/build-package
@@ -1,11 +1,15 @@
#!/bin/bash
-VERSION=0.40
+BASEVERSION=$(dpkg-parsechangelog --show-field Version | cut -d- -f1)
+DEBVERSION=$(dpkg-parsechangelog --show-field Version)
-cd ../..
+debdir=$(cd $(dirname $0); pwd)
+pkgdir=$(cd $debdir/..; pwd)
+pkgbasedir=$(cd $debdir/..; basename $(pwd))
+cd $pkgdir/..
-tar -acf gr-gsm_${VERSION}.orig.tar.gz gr-gsm
-cd gr-gsm
+tar -acf gr-gsm_${BASEVERSION}.orig.tar.gz $pkgbasedir
+cd $pkgdir
debuild -S -sa
#pdebuild
cd ..
-dput ppa:ptrkrysik/gr-gsm gr-gsm_${VERSION}-0ppa0_source.changes
+dput ppa:ptrkrysik/gr-gsm gr-gsm_${DEBVERSION}_source.changes
diff --git a/debian/copyright b/debian/copyright
index 51af985..aa7bcef 100644
--- a/debian/copyright
+++ b/debian/copyright
@@ -1,18 +1,156 @@
-####################################################################
-# gr-gsm #
-####################################################################
+Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
-Copyright (C) 2011 Your Name
+Files: *
+Copyright: 2015-2017, Roman Khassraf <rkhassraf@gmail.com>
+License: GPL-3+
-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.
+Files: lib/decoding/*
+Copyright: 2009-2017, Piotr Krysik <ptrkrysik@gmail.com>
+License: GPL-3+
-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.
+Files: lib/decoding/openbts/*
+Copyright: 2012-2014, Range Networks, Inc
+License: AGPL-3+
-You should have received a copy of the GNU General Public License
-along with this program. If not, see <http://www.gnu.org/licenses/>.
+Files: lib/decoding/openbts/BitVector.cpp
+ lib/decoding/openbts/BitVector.h
+ lib/decoding/openbts/Vector.h
+ lib/decoding/openbts/ViterbiR204.cpp
+ lib/decoding/openbts/ViterbiR204.h
+Copyright: 2014, Range Networks, Inc
+ 2008, 2009, 2014, Free Software Foundation, Inc
+License: AGPL-3+
+
+Files: lib/decoding/openbts/GSM610Tables.cpp
+ lib/decoding/openbts/GSM610Tables.h
+Copyright: 2008, Free Software Foundation, Inc
+License: AGPL-3+
+
+Files: lib/decoding/openbts/GSM660Tables.cpp
+ lib/decoding/openbts/GSM660Tables.h
+Copyright: 2010, Sylvain Munaut <tnt@246tNt.com>
+License: AGPL-3+
+
+Files: lib/decoding/osmocom/*
+Copyright: 2016, Tom Tsou <tom.tsou@ettus.com>
+ 2013, Andreas Eversberg <jolly@eversberg.eu>
+License: GPL-2+
+
+Files: lib/decoding/osmocom/coding/gsm0503.h
+Copyright: 2016, sysmocom s.f.m.c. GmbH
+License: GPL-2+
+
+Files: lib/decoding/osmocom/coding/gsm0503_coding.c
+ lib/decoding/osmocom/coding/gsm0503_coding.h
+Copyright: 2016, Tom Tsou <tom.tsou@ettus.com>
+ 2015, Alexander Chemeris <Alexander.Chemeris@fairwaves.co>
+ 2013, Andreas Eversberg <jolly@eversberg.eu>
+License: GPL-2+
+
+Files: lib/decoding/osmocom/coding/gsm0503_conv.c
+Copyright: 2016, sysmocom s.f.m.c. GmbH
+ 2011-2016, Sylvain Munaut <tnt@246tNt.com>
+License: GPL-3+
+
+Files: lib/decoding/tch_f_decoder_impl.cc
+Copyright: 2017, Piotr Krysik <ptrkrysik@gmail.com>
+ 2015, Roman Khassraf <rkhassraf@gmail.com>
+License: GPL-3+
+
+Files: lib/decoding/tch_f_decoder_impl.h
+Copyright: 2015-2017, Roman Khassraf <rkhassraf@gmail.com>
+License: GPL-3+
+
+Files: lib/decryption/*
+Copyright: 2015, Roman Khassraf <rkhassraf@gmail.com>
+ 2014, Piotr Krysik <ptrkrysik@gmail.com>
+License: GPL-3+
+
+Files: lib/decryption/decryption_impl.h
+Copyright: 2009-2017, Piotr Krysik <ptrkrysik@gmail.com>
+License: GPL-3+
+
+Files: lib/demapping/universal_ctrl_chans_demapper_impl.cc
+ lib/demapping/universal_ctrl_chans_demapper_impl.h
+Copyright: 2009-2017, Piotr Krysik <ptrkrysik@gmail.com>
+License: GPL-3+
+
+Files: lib/flow_control/uplink_downlink_splitter_impl.cc
+ lib/flow_control/uplink_downlink_splitter_impl.h
+Copyright: 2009-2017, Piotr Krysik <ptrkrysik@gmail.com>
+License: GPL-3+
+
+Files: lib/misc_utils/bursts_printer_impl.cc
+ lib/misc_utils/bursts_printer_impl.h
+ lib/misc_utils/controlled_fractional_resampler_cc_impl.cc
+ lib/misc_utils/controlled_fractional_resampler_cc_impl.h
+ lib/misc_utils/controlled_rotator_cc_impl.cc
+ lib/misc_utils/controlled_rotator_cc_impl.h
+ lib/misc_utils/extract_system_info_impl.cc
+ lib/misc_utils/extract_system_info_impl.h
+ lib/misc_utils/message_printer_impl.cc
+ lib/misc_utils/message_printer_impl.h
+ lib/misc_utils/msg_to_tag_impl.cc
+ lib/misc_utils/msg_to_tag_impl.h
+ lib/misc_utils/tmsi_dumper_impl.cc
+ lib/misc_utils/tmsi_dumper_impl.h
+Copyright: 2009-2017, Piotr Krysik <ptrkrysik@gmail.com>
+License: GPL-3+
+
+Files: lib/receiver/*
+Copyright: 2009-2017, Piotr Krysik <ptrkrysik@gmail.com>
+License: GPL-3+
+
+Files: lib/receiver/cx_channel_hopper_impl.cc
+ lib/receiver/cx_channel_hopper_impl.h
+Copyright: 2015, Pieter Robyns <pieter.robyns@uhasselt.be>
+License: GPL-3+
+
+Files: python/__init__.py
+ python/build_utils.py
+ python/build_utils_codes.py
+Copyright: 2004, 2008, 2009, 2012, Free Software Foundation, Inc
+License: GPL-3+
+
+Files: python/demapping/*
+Copyright: 2009-2017, Piotr Krysik <ptrkrysik@gmail.com>
+License: GPL-3+
+
+Files: python/misc_utils/*
+Copyright: 2009-2017, Piotr Krysik <ptrkrysik@gmail.com>
+License: GPL-3+
+
+Files: python/misc_utils/arfcn.py
+Copyright: 2015-2017, Roman Khassraf <rkhassraf@gmail.com>
+License: GPL-3+
+
+Files: python/qa_controlled_fractional_resampler_cc.py
+ python/qa_msg_to_tag.py
+ python/qa_uplink_downlink_splitter.py
+Copyright: 2009-2017, Piotr Krysik <ptrkrysik@gmail.com>
+License: GPL-3+
+
+Files: python/receiver/*
+Copyright: 2009-2017, Piotr Krysik <ptrkrysik@gmail.com>
+License: GPL-3+
+
+License: AGPL-3+
+ Please fill license AGPL-3+ from header of lib/decoding/openbts/*
+
+License: GPL-2+
+ 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; version 2 dated June, 1991, or (at
+ your option) any later version.
+ .
+ On Debian systems, the complete text of version 2 of the GNU General
+ Public License can be found in '/usr/share/common-licenses/GPL-2'.
+
+License: GPL-3+
+ 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; version 3 dated June, 2007, or (at
+ your option) any later version.
+ .
+ On Debian systems, the complete text of version 3 of the GNU General
+ Public License can be found in '/usr/share/common-licenses/GPL-3'.
diff --git a/examples b/examples
index f4f7c95..e4e387d 160000
--- a/examples
+++ b/examples
@@ -1 +1 @@
-Subproject commit f4f7c95b491fd6ce0b47d4f16b5019d69e5e22e8
+Subproject commit e4e387dddc3d9b860ae0938902fd59c1a569138c
diff --git a/include/grgsm/api.h b/include/grgsm/api.h
index d36befb..a5684b4 100644
--- a/include/grgsm/api.h
+++ b/include/grgsm/api.h
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2014 by Piotr Krysik <ptrkrysik@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/include/grgsm/decoding/control_channels_decoder.h b/include/grgsm/decoding/control_channels_decoder.h
index 066eaa0..0bb3563 100644
--- a/include/grgsm/decoding/control_channels_decoder.h
+++ b/include/grgsm/decoding/control_channels_decoder.h
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2014 by Piotr Krysik <ptrkrysik@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/include/grgsm/decoding/tch_f_decoder.h b/include/grgsm/decoding/tch_f_decoder.h
index 93fe971..df5f0ff 100644
--- a/include/grgsm/decoding/tch_f_decoder.h
+++ b/include/grgsm/decoding/tch_f_decoder.h
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/include/grgsm/decryption/decryption.h b/include/grgsm/decryption/decryption.h
index b3a66e1..e30e567 100644
--- a/include/grgsm/decryption/decryption.h
+++ b/include/grgsm/decryption/decryption.h
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2014 by Piotr Krysik <ptrkrysik@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/include/grgsm/demapping/tch_f_chans_demapper.h b/include/grgsm/demapping/tch_f_chans_demapper.h
index cdd7457..c04c749 100644
--- a/include/grgsm/demapping/tch_f_chans_demapper.h
+++ b/include/grgsm/demapping/tch_f_chans_demapper.h
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/include/grgsm/demapping/universal_ctrl_chans_demapper.h b/include/grgsm/demapping/universal_ctrl_chans_demapper.h
index 34bcafd..0e614d4 100644
--- a/include/grgsm/demapping/universal_ctrl_chans_demapper.h
+++ b/include/grgsm/demapping/universal_ctrl_chans_demapper.h
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2014-2016 by Piotr Krysik <ptrkrysik@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/include/grgsm/flow_control/burst_fnr_filter.h b/include/grgsm/flow_control/burst_fnr_filter.h
index 0d94ff8..c1c6287 100644
--- a/include/grgsm/flow_control/burst_fnr_filter.h
+++ b/include/grgsm/flow_control/burst_fnr_filter.h
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/include/grgsm/flow_control/burst_sdcch_subslot_filter.h b/include/grgsm/flow_control/burst_sdcch_subslot_filter.h
index a68782f..a0a23bc 100644
--- a/include/grgsm/flow_control/burst_sdcch_subslot_filter.h
+++ b/include/grgsm/flow_control/burst_sdcch_subslot_filter.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/include/grgsm/flow_control/burst_sdcch_subslot_splitter.h b/include/grgsm/flow_control/burst_sdcch_subslot_splitter.h
index 83f98ba..d894128 100644
--- a/include/grgsm/flow_control/burst_sdcch_subslot_splitter.h
+++ b/include/grgsm/flow_control/burst_sdcch_subslot_splitter.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/include/grgsm/flow_control/burst_timeslot_filter.h b/include/grgsm/flow_control/burst_timeslot_filter.h
index 79d677c..45df8f4 100644
--- a/include/grgsm/flow_control/burst_timeslot_filter.h
+++ b/include/grgsm/flow_control/burst_timeslot_filter.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/include/grgsm/flow_control/burst_timeslot_splitter.h b/include/grgsm/flow_control/burst_timeslot_splitter.h
index 4daac08..f4abcae 100644
--- a/include/grgsm/flow_control/burst_timeslot_splitter.h
+++ b/include/grgsm/flow_control/burst_timeslot_splitter.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/include/grgsm/flow_control/common.h b/include/grgsm/flow_control/common.h
index fa4725c..8a9f638 100644
--- a/include/grgsm/flow_control/common.h
+++ b/include/grgsm/flow_control/common.h
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Vadim Yanitskiy <axilirator@gmail.com>
+ * @author (C) 2017 by Vadim Yanitskiy <axilirator@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/include/grgsm/flow_control/dummy_burst_filter.h b/include/grgsm/flow_control/dummy_burst_filter.h
index bf956bb..993b418 100644
--- a/include/grgsm/flow_control/dummy_burst_filter.h
+++ b/include/grgsm/flow_control/dummy_burst_filter.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/include/grgsm/flow_control/uplink_downlink_splitter.h b/include/grgsm/flow_control/uplink_downlink_splitter.h
index c8f1321..0dbc0bc 100644
--- a/include/grgsm/flow_control/uplink_downlink_splitter.h
+++ b/include/grgsm/flow_control/uplink_downlink_splitter.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2016 by Piotr Krysik <ptrkrysik@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/include/grgsm/misc_utils/burst_file_sink.h b/include/grgsm/misc_utils/burst_file_sink.h
index 3a567e9..3f80ca3 100644
--- a/include/grgsm/misc_utils/burst_file_sink.h
+++ b/include/grgsm/misc_utils/burst_file_sink.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/include/grgsm/misc_utils/burst_file_source.h b/include/grgsm/misc_utils/burst_file_source.h
index b401848..0095d5d 100644
--- a/include/grgsm/misc_utils/burst_file_source.h
+++ b/include/grgsm/misc_utils/burst_file_source.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/include/grgsm/misc_utils/bursts_printer.h b/include/grgsm/misc_utils/bursts_printer.h
index 36e30b8..e705214 100644
--- a/include/grgsm/misc_utils/bursts_printer.h
+++ b/include/grgsm/misc_utils/bursts_printer.h
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2014 by Piotr Krysik <ptrkrysik@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/include/grgsm/misc_utils/collect_system_info.h b/include/grgsm/misc_utils/collect_system_info.h
old mode 100755
new mode 100644
index 95871d5..e9f45cb
--- a/include/grgsm/misc_utils/collect_system_info.h
+++ b/include/grgsm/misc_utils/collect_system_info.h
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2017 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/include/grgsm/misc_utils/controlled_fractional_resampler_cc.h b/include/grgsm/misc_utils/controlled_fractional_resampler_cc.h
index 9eeb393..b085f94 100644
--- a/include/grgsm/misc_utils/controlled_fractional_resampler_cc.h
+++ b/include/grgsm/misc_utils/controlled_fractional_resampler_cc.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2016 by Piotr Krysik <ptrkrysik@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/include/grgsm/misc_utils/controlled_rotator_cc.h b/include/grgsm/misc_utils/controlled_rotator_cc.h
index 8c38eff..249af13 100644
--- a/include/grgsm/misc_utils/controlled_rotator_cc.h
+++ b/include/grgsm/misc_utils/controlled_rotator_cc.h
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2014-2016 by Piotr Krysik <ptrkrysik@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/include/grgsm/misc_utils/extract_cmc.h b/include/grgsm/misc_utils/extract_cmc.h
old mode 100755
new mode 100644
index 7b31564..2b07bbe
--- a/include/grgsm/misc_utils/extract_cmc.h
+++ b/include/grgsm/misc_utils/extract_cmc.h
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2016 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/include/grgsm/misc_utils/extract_immediate_assignment.h b/include/grgsm/misc_utils/extract_immediate_assignment.h
index f848cd2..31fd7d9 100644
--- a/include/grgsm/misc_utils/extract_immediate_assignment.h
+++ b/include/grgsm/misc_utils/extract_immediate_assignment.h
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/include/grgsm/misc_utils/extract_system_info.h b/include/grgsm/misc_utils/extract_system_info.h
index 32331b4..9bf56b3 100644
--- a/include/grgsm/misc_utils/extract_system_info.h
+++ b/include/grgsm/misc_utils/extract_system_info.h
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2014 by Piotr Krysik <ptrkrysik@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/include/grgsm/misc_utils/message_file_sink.h b/include/grgsm/misc_utils/message_file_sink.h
index 16c6253..46cb096 100644
--- a/include/grgsm/misc_utils/message_file_sink.h
+++ b/include/grgsm/misc_utils/message_file_sink.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/include/grgsm/misc_utils/message_file_source.h b/include/grgsm/misc_utils/message_file_source.h
index 2ad61f9..33f9e25 100644
--- a/include/grgsm/misc_utils/message_file_source.h
+++ b/include/grgsm/misc_utils/message_file_source.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/include/grgsm/misc_utils/message_printer.h b/include/grgsm/misc_utils/message_printer.h
index 6755b76..c81fd87 100644
--- a/include/grgsm/misc_utils/message_printer.h
+++ b/include/grgsm/misc_utils/message_printer.h
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2014 by Piotr Krysik <ptrkrysik@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/include/grgsm/misc_utils/msg_to_tag.h b/include/grgsm/misc_utils/msg_to_tag.h
index 69232fc..87e2e78 100644
--- a/include/grgsm/misc_utils/msg_to_tag.h
+++ b/include/grgsm/misc_utils/msg_to_tag.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2016 by Piotr Krysik <ptrkrysik@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/include/grgsm/misc_utils/tmsi_dumper.h b/include/grgsm/misc_utils/tmsi_dumper.h
index 8ea19a4..10add7c 100644
--- a/include/grgsm/misc_utils/tmsi_dumper.h
+++ b/include/grgsm/misc_utils/tmsi_dumper.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2015 by Piotr Krysik <ptrkrysik@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/include/grgsm/plotting.hpp b/include/grgsm/plotting.hpp
index ff37fec..21890e4 100644
--- a/include/grgsm/plotting.hpp
+++ b/include/grgsm/plotting.hpp
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2014 by Piotr Krysik <ptrkrysik@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/include/grgsm/qa_utils/burst_sink.h b/include/grgsm/qa_utils/burst_sink.h
index 0d1330c..e12d027 100644
--- a/include/grgsm/qa_utils/burst_sink.h
+++ b/include/grgsm/qa_utils/burst_sink.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/include/grgsm/qa_utils/burst_source.h b/include/grgsm/qa_utils/burst_source.h
index 67c881c..e74a8aa 100644
--- a/include/grgsm/qa_utils/burst_source.h
+++ b/include/grgsm/qa_utils/burst_source.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/include/grgsm/qa_utils/message_sink.h b/include/grgsm/qa_utils/message_sink.h
index 14369b0..d4a8e6b 100644
--- a/include/grgsm/qa_utils/message_sink.h
+++ b/include/grgsm/qa_utils/message_sink.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/include/grgsm/qa_utils/message_source.h b/include/grgsm/qa_utils/message_source.h
index dc1f546..0d34ec1 100644
--- a/include/grgsm/qa_utils/message_source.h
+++ b/include/grgsm/qa_utils/message_source.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/include/grgsm/receiver/clock_offset_control.h b/include/grgsm/receiver/clock_offset_control.h
index c4ea8b1..00756cb 100644
--- a/include/grgsm/receiver/clock_offset_control.h
+++ b/include/grgsm/receiver/clock_offset_control.h
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2015-2016 by Piotr Krysik <ptrkrysik@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/include/grgsm/receiver/cx_channel_hopper.h b/include/grgsm/receiver/cx_channel_hopper.h
index 99a65c7..0352717 100644
--- a/include/grgsm/receiver/cx_channel_hopper.h
+++ b/include/grgsm/receiver/cx_channel_hopper.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2015 by Pieter Robyns <pieter.robyns@uhasselt.be>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/include/grgsm/receiver/receiver.h b/include/grgsm/receiver/receiver.h
index e19fe7a..dbbe327 100644
--- a/include/grgsm/receiver/receiver.h
+++ b/include/grgsm/receiver/receiver.h
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2014-2016 by Piotr Krysik <ptrkrysik@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index 680c41f..1686de5 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -28,21 +28,25 @@
receiver/receiver_impl.cc
receiver/receiver_config.cc
receiver/viterbi_detector.cc
- receiver/sch.c
+ decoding/sch.c
receiver/clock_offset_control_impl.cc
receiver/cx_channel_hopper_impl.cc
demapping/universal_ctrl_chans_demapper_impl.cc
demapping/tch_f_chans_demapper_impl.cc
decoding/control_channels_decoder_impl.cc
- decoding/cch.c
- decoding/fire_crc.c
decoding/tch_f_decoder_impl.cc
- decoding/AmrCoder.cpp
- decoding/BitVector.cpp
- decoding/GSM610Tables.cpp
- decoding/GSM660Tables.cpp
- decoding/GSM503Tables.cpp
- decoding/ViterbiR204.cpp
+ decoding/openbts/AmrCoder.cpp
+ decoding/openbts/BitVector.cpp
+ decoding/openbts/GSM610Tables.cpp
+ decoding/openbts/GSM660Tables.cpp
+ decoding/openbts/GSM503Tables.cpp
+ decoding/openbts/ViterbiR204.cpp
+ decoding/osmocom/coding/gsm0503_conv.c
+ decoding/osmocom/coding/gsm0503_coding.c
+ decoding/osmocom/coding/gsm0503_interleaving.c
+ decoding/osmocom/coding/gsm0503_mapping.c
+ decoding/osmocom/coding/gsm0503_parity.c
+ decoding/osmocom/coding/gsm0503_tables.c
flow_control/burst_timeslot_splitter_impl.cc
flow_control/burst_sdcch_subslot_splitter_impl.cc
flow_control/burst_timeslot_filter_impl.cc
@@ -73,7 +77,8 @@
add_library(grgsm SHARED ${grgsm_sources})
-target_link_libraries(grgsm ${Boost_LIBRARIES} ${GNURADIO_ALL_LIBRARIES} ${VOLK_LIBRARIES} ${LIBOSMOCORE_LIBRARIES}
+target_link_libraries(grgsm ${Boost_LIBRARIES} ${GNURADIO_ALL_LIBRARIES} ${VOLK_LIBRARIES} ${LIBOSMOCODEC_LIBRARIES} ${LIBOSMOCORE_LIBRARIES}
+# ${LIBOSMOCODING_LIBRARIES}
# libraries required by plotting.h - have troubles to be installed by pybombs
# boost_iostreams
# boost_system
diff --git a/lib/decoding/GSM610Tables.h b/lib/decoding/GSM610Tables.h
deleted file mode 100644
index 53a8e1c..0000000
--- a/lib/decoding/GSM610Tables.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
-* Copyright 2008 Free Software Foundation, Inc.
-*
-* This software is distributed under the terms of the GNU Public License.
-* See the COPYING file in the main directory for details.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-*/
-
-
-
-#ifndef GSM610TABLES_H
-#define GSM610TABLES_H
-
-
-
-namespace GSM {
-
-/** Table #2 from GSM 05.03 */
-extern unsigned int g610BitOrder[260];
-
-}
-
-
-#endif
diff --git a/lib/decoding/Viterbi.h b/lib/decoding/Viterbi.h
deleted file mode 100644
index 8635bf5..0000000
--- a/lib/decoding/Viterbi.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
-* Copyright 2013, 2014 Range Networks, Inc.
-*
-* This software is distributed under multiple licenses;
-* see the COPYING file in the main directory for licensing
-* information for this specific distribution.
-*
-* This use of this software may be subject to additional restrictions.
-* See the LEGAL file in the main directory for details.
-
- 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.
-
-*/
-
-
-#ifndef _VITERBI_H_
-#define _VITERBI_H_ 1
-
-// (pat) Virtual base class for Viterbi and Turbo coder/decoders.
-class ViterbiBase {
- public:
- virtual void encode(const BitVector &in, BitVector& target) const = 0;
- virtual void decode(const SoftVector &in, BitVector& target) = 0;
- // (pat) Return error count from most recent decoder run.
- // If you get -1 from this, the method is not defined in the Viterbi class.
- virtual int getBEC() { return -1; }
- //virtual ~ViterbiBase(); Currently None of these have destructors.
-
- // These functions are logically part of the Viterbi functionality, even though they do not use any class variables.
- unsigned applyPoly(uint64_t val, uint64_t poly);
- unsigned applyPoly(uint64_t val, uint64_t poly, unsigned order);
-};
-#endif
diff --git a/lib/decoding/cch.c b/lib/decoding/cch.c
deleted file mode 100644
index df83d3e..0000000
--- a/lib/decoding/cch.c
+++ /dev/null
@@ -1,558 +0,0 @@
-/*
- The Hacker's Choice - http://www.thc.org
- Part of THC's GSM SCANNER PROJECT
-*/
-
-//#include "system.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <ctype.h>
-
-//#include <exception>
-//#include <stdexcept>
-#include <math.h>
-//#include "burst_types.h"
-#include "cch.h"
-#include "fire_crc.h"
-
-
-/*
- * GSM SACCH -- Slow Associated Control Channel
- *
- * These messages are encoded exactly the same as on the BCCH.
- * (Broadcast Control Channel.)
- *
- * Input: 184 bits
- *
- * 1. Add parity and flushing bits. (Output 184 + 40 + 4 = 228 bit)
- * 2. Convolutional encode. (Output 228 * 2 = 456 bit)
- * 3. Interleave. (Output 456 bit)
- * 4. Map on bursts. (4 x 156 bit bursts with each 2x57 bit content data)
- */
-
-
-/*
- * Parity (FIRE) for the GSM SACCH channel.
- *
- * g(x) = (x^23 + 1)(x^17 + x^3 + 1)
- * = x^40 + x^26 + x^23 + x^17 + x^3 + 1
- */
-
-static const unsigned char parity_polynomial[PARITY_SIZE + 1] = {
- 1, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 1, 0,
- 0, 1, 0, 0, 0, 0, 0, 1,
- 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 1, 0, 0,
- 1
-};
-
-// remainder after dividing data polynomial by g(x)
-static const unsigned char parity_remainder[PARITY_SIZE] = {
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1,
- 1, 1, 1, 1, 1, 1, 1, 1
-};
-
-
-/*
-static void parity_encode(unsigned char *d, unsigned char *p) {
-
- int i;
- unsigned char buf[DATA_BLOCK_SIZE + PARITY_SIZE], *q;
-
- memcpy(buf, d, DATA_BLOCK_SIZE);
- memset(buf + DATA_BLOCK_SIZE, 0, PARITY_SIZE);
-
- for(q = buf; q < buf + DATA_BLOCK_SIZE; q++)
- if(*q)
- for(i = 0; i < PARITY_SIZE + 1; i++)
- q[i] ^= parity_polynomial[i];
- for(i = 0; i < PARITY_SIZE; i++)
- p[i] = !buf[DATA_BLOCK_SIZE + i];
-}
- */
-
-
-int parity_check(unsigned char *d) {
-
- unsigned int i;
- unsigned char buf[DATA_BLOCK_SIZE + PARITY_SIZE], *q;
-
- memcpy(buf, d, DATA_BLOCK_SIZE + PARITY_SIZE);
-
- for(q = buf; q < buf + DATA_BLOCK_SIZE; q++)
- if(*q)
- for(i = 0; i < PARITY_SIZE + 1; i++)
- q[i] ^= parity_polynomial[i];
- return memcmp(buf + DATA_BLOCK_SIZE, parity_remainder, PARITY_SIZE);
-}
-
-
-/*
- * Convolutional encoding and Viterbi decoding for the GSM SACCH channel.
- */
-
-/*
- * Convolutional encoding:
- *
- * G_0 = 1 + x^3 + x^4
- * G_1 = 1 + x + x^3 + x^4
- *
- * i.e.,
- *
- * c_{2k} = u_k + u_{k - 3} + u_{k - 4}
- * c_{2k + 1} = u_k + u_{k - 1} + u_{k - 3} + u_{k - 4}
- */
-#define K 5
-#define MAX_ERROR (2 * CONV_INPUT_SIZE + 1)
-
-
-/*
- * Given the current state and input bit, what are the output bits?
- *
- * encode[current_state][input_bit]
- */
-static const unsigned int encode[1 << (K - 1)][2] = {
- {0, 3}, {3, 0}, {3, 0}, {0, 3},
- {0, 3}, {3, 0}, {3, 0}, {0, 3},
- {1, 2}, {2, 1}, {2, 1}, {1, 2},
- {1, 2}, {2, 1}, {2, 1}, {1, 2}
-};
-
-
-/*
- * Given the current state and input bit, what is the next state?
- *
- * next_state[current_state][input_bit]
- */
-static const unsigned int next_state[1 << (K - 1)][2] = {
- {0, 8}, {0, 8}, {1, 9}, {1, 9},
- {2, 10}, {2, 10}, {3, 11}, {3, 11},
- {4, 12}, {4, 12}, {5, 13}, {5, 13},
- {6, 14}, {6, 14}, {7, 15}, {7, 15}
-};
-
-
-/*
- * Given the previous state and the current state, what input bit caused
- * the transition? If it is impossible to transition between the two
- * states, the value is 2.
- *
- * prev_next_state[previous_state][current_state]
- */
-static const unsigned int prev_next_state[1 << (K - 1)][1 << (K - 1)] = {
- { 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2},
- { 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2},
- { 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2},
- { 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2},
- { 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2},
- { 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2},
- { 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2},
- { 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2},
- { 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2},
- { 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2},
- { 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2},
- { 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2},
- { 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2},
- { 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2},
- { 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1},
- { 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1}
-};
-
-
-static inline unsigned int hamming_distance2(unsigned int w) {
-
- return (w & 1) + !!(w & 2);
-}
-
-
-/*
-static void conv_encode(unsigned char *data, unsigned char *output) {
-
- unsigned int i, state = 0, o;
-
- // encode data
- for(i = 0; i < CONV_INPUT_SIZE; i++) {
- o = encode[state][data[i]];
- state = next_state[state][data[i]];
- *output++ = !!(o & 2);
- *output++ = o & 1;
- }
-}
- */
-
-
-int conv_decode(unsigned char *output, unsigned char *data) {
-
- int i, t;
- unsigned int rdata, state, nstate, b, o, distance, accumulated_error,
- min_state, min_error, cur_state;
-
- unsigned int ae[1 << (K - 1)]; // accumulated error
- unsigned int nae[1 << (K - 1)]; // next accumulated error
- unsigned int state_history[1 << (K - 1)][CONV_INPUT_SIZE + 1];
-
- // initialize accumulated error, assume starting state is 0
- for(i = 0; i < (1 << (K - 1)); i++){
- ae[i] = nae[i] = MAX_ERROR;
- }
-
- ae[0] = 0;
-
- // build trellis
- for(t = 0; t < CONV_INPUT_SIZE; t++) {
-
- // get received data symbol
- rdata = (data[2 * t] << 1) | data[2 * t + 1];
-
- // for each state
- for(state = 0; state < (1 << (K - 1)); state++) {
-
- // make sure this state is possible
- if(ae[state] >= MAX_ERROR)
- continue;
-
- // find all states we lead to
- for(b = 0; b < 2; b++) {
-
- // get next state given input bit b
- nstate = next_state[state][b];
-
- // find output for this transition
- o = encode[state][b];
-
- // calculate distance from received data
- distance = hamming_distance2(rdata ^ o);
-
- // choose surviving path
- accumulated_error = ae[state] + distance;
- if(accumulated_error < nae[nstate]) {
-
- // save error for surviving state
- nae[nstate] = accumulated_error;
-
- // update state history
- state_history[nstate][t + 1] = state;
- }
- }
- }
-
- // get accumulated error ready for next time slice
- for(i = 0; i < (1 << (K - 1)); i++) {
- ae[i] = nae[i];
- nae[i] = MAX_ERROR;
- }
- }
-
- // the final state is the state with the fewest errors
- min_state = (unsigned int)-1;
- min_error = MAX_ERROR;
- for(i = 0; i < (1 << (K - 1)); i++) {
- if(ae[i] < min_error) {
- min_state = i;
- min_error = ae[i];
- }
- }
-
- // trace the path
- cur_state = min_state;
- for(t = CONV_INPUT_SIZE; t >= 1; t--) {
- min_state = cur_state;
- cur_state = state_history[cur_state][t]; // get previous
- output[t - 1] = prev_next_state[cur_state][min_state];
- }
-
- // return the number of errors detected (hard-decision)
- return min_error;
-}
-
-
-/*
- * GSM SACCH interleaving and burst mapping
- *
- * Interleaving:
- *
- * Given 456 coded input bits, form 4 blocks of 114 bits:
- *
- * i(B, j) = c(n, k) k = 0, ..., 455
- * n = 0, ..., N, N + 1, ...
- * B = B_0 + 4n + (k mod 4)
- * j = 2(49k mod 57) + ((k mod 8) div 4)
- *
- * Mapping on Burst:
- *
- * e(B, j) = i(B, j)
- * e(B, 59 + j) = i(B, 57 + j) j = 0, ..., 56
- * e(B, 57) = h_l(B)
- * e(B, 58) = h_n(B)
- *
- * Where h_l(B) and h_n(B) are bits in burst B indicating flags.
- */
-
-/*
-static void interleave(unsigned char *data, unsigned char *iBLOCK) {
-
- int j, k, B;
-
- // for each bit in input data
- for(k = 0; k < CONV_SIZE; k++) {
- B = k % 4;
- j = 2 * ((49 * k) % 57) + ((k % 8) / 4);
- iBLOCK[B * iBLOCK_SIZE + j] = data[k];
- }
-}
- */
-
-
-#if 0
-static void decode_interleave(unsigned char *data, unsigned char *iBLOCK) {
-
- int j, k, B;
-
- for(k = 0; k < CONV_SIZE; k++) {
- B = k % 4;
- j = 2 * ((49 * k) % 57) + ((k % 8) / 4);
- data[k] = iBLOCK[B * iBLOCK_SIZE + j];
- }
-}
-
-#endif
-
-/*
-static void burstmap(unsigned char *iBLOCK, unsigned char *eBLOCK,
- unsigned char hl, unsigned char hn) {
-
- int j;
-
- for(j = 0; j < 57; j++) {
- eBLOCK[j] = iBLOCK[j];
- eBLOCK[j + 59] = iBLOCK[j + 57];
- }
- eBLOCK[57] = hl;
- eBLOCK[58] = hn;
-}
- */
-
-
-static void decode_burstmap(unsigned char *iBLOCK, unsigned char *eBLOCK,
- unsigned char *hl, unsigned char *hn) {
-
- int j;
-
- for(j = 0; j < 57; j++) {
- iBLOCK[j] = eBLOCK[j];
- iBLOCK[j + 57] = eBLOCK[j + 59];
- }
- *hl = eBLOCK[57];
- *hn = eBLOCK[58];
-}
-
-
-/*
- * Transmitted bits are sent least-significant first.
- */
-static int compress_bits(unsigned char *dbuf, unsigned int dbuf_len,
- unsigned char *sbuf, unsigned int sbuf_len) {
-
- unsigned int i, j, c, pos = 0;
-
- if(dbuf_len < ((sbuf_len + 7) >> 3))
- return -1;
-
- for(i = 0; i < sbuf_len; i += 8) {
- for(j = 0, c = 0; (j < 8) && (i + j < sbuf_len); j++)
- c |= (!!sbuf[i + j]) << j;
- dbuf[pos++] = c & 0xff;
- }
- return pos;
-}
-
-
-#if 0
-int get_ns_l3_len(unsigned char *data, unsigned int datalen) {
-
- if((data[0] & 3) != 1) {
- fprintf(stderr, "error: get_ns_l3_len: pseudo-length reserved "
- "bits bad (%2.2x)\n", data[0] & 3);
- return -1;
- }
- return (data[0] >> 2);
-}
-
-#endif
-
-
-/*static unsigned char *decode_sacch(GS_CTX *ctx, unsigned char *burst, unsigned int *datalen) {*/
-
-/* int errors, len, data_size;*/
-/* unsigned char conv_data[CONV_SIZE], iBLOCK[BLOCKS][iBLOCK_SIZE],*/
-/* hl, hn, decoded_data[PARITY_OUTPUT_SIZE];*/
-/* FC_CTX fc_ctx;*/
-
-/* data_size = sizeof ctx->msg;*/
-/* if(datalen)*/
-/* *datalen = 0;*/
-
-/* // unmap the bursts*/
-/* decode_burstmap(iBLOCK[0], burst, &hl, &hn); // XXX ignore stealing bits*/
-/* decode_burstmap(iBLOCK[1], burst + 116, &hl, &hn);*/
-/* decode_burstmap(iBLOCK[2], burst + 116 * 2, &hl, &hn);*/
-/* decode_burstmap(iBLOCK[3], burst + 116 * 3, &hl, &hn);*/
-
-/* // remove interleave*/
-/* interleave_decode(&ctx->interleave_ctx, conv_data, (unsigned char *)iBLOCK);*/
-/* //decode_interleave(conv_data, (unsigned char *)iBLOCK);*/
-
-/* // Viterbi decode*/
-/* errors = conv_decode(decoded_data, conv_data);*/
-/* //DEBUGF("conv_decode: %d\n", errors);*/
-
-/* // check parity*/
-/* // If parity check error detected try to fix it.*/
-/* if (parity_check(decoded_data))*/
-/* {*/
-/* unsigned char crc_result[224];*/
-/* if (FC_check_crc(&fc_ctx, decoded_data, crc_result) == 0)*/
-/* {*/
-/* errors = -1;*/
-/* //DEBUGF("error: sacch: parity error (%d fn=%d)\n",*/
-/* // errors, ctx->fn);*/
-/* return NULL;*/
-/* } else {*/
-/* //DEBUGF("Successfully corrected parity bits! (errors=%d fn=%d)\n",*/
-/* // errors, ctx->fn);*/
-/* memcpy(decoded_data, crc_result, sizeof crc_result);*/
-/* errors = 0;*/
-/* }*/
-/* }*/
-
-/* if (errors)*/
-/* printf("WRN: errors=%d fn=%d\n", errors, ctx->fn);*/
-
-/* if((len = compress_bits(ctx->msg, data_size, decoded_data,*/
-/* DATA_BLOCK_SIZE)) < 0) {*/
-/* fprintf(stderr, "error: compress_bits\n");*/
-/* return NULL;*/
-/* }*/
-/* if(len < data_size) {*/
-/* fprintf(stderr, "error: buf too small (%d < %d)\n",*/
-/* sizeof(ctx->msg), len);*/
-/* return NULL;*/
-/* }*/
-
-/* if(datalen)*/
-/* *datalen = (unsigned int)len;*/
-/* return ctx->msg;*/
-/*}*/
-
-
-/*
- * decode_cch
- *
- * Decode a "common" control channel. Most control channels use
- * the same burst, interleave, Viterbi and parity configuration.
- * The documentation for the control channels defines SACCH first
- * and then just keeps referring to that.
- *
- * The current (investigated) list is as follows:
- *
- * BCCH Norm
- * BCCH Ext
- * PCH
- * AGCH
- * CBCH (SDCCH/4)
- * CBCH (SDCCH/8)
- * SDCCH/4
- * SACCH/C4
- * SDCCH/8
- * SACCH/C8
- *
- * We provide two functions, one for where all four bursts are
- * contiguous, and one where they aren't.
- */
-/*unsigned char *decode_cch(GS_CTX *ctx, unsigned char *burst, unsigned int *datalen) {*/
-
-/* return decode_sacch(ctx, burst, datalen);*/
-/*}*/
-
-
-#if 0
-unsigned char *decode_cch(GS_CTX *ctx, unsigned char *e, unsigned int *datalen) {
-
- return decode_sacch(ctx, e, e + eBLOCK_SIZE, e + 2 * eBLOCK_SIZE,
- e + 3 * eBLOCK_SIZE, datalen);
-}
-#endif
-
-/*unsigned char *decode_facch(GS_CTX *ctx, unsigned char *burst, unsigned int *datalen, int offset) {*/
-
-/* int errors, len, data_size;*/
-/* unsigned char conv_data[CONV_SIZE], iBLOCK[BLOCKS * 2][iBLOCK_SIZE],*/
-/* hl, hn, decoded_data[PARITY_OUTPUT_SIZE];*/
-/* FC_CTX fc_ctx;*/
-
-/* data_size = sizeof ctx->msg;*/
-/* if(datalen)*/
-/* *datalen = 0;*/
-
-/* // unmap the bursts*/
-/* decode_burstmap(iBLOCK[0], burst, &hl, &hn); // XXX ignore stealing bits*/
-/* decode_burstmap(iBLOCK[1], burst + 116, &hl, &hn);*/
-/* decode_burstmap(iBLOCK[2], burst + 116 * 2, &hl, &hn);*/
-/* decode_burstmap(iBLOCK[3], burst + 116 * 3, &hl, &hn);*/
-/* decode_burstmap(iBLOCK[4], burst + 116 * 4, &hl, &hn);*/
-/* decode_burstmap(iBLOCK[5], burst + 116 * 5, &hl, &hn);*/
-/* decode_burstmap(iBLOCK[6], burst + 116 * 6, &hl, &hn);*/
-/* decode_burstmap(iBLOCK[7], burst + 116 * 7, &hl, &hn);*/
-
-/* // remove interleave*/
-/* if (offset == 0)*/
-/* interleave_decode(&ctx->interleave_facch_f1_ctx, conv_data, (unsigned char *)iBLOCK);*/
-/* else*/
-/* interleave_decode(&ctx->interleave_facch_f2_ctx, conv_data, (unsigned char *)iBLOCK);*/
-/* //decode_interleave(conv_data, (unsigned char *)iBLOCK);*/
-
-/* // Viterbi decode*/
-/* errors = conv_decode(decoded_data, conv_data);*/
-/* //DEBUGF("conv_decode: %d\n", errors);*/
-
-/* // check parity*/
-/* // If parity check error detected try to fix it.*/
-/* if (parity_check(decoded_data)) {*/
-/* FC_init(&fc_ctx, 40, 184);*/
-/* unsigned char crc_result[224];*/
-/* if (FC_check_crc(&fc_ctx, decoded_data, crc_result) == 0)*/
-/* {*/
-/* //DEBUGF("error: sacch: parity error (errors=%d fn=%d)\n", errors, ctx->fn);*/
-/* errors = -1;*/
-/* return NULL;*/
-/* } else {*/
-/* //DEBUGF("Successfully corrected parity bits! (errors=%d fn=%d)\n", errors, ctx->fn);*/
-/* memcpy(decoded_data, crc_result, sizeof crc_result);*/
-/* errors = 0;*/
-/* }*/
-/* }*/
-
-/* if (errors)*/
-/* fprintf(stderr, "WRN: errors=%d fn=%d\n", errors, ctx->fn);*/
-
-/* if ((len = compress_bits(ctx->msg, data_size, decoded_data,*/
-/* DATA_BLOCK_SIZE)) < 0) {*/
-/* fprintf(stderr, "error: compress_bits\n");*/
-/* return NULL;*/
-/* }*/
-/* if (len < data_size) {*/
-/* fprintf(stderr, "error: buf too small (%d < %d)\n",*/
-/* sizeof(ctx->msg), len);*/
-/* return NULL;*/
-/* }*/
-
-/* if (datalen)*/
-/* *datalen = (unsigned int)len;*/
-/* return ctx->msg;*/
-/*}*/
diff --git a/lib/decoding/cch.h b/lib/decoding/cch.h
deleted file mode 100644
index e371213..0000000
--- a/lib/decoding/cch.h
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- The Hacker's Choice - http://www.thc.org
- Part of THC's GSM SCANNER PROJECT
-*/
-
-#ifndef __GSMSTACK_CCH_H__
-#define __GSMSTACK_CCH_H__ 1
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-//#include "gsmstack.h"
-
-/*
- * decode_cch
- *
- * Decode a "common" control channel. Most control channels use
- * the same burst, interleave, Viterbi and parity configuration.
- * The documentation for the control channels defines SACCH first
- * and then just keeps referring to that.
- *
- * The current (investigated) list is as follows:
- *
- * BCCH Norm
- * BCCH Ext
- * PCH
- * AGCH
- * CBCH (SDCCH/4)
- * CBCH (SDCCH/8)
- * SDCCH/4
- * SACCH/C4
- * SDCCH/8
- * SACCH/C8
- *
- * We provide two functions, one for where all four bursts are
- * contiguous, and one where they aren't.
- */
-
-#define DATA_BLOCK_SIZE 184
-#define PARITY_SIZE 40
-#define FLUSH_BITS_SIZE 4
-#define PARITY_OUTPUT_SIZE (DATA_BLOCK_SIZE + PARITY_SIZE + FLUSH_BITS_SIZE)
-
-#define CONV_INPUT_SIZE PARITY_OUTPUT_SIZE
-#define CONV_SIZE (2 * CONV_INPUT_SIZE)
-
-#define BLOCKS 4
-#define iBLOCK_SIZE (CONV_SIZE / BLOCKS)
-#define eBLOCK_SIZE (iBLOCK_SIZE + 2)
-
-int conv_decode(unsigned char *output, unsigned char *data);
-int parity_check(unsigned char *d);
-//unsigned char *decode_cch(GS_CTX *ctx, unsigned char *burst, unsigned int *len);
-//unsigned char *decode_facch(GS_CTX *ctx, unsigned char *burst, unsigned int *len, int offset);
-//unsigned char *decode_cch(GS_CTX *ctx, unsigned char *, unsigned char *, unsigned char *, unsigned char *, unsigned int *len);
-//unsigned char *decode_cch(GS_CTX *ctx, unsigned char *, unsigned int *);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/lib/decoding/control_channels_decoder_impl.cc b/lib/decoding/control_channels_decoder_impl.cc
index 532e255..a6abaa3 100644
--- a/lib/decoding/control_channels_decoder_impl.cc
+++ b/lib/decoding/control_channels_decoder_impl.cc
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2014 by Piotr Krysik <ptrkrysik@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
@@ -33,6 +33,25 @@
namespace gr {
namespace gsm {
+ static int ubits2sbits(ubit_t *ubits, sbit_t *sbits, int count)
+ {
+ int i;
+
+ for (i = 0; i < count; i++) {
+ if (*ubits == 0x23) {
+ ubits++;
+ sbits++;
+ continue;
+ }
+ if ((*ubits++) & 1)
+ *sbits++ = -127;
+ else
+ *sbits++ = 127;
+ }
+
+ return count;
+ }
+
control_channels_decoder::sptr
control_channels_decoder::make()
{
@@ -49,18 +68,6 @@
gr::io_signature::make(0, 0, 0)),
d_collected_bursts_num(0)
{
- //initialize de/interleaver
- int j, k, B;
- for (k = 0; k < CONV_SIZE; k++)
- {
- B = k % 4;
- j = 2 * ((49 * k) % 57) + ((k % 8) / 4);
- interleave_trans[k] = B * 114 + j; //114=57 + 57
- }
-
- //initialize decoder
- FC_init(&fc_ctx, 40, 184);
-
//setup input/output ports
message_port_register_in(pmt::mp("bursts"));
set_msg_handler(pmt::mp("bursts"), boost::bind(&control_channels_decoder_impl::decode, this, _1));
@@ -73,78 +80,44 @@
void control_channels_decoder_impl::decode(pmt::pmt_t msg)
{
- unsigned char iBLOCK[BLOCKS*iBLOCK_SIZE], hl, hn, conv_data[CONV_SIZE], decoded_data[PARITY_OUTPUT_SIZE];
+ ubit_t bursts_u[116 * 4];
+ sbit_t bursts_s[116 * 4];
+ uint8_t result[23];
+ int n_errors, n_bits_total;
+ int8_t header_plus_data[sizeof(gsmtap_hdr)+DATA_BYTES];
+
d_bursts[d_collected_bursts_num] = msg;
d_collected_bursts_num++;
+
//get convecutive bursts
-
if(d_collected_bursts_num==4)
{
d_collected_bursts_num=0;
- //reorganize data
+ //reorganize data from input bursts
for(int ii = 0; ii < 4; ii++)
{
pmt::pmt_t header_plus_burst = pmt::cdr(d_bursts[ii]);
int8_t * burst_bits = (int8_t *)(pmt::blob_data(header_plus_burst))+sizeof(gsmtap_hdr);
- for(int jj = 0; jj < 57; jj++)
- {
- iBLOCK[ii*iBLOCK_SIZE+jj] = burst_bits[jj + 3];
- iBLOCK[ii*iBLOCK_SIZE+jj+57] = burst_bits[jj + 88]; //88 = 3+57+1+26+1
- }
+ memcpy(&bursts_u[ii*116], &burst_bits[3],58);
+ memcpy(&bursts_u[ii*116+58], &burst_bits[3+57+1+26],58);
}
- //deinterleave
- for (int k = 0; k < CONV_SIZE; k++)
- {
- conv_data[k] = iBLOCK[interleave_trans[k]];
- }
- //convolutional code decode
- int errors = conv_decode(decoded_data, conv_data);
- //std::cout << "Errors:" << errors << " " << parity_check(decoded_data) << std::endl;
- // check parity
- // If parity check error detected try to fix it.
+ //convert to soft bits
+ ubits2sbits(bursts_u, bursts_s, 116 * 4);
+ //decode
+ gsm0503_xcch_decode(result, bursts_s, &n_errors, &n_bits_total);
- if (parity_check(decoded_data))
- {
- FC_init(&fc_ctx, 40, 184);
- unsigned char crc_result[PARITY_OUTPUT_SIZE];
- if (FC_check_crc(&fc_ctx, decoded_data, crc_result) == 0)
- {
- //("error: sacch: parity error (errors=%d fn=%d)\n", errors, ctx->fn);
- //std::cout << "Uncorrectable errors!" << std::endl;
- errors = -1;
- return;
- } else {
- //DEBUGF("Successfully corrected parity bits! (errors=%d fn=%d)\n", errors, ctx->fn);
- //std::cout << "Corrected some errors" << std::endl;
- memcpy(decoded_data, crc_result, PARITY_OUTPUT_SIZE);
- errors = 0;
- }
- } else {
- //std::cout << "Everything correct" << std::endl;
- }
- //compress bits
- unsigned char outmsg[28];
- unsigned char sbuf_len=224;
- int i, j, c, pos=0;
- for(i = 0; i < sbuf_len; i += 8) {
- for(j = 0, c = 0; (j < 8) && (i + j < sbuf_len); j++){
- c |= (!!decoded_data[i + j]) << j;
- }
- outmsg[pos++] = c & 0xff;
- }
-
- //send message with header of the first burst
+ //extract header of the first burst of the four bursts
pmt::pmt_t first_header_plus_burst = pmt::cdr(d_bursts[0]);
gsmtap_hdr * header = (gsmtap_hdr *)pmt::blob_data(first_header_plus_burst);
- int8_t header_plus_data[sizeof(gsmtap_hdr)+DATA_BYTES];
+ //copy header and data
memcpy(header_plus_data, header, sizeof(gsmtap_hdr));
- memcpy(header_plus_data+sizeof(gsmtap_hdr), outmsg, DATA_BYTES);
+ memcpy(header_plus_data+sizeof(gsmtap_hdr), result, DATA_BYTES);
+ //set data type in the header
((gsmtap_hdr*)header_plus_data)->type = GSMTAP_TYPE_UM;
-
- pmt::pmt_t msg_binary_blob = pmt::make_blob(header_plus_data,DATA_BYTES+sizeof(gsmtap_hdr));
- pmt::pmt_t msg_out = pmt::cons(pmt::PMT_NIL, msg_binary_blob);
-
+ //prepare message
+ pmt::pmt_t msg_out = pmt::cons(pmt::PMT_NIL, pmt::make_blob(header_plus_data,DATA_BYTES+sizeof(gsmtap_hdr)));
+ //send message to the output
message_port_pub(pmt::mp("msgs"), msg_out);
}
return;
diff --git a/lib/decoding/control_channels_decoder_impl.h b/lib/decoding/control_channels_decoder_impl.h
index 2fa3dce..3464324 100644
--- a/lib/decoding/control_channels_decoder_impl.h
+++ b/lib/decoding/control_channels_decoder_impl.h
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2014 by Piotr Krysik <ptrkrysik@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
@@ -24,8 +24,9 @@
#define INCLUDED_GSM_CONTROL_CHANNELS_DECODER_IMPL_H
#include <grgsm/decoding/control_channels_decoder.h>
-#include "fire_crc.h"
-#include "cch.h"
+extern "C" {
+ #include "osmocom/coding/gsm0503_coding.h"
+}
namespace gr {
namespace gsm {
@@ -35,9 +36,8 @@
private:
unsigned int d_collected_bursts_num;
pmt::pmt_t d_bursts[4];
- unsigned short interleave_trans[CONV_SIZE];
- FC_CTX fc_ctx;
- void decode(pmt::pmt_t msg);
+
+ void decode(pmt::pmt_t msg);
public:
control_channels_decoder_impl();
~control_channels_decoder_impl();
diff --git a/lib/decoding/fire_crc.c b/lib/decoding/fire_crc.c
deleted file mode 100644
index 5800517..0000000
--- a/lib/decoding/fire_crc.c
+++ /dev/null
@@ -1,163 +0,0 @@
-/*
- The Hacker's Choice - http://www.thc.org
- Part of THC's GSM SCANNER PROJECT
-*/
-
-
-#include "fire_crc.h"
-#include <stdio.h>
-#include <string.h>
-
-#define REM(x, y) (x) % (y)
-
-static int FC_syndrome_shift(FC_CTX *ctx, unsigned int bit);
-
-static int
-outit(int *data, int len)
-{
- int i;
-
- for (i = 0; i < len; i++)
- printf("%d ", data[i]);
- printf("\n");
- return 0;
-}
-
-int
-FC_init(FC_CTX *ctx, unsigned int crc_size, unsigned int data_size)
-{
- ctx->crc_size = crc_size;
- ctx->data_size = data_size;
- ctx->syn_start = 0;
-
- return 0;
-}
-
-int
-FC_check_crc(FC_CTX *ctx, unsigned char *input_bits, unsigned char *control_data)
-{
- int j,error_count = 0, error_index = 0, success_flag = 0, syn_index = 0;
- unsigned int i;
-
- ctx->syn_start = 0;
- // reset the syndrome register
- memset(ctx->syndrome_reg, 0, sizeof ctx->syndrome_reg);
-
- // shift in the data bits
- for (i=0; i < ctx->data_size; i++) {
- error_count = FC_syndrome_shift(ctx, input_bits[i]);
- control_data[i] = input_bits[i];
- }
-
- // shift in the crc bits
- for (i=0; i < ctx->crc_size; i++) {
- error_count = FC_syndrome_shift(ctx, 1-input_bits[i+ctx->data_size]);
- }
-
- // Find position of error burst
- if (error_count == 0) {
- error_index = 0;
- }
- else {
- error_index = 1;
- error_count = FC_syndrome_shift(ctx, 0);
- error_index += 1;
- while (error_index < (ctx->data_size + ctx->crc_size) ) {
- error_count = FC_syndrome_shift(ctx, 0);
- error_index += 1;
- if ( error_count == 0 ) break;
- }
- }
-
- // Test for correctable errors
- //printf("error_index %d\n",error_index);
- if (error_index == 224) success_flag = 0;
- else {
-
- // correct index depending on the position of the error
- if (error_index == 0) syn_index = error_index;
- else syn_index = error_index - 1;
-
- // error burst lies within data bits
- if (error_index < 184) {
- //printf("error < bit 184,%d\n",error_index);
- j = error_index;
- while ( j < (error_index+12) ) {
- if (j < 184) {
- control_data[j] = control_data[j] ^
- ctx->syndrome_reg[REM(ctx->syn_start+39-j+syn_index,40)];
- }
- else break;
- j = j + 1;
- }
- }
- else if ( error_index > 212 ) {
- //printf("error > bit 212,%d\n",error_index);
- j = 0;
- while ( j < (error_index - 212) ) {
- control_data[j] = control_data[j] ^
- ctx->syndrome_reg[REM(ctx->syn_start+39-j-224+syn_index,40)];
- j = j + 1;
- }
- }
- // for 183 < error_index < 213 error in parity alone so ignore
- success_flag = 1;
- }
- return success_flag;
-}
-
-static int
-FC_syndrome_shift(FC_CTX *ctx, unsigned int bit)
-{
- int error_count = 0;
- unsigned int i;
-
- if (ctx->syn_start == 0)
- ctx->syn_start = 39;
- else ctx->syn_start -= 1;
-
- int temp_syndrome_reg[sizeof ctx->syndrome_reg];
-
- memcpy(temp_syndrome_reg, ctx->syndrome_reg, sizeof temp_syndrome_reg);
-
- temp_syndrome_reg[REM(ctx->syn_start+3,40)] =
- ctx->syndrome_reg[REM(ctx->syn_start+3,40)] ^
- ctx->syndrome_reg[ctx->syn_start];
- temp_syndrome_reg[REM(ctx->syn_start+17,40)] =
- ctx->syndrome_reg[REM(ctx->syn_start+17,40)] ^
- ctx->syndrome_reg[ctx->syn_start];
- temp_syndrome_reg[REM(ctx->syn_start+23,40)] =
- ctx->syndrome_reg[REM(ctx->syn_start+23,40)] ^
- ctx->syndrome_reg[ctx->syn_start];
- temp_syndrome_reg[REM(ctx->syn_start+26,40)] =
- ctx->syndrome_reg[REM(ctx->syn_start+26,40)] ^
- ctx->syndrome_reg[ctx->syn_start];
-
- temp_syndrome_reg[REM(ctx->syn_start+4,40)] =
- ctx->syndrome_reg[REM(ctx->syn_start+4,40)] ^ bit;
- temp_syndrome_reg[REM(ctx->syn_start+6,40)] =
- ctx->syndrome_reg[REM(ctx->syn_start+6,40)] ^ bit;
- temp_syndrome_reg[REM(ctx->syn_start+10,40)] =
- ctx->syndrome_reg[REM(ctx->syn_start+10,40)] ^ bit;
- temp_syndrome_reg[REM(ctx->syn_start+16,40)] =
- ctx->syndrome_reg[REM(ctx->syn_start+16,40)] ^ bit;
- temp_syndrome_reg[REM(ctx->syn_start+27,40)] =
- ctx->syndrome_reg[REM(ctx->syn_start+27,40)] ^ bit;
- temp_syndrome_reg[REM(ctx->syn_start+29,40)] =
- ctx->syndrome_reg[REM(ctx->syn_start+29,40)] ^ bit;
- temp_syndrome_reg[REM(ctx->syn_start+33,40)] =
- ctx->syndrome_reg[REM(ctx->syn_start+33,40)] ^ bit;
- temp_syndrome_reg[REM(ctx->syn_start+39,40)] =
- ctx->syndrome_reg[REM(ctx->syn_start+39,40)] ^ bit;
-
- temp_syndrome_reg[ctx->syn_start] = ctx->syndrome_reg[ctx->syn_start] ^ bit;
-
- memcpy(ctx->syndrome_reg, temp_syndrome_reg, sizeof ctx->syndrome_reg);
-
- for (i = 0; i < 28; i++) {
- error_count = error_count + ctx->syndrome_reg[REM(ctx->syn_start+i,40)];
- }
- return error_count;
-}
-
-
diff --git a/lib/decoding/fire_crc.h b/lib/decoding/fire_crc.h
deleted file mode 100644
index d02021e..0000000
--- a/lib/decoding/fire_crc.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- The Hacker's Choice - http://www.thc.org
- Part of THC's GSM SCANNER PROJECT
-*/
-
-
-
-#ifndef INCLUDED_FIRE_CRC_H
-#define INCLUDED_FIRE_CRC_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct
-{
- unsigned int crc_size;
- unsigned int data_size;
- unsigned int syn_start;
- int syndrome_reg[40];
-} FC_CTX;
-
-int FC_init(FC_CTX *ctx, unsigned int crc_size, unsigned int data_size);
-int FC_check_crc(FC_CTX *ctx, unsigned char *input_bits, unsigned char *control_data);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/lib/decoding/interleave.c b/lib/decoding/interleave.c
deleted file mode 100644
index c6304db..0000000
--- a/lib/decoding/interleave.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- The Hacker's Choice - http://www.thc.org
- Part of THC's GSM SCANNER PROJECT
-*/
-
-#include <stdlib.h>
-#include <stdio.h>
-#include "interleave.h"
-
-int
-interleave_init(INTERLEAVE_CTX *ictx, int size, int block_size)
-{
- ictx->trans_size = size;
- ictx->trans = (unsigned short *)malloc(size * sizeof *ictx->trans);
-
-// DEBUGF("size: %d\n", size);
-// DEBUGF("Block size: %d\n", block_size);
- int j, k, B;
- for (k = 0; k < size; k++)
- {
- B = k % 4;
- j = 2 * ((49 * k) % 57) + ((k % 8) / 4);
- ictx->trans[k] = B * block_size + j;
- /* Mapping: pos1 goes to pos2: pos1 -> pos2 */
- //printf("%d -> %d\n", ictx->trans[k], k);
- }
-// exit(0);
- return 0;
-}
-
-int
-interleave_init_facch_f(INTERLEAVE_CTX *ictx, int size, int block_size, int block_offset)
-{
- ictx->trans_size = size;
- ictx->trans = (unsigned short *)malloc(size * sizeof *ictx->trans);
-
-// DEBUGF("size: %d\n", size);
-// DEBUGF("Block size: %d\n", block_size);
- int j, k, B;
- for (k = 0; k < size; k++)
- {
- B = (k + block_offset) % 8;
- j = 2 * ((49 * k) % 57) + ((k % 8) / 4);
- ictx->trans[k] = B * block_size + j;
- /* Mapping: pos1 goes to pos2: pos1 -> pos2 */
-// DEBUGF("%d -> %d\n", ictx->trans[k], k);
- }
-// exit(0);
- return 0;
-}
-
-int
-interleave_deinit(INTERLEAVE_CTX *ictx)
-{
- if (ictx->trans != NULL)
- {
- free(ictx->trans);
- ictx->trans = NULL;
- }
-
- return 0;
-}
-
-void
-interleave_decode(INTERLEAVE_CTX *ictx, unsigned char *dst, unsigned char *src)
-{
- printf("Lol\n");
- int k;
- for (k = 0; k < ictx->trans_size; k++)
- {
- printf("k=%d, ictx->trans[k]=%d\n", k, ictx->trans[k]);
- dst[k] = src[ictx->trans[k]];
- }
-}
-
diff --git a/lib/decoding/interleave.h b/lib/decoding/interleave.h
deleted file mode 100644
index aba1dfd..0000000
--- a/lib/decoding/interleave.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- The Hacker's Choice - http://www.thc.org
- Part of THC's GSM SCANNER PROJECT
-*/
-
-/*
- * $Id:$
- */
-
-#ifndef __GSMSP_INTERLEAVE_H__
-#define __GSMSP_INTERLEAVE_H__ 1
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct _interleave_ctx
-{
- unsigned short *trans;
- int trans_size;
-} INTERLEAVE_CTX;
-
-int interleave_init(INTERLEAVE_CTX *ictx, int size, int block_size);
-int interleave_init_facch_f(INTERLEAVE_CTX *ictx, int size, int block_size, int block_offset);
-int interleave_deinit(INTERLEAVE_CTX *ictx);
-void interleave_decode(INTERLEAVE_CTX *ictx, unsigned char *dst, unsigned char *src);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
diff --git a/lib/decoding/AmrCoder.cpp b/lib/decoding/openbts/AmrCoder.cpp
similarity index 98%
rename from lib/decoding/AmrCoder.cpp
rename to lib/decoding/openbts/AmrCoder.cpp
index d02e69c..718baf0 100644
--- a/lib/decoding/AmrCoder.cpp
+++ b/lib/decoding/openbts/AmrCoder.cpp
@@ -1,18 +1,22 @@
/*
-* Copyright 2013, 2014 Range Networks, Inc.
-*
-* This software is distributed under multiple licenses;
-* see the COPYING file in the main directory for licensing
-* information for this specific distribution.
-*
-* This use of this software may be subject to additional restrictions.
-* See the LEGAL file in the main directory for details.
+ * Copyright 2013, 2014 Range Networks, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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.
-
-*/
+ * 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * This use of this software may be subject to additional restrictions.
+ * See the LEGAL file in the main directory for details.
+ */
#include "BitVector.h"
diff --git a/lib/decoding/AmrCoder.h b/lib/decoding/openbts/AmrCoder.h
similarity index 96%
rename from lib/decoding/AmrCoder.h
rename to lib/decoding/openbts/AmrCoder.h
index c1df823..ae49bd0 100644
--- a/lib/decoding/AmrCoder.h
+++ b/lib/decoding/openbts/AmrCoder.h
@@ -1,18 +1,23 @@
/*
-* Copyright 2013, 2014 Range Networks, Inc.
-*
-* This software is distributed under multiple licenses;
-* see the COPYING file in the main directory for licensing
-* information for this specific distribution.
-*
-* This use of this software may be subject to additional restrictions.
-* See the LEGAL file in the main directory for details.
+ * Copyright 2013, 2014 Range Networks, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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.
+ * 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * This use of this software may be subject to additional restrictions.
+ * See the LEGAL file in the main directory for details.
+ */
-*/
#ifndef _AMRCODER_H_
#define _AMRCODER_H_
#include <stdint.h>
diff --git a/lib/decoding/BitVector.cpp b/lib/decoding/openbts/BitVector.cpp
similarity index 90%
rename from lib/decoding/BitVector.cpp
rename to lib/decoding/openbts/BitVector.cpp
index 86f326a..00730f6 100644
--- a/lib/decoding/BitVector.cpp
+++ b/lib/decoding/openbts/BitVector.cpp
@@ -1,31 +1,23 @@
/*
-* Copyright 2008, 2009, 2014 Free Software Foundation, Inc.
-* Copyright 2014 Range Networks, Inc.
-*
-*
-* This software is distributed under the terms of the GNU Affero Public License.
-* See the COPYING file in the main directory for details.
-*
-* This use of this software may be subject to additional restrictions.
-* See the LEGAL file in the main directory for details.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero 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 Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-*/
-
-
-
+ * Copyright 2008, 2009, 2014 Free Software Foundation, Inc.
+ * Copyright 2014 Range Networks, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * This use of this software may be subject to additional restrictions.
+ * See the LEGAL file in the main directory for details.
+ */
#include "BitVector.h"
#include <iostream>
diff --git a/lib/decoding/BitVector.h b/lib/decoding/openbts/BitVector.h
similarity index 91%
rename from lib/decoding/BitVector.h
rename to lib/decoding/openbts/BitVector.h
index 0899817..c8782eb 100644
--- a/lib/decoding/BitVector.h
+++ b/lib/decoding/openbts/BitVector.h
@@ -1,28 +1,23 @@
/*
-* Copyright 2008, 2009, 2014 Free Software Foundation, Inc.
-* Copyright 2014 Range Networks, Inc.
-*
-* This software is distributed under the terms of the GNU Affero Public License.
-* See the COPYING file in the main directory for details.
-*
-* This use of this software may be subject to additional restrictions.
-* See the LEGAL file in the main directory for details.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero 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 Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-*/
-
+ * Copyright 2008, 2009, 2014 Free Software Foundation, Inc.
+ * Copyright 2014 Range Networks, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * This use of this software may be subject to additional restrictions.
+ * See the LEGAL file in the main directory for details.
+ */
#ifndef BITVECTORS_H
#define BITVECTORS_H
diff --git a/lib/decoding/GSM503Tables.cpp b/lib/decoding/openbts/GSM503Tables.cpp
similarity index 93%
rename from lib/decoding/GSM503Tables.cpp
rename to lib/decoding/openbts/GSM503Tables.cpp
index 02150f2..fb0f235 100644
--- a/lib/decoding/GSM503Tables.cpp
+++ b/lib/decoding/openbts/GSM503Tables.cpp
@@ -1,18 +1,22 @@
/*
-* Copyright 2012, 2014 Range Networks, Inc.
-*
-* This software is distributed under multiple licenses; see the COPYING file in the main directory for licensing information for this specific distribution.
-*
-* This use of this software may be subject to additional restrictions.
-* See the LEGAL file in the main directory for details.
-
- 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.
-
-*/
-
-
+ * Copyright 2012, 2014 Range Networks, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * This use of this software may be subject to additional restrictions.
+ * See the LEGAL file in the main directory for details.
+ */
#include "GSM503Tables.h"
diff --git a/lib/decoding/GSM503Tables.h b/lib/decoding/openbts/GSM503Tables.h
similarity index 67%
rename from lib/decoding/GSM503Tables.h
rename to lib/decoding/openbts/GSM503Tables.h
index 6b6327c..1fe405e 100644
--- a/lib/decoding/GSM503Tables.h
+++ b/lib/decoding/openbts/GSM503Tables.h
@@ -1,18 +1,22 @@
/*
-* Copyright 2012, 2014 Range Networks, Inc.
-*
-* This software is distributed under multiple licenses; see the COPYING file in the main directory for licensing information for this specific distribution.
-*
-* This use of this software may be subject to additional restrictions.
-* See the LEGAL file in the main directory for details.
-
- 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.
-
-*/
-
-
+ * Copyright 2012, 2014 Range Networks, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * This use of this software may be subject to additional restrictions.
+ * See the LEGAL file in the main directory for details.
+ */
#ifndef GSM503TABLES_H
#define GSM503TABLES_H
diff --git a/lib/decoding/GSM610Tables.cpp b/lib/decoding/openbts/GSM610Tables.cpp
similarity index 94%
rename from lib/decoding/GSM610Tables.cpp
rename to lib/decoding/openbts/GSM610Tables.cpp
index 38f643f..1b08496 100644
--- a/lib/decoding/GSM610Tables.cpp
+++ b/lib/decoding/openbts/GSM610Tables.cpp
@@ -1,25 +1,22 @@
/*
-* Copyright 2008 Free Software Foundation, Inc.
-*
-* This software is distributed under the terms of the GNU Public License.
-* See the COPYING file in the main directory for details.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-*/
-
-
+ * Copyright 2008 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * This use of this software may be subject to additional restrictions.
+ * See the LEGAL file in the main directory for details.
+ */
#include "GSM610Tables.h"
diff --git a/lib/decoding/openbts/GSM610Tables.h b/lib/decoding/openbts/GSM610Tables.h
new file mode 100644
index 0000000..0b8d64f
--- /dev/null
+++ b/lib/decoding/openbts/GSM610Tables.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2008 Free Software Foundation, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * This use of this software may be subject to additional restrictions.
+ * See the LEGAL file in the main directory for details.
+ */
+
+#ifndef GSM610TABLES_H
+#define GSM610TABLES_H
+
+
+
+namespace GSM {
+
+/** Table #2 from GSM 05.03 */
+extern unsigned int g610BitOrder[260];
+
+}
+
+
+#endif
diff --git a/lib/decoding/GSM660Tables.cpp b/lib/decoding/openbts/GSM660Tables.cpp
similarity index 95%
rename from lib/decoding/GSM660Tables.cpp
rename to lib/decoding/openbts/GSM660Tables.cpp
index 520a6c1..e5687c3 100644
--- a/lib/decoding/GSM660Tables.cpp
+++ b/lib/decoding/openbts/GSM660Tables.cpp
@@ -1,23 +1,26 @@
-/* EFR (GSM 06.60) importance bit ordering */
-
/*
* Copyright 2010 Sylvain Munaut <tnt@246tNt.com>
* All Rights Reserved
*
* 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
+ * it under the terms of the GNU Affero 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.
+ * GNU Affero General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * This use of this software may be subject to additional restrictions.
+ * See the LEGAL file in the main directory for details.
*/
+/* EFR (GSM 06.60) importance bit ordering */
+
#include "GSM660Tables.h"
unsigned int GSM::g660BitOrder[260] = {
diff --git a/lib/decoding/GSM660Tables.h b/lib/decoding/openbts/GSM660Tables.h
similarity index 62%
rename from lib/decoding/GSM660Tables.h
rename to lib/decoding/openbts/GSM660Tables.h
index 9d639fc..9052c3b 100644
--- a/lib/decoding/GSM660Tables.h
+++ b/lib/decoding/openbts/GSM660Tables.h
@@ -5,17 +5,20 @@
* All Rights Reserved
*
* 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
+ * it under the terms of the GNU Affero 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.
+ * GNU Affero General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * This use of this software may be subject to additional restrictions.
+ * See the LEGAL file in the main directory for details.
*/
#ifndef GSM660TABLES_H
diff --git a/lib/decoding/Vector.h b/lib/decoding/openbts/Vector.h
similarity index 93%
rename from lib/decoding/Vector.h
rename to lib/decoding/openbts/Vector.h
index 23b4dd3..e1224e8 100644
--- a/lib/decoding/Vector.h
+++ b/lib/decoding/openbts/Vector.h
@@ -1,26 +1,25 @@
-/**@file Simplified Vector template with aliases. */
/*
-* Copyright 2008 Free Software Foundation, Inc.
-* Copyright 2014 Range Networks, Inc.
-*
-* This software is distributed under the terms of the GNU Affero Public License.
-* See the COPYING file in the main directory for details.
-*
-* This use of this software may be subject to additional restrictions.
-* See the LEGAL file in the main directory for details.
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero 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 Affero General Public License for more details.
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-*/
+ * Copyright 2008 Free Software Foundation, Inc.
+ * Copyright 2014 Range Networks, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * This use of this software may be subject to additional restrictions.
+ * See the LEGAL file in the main directory for details.
+ */
-
+/**@file Simplified Vector template with aliases. */
#ifndef VECTOR_H
diff --git a/lib/decoding/openbts/Viterbi.h b/lib/decoding/openbts/Viterbi.h
new file mode 100644
index 0000000..77bd599
--- /dev/null
+++ b/lib/decoding/openbts/Viterbi.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2013, 2014 Range Networks, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * This use of this software may be subject to additional restrictions.
+ * See the LEGAL file in the main directory for details.
+ */
+
+
+#ifndef _VITERBI_H_
+#define _VITERBI_H_ 1
+
+// (pat) Virtual base class for Viterbi and Turbo coder/decoders.
+class ViterbiBase {
+ public:
+ virtual void encode(const BitVector &in, BitVector& target) const = 0;
+ virtual void decode(const SoftVector &in, BitVector& target) = 0;
+ // (pat) Return error count from most recent decoder run.
+ // If you get -1 from this, the method is not defined in the Viterbi class.
+ virtual int getBEC() { return -1; }
+ //virtual ~ViterbiBase(); Currently None of these have destructors.
+
+ // These functions are logically part of the Viterbi functionality, even though they do not use any class variables.
+ unsigned applyPoly(uint64_t val, uint64_t poly);
+ unsigned applyPoly(uint64_t val, uint64_t poly, unsigned order);
+};
+#endif
diff --git a/lib/decoding/ViterbiR204.cpp b/lib/decoding/openbts/ViterbiR204.cpp
similarity index 88%
rename from lib/decoding/ViterbiR204.cpp
rename to lib/decoding/openbts/ViterbiR204.cpp
index 999b31b..296e292 100644
--- a/lib/decoding/ViterbiR204.cpp
+++ b/lib/decoding/openbts/ViterbiR204.cpp
@@ -1,28 +1,23 @@
/*
-* Copyright 2008, 2009, 2014 Free Software Foundation, Inc.
-* Copyright 2014 Range Networks, Inc.
-*
-*
-* This software is distributed under the terms of the GNU Affero Public License.
-* See the COPYING file in the main directory for details.
-*
-* This use of this software may be subject to additional restrictions.
-* See the LEGAL file in the main directory for details.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero 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 Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-*/
+ * Copyright 2008, 2009, 2014 Free Software Foundation, Inc.
+ * Copyright 2014 Range Networks, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * This use of this software may be subject to additional restrictions.
+ * See the LEGAL file in the main directory for details.
+ */
diff --git a/lib/decoding/ViterbiR204.h b/lib/decoding/openbts/ViterbiR204.h
similarity index 78%
rename from lib/decoding/ViterbiR204.h
rename to lib/decoding/openbts/ViterbiR204.h
index 4fd053f..090f1e8 100644
--- a/lib/decoding/ViterbiR204.h
+++ b/lib/decoding/openbts/ViterbiR204.h
@@ -1,27 +1,23 @@
/*
-* Copyright 2008, 2009, 2014 Free Software Foundation, Inc.
-* Copyright 2014 Range Networks, Inc.
-*
-* This software is distributed under the terms of the GNU Affero Public License.
-* See the COPYING file in the main directory for details.
-*
-* This use of this software may be subject to additional restrictions.
-* See the LEGAL file in the main directory for details.
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero 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 Affero General Public License for more details.
-
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-*/
+ * Copyright 2008, 2009, 2014 Free Software Foundation, Inc.
+ * Copyright 2014 Range Networks, Inc.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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 Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * This use of this software may be subject to additional restrictions.
+ * See the LEGAL file in the main directory for details.
+ */
#ifndef _VITERBIR204_H_
#define _VITERBIR204_H_ 1
diff --git a/lib/decoding/osmocom/coding/gsm0503.h b/lib/decoding/osmocom/coding/gsm0503.h
new file mode 100644
index 0000000..e1c62a6
--- /dev/null
+++ b/lib/decoding/osmocom/coding/gsm0503.h
@@ -0,0 +1,183 @@
+/*
+ * gsm0503.h
+ *
+ * Copyright (C) 2016 sysmocom s.f.m.c. GmbH
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#include <stdint.h>
+
+#include <osmocom/core/conv.h>
+
+/*! \file gsm0503.h
+ * Osmocom convolutional encoder/decoder for xCCH channels, see 3GPP TS 05.03
+ */
+
+/*! \brief structure describing convolutional code xCCH
+ *
+ * Non-recursive code, flushed, not punctured code.
+ */
+extern const struct osmo_conv_code gsm0503_xcch;
+
+/*! \brief structure describing convolutional code RACH
+ */
+extern const struct osmo_conv_code gsm0503_rach;
+
+/*! \brief structure describing convolutional code SCH
+ */
+extern const struct osmo_conv_code gsm0503_sch;
+
+/*! \brief structures describing convolutional codes CS2/3
+ */
+extern const struct osmo_conv_code gsm0503_cs2;
+extern const struct osmo_conv_code gsm0503_cs3;
+
+/*! \brief structure describing convolutional code TCH/FR
+ */
+extern const struct osmo_conv_code gsm0503_tch_fr;
+
+/*! \brief structure describing convolutional code TCH/HR
+ */
+extern const struct osmo_conv_code gsm0503_tch_hr;
+
+/*! \brief structure describing convolutional code TCH/AFS 12.2
+ */
+extern const struct osmo_conv_code gsm0503_tch_afs_12_2;
+
+/*! \brief structure describing convolutional code TCH/AFS 10.2
+ */
+extern const struct osmo_conv_code gsm0503_tch_afs_10_2;
+
+/*! \brief structure describing convolutional code TCH/AFS 7.95
+ */
+extern const struct osmo_conv_code gsm0503_tch_afs_7_95;
+
+/*! \brief structure describing convolutional code TCH/AFS 7.4
+ */
+extern const struct osmo_conv_code gsm0503_tch_afs_7_4;
+
+/*! \brief structure describing convolutional code TCH/AFS 6.7
+ */
+extern const struct osmo_conv_code gsm0503_tch_afs_6_7;
+
+/*! \brief structure describing convolutional code TCH/AFS 5.9
+ */
+extern const struct osmo_conv_code gsm0503_tch_afs_5_9;
+
+/*! \brief structure describing convolutional code TCH/AFS 5.15
+ */
+extern const struct osmo_conv_code gsm0503_tch_afs_5_15;
+
+/*! \brief structure describing convolutional code TCH/AFS 4.75
+ */
+extern const struct osmo_conv_code gsm0503_tch_afs_4_75;
+
+/*! \brief structure describing convolutional code TCH/AHS 7.95
+ */
+extern const struct osmo_conv_code gsm0503_tch_ahs_7_95;
+
+/*! \brief structure describing convolutional code TCH/AHS 7.4
+ */
+extern const struct osmo_conv_code gsm0503_tch_ahs_7_4;
+
+/*! \brief structure describing convolutional code TCH/AHS 6.7
+ */
+extern const struct osmo_conv_code gsm0503_tch_ahs_6_7;
+
+/*! \brief structure describing convolutional code TCH/AHS 5.9
+ */
+extern const struct osmo_conv_code gsm0503_tch_ahs_5_9;
+
+/*! \brief structure describing convolutional code TCH/AHS 5.15
+ */
+extern const struct osmo_conv_code gsm0503_tch_ahs_5_15;
+
+/*! \brief structure describing convolutional code TCH/AHS 4.75
+ */
+extern const struct osmo_conv_code gsm0503_tch_ahs_4_75;
+
+/*! \brief structure describing convolutional code EDGE MCS-1 DL HDR
+ */
+extern const struct osmo_conv_code gsm0503_mcs1_dl_hdr;
+
+/*! \brief structure describing convolutional code EDGE MCS-1 UL HDR
+ */
+extern const struct osmo_conv_code gsm0503_mcs1_ul_hdr;
+
+/*! \brief structure describing convolutional code EDGE MCS-1
+ */
+extern const struct osmo_conv_code gsm0503_mcs1;
+
+/*! \brief structure describing convolutional code EDGE MCS-2
+ */
+extern const struct osmo_conv_code gsm0503_mcs2;
+
+/*! \brief structure describing convolutional code EDGE MCS-3
+ */
+extern const struct osmo_conv_code gsm0503_mcs3;
+
+/*! \brief structure describing convolutional code EDGE MCS-4
+ */
+extern const struct osmo_conv_code gsm0503_mcs4;
+
+/*! \brief structure describing convolutional code EDGE MCS-5 DL HDR
+ */
+extern const struct osmo_conv_code gsm0503_mcs5_dl_hdr;
+
+/*! \brief structure describing convolutional code EDGE MCS-5 UL HDR
+ */
+extern const struct osmo_conv_code gsm0503_mcs5_ul_hdr;
+
+/*! \brief structure describing convolutional code EDGE MCS-5
+ */
+extern const struct osmo_conv_code gsm0503_mcs5;
+
+/*! \brief structure describing convolutional code EDGE MCS-6
+ */
+extern const struct osmo_conv_code gsm0503_mcs6;
+
+/*! \brief structure describing convolutional code EDGE MCS-7 DL HDR
+ */
+extern const struct osmo_conv_code gsm0503_mcs7_dl_hdr;
+
+/*! \brief structure describing convolutional code EDGE MCS-7 UL HDR
+ */
+extern const struct osmo_conv_code gsm0503_mcs7_ul_hdr;
+
+/*! \brief structure describing convolutional code EDGE MCS-7
+ */
+extern const struct osmo_conv_code gsm0503_mcs7;
+
+/*! \brief structure describing convolutional code EDGE MCS-8
+ */
+extern const struct osmo_conv_code gsm0503_mcs8;
+
+/*! \brief structure describing convolutional code EDGE MCS-9
+ */
+extern const struct osmo_conv_code gsm0503_mcs9;
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/lib/decoding/osmocom/coding/gsm0503_coding.c b/lib/decoding/osmocom/coding/gsm0503_coding.c
new file mode 100644
index 0000000..afbba88
--- /dev/null
+++ b/lib/decoding/osmocom/coding/gsm0503_coding.c
@@ -0,0 +1,1753 @@
+/*
+ * (C) 2013 by Andreas Eversberg <jolly@eversberg.eu>
+ * (C) 2015 by Alexander Chemeris <Alexander.Chemeris@fairwaves.co>
+ * (C) 2016 by Tom Tsou <tom.tsou@ettus.com>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <osmocom/core/bits.h>
+#include <osmocom/core/conv.h>
+#include <osmocom/core/utils.h>
+#include <osmocom/core/crcgen.h>
+#include <osmocom/core/endian.h>
+
+#include <osmocom/gsm/protocol/gsm_04_08.h>
+#include "gsm0503.h"
+#include <osmocom/codec/codec.h>
+
+#include "gsm0503_interleaving.h"
+#include "gsm0503_mapping.h"
+#include "gsm0503_tables.h"
+#include "gsm0503_coding.h"
+#include "gsm0503_parity.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+
+/*
+ * EGPRS coding limits
+ */
+
+/* Max header size with parity bits */
+#define EGPRS_HDR_UPP_MAX 54
+
+/* Max encoded header size */
+#define EGPRS_HDR_C_MAX 162
+
+/* Max punctured header size */
+#define EGPRS_HDR_HC_MAX 160
+
+/* Max data block size with parity bits */
+#define EGPRS_DATA_U_MAX 612
+
+/* Max encoded data block size */
+#define EGPRS_DATA_C_MAX 1836
+
+/* Max single block punctured data size */
+#define EGPRS_DATA_DC_MAX 1248
+
+/* Dual block punctured data size */
+#define EGPRS_DATA_C1 612
+#define EGPRS_DATA_C2 EGPRS_DATA_C1
+
+/* TS 101318 Chapter 5.1: 260 bits + 4bit sig */
+#define GSM_FR_BYTES 33
+/* TS 101318 Chapter 5.2: 112 bits, no sig */
+#define GSM_HR_BYTES 14
+/* TS 101318 Chapter 5.3: 244 bits + 4bit sig */
+#define GSM_EFR_BYTES 31
+
+struct gsm0503_mcs_code {
+ uint8_t mcs;
+ uint8_t usf_len;
+
+ /* Header coding */
+ uint8_t hdr_len;
+ uint8_t hdr_code_len;
+ uint8_t hdr_punc_len;
+ const struct osmo_conv_code *hdr_conv;
+ const uint8_t *hdr_punc;
+
+ /* Data coding */
+ uint16_t data_len;
+ uint16_t data_code_len;
+ uint16_t data_punc_len;
+ const struct osmo_conv_code *data_conv;
+ const uint8_t *data_punc[3];
+};
+
+static int osmo_conv_decode_ber(const struct osmo_conv_code *code,
+ const sbit_t *input, ubit_t *output,
+ int *n_errors, int *n_bits_total)
+{
+ int res, i, coded_len;
+ ubit_t recoded[EGPRS_DATA_C_MAX];
+
+ res = osmo_conv_decode(code, input, output);
+
+ if (n_bits_total || n_errors) {
+ coded_len = osmo_conv_encode(code, output, recoded);
+ OSMO_ASSERT(sizeof(recoded) / sizeof(recoded[0]) >= coded_len);
+ }
+
+ /* Count bit errors */
+ if (n_errors) {
+ *n_errors = 0;
+ for (i = 0; i < coded_len; i++) {
+ if (!((recoded[i] && input[i] < 0) ||
+ (!recoded[i] && input[i] > 0)) )
+ *n_errors += 1;
+ }
+ }
+
+ if (n_bits_total)
+ *n_bits_total = coded_len;
+
+ return res;
+}
+
+static int _xcch_decode_cB(uint8_t *l2_data, sbit_t *cB,
+ int *n_errors, int *n_bits_total)
+{
+ ubit_t conv[224];
+ int rv;
+
+ osmo_conv_decode_ber(&gsm0503_xcch, cB,
+ conv, n_errors, n_bits_total);
+
+ rv = osmo_crc64gen_check_bits(&gsm0503_fire_crc40,
+ conv, 184, conv + 184);
+ if (rv)
+ return -1;
+
+ osmo_ubit2pbit_ext(l2_data, 0, conv, 0, 184, 1);
+
+ return 0;
+}
+
+static int _xcch_encode_cB(ubit_t *cB, uint8_t *l2_data)
+{
+ ubit_t conv[224];
+
+ osmo_pbit2ubit_ext(conv, 0, l2_data, 0, 184, 1);
+
+ osmo_crc64gen_set_bits(&gsm0503_fire_crc40, conv, 184, conv + 184);
+
+ osmo_conv_encode(&gsm0503_xcch, conv, cB);
+
+ return 0;
+}
+
+/*
+ * GSM xCCH block transcoding
+ */
+int gsm0503_xcch_decode(uint8_t *l2_data, sbit_t *bursts,
+ int *n_errors, int *n_bits_total)
+{
+ sbit_t iB[456], cB[456];
+ int i;
+
+ for (i = 0; i < 4; i++)
+ gsm0503_xcch_burst_unmap(&iB[i * 114], &bursts[i * 116], NULL, NULL);
+
+ gsm0503_xcch_deinterleave(cB, iB);
+
+ return _xcch_decode_cB(l2_data, cB, n_errors, n_bits_total);
+}
+
+int gsm0503_xcch_encode(ubit_t *bursts, uint8_t *l2_data)
+{
+ ubit_t iB[456], cB[456], hl = 1, hn = 1;
+ int i;
+
+ _xcch_encode_cB(cB, l2_data);
+
+ gsm0503_xcch_interleave(cB, iB);
+
+ for (i = 0; i < 4; i++)
+ gsm0503_xcch_burst_map(&iB[i * 114], &bursts[i * 116], &hl, &hn);
+
+ return 0;
+}
+
+
+
+/*
+ * GSM PDTCH block transcoding
+ */
+
+int gsm0503_pdtch_decode(uint8_t *l2_data, sbit_t *bursts, uint8_t *usf_p,
+ int *n_errors, int *n_bits_total)
+{
+ sbit_t iB[456], cB[676], hl_hn[8];
+ ubit_t conv[456];
+ int i, j, k, rv, best = 0, cs = 0, usf = 0; /* make GCC happy */
+
+ for (i = 0; i < 4; i++)
+ gsm0503_xcch_burst_unmap(&iB[i * 114], &bursts[i * 116],
+ hl_hn + i * 2, hl_hn + i * 2 + 1);
+
+ for (i = 0; i < 4; i++) {
+ for (j = 0, k = 0; j < 8; j++)
+ k += abs(((int)gsm0503_pdtch_hl_hn_sbit[i][j]) - ((int)hl_hn[j]));
+
+ if (i == 0 || k < best) {
+ best = k;
+ cs = i+1;
+ }
+ }
+
+ gsm0503_xcch_deinterleave(cB, iB);
+
+ switch (cs) {
+ case 1:
+ osmo_conv_decode_ber(&gsm0503_xcch, cB,
+ conv, n_errors, n_bits_total);
+
+ rv = osmo_crc64gen_check_bits(&gsm0503_fire_crc40,
+ conv, 184, conv + 184);
+ if (rv)
+ return -1;
+
+ osmo_ubit2pbit_ext(l2_data, 0, conv, 0, 184, 1);
+
+ return 23;
+ case 2:
+ for (i = 587, j = 455; i >= 0; i--) {
+ if (!gsm0503_puncture_cs2[i])
+ cB[i] = cB[j--];
+ else
+ cB[i] = 0;
+ }
+
+ osmo_conv_decode_ber(&gsm0503_cs2, cB,
+ conv, n_errors, n_bits_total);
+
+ for (i = 0; i < 8; i++) {
+ for (j = 0, k = 0; j < 6; j++)
+ k += abs(((int)gsm0503_usf2six[i][j]) - ((int)conv[j]));
+
+ if (i == 0 || k < best) {
+ best = k;
+ usf = i;
+ }
+ }
+
+ conv[3] = usf & 1;
+ conv[4] = (usf >> 1) & 1;
+ conv[5] = (usf >> 2) & 1;
+ if (usf_p)
+ *usf_p = usf;
+
+ rv = osmo_crc16gen_check_bits(&gsm0503_cs234_crc16,
+ conv + 3, 271, conv + 3 + 271);
+ if (rv)
+ return -1;
+
+ osmo_ubit2pbit_ext(l2_data, 0, conv, 3, 271, 1);
+
+ return 34;
+ case 3:
+ for (i = 675, j = 455; i >= 0; i--) {
+ if (!gsm0503_puncture_cs3[i])
+ cB[i] = cB[j--];
+ else
+ cB[i] = 0;
+ }
+
+ osmo_conv_decode_ber(&gsm0503_cs3, cB,
+ conv, n_errors, n_bits_total);
+
+ for (i = 0; i < 8; i++) {
+ for (j = 0, k = 0; j < 6; j++)
+ k += abs(((int)gsm0503_usf2six[i][j]) - ((int)conv[j]));
+
+ if (i == 0 || k < best) {
+ best = k;
+ usf = i;
+ }
+ }
+
+ conv[3] = usf & 1;
+ conv[4] = (usf >> 1) & 1;
+ conv[5] = (usf >> 2) & 1;
+ if (usf_p)
+ *usf_p = usf;
+
+ rv = osmo_crc16gen_check_bits(&gsm0503_cs234_crc16,
+ conv + 3, 315, conv + 3 + 315);
+ if (rv)
+ return -1;
+
+ osmo_ubit2pbit_ext(l2_data, 0, conv, 3, 315, 1);
+
+ return 40;
+ case 4:
+ for (i = 12; i < 456; i++)
+ conv[i] = (cB[i] < 0) ? 1 : 0;
+
+ for (i = 0; i < 8; i++) {
+ for (j = 0, k = 0; j < 12; j++)
+ k += abs(((int)gsm0503_usf2twelve_sbit[i][j]) - ((int)cB[j]));
+
+ if (i == 0 || k < best) {
+ best = k;
+ usf = i;
+ }
+ }
+
+ conv[9] = usf & 1;
+ conv[10] = (usf >> 1) & 1;
+ conv[11] = (usf >> 2) & 1;
+ if (usf_p)
+ *usf_p = usf;
+
+ rv = osmo_crc16gen_check_bits(&gsm0503_cs234_crc16,
+ conv + 9, 431, conv + 9 + 431);
+ if (rv) {
+ *n_bits_total = 456 - 12;
+ *n_errors = *n_bits_total;
+ return -1;
+ }
+
+ *n_bits_total = 456 - 12;
+ *n_errors = 0;
+
+ osmo_ubit2pbit_ext(l2_data, 0, conv, 9, 431, 1);
+
+ return 54;
+ default:
+ *n_bits_total = 0;
+ *n_errors = 0;
+ break;
+ }
+
+ return -1;
+}
+
+int gsm0503_pdtch_encode(ubit_t *bursts, uint8_t *l2_data, uint8_t l2_len)
+{
+ ubit_t iB[456], cB[676];
+ const ubit_t *hl_hn;
+ ubit_t conv[334];
+ int i, j, usf;
+
+ switch (l2_len) {
+ case 23:
+ osmo_pbit2ubit_ext(conv, 0, l2_data, 0, 184, 1);
+
+ osmo_crc64gen_set_bits(&gsm0503_fire_crc40, conv, 184, conv + 184);
+
+ osmo_conv_encode(&gsm0503_xcch, conv, cB);
+
+ hl_hn = gsm0503_pdtch_hl_hn_ubit[0];
+
+ break;
+ case 34:
+ osmo_pbit2ubit_ext(conv, 3, l2_data, 0, 271, 1);
+ usf = l2_data[0] & 0x7;
+
+ osmo_crc16gen_set_bits(&gsm0503_cs234_crc16, conv + 3,
+ 271, conv + 3 + 271);
+
+ memcpy(conv, gsm0503_usf2six[usf], 6);
+
+ osmo_conv_encode(&gsm0503_cs2, conv, cB);
+
+ for (i = 0, j = 0; i < 588; i++)
+ if (!gsm0503_puncture_cs2[i])
+ cB[j++] = cB[i];
+
+ hl_hn = gsm0503_pdtch_hl_hn_ubit[1];
+
+ break;
+ case 40:
+ osmo_pbit2ubit_ext(conv, 3, l2_data, 0, 315, 1);
+ usf = l2_data[0] & 0x7;
+
+ osmo_crc16gen_set_bits(&gsm0503_cs234_crc16, conv + 3,
+ 315, conv + 3 + 315);
+
+ memcpy(conv, gsm0503_usf2six[usf], 6);
+
+ osmo_conv_encode(&gsm0503_cs3, conv, cB);
+
+ for (i = 0, j = 0; i < 676; i++)
+ if (!gsm0503_puncture_cs3[i])
+ cB[j++] = cB[i];
+
+ hl_hn = gsm0503_pdtch_hl_hn_ubit[2];
+
+ break;
+ case 54:
+ osmo_pbit2ubit_ext(cB, 9, l2_data, 0, 431, 1);
+ usf = l2_data[0] & 0x7;
+
+ osmo_crc16gen_set_bits(&gsm0503_cs234_crc16, cB + 9,
+ 431, cB + 9 + 431);
+
+ memcpy(cB, gsm0503_usf2twelve_ubit[usf], 12);
+
+ hl_hn = gsm0503_pdtch_hl_hn_ubit[3];
+
+ break;
+ default:
+ return -1;
+ }
+
+ gsm0503_xcch_interleave(cB, iB);
+
+ for (i = 0; i < 4; i++) {
+ gsm0503_xcch_burst_map(&iB[i * 114], &bursts[i * 116],
+ hl_hn + i * 2, hl_hn + i * 2 + 1);
+ }
+
+ return GSM0503_GPRS_BURSTS_NBITS;
+}
+
+/*
+ * GSM TCH/F FR/EFR transcoding
+ */
+
+static void tch_fr_reassemble(uint8_t *tch_data,
+ ubit_t *b_bits, int net_order)
+{
+ int i, j, k, l, o;
+
+ tch_data[0] = 0xd << 4;
+ memset(tch_data + 1, 0, 32);
+
+ if (net_order) {
+ for (i = 0, j = 4; i < 260; i++, j++)
+ tch_data[j >> 3] |= (b_bits[i] << (7 - (j & 7)));
+
+ return;
+ }
+
+ /* reassemble d-bits */
+ i = 0; /* counts bits */
+ j = 4; /* counts output bits */
+ k = gsm0503_gsm_fr_map[0]-1; /* current number bit in element */
+ l = 0; /* counts element bits */
+ o = 0; /* offset input bits */
+ while (i < 260) {
+ tch_data[j >> 3] |= (b_bits[k + o] << (7 - (j & 7)));
+ if (--k < 0) {
+ o += gsm0503_gsm_fr_map[l];
+ k = gsm0503_gsm_fr_map[++l]-1;
+ }
+ i++;
+ j++;
+ }
+}
+
+static void tch_fr_disassemble(ubit_t *b_bits,
+ uint8_t *tch_data, int net_order)
+{
+ int i, j, k, l, o;
+
+ if (net_order) {
+ for (i = 0, j = 4; i < 260; i++, j++)
+ b_bits[i] = (tch_data[j >> 3] >> (7 - (j & 7))) & 1;
+
+ return;
+ }
+
+ i = 0; /* counts bits */
+ j = 4; /* counts input bits */
+ k = gsm0503_gsm_fr_map[0] - 1; /* current number bit in element */
+ l = 0; /* counts element bits */
+ o = 0; /* offset output bits */
+ while (i < 260) {
+ b_bits[k + o] = (tch_data[j >> 3] >> (7 - (j & 7))) & 1;
+ if (--k < 0) {
+ o += gsm0503_gsm_fr_map[l];
+ k = gsm0503_gsm_fr_map[++l] - 1;
+ }
+ i++;
+ j++;
+ }
+}
+
+static void tch_hr_reassemble(uint8_t *tch_data, ubit_t *b_bits)
+{
+ int i, j;
+
+ tch_data[0] = 0x00; /* F = 0, FT = 000 */
+ memset(tch_data + 1, 0, 14);
+
+ for (i = 0, j = 8; i < 112; i++, j++)
+ tch_data[j >> 3] |= (b_bits[i] << (7 - (j & 7)));
+}
+
+static void tch_hr_disassemble(ubit_t *b_bits, uint8_t *tch_data)
+{
+ int i, j;
+
+ for (i = 0, j = 8; i < 112; i++, j++)
+ b_bits[i] = (tch_data[j >> 3] >> (7 - (j & 7))) & 1;
+}
+
+static void tch_efr_reassemble(uint8_t *tch_data, ubit_t *b_bits)
+{
+ int i, j;
+
+ tch_data[0] = 0xc << 4;
+ memset(tch_data + 1, 0, 30);
+
+ for (i = 0, j = 4; i < 244; i++, j++)
+ tch_data[j >> 3] |= (b_bits[i] << (7 - (j & 7)));
+}
+
+static void tch_efr_disassemble(ubit_t *b_bits, uint8_t *tch_data)
+{
+ int i, j;
+
+ for (i = 0, j = 4; i < 244; i++, j++)
+ b_bits[i] = (tch_data[j >> 3] >> (7 - (j & 7))) & 1;
+}
+
+static void tch_amr_reassemble(uint8_t *tch_data, ubit_t *d_bits, int len)
+{
+ int i, j;
+
+ memset(tch_data, 0, (len + 7) >> 3);
+
+ for (i = 0, j = 0; i < len; i++, j++)
+ tch_data[j >> 3] |= (d_bits[i] << (7 - (j & 7)));
+}
+
+static void tch_amr_disassemble(ubit_t *d_bits, uint8_t *tch_data, int len)
+{
+ int i, j;
+
+ for (i = 0, j = 0; i < len; i++, j++)
+ d_bits[i] = (tch_data[j >> 3] >> (7 - (j & 7))) & 1;
+}
+
+static void tch_fr_d_to_b(ubit_t *b_bits, ubit_t *d_bits)
+{
+ int i;
+
+ for (i = 0; i < 260; i++)
+ b_bits[gsm610_bitorder[i]] = d_bits[i];
+}
+
+static void tch_fr_b_to_d(ubit_t *d_bits, ubit_t *b_bits)
+{
+ int i;
+
+ for (i = 0; i < 260; i++)
+ d_bits[i] = b_bits[gsm610_bitorder[i]];
+}
+
+static void tch_hr_d_to_b(ubit_t *b_bits, ubit_t *d_bits)
+{
+ int i;
+
+ const uint16_t *map;
+
+ if (!d_bits[93] && !d_bits[94])
+ map = gsm620_unvoiced_bitorder;
+ else
+ map = gsm620_voiced_bitorder;
+
+ for (i = 0; i < 112; i++)
+ b_bits[map[i]] = d_bits[i];
+}
+
+static void tch_hr_b_to_d(ubit_t *d_bits, ubit_t *b_bits)
+{
+ int i;
+ const uint16_t *map;
+
+ if (!b_bits[34] && !b_bits[35])
+ map = gsm620_unvoiced_bitorder;
+ else
+ map = gsm620_voiced_bitorder;
+
+ for (i = 0; i < 112; i++)
+ d_bits[i] = b_bits[map[i]];
+}
+
+static void tch_efr_d_to_w(ubit_t *b_bits, ubit_t *d_bits)
+{
+ int i;
+
+ for (i = 0; i < 260; i++)
+ b_bits[gsm660_bitorder[i]] = d_bits[i];
+}
+
+static void tch_efr_w_to_d(ubit_t *d_bits, ubit_t *b_bits)
+{
+ int i;
+
+ for (i = 0; i < 260; i++)
+ d_bits[i] = b_bits[gsm660_bitorder[i]];
+}
+
+static void tch_efr_protected(ubit_t *s_bits, ubit_t *b_bits)
+{
+ int i;
+
+ for (i = 0; i < 65; i++)
+ b_bits[i] = s_bits[gsm0503_gsm_efr_protected_bits[i] - 1];
+}
+
+static void tch_fr_unreorder(ubit_t *d, ubit_t *p, ubit_t *u)
+{
+ int i;
+
+ for (i = 0; i < 91; i++) {
+ d[i << 1] = u[i];
+ d[(i << 1) + 1] = u[184 - i];
+ }
+
+ for (i = 0; i < 3; i++)
+ p[i] = u[91 + i];
+}
+
+static void tch_fr_reorder(ubit_t *u, ubit_t *d, ubit_t *p)
+{
+ int i;
+
+ for (i = 0; i < 91; i++) {
+ u[i] = d[i << 1];
+ u[184 - i] = d[(i << 1) + 1];
+ }
+
+ for (i = 0; i < 3; i++)
+ u[91 + i] = p[i];
+}
+
+static void tch_hr_unreorder(ubit_t *d, ubit_t *p, ubit_t *u)
+{
+ memcpy(d, u, 95);
+ memcpy(p, u + 95, 3);
+}
+
+static void tch_hr_reorder(ubit_t *u, ubit_t *d, ubit_t *p)
+{
+ memcpy(u, d, 95);
+ memcpy(u + 95, p, 3);
+}
+
+static void tch_efr_reorder(ubit_t *w, ubit_t *s, ubit_t *p)
+{
+ memcpy(w, s, 71);
+ w[71] = w[72] = s[69];
+ memcpy(w + 73, s + 71, 50);
+ w[123] = w[124] = s[119];
+ memcpy(w + 125, s + 121, 53);
+ w[178] = w[179] = s[172];
+ memcpy(w + 180, s + 174, 50);
+ w[230] = w[231] = s[222];
+ memcpy(w + 232, s + 224, 20);
+ memcpy(w + 252, p, 8);
+}
+
+static void tch_efr_unreorder(ubit_t *s, ubit_t *p, ubit_t *w)
+{
+ int sum;
+
+ memcpy(s, w, 71);
+ sum = s[69] + w[71] + w[72];
+ s[69] = (sum > 2);
+ memcpy(s + 71, w + 73, 50);
+ sum = s[119] + w[123] + w[124];
+ s[119] = (sum > 2);
+ memcpy(s + 121, w + 125, 53);
+ sum = s[172] + w[178] + w[179];
+ s[172] = (sum > 2);
+ memcpy(s + 174, w + 180, 50);
+ sum = s[220] + w[230] + w[231];
+ s[222] = (sum > 2);
+ memcpy(s + 224, w + 232, 20);
+ memcpy(p, w + 252, 8);
+}
+
+static void tch_amr_merge(ubit_t *u, ubit_t *d, ubit_t *p, int len, int prot)
+{
+ memcpy(u, d, prot);
+ memcpy(u + prot, p, 6);
+ memcpy(u + prot + 6, d + prot, len - prot);
+}
+
+static void tch_amr_unmerge(ubit_t *d, ubit_t *p,
+ ubit_t *u, int len, int prot)
+{
+ memcpy(d, u, prot);
+ memcpy(p, u+prot, 6);
+ memcpy(d + prot, u + prot + 6, len - prot);
+}
+
+int gsm0503_tch_fr_decode(uint8_t *tch_data, sbit_t *bursts,
+ int net_order, int efr, int *n_errors, int *n_bits_total)
+{
+ sbit_t iB[912], cB[456], h;
+ ubit_t conv[185], s[244], w[260], b[65], d[260], p[8];
+ int i, rv, len, steal = 0;
+
+ for (i=0; i<8; i++) {
+ gsm0503_tch_burst_unmap(&iB[i * 114],
+ &bursts[i * 116], &h, i >> 2);
+ steal -= h;
+ }
+
+ gsm0503_tch_fr_deinterleave(cB, iB);
+
+ if (steal > 0) {
+ rv = _xcch_decode_cB(tch_data, cB, n_errors, n_bits_total);
+ if (rv) {
+ /* Error decoding FACCH frame */
+ return -1;
+ }
+
+ return 23;
+ }
+
+ osmo_conv_decode_ber(&gsm0503_tch_fr, cB, conv, n_errors, n_bits_total);
+
+ tch_fr_unreorder(d, p, conv);
+
+ for (i = 0; i < 78; i++)
+ d[i + 182] = (cB[i + 378] < 0) ? 1 : 0;
+
+ rv = osmo_crc8gen_check_bits(&gsm0503_tch_fr_crc3, d, 50, p);
+ if (rv) {
+ /* Error checking CRC8 for the FR part of an EFR/FR frame */
+ return -1;
+ }
+
+ if (efr) {
+ tch_efr_d_to_w(w, d);
+
+ tch_efr_unreorder(s, p, w);
+
+ tch_efr_protected(s, b);
+
+ rv = osmo_crc8gen_check_bits(&gsm0503_tch_efr_crc8, b, 65, p);
+ if (rv) {
+ /* Error checking CRC8 for the EFR part of an EFR frame */
+ return -1;
+ }
+
+ tch_efr_reassemble(tch_data, s);
+
+ len = GSM_EFR_BYTES;
+ } else {
+ tch_fr_d_to_b(w, d);
+
+ tch_fr_reassemble(tch_data, w, net_order);
+
+ len = GSM_FR_BYTES;
+ }
+
+ return len;
+}
+
+int gsm0503_tch_fr_encode(ubit_t *bursts, uint8_t *tch_data,
+ int len, int net_order)
+{
+ ubit_t iB[912], cB[456], h;
+ ubit_t conv[185], w[260], b[65], s[244], d[260], p[8];
+ int i;
+
+ switch (len) {
+ case GSM_EFR_BYTES: /* TCH EFR */
+
+ tch_efr_disassemble(s, tch_data);
+
+ tch_efr_protected(s, b);
+
+ osmo_crc8gen_set_bits(&gsm0503_tch_efr_crc8, b, 65, p);
+
+ tch_efr_reorder(w, s, p);
+
+ tch_efr_w_to_d(d, w);
+
+ goto coding_efr_fr;
+ case GSM_FR_BYTES: /* TCH FR */
+ tch_fr_disassemble(w, tch_data, net_order);
+
+ tch_fr_b_to_d(d, w);
+
+coding_efr_fr:
+ osmo_crc8gen_set_bits(&gsm0503_tch_fr_crc3, d, 50, p);
+
+ tch_fr_reorder(conv, d, p);
+
+ memcpy(cB + 378, d + 182, 78);
+
+ osmo_conv_encode(&gsm0503_tch_fr, conv, cB);
+
+ h = 0;
+
+ break;
+ case GSM_MACBLOCK_LEN: /* FACCH */
+ _xcch_encode_cB(cB, tch_data);
+
+ h = 1;
+
+ break;
+ default:
+ return -1;
+ }
+
+ gsm0503_tch_fr_interleave(cB, iB);
+
+ for (i = 0; i < 8; i++) {
+ gsm0503_tch_burst_map(&iB[i * 114],
+ &bursts[i * 116], &h, i >> 2);
+ }
+
+ return 0;
+}
+
+int gsm0503_tch_hr_decode(uint8_t *tch_data, sbit_t *bursts, int odd,
+ int *n_errors, int *n_bits_total)
+{
+ sbit_t iB[912], cB[456], h;
+ ubit_t conv[98], b[112], d[112], p[3];
+ int i, rv, steal = 0;
+
+ /* Only unmap the stealing bits */
+ if (!odd) {
+ for (i = 0; i < 4; i++) {
+ gsm0503_tch_burst_unmap(NULL, &bursts[i * 116], &h, 0);
+ steal -= h;
+ }
+
+ for (i = 2; i < 5; i++) {
+ gsm0503_tch_burst_unmap(NULL, &bursts[i * 116], &h, 1);
+ steal -= h;
+ }
+ }
+
+ /* If we found a stole FACCH, but only at correct alignment */
+ if (steal > 0) {
+ for (i = 0; i < 6; i++) {
+ gsm0503_tch_burst_unmap(&iB[i * 114],
+ &bursts[i * 116], NULL, i >> 2);
+ }
+
+ for (i = 2; i < 4; i++) {
+ gsm0503_tch_burst_unmap(&iB[i * 114 + 456],
+ &bursts[i * 116], NULL, 1);
+ }
+
+ gsm0503_tch_fr_deinterleave(cB, iB);
+
+ rv = _xcch_decode_cB(tch_data, cB, n_errors, n_bits_total);
+ if (rv) {
+ /* Error decoding FACCH frame */
+ return -1;
+ }
+
+ return GSM_MACBLOCK_LEN;
+ }
+
+ for (i = 0; i < 4; i++) {
+ gsm0503_tch_burst_unmap(&iB[i * 114],
+ &bursts[i * 116], NULL, i >> 1);
+ }
+
+ gsm0503_tch_hr_deinterleave(cB, iB);
+
+ osmo_conv_decode_ber(&gsm0503_tch_hr, cB, conv, n_errors, n_bits_total);
+
+ tch_hr_unreorder(d, p, conv);
+
+ for (i = 0; i < 17; i++)
+ d[i + 95] = (cB[i + 211] < 0) ? 1 : 0;
+
+ rv = osmo_crc8gen_check_bits(&gsm0503_tch_fr_crc3, d + 73, 22, p);
+ if (rv) {
+ /* Error checking CRC8 for an HR frame */
+ return -1;
+ }
+
+ tch_hr_d_to_b(b, d);
+
+ tch_hr_reassemble(tch_data, b);
+
+ return 15;
+}
+
+int gsm0503_tch_hr_encode(ubit_t *bursts, uint8_t *tch_data, int len)
+{
+ ubit_t iB[912], cB[456], h;
+ ubit_t conv[98], b[112], d[112], p[3];
+ int i;
+
+ switch (len) {
+ case 15: /* TCH HR */
+ tch_hr_disassemble(b, tch_data);
+
+ tch_hr_b_to_d(d, b);
+
+ osmo_crc8gen_set_bits(&gsm0503_tch_fr_crc3, d + 73, 22, p);
+
+ tch_hr_reorder(conv, d, p);
+
+ osmo_conv_encode(&gsm0503_tch_hr, conv, cB);
+
+ memcpy(cB + 211, d + 95, 17);
+
+ h = 0;
+
+ gsm0503_tch_hr_interleave(cB, iB);
+
+ for (i = 0; i < 4; i++) {
+ gsm0503_tch_burst_map(&iB[i * 114],
+ &bursts[i * 116], &h, i >> 1);
+ }
+
+ break;
+ case GSM_MACBLOCK_LEN: /* FACCH */
+ _xcch_encode_cB(cB, tch_data);
+
+ h = 1;
+
+ gsm0503_tch_fr_interleave(cB, iB);
+
+ for (i=0; i<6; i++) {
+ gsm0503_tch_burst_map(&iB[i * 114],
+ &bursts[i * 116], &h, i >> 2);
+ }
+
+ for (i=2; i<4; i++) {
+ gsm0503_tch_burst_map(&iB[i * 114 + 456],
+ &bursts[i * 116], &h, 1);
+ }
+
+ break;
+ default:
+ return -1;
+ }
+
+ return 0;
+}
+
+int gsm0503_tch_afs_decode(uint8_t *tch_data, sbit_t *bursts,
+ int codec_mode_req, uint8_t *codec, int codecs, uint8_t *ft,
+ uint8_t *cmr, int *n_errors, int *n_bits_total)
+{
+ sbit_t iB[912], cB[456], h;
+ ubit_t d[244], p[6], conv[250];
+ int i, j, k, best = 0, rv, len, steal = 0, id = 0;
+ *n_errors = 0; *n_bits_total = 0;
+
+ for (i=0; i<8; i++) {
+ gsm0503_tch_burst_unmap(&iB[i * 114], &bursts[i * 116], &h, i >> 2);
+ steal -= h;
+ }
+
+ gsm0503_tch_fr_deinterleave(cB, iB);
+
+ if (steal > 0) {
+ rv = _xcch_decode_cB(tch_data, cB, n_errors, n_bits_total);
+ if (rv) {
+ /* Error decoding FACCH frame */
+ return -1;
+ }
+
+ return GSM_MACBLOCK_LEN;
+ }
+
+ for (i = 0; i < 4; i++) {
+ for (j = 0, k = 0; j < 8; j++)
+ k += abs(((int)gsm0503_afs_ic_sbit[i][j]) - ((int)cB[j]));
+
+ if (i == 0 || k < best) {
+ best = k;
+ id = i;
+ }
+ }
+
+ /* Check if indicated codec fits into range of codecs */
+ if (id >= codecs) {
+ /* Codec mode out of range, return id */
+ return id;
+ }
+
+ switch ((codec_mode_req) ? codec[*ft] : codec[id]) {
+ case 7: /* TCH/AFS12.2 */
+ osmo_conv_decode_ber(&gsm0503_tch_afs_12_2, cB + 8,
+ conv, n_errors, n_bits_total);
+
+ tch_amr_unmerge(d, p, conv, 244, 81);
+
+ rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 81, p);
+ if (rv) {
+ /* Error checking CRC8 for an AMR 12.2 frame */
+ return -1;
+ }
+
+ tch_amr_reassemble(tch_data, d, 244);
+
+ len = 31;
+
+ break;
+ case 6: /* TCH/AFS10.2 */
+ osmo_conv_decode_ber(&gsm0503_tch_afs_10_2, cB + 8,
+ conv, n_errors, n_bits_total);
+
+ tch_amr_unmerge(d, p, conv, 204, 65);
+
+ rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 65, p);
+ if (rv) {
+ /* Error checking CRC8 for an AMR 10.2 frame */
+ return -1;
+ }
+
+ tch_amr_reassemble(tch_data, d, 204);
+
+ len = 26;
+
+ break;
+ case 5: /* TCH/AFS7.95 */
+ osmo_conv_decode_ber(&gsm0503_tch_afs_7_95, cB + 8,
+ conv, n_errors, n_bits_total);
+
+ tch_amr_unmerge(d, p, conv, 159, 75);
+
+ rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 75, p);
+ if (rv) {
+ /* Error checking CRC8 for an AMR 7.95 frame */
+ return -1;
+ }
+
+ tch_amr_reassemble(tch_data, d, 159);
+
+ len = 20;
+
+ break;
+ case 4: /* TCH/AFS7.4 */
+ osmo_conv_decode_ber(&gsm0503_tch_afs_7_4, cB + 8,
+ conv, n_errors, n_bits_total);
+
+ tch_amr_unmerge(d, p, conv, 148, 61);
+
+ rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 61, p);
+ if (rv) {
+ /* Error checking CRC8 for an AMR 7.4 frame */
+ return -1;
+ }
+
+ tch_amr_reassemble(tch_data, d, 148);
+
+ len = 19;
+
+ break;
+ case 3: /* TCH/AFS6.7 */
+ osmo_conv_decode_ber(&gsm0503_tch_afs_6_7, cB + 8,
+ conv, n_errors, n_bits_total);
+
+ tch_amr_unmerge(d, p, conv, 134, 55);
+
+ rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 55, p);
+ if (rv) {
+ /* Error checking CRC8 for an AMR 6.7 frame */
+ return -1;
+ }
+
+ tch_amr_reassemble(tch_data, d, 134);
+
+ len = 17;
+
+ break;
+ case 2: /* TCH/AFS5.9 */
+ osmo_conv_decode_ber(&gsm0503_tch_afs_5_9, cB + 8,
+ conv, n_errors, n_bits_total);
+
+ tch_amr_unmerge(d, p, conv, 118, 55);
+
+ rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 55, p);
+ if (rv) {
+ /* Error checking CRC8 for an AMR 5.9 frame */
+ return -1;
+ }
+
+ tch_amr_reassemble(tch_data, d, 118);
+
+ len = 15;
+
+ break;
+ case 1: /* TCH/AFS5.15 */
+ osmo_conv_decode_ber(&gsm0503_tch_afs_5_15, cB + 8,
+ conv, n_errors, n_bits_total);
+
+ tch_amr_unmerge(d, p, conv, 103, 49);
+
+ rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 49, p);
+ if (rv) {
+ /* Error checking CRC8 for an AMR 5.15 frame */
+ return -1;
+ }
+
+ tch_amr_reassemble(tch_data, d, 103);
+
+ len = 13;
+
+ break;
+ case 0: /* TCH/AFS4.75 */
+ osmo_conv_decode_ber(&gsm0503_tch_afs_4_75, cB + 8,
+ conv, n_errors, n_bits_total);
+
+ tch_amr_unmerge(d, p, conv, 95, 39);
+
+ rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 39, p);
+ if (rv) {
+ /* Error checking CRC8 for an AMR 4.75 frame */
+ return -1;
+ }
+
+ tch_amr_reassemble(tch_data, d, 95);
+
+ len = 12;
+
+ break;
+ default:
+ /* Unknown frame type */
+ *n_bits_total = 448;
+ *n_errors = *n_bits_total;
+ return -1;
+ }
+
+ /* Change codec request / indication, if frame is valid */
+ if (codec_mode_req)
+ *cmr = id;
+ else
+ *ft = id;
+
+ return len;
+}
+
+int gsm0503_tch_afs_encode(ubit_t *bursts, uint8_t *tch_data, int len,
+ int codec_mode_req, uint8_t *codec, int codecs, uint8_t ft,
+ uint8_t cmr)
+{
+ ubit_t iB[912], cB[456], h;
+ ubit_t d[244], p[6], conv[250];
+ int i;
+ uint8_t id;
+
+ if (len == GSM_MACBLOCK_LEN) { /* FACCH */
+ _xcch_encode_cB(cB, tch_data);
+
+ h = 1;
+
+ goto facch;
+ }
+
+ h = 0;
+
+ if (codec_mode_req) {
+ if (cmr >= codecs) {
+ /* FIXME: CMR ID is not in codec list! */
+ return -1;
+ }
+ id = cmr;
+ } else {
+ if (ft >= codecs) {
+ /* FIXME: FT ID is not in codec list! */
+ return -1;
+ }
+ id = ft;
+ }
+
+ switch (codec[ft]) {
+ case 7: /* TCH/AFS12.2 */
+ if (len != 31)
+ goto invalid_length;
+
+ tch_amr_disassemble(d, tch_data, 244);
+
+ osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 81, p);
+
+ tch_amr_merge(conv, d, p, 244, 81);
+
+ osmo_conv_encode(&gsm0503_tch_afs_12_2, conv, cB + 8);
+
+ break;
+ case 6: /* TCH/AFS10.2 */
+ if (len != 26)
+ goto invalid_length;
+
+ tch_amr_disassemble(d, tch_data, 204);
+
+ osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 65, p);
+
+ tch_amr_merge(conv, d, p, 204, 65);
+
+ osmo_conv_encode(&gsm0503_tch_afs_10_2, conv, cB + 8);
+
+ break;
+ case 5: /* TCH/AFS7.95 */
+ if (len != 20)
+ goto invalid_length;
+
+ tch_amr_disassemble(d, tch_data, 159);
+
+ osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 75, p);
+
+ tch_amr_merge(conv, d, p, 159, 75);
+
+ osmo_conv_encode(&gsm0503_tch_afs_7_95, conv, cB + 8);
+
+ break;
+ case 4: /* TCH/AFS7.4 */
+ if (len != 19)
+ goto invalid_length;
+
+ tch_amr_disassemble(d, tch_data, 148);
+
+ osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 61, p);
+
+ tch_amr_merge(conv, d, p, 148, 61);
+
+ osmo_conv_encode(&gsm0503_tch_afs_7_4, conv, cB + 8);
+
+ break;
+ case 3: /* TCH/AFS6.7 */
+ if (len != 17)
+ goto invalid_length;
+
+ tch_amr_disassemble(d, tch_data, 134);
+
+ osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 55, p);
+
+ tch_amr_merge(conv, d, p, 134, 55);
+
+ osmo_conv_encode(&gsm0503_tch_afs_6_7, conv, cB + 8);
+
+ break;
+ case 2: /* TCH/AFS5.9 */
+ if (len != 15)
+ goto invalid_length;
+
+ tch_amr_disassemble(d, tch_data, 118);
+
+ osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 55, p);
+
+ tch_amr_merge(conv, d, p, 118, 55);
+
+ osmo_conv_encode(&gsm0503_tch_afs_5_9, conv, cB + 8);
+
+ break;
+ case 1: /* TCH/AFS5.15 */
+ if (len != 13)
+ goto invalid_length;
+
+ tch_amr_disassemble(d, tch_data, 103);
+
+ osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 49, p);
+
+ tch_amr_merge(conv, d, p, 103, 49);
+
+ osmo_conv_encode(&gsm0503_tch_afs_5_15, conv, cB + 8);
+
+ break;
+ case 0: /* TCH/AFS4.75 */
+ if (len != 12)
+ goto invalid_length;
+
+ tch_amr_disassemble(d, tch_data, 95);
+
+ osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 39, p);
+
+ tch_amr_merge(conv, d, p, 95, 39);
+
+ osmo_conv_encode(&gsm0503_tch_afs_4_75, conv, cB + 8);
+
+ break;
+ default:
+ /* FIXME: FT %ft is not supported */
+ return -1;
+ }
+
+ memcpy(cB, gsm0503_afs_ic_ubit[id], 8);
+
+facch:
+ gsm0503_tch_fr_interleave(cB, iB);
+
+ for (i = 0; i < 8; i++) {
+ gsm0503_tch_burst_map(&iB[i * 114],
+ &bursts[i * 116], &h, i >> 2);
+ }
+
+ return 0;
+
+invalid_length:
+ /* FIXME: payload length %len does not comply with codec type %ft */
+ return -1;
+}
+
+int gsm0503_tch_ahs_decode(uint8_t *tch_data, sbit_t *bursts, int odd,
+ int codec_mode_req, uint8_t *codec, int codecs, uint8_t *ft,
+ uint8_t *cmr, int *n_errors, int *n_bits_total)
+{
+ sbit_t iB[912], cB[456], h;
+ ubit_t d[244], p[6], conv[135];
+ int i, j, k, best = 0, rv, len, steal = 0, id = 0;
+
+ /* only unmap the stealing bits */
+ if (!odd) {
+ for (i = 0; i < 4; i++) {
+ gsm0503_tch_burst_unmap(NULL, &bursts[i * 116], &h, 0);
+ steal -= h;
+ }
+ for (i = 2; i < 5; i++) {
+ gsm0503_tch_burst_unmap(NULL, &bursts[i * 116], &h, 1);
+ steal -= h;
+ }
+ }
+
+ /* if we found a stole FACCH, but only at correct alignment */
+ if (steal > 0) {
+ for (i = 0; i < 6; i++) {
+ gsm0503_tch_burst_unmap(&iB[i * 114],
+ &bursts[i * 116], NULL, i >> 2);
+ }
+
+ for (i = 2; i < 4; i++) {
+ gsm0503_tch_burst_unmap(&iB[i * 114 + 456],
+ &bursts[i * 116], NULL, 1);
+ }
+
+ gsm0503_tch_fr_deinterleave(cB, iB);
+
+ rv = _xcch_decode_cB(tch_data, cB, n_errors, n_bits_total);
+ if (rv) {
+ /* Error decoding FACCH frame */
+ return -1;
+ }
+
+ return GSM_MACBLOCK_LEN;
+ }
+
+ for (i = 0; i < 4; i++) {
+ gsm0503_tch_burst_unmap(&iB[i * 114],
+ &bursts[i * 116], NULL, i >> 1);
+ }
+
+ gsm0503_tch_hr_deinterleave(cB, iB);
+
+ for (i = 0; i < 4; i++) {
+ for (j = 0, k = 0; j < 4; j++)
+ k += abs(((int)gsm0503_ahs_ic_sbit[i][j]) - ((int)cB[j]));
+
+ if (i == 0 || k < best) {
+ best = k;
+ id = i;
+ }
+ }
+
+ /* Check if indicated codec fits into range of codecs */
+ if (id >= codecs) {
+ /* Codec mode out of range, return id */
+ return id;
+ }
+
+ switch ((codec_mode_req) ? codec[*ft] : codec[id]) {
+ case 5: /* TCH/AHS7.95 */
+ osmo_conv_decode_ber(&gsm0503_tch_ahs_7_95, cB + 4,
+ conv, n_errors, n_bits_total);
+
+ tch_amr_unmerge(d, p, conv, 123, 67);
+
+ rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 67, p);
+ if (rv) {
+ /* Error checking CRC8 for an AMR 7.95 frame */
+ return -1;
+ }
+
+ for (i = 0; i < 36; i++)
+ d[i + 123] = (cB[i + 192] < 0) ? 1 : 0;
+
+ tch_amr_reassemble(tch_data, d, 159);
+
+ len = 20;
+
+ break;
+ case 4: /* TCH/AHS7.4 */
+ osmo_conv_decode_ber(&gsm0503_tch_ahs_7_4, cB + 4,
+ conv, n_errors, n_bits_total);
+
+ tch_amr_unmerge(d, p, conv, 120, 61);
+
+ rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 61, p);
+ if (rv) {
+ /* Error checking CRC8 for an AMR 7.4 frame */
+ return -1;
+ }
+
+ for (i = 0; i < 28; i++)
+ d[i + 120] = (cB[i + 200] < 0) ? 1 : 0;
+
+ tch_amr_reassemble(tch_data, d, 148);
+
+ len = 19;
+
+ break;
+ case 3: /* TCH/AHS6.7 */
+ osmo_conv_decode_ber(&gsm0503_tch_ahs_6_7, cB + 4,
+ conv, n_errors, n_bits_total);
+
+ tch_amr_unmerge(d, p, conv, 110, 55);
+
+ rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 55, p);
+ if (rv) {
+ /* Error checking CRC8 for an AMR 6.7 frame */
+ return -1;
+ }
+
+ for (i = 0; i < 24; i++)
+ d[i + 110] = (cB[i + 204] < 0) ? 1 : 0;
+
+ tch_amr_reassemble(tch_data, d, 134);
+
+ len = 17;
+
+ break;
+ case 2: /* TCH/AHS5.9 */
+ osmo_conv_decode_ber(&gsm0503_tch_ahs_5_9, cB + 4,
+ conv, n_errors, n_bits_total);
+
+ tch_amr_unmerge(d, p, conv, 102, 55);
+
+ rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 55, p);
+ if (rv) {
+ /* Error checking CRC8 for an AMR 5.9 frame */
+ return -1;
+ }
+
+ for (i = 0; i < 16; i++)
+ d[i + 102] = (cB[i + 212] < 0) ? 1 : 0;
+
+ tch_amr_reassemble(tch_data, d, 118);
+
+ len = 15;
+
+ break;
+ case 1: /* TCH/AHS5.15 */
+ osmo_conv_decode_ber(&gsm0503_tch_ahs_5_15, cB + 4,
+ conv, n_errors, n_bits_total);
+
+ tch_amr_unmerge(d, p, conv, 91, 49);
+
+ rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 49, p);
+ if (rv) {
+ /* Error checking CRC8 for an AMR 5.15 frame */
+ return -1;
+ }
+
+ for (i = 0; i < 12; i++)
+ d[i + 91] = (cB[i + 216] < 0) ? 1 : 0;
+
+ tch_amr_reassemble(tch_data, d, 103);
+
+ len = 13;
+
+ break;
+ case 0: /* TCH/AHS4.75 */
+ osmo_conv_decode_ber(&gsm0503_tch_ahs_4_75, cB + 4,
+ conv, n_errors, n_bits_total);
+
+ tch_amr_unmerge(d, p, conv, 83, 39);
+
+ rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 39, p);
+ if (rv) {
+ /* Error checking CRC8 for an AMR 4.75 frame */
+ return -1;
+ }
+
+ for (i = 0; i < 12; i++)
+ d[i + 83] = (cB[i + 216] < 0) ? 1 : 0;
+
+ tch_amr_reassemble(tch_data, d, 95);
+
+ len = 12;
+
+ break;
+ default:
+ /* Unknown frame type */
+ *n_bits_total = 159;
+ *n_errors = *n_bits_total;
+ return -1;
+ }
+
+ /* Change codec request / indication, if frame is valid */
+ if (codec_mode_req)
+ *cmr = id;
+ else
+ *ft = id;
+
+ return len;
+}
+
+int gsm0503_tch_ahs_encode(ubit_t *bursts, uint8_t *tch_data, int len,
+ int codec_mode_req, uint8_t *codec, int codecs, uint8_t ft,
+ uint8_t cmr)
+{
+ ubit_t iB[912], cB[456], h;
+ ubit_t d[244], p[6], conv[135];
+ int i;
+ uint8_t id;
+
+ if (len == GSM_MACBLOCK_LEN) { /* FACCH */
+ _xcch_encode_cB(cB, tch_data);
+
+ h = 1;
+
+ gsm0503_tch_fr_interleave(cB, iB);
+
+ for (i = 0; i < 6; i++)
+ gsm0503_tch_burst_map(&iB[i * 114], &bursts[i * 116],
+ &h, i >> 2);
+ for (i = 2; i < 4; i++)
+ gsm0503_tch_burst_map(&iB[i * 114 + 456],
+ &bursts[i * 116], &h, 1);
+
+ return 0;
+ }
+
+ h = 0;
+
+ if (codec_mode_req) {
+ if (cmr >= codecs) {
+ /* FIXME: CMR ID %d not in codec list */
+ return -1;
+ }
+ id = cmr;
+ } else {
+ if (ft >= codecs) {
+ /* FIXME: FT ID %d not in codec list */
+ return -1;
+ }
+ id = ft;
+ }
+
+ switch (codec[ft]) {
+ case 5: /* TCH/AHS7.95 */
+ if (len != 20)
+ goto invalid_length;
+
+ tch_amr_disassemble(d, tch_data, 159);
+
+ osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 67, p);
+
+ tch_amr_merge(conv, d, p, 123, 67);
+
+ osmo_conv_encode(&gsm0503_tch_ahs_7_95, conv, cB + 4);
+
+ memcpy(cB + 192, d + 123, 36);
+
+ break;
+ case 4: /* TCH/AHS7.4 */
+ if (len != 19)
+ goto invalid_length;
+
+ tch_amr_disassemble(d, tch_data, 148);
+
+ osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 61, p);
+
+ tch_amr_merge(conv, d, p, 120, 61);
+
+ osmo_conv_encode(&gsm0503_tch_ahs_7_4, conv, cB + 4);
+
+ memcpy(cB + 200, d + 120, 28);
+
+ break;
+ case 3: /* TCH/AHS6.7 */
+ if (len != 17)
+ goto invalid_length;
+
+ tch_amr_disassemble(d, tch_data, 134);
+
+ osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 55, p);
+
+ tch_amr_merge(conv, d, p, 110, 55);
+
+ osmo_conv_encode(&gsm0503_tch_ahs_6_7, conv, cB + 4);
+
+ memcpy(cB + 204, d + 110, 24);
+
+ break;
+ case 2: /* TCH/AHS5.9 */
+ if (len != 15)
+ goto invalid_length;
+
+ tch_amr_disassemble(d, tch_data, 118);
+
+ osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 55, p);
+
+ tch_amr_merge(conv, d, p, 102, 55);
+
+ osmo_conv_encode(&gsm0503_tch_ahs_5_9, conv, cB + 4);
+
+ memcpy(cB + 212, d + 102, 16);
+
+ break;
+ case 1: /* TCH/AHS5.15 */
+ if (len != 13)
+ goto invalid_length;
+
+ tch_amr_disassemble(d, tch_data, 103);
+
+ osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 49, p);
+
+ tch_amr_merge(conv, d, p, 91, 49);
+
+ osmo_conv_encode(&gsm0503_tch_ahs_5_15, conv, cB + 4);
+
+ memcpy(cB + 216, d + 91, 12);
+
+ break;
+ case 0: /* TCH/AHS4.75 */
+ if (len != 12)
+ goto invalid_length;
+
+ tch_amr_disassemble(d, tch_data, 95);
+
+ osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 39, p);
+
+ tch_amr_merge(conv, d, p, 83, 39);
+
+ osmo_conv_encode(&gsm0503_tch_ahs_4_75, conv, cB + 4);
+
+ memcpy(cB + 216, d + 83, 12);
+
+ break;
+ default:
+ /* FIXME: FT %ft is not supported */
+ return -1;
+ }
+
+ memcpy(cB, gsm0503_afs_ic_ubit[id], 4);
+
+ gsm0503_tch_hr_interleave(cB, iB);
+
+ for (i = 0; i < 4; i++)
+ gsm0503_tch_burst_map(&iB[i * 114], &bursts[i * 116], &h, i >> 1);
+
+ return 0;
+
+invalid_length:
+ /* FIXME: payload length %len does not comply with codec type %ft */
+ return -1;
+}
+
+/*
+ * GSM RACH transcoding
+ */
+
+/*
+ * GSM RACH apply BSIC to parity
+ *
+ * p(j) = p(j) xor b(j) j = 0, ..., 5
+ * b(0) = MSB of PLMN colour code
+ * b(5) = LSB of BS colour code
+ */
+static int rach_apply_bsic(ubit_t *d, uint8_t bsic)
+{
+ int i;
+
+ /* Apply it */
+ for (i = 0; i < 6; i++)
+ d[8 + i] ^= ((bsic >> (5 - i)) & 1);
+
+ return 0;
+}
+
+int gsm0503_rach_decode(uint8_t *ra, sbit_t *burst, uint8_t bsic)
+{
+ ubit_t conv[14];
+ int rv;
+
+ osmo_conv_decode(&gsm0503_rach, burst, conv);
+
+ rach_apply_bsic(conv, bsic);
+
+ rv = osmo_crc8gen_check_bits(&gsm0503_rach_crc6, conv, 8, conv + 8);
+ if (rv)
+ return -1;
+
+ osmo_ubit2pbit_ext(ra, 0, conv, 0, 8, 1);
+
+ return 0;
+}
+
+int gsm0503_rach_encode(ubit_t *burst, uint8_t *ra, uint8_t bsic)
+{
+ ubit_t conv[14];
+
+ osmo_pbit2ubit_ext(conv, 0, ra, 0, 8, 1);
+
+ osmo_crc8gen_set_bits(&gsm0503_rach_crc6, conv, 8, conv + 8);
+
+ rach_apply_bsic(conv, bsic);
+
+ osmo_conv_encode(&gsm0503_rach, conv, burst);
+
+ return 0;
+}
+
+/*
+ * GSM SCH transcoding
+ */
+int gsm0503_sch_decode(uint8_t *sb_info, sbit_t *burst)
+{
+ ubit_t conv[35];
+ int rv;
+
+ osmo_conv_decode(&gsm0503_sch, burst, conv);
+
+ rv = osmo_crc16gen_check_bits(&gsm0503_sch_crc10, conv, 25, conv + 25);
+ if (rv)
+ return -1;
+
+ osmo_ubit2pbit_ext(sb_info, 0, conv, 0, 25, 1);
+
+ return 0;
+}
+
+int gsm0503_sch_encode(ubit_t *burst, uint8_t *sb_info)
+{
+ ubit_t conv[35];
+
+ osmo_pbit2ubit_ext(conv, 0, sb_info, 0, 25, 1);
+
+ osmo_crc16gen_set_bits(&gsm0503_sch_crc10, conv, 25, conv + 25);
+
+ osmo_conv_encode(&gsm0503_sch, conv, burst);
+
+ return 0;
+}
diff --git a/lib/decoding/osmocom/coding/gsm0503_coding.h b/lib/decoding/osmocom/coding/gsm0503_coding.h
new file mode 100644
index 0000000..5e3e9db
--- /dev/null
+++ b/lib/decoding/osmocom/coding/gsm0503_coding.h
@@ -0,0 +1,68 @@
+/*
+ * (C) 2013 by Andreas Eversberg <jolly@eversberg.eu>
+ * (C) 2015 by Alexander Chemeris <Alexander.Chemeris@fairwaves.co>
+ * (C) 2016 by Tom Tsou <tom.tsou@ettus.com>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <osmocom/core/bits.h>
+
+#define GSM0503_GPRS_BURSTS_NBITS (116 * 4)
+#define GSM0503_EGPRS_BURSTS_NBITS (348 * 4)
+#define NUM_BYTES(N) ((N + 8 - 1) / 8)
+
+
+
+int gsm0503_xcch_encode(ubit_t *bursts, uint8_t *l2_data);
+int gsm0503_xcch_decode(uint8_t *l2_data, sbit_t *bursts,
+ int *n_errors, int *n_bits_total);
+
+int gsm0503_pdtch_encode(ubit_t *bursts, uint8_t *l2_data, uint8_t l2_len);
+int gsm0503_pdtch_decode(uint8_t *l2_data, sbit_t *bursts, uint8_t *usf_p,
+ int *n_errors, int *n_bits_total);
+
+int gsm0503_tch_fr_encode(ubit_t *bursts, uint8_t *tch_data, int len,
+ int net_order);
+int gsm0503_tch_fr_decode(uint8_t *tch_data, sbit_t *bursts, int net_order,
+ int efr, int *n_errors, int *n_bits_total);
+
+int gsm0503_tch_hr_encode(ubit_t *bursts, uint8_t *tch_data, int len);
+int gsm0503_tch_hr_decode(uint8_t *tch_data, sbit_t *bursts, int odd,
+ int *n_errors, int *n_bits_total);
+
+int gsm0503_tch_afs_encode(ubit_t *bursts, uint8_t *tch_data, int len,
+ int codec_mode_req, uint8_t *codec, int codecs, uint8_t ft,
+ uint8_t cmr);
+int gsm0503_tch_afs_decode(uint8_t *tch_data, sbit_t *bursts,
+ int codec_mode_req, uint8_t *codec, int codecs, uint8_t *ft,
+ uint8_t *cmr, int *n_errors, int *n_bits_total);
+
+int gsm0503_tch_ahs_encode(ubit_t *bursts, uint8_t *tch_data, int len,
+ int codec_mode_req, uint8_t *codec, int codecs, uint8_t ft, uint8_t cmr);
+int gsm0503_tch_ahs_decode(uint8_t *tch_data, sbit_t *bursts, int odd,
+ int codec_mode_req, uint8_t *codec, int codecs, uint8_t *ft,
+ uint8_t *cmr, int *n_errors, int *n_bits_total);
+
+int gsm0503_rach_encode(ubit_t *burst, uint8_t *ra, uint8_t bsic);
+int gsm0503_rach_decode(uint8_t *ra, sbit_t *burst, uint8_t bsic);
+
+int gsm0503_sch_encode(ubit_t *burst, uint8_t *sb_info);
+int gsm0503_sch_decode(uint8_t *sb_info, sbit_t *burst);
diff --git a/lib/decoding/osmocom/coding/gsm0503_conv.c b/lib/decoding/osmocom/coding/gsm0503_conv.c
new file mode 100644
index 0000000..5ab63a6
--- /dev/null
+++ b/lib/decoding/osmocom/coding/gsm0503_conv.c
@@ -0,0 +1,1918 @@
+/*
+ * Copyright (C) 2011-2016 Sylvain Munaut <tnt@246tNt.com>
+ * Copyright (C) 2016 sysmocom s.f.m.c. GmbH
+ *
+ * All Rights Reserved
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdint.h>
+#include <osmocom/core/conv.h>
+
+static const uint8_t xcch_state[][2] = {
+ { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 },
+ { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 },
+ { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 },
+ { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 },
+};
+
+static const uint8_t xcch_output[][2] = {
+ { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 },
+ { 3, 0 }, { 2, 1 }, { 3, 0 }, { 2, 1 },
+ { 3, 0 }, { 2, 1 }, { 3, 0 }, { 2, 1 },
+ { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 },
+};
+
+/**
+ * xCCH convolutional code:
+ * 228 bits blocks, rate 1/2, k = 5
+ * G0 = 1 + D3 + D4
+ * G1 = 1 + D + D3 + D4
+ */
+const struct osmo_conv_code gsm0503_xcch = {
+ .N = 2,
+ .K = 5,
+ .len = 224,
+ .next_output = xcch_output,
+ .next_state = xcch_state,
+};
+
+static const uint8_t rach_state[][2] = {
+ { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 },
+ { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 },
+ { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 },
+ { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 },
+};
+
+static const uint8_t rach_output[][2] = {
+ { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 },
+ { 3, 0 }, { 2, 1 }, { 3, 0 }, { 2, 1 },
+ { 3, 0 }, { 2, 1 }, { 3, 0 }, { 2, 1 },
+ { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 },
+};
+
+/**
+ * RACH convolutional code
+ */
+const struct osmo_conv_code gsm0503_rach = {
+ .N = 2,
+ .K = 5,
+ .len = 14,
+ .next_output = rach_output,
+ .next_state = rach_state,
+};
+
+static const uint8_t sch_state[][2] = {
+ { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 },
+ { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 },
+ { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 },
+ { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 },
+};
+
+static const uint8_t sch_output[][2] = {
+ { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 },
+ { 3, 0 }, { 2, 1 }, { 3, 0 }, { 2, 1 },
+ { 3, 0 }, { 2, 1 }, { 3, 0 }, { 2, 1 },
+ { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 },
+};
+
+/**
+ * SCH convolutional code
+ */
+const struct osmo_conv_code gsm0503_sch = {
+ .N = 2,
+ .K = 5,
+ .len = 35,
+ .next_output = sch_output,
+ .next_state = sch_state,
+};
+
+static const uint8_t cs2_state[][2] = {
+ { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 },
+ { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 },
+ { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 },
+ { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 },
+};
+
+static const uint8_t cs2_output[][2] = {
+ { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 },
+ { 3, 0 }, { 2, 1 }, { 3, 0 }, { 2, 1 },
+ { 3, 0 }, { 2, 1 }, { 3, 0 }, { 2, 1 },
+ { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 },
+};
+
+static const int cs2_puncture[] = {
+ 15, 19, 23, 27, 31, 35, 43, 47, 51, 55, 59, 63,
+ 67, 71, 75, 79, 83, 91, 95, 99, 103, 107, 111, 115,
+ 119, 123, 127, 131, 139, 143, 147, 151, 155, 159, 163, 167,
+ 171, 175, 179, 187, 191, 195, 199, 203, 207, 211, 215, 219,
+ 223, 227, 235, 239, 243, 247, 251, 255, 259, 263, 267, 271,
+ 275, 283, 287, 291, 295, 299, 303, 307, 311, 315, 319, 323,
+ 331, 335, 339, 343, 347, 351, 355, 359, 363, 367, 371, 379,
+ 383, 387, 391, 395, 399, 403, 407, 411, 415, 419, 427, 431,
+ 435, 439, 443, 447, 451, 455, 459, 463, 467, 475, 479, 483,
+ 487, 491, 495, 499, 503, 507, 511, 515, 523, 527, 531, 535,
+ 539, 543, 547, 551, 555, 559, 563, 571, 575, 579, 583, 587,
+ -1,
+};
+
+/**
+ * CS2 convolutional code:
+ * G0 = 1 + D3 + D4
+ * G1 = 1 + D + D3 + D4
+ */
+const struct osmo_conv_code gsm0503_cs2 = {
+ .N = 2,
+ .K = 5,
+ .len = 290,
+ .next_output = cs2_output,
+ .next_state = cs2_state,
+ .puncture = cs2_puncture,
+};
+
+static const uint8_t cs3_state[][2] = {
+ { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 },
+ { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 },
+ { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 },
+ { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 },
+};
+
+static const uint8_t cs3_output[][2] = {
+ { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 },
+ { 3, 0 }, { 2, 1 }, { 3, 0 }, { 2, 1 },
+ { 3, 0 }, { 2, 1 }, { 3, 0 }, { 2, 1 },
+ { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 },
+};
+
+static const int cs3_puncture[] = {
+ 15, 17, 21, 23, 27, 29, 33, 35, 39, 41, 45, 47,
+ 51, 53, 57, 59, 63, 65, 69, 71, 75, 77, 81, 83,
+ 87, 89, 93, 95, 99, 101, 105, 107, 111, 113, 117, 119,
+ 123, 125, 129, 131, 135, 137, 141, 143, 147, 149, 153, 155,
+ 159, 161, 165, 167, 171, 173, 177, 179, 183, 185, 189, 191,
+ 195, 197, 201, 203, 207, 209, 213, 215, 219, 221, 225, 227,
+ 231, 233, 237, 239, 243, 245, 249, 251, 255, 257, 261, 263,
+ 267, 269, 273, 275, 279, 281, 285, 287, 291, 293, 297, 299,
+ 303, 305, 309, 311, 315, 317, 321, 323, 327, 329, 333, 335,
+ 339, 341, 345, 347, 351, 353, 357, 359, 363, 365, 369, 371,
+ 375, 377, 381, 383, 387, 389, 393, 395, 399, 401, 405, 407,
+ 411, 413, 417, 419, 423, 425, 429, 431, 435, 437, 441, 443,
+ 447, 449, 453, 455, 459, 461, 465, 467, 471, 473, 477, 479,
+ 483, 485, 489, 491, 495, 497, 501, 503, 507, 509, 513, 515,
+ 519, 521, 525, 527, 531, 533, 537, 539, 543, 545, 549, 551,
+ 555, 557, 561, 563, 567, 569, 573, 575, 579, 581, 585, 587,
+ 591, 593, 597, 599, 603, 605, 609, 611, 615, 617, 621, 623,
+ 627, 629, 633, 635, 639, 641, 645, 647, 651, 653, 657, 659,
+ 663, 665, 669, 671, -1,
+};
+
+/**
+ * CS3 convolutional code:
+ * G0 = 1 + D3 + D4
+ * G1 = 1 + D + D3 + D4
+ */
+const struct osmo_conv_code gsm0503_cs3 = {
+ .N = 2,
+ .K = 5,
+ .len = 334,
+ .next_output = cs3_output,
+ .next_state = cs3_state,
+ .puncture = cs3_puncture,
+};
+
+static const uint8_t tch_afs_12_2_state[][2] = {
+ { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 },
+ { 9, 8 }, { 11, 10 }, { 13, 12 }, { 15, 14 },
+ { 1, 0 }, { 3, 2 }, { 5, 4 }, { 7, 6 },
+ { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 },
+};
+
+static const uint8_t tch_afs_12_2_output[][2] = {
+ { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 },
+ { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 },
+ { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 },
+ { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 },
+};
+
+static const uint8_t tch_afs_12_2_term_state[] = {
+ 0, 2, 4, 6, 8, 10, 12, 14, 0, 2, 4, 6,
+ 8, 10, 12, 14,
+};
+
+static const uint8_t tch_afs_12_2_term_output[] = {
+ 0, 1, 0, 1, 3, 2, 3, 2, 3, 2, 3, 2,
+ 0, 1, 0, 1,
+};
+
+static const int tch_afs_12_2_puncture[] = {
+ 321, 325, 329, 333, 337, 341, 345, 349, 353, 357, 361, 363,
+ 365, 369, 373, 377, 379, 381, 385, 389, 393, 395, 397, 401,
+ 405, 409, 411, 413, 417, 421, 425, 427, 429, 433, 437, 441,
+ 443, 445, 449, 453, 457, 459, 461, 465, 469, 473, 475, 477,
+ 481, 485, 489, 491, 493, 495, 497, 499, 501, 503, 505, 507,
+ -1,
+};
+
+/**
+ * TCH/AFS 12.2 kbits convolutional code:
+ * 250 bits block, rate 1/2, punctured
+ * G0/G0 = 1
+ * G1/G0 = 1 + D + D3 + D4 / 1 + D3 + D4
+ */
+const struct osmo_conv_code gsm0503_tch_afs_12_2 = {
+ .N = 2,
+ .K = 5,
+ .len = 250,
+ .next_output = tch_afs_12_2_output,
+ .next_state = tch_afs_12_2_state,
+ .next_term_output = tch_afs_12_2_term_output,
+ .next_term_state = tch_afs_12_2_term_state,
+ .puncture = tch_afs_12_2_puncture,
+};
+
+static const uint8_t tch_afs_10_2_state[][2] = {
+ { 0, 1 }, { 3, 2 }, { 5, 4 }, { 6, 7 },
+ { 9, 8 }, { 10, 11 }, { 12, 13 }, { 15, 14 },
+ { 1, 0 }, { 2, 3 }, { 4, 5 }, { 7, 6 },
+ { 8, 9 }, { 11, 10 }, { 13, 12 }, { 14, 15 },
+};
+
+static const uint8_t tch_afs_10_2_output[][2] = {
+ { 0, 7 }, { 2, 5 }, { 4, 3 }, { 6, 1 },
+ { 2, 5 }, { 0, 7 }, { 6, 1 }, { 4, 3 },
+ { 0, 7 }, { 2, 5 }, { 4, 3 }, { 6, 1 },
+ { 2, 5 }, { 0, 7 }, { 6, 1 }, { 4, 3 },
+};
+
+static const uint8_t tch_afs_10_2_term_state[] = {
+ 0, 2, 4, 6, 8, 10, 12, 14, 0, 2, 4, 6,
+ 8, 10, 12, 14,
+};
+
+static const uint8_t tch_afs_10_2_term_output[] = {
+ 0, 5, 3, 6, 5, 0, 6, 3, 7, 2, 4, 1,
+ 2, 7, 1, 4,
+};
+
+static const int tch_afs_10_2_puncture[] = {
+ 1, 4, 7, 10, 16, 19, 22, 28, 31, 34, 40, 43,
+ 46, 52, 55, 58, 64, 67, 70, 76, 79, 82, 88, 91,
+ 94, 100, 103, 106, 112, 115, 118, 124, 127, 130, 136, 139,
+ 142, 148, 151, 154, 160, 163, 166, 172, 175, 178, 184, 187,
+ 190, 196, 199, 202, 208, 211, 214, 220, 223, 226, 232, 235,
+ 238, 244, 247, 250, 256, 259, 262, 268, 271, 274, 280, 283,
+ 286, 292, 295, 298, 304, 307, 310, 316, 319, 322, 325, 328,
+ 331, 334, 337, 340, 343, 346, 349, 352, 355, 358, 361, 364,
+ 367, 370, 373, 376, 379, 382, 385, 388, 391, 394, 397, 400,
+ 403, 406, 409, 412, 415, 418, 421, 424, 427, 430, 433, 436,
+ 439, 442, 445, 448, 451, 454, 457, 460, 463, 466, 469, 472,
+ 475, 478, 481, 484, 487, 490, 493, 496, 499, 502, 505, 508,
+ 511, 514, 517, 520, 523, 526, 529, 532, 535, 538, 541, 544,
+ 547, 550, 553, 556, 559, 562, 565, 568, 571, 574, 577, 580,
+ 583, 586, 589, 592, 595, 598, 601, 604, 607, 609, 610, 613,
+ 616, 619, 621, 622, 625, 627, 628, 631, 633, 634, 636, 637,
+ 639, 640, -1,
+};
+
+/**
+ * TCH/AFS 10.2 kbits convolutional code:
+ * G1/G3 = 1 + D + D3 + D4 / 1 + D + D2 + D3 + D4
+ * G2/G3 = 1 + D2 + D4 / 1 + D + D2 + D3 + D4
+ * G3/G3 = 1
+ */
+const struct osmo_conv_code gsm0503_tch_afs_10_2 = {
+ .N = 3,
+ .K = 5,
+ .len = 210,
+ .next_output = tch_afs_10_2_output,
+ .next_state = tch_afs_10_2_state,
+ .next_term_output = tch_afs_10_2_term_output,
+ .next_term_state = tch_afs_10_2_term_state,
+ .puncture = tch_afs_10_2_puncture,
+};
+
+static const uint8_t tch_afs_7_95_state[][2] = {
+ { 0, 1 }, { 2, 3 }, { 5, 4 }, { 7, 6 },
+ { 9, 8 }, { 11, 10 }, { 12, 13 }, { 14, 15 },
+ { 16, 17 }, { 18, 19 }, { 21, 20 }, { 23, 22 },
+ { 25, 24 }, { 27, 26 }, { 28, 29 }, { 30, 31 },
+ { 33, 32 }, { 35, 34 }, { 36, 37 }, { 38, 39 },
+ { 40, 41 }, { 42, 43 }, { 45, 44 }, { 47, 46 },
+ { 49, 48 }, { 51, 50 }, { 52, 53 }, { 54, 55 },
+ { 56, 57 }, { 58, 59 }, { 61, 60 }, { 63, 62 },
+ { 1, 0 }, { 3, 2 }, { 4, 5 }, { 6, 7 },
+ { 8, 9 }, { 10, 11 }, { 13, 12 }, { 15, 14 },
+ { 17, 16 }, { 19, 18 }, { 20, 21 }, { 22, 23 },
+ { 24, 25 }, { 26, 27 }, { 29, 28 }, { 31, 30 },
+ { 32, 33 }, { 34, 35 }, { 37, 36 }, { 39, 38 },
+ { 41, 40 }, { 43, 42 }, { 44, 45 }, { 46, 47 },
+ { 48, 49 }, { 50, 51 }, { 53, 52 }, { 55, 54 },
+ { 57, 56 }, { 59, 58 }, { 60, 61 }, { 62, 63 },
+};
+
+static const uint8_t tch_afs_7_95_output[][2] = {
+ { 0, 7 }, { 3, 4 }, { 2, 5 }, { 1, 6 },
+ { 2, 5 }, { 1, 6 }, { 0, 7 }, { 3, 4 },
+ { 3, 4 }, { 0, 7 }, { 1, 6 }, { 2, 5 },
+ { 1, 6 }, { 2, 5 }, { 3, 4 }, { 0, 7 },
+ { 3, 4 }, { 0, 7 }, { 1, 6 }, { 2, 5 },
+ { 1, 6 }, { 2, 5 }, { 3, 4 }, { 0, 7 },
+ { 0, 7 }, { 3, 4 }, { 2, 5 }, { 1, 6 },
+ { 2, 5 }, { 1, 6 }, { 0, 7 }, { 3, 4 },
+ { 0, 7 }, { 3, 4 }, { 2, 5 }, { 1, 6 },
+ { 2, 5 }, { 1, 6 }, { 0, 7 }, { 3, 4 },
+ { 3, 4 }, { 0, 7 }, { 1, 6 }, { 2, 5 },
+ { 1, 6 }, { 2, 5 }, { 3, 4 }, { 0, 7 },
+ { 3, 4 }, { 0, 7 }, { 1, 6 }, { 2, 5 },
+ { 1, 6 }, { 2, 5 }, { 3, 4 }, { 0, 7 },
+ { 0, 7 }, { 3, 4 }, { 2, 5 }, { 1, 6 },
+ { 2, 5 }, { 1, 6 }, { 0, 7 }, { 3, 4 },
+};
+
+static const uint8_t tch_afs_7_95_term_state[] = {
+ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22,
+ 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46,
+ 48, 50, 52, 54, 56, 58, 60, 62, 0, 2, 4, 6,
+ 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30,
+ 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54,
+ 56, 58, 60, 62,
+};
+
+static const uint8_t tch_afs_7_95_term_output[] = {
+ 0, 3, 5, 6, 5, 6, 0, 3, 3, 0, 6, 5,
+ 6, 5, 3, 0, 4, 7, 1, 2, 1, 2, 4, 7,
+ 7, 4, 2, 1, 2, 1, 7, 4, 7, 4, 2, 1,
+ 2, 1, 7, 4, 4, 7, 1, 2, 1, 2, 4, 7,
+ 3, 0, 6, 5, 6, 5, 3, 0, 0, 3, 5, 6,
+ 5, 6, 0, 3,
+};
+
+static const int tch_afs_7_95_puncture[] = {
+ 1, 2, 4, 5, 8, 22, 70, 118, 166, 214, 262, 310,
+ 317, 319, 325, 332, 334, 341, 343, 349, 356, 358, 365, 367,
+ 373, 380, 382, 385, 389, 391, 397, 404, 406, 409, 413, 415,
+ 421, 428, 430, 433, 437, 439, 445, 452, 454, 457, 461, 463,
+ 469, 476, 478, 481, 485, 487, 490, 493, 500, 502, 503, 505,
+ 506, 508, 509, 511, 512, -1,
+};
+
+/**
+ * TCH/AFS 7.95 kbits convolutional code:
+ * G4/G4 = 1
+ * G5/G4 = 1 + D + D4 + D6 / 1 + D2 + D3 + D5 + D6
+ * G6/G4 = 1 + D + D2 + D3 + D4 + D6 / 1 + D2 + D3 + D5 + D6
+ */
+const struct osmo_conv_code gsm0503_tch_afs_7_95 = {
+ .N = 3,
+ .K = 7,
+ .len = 165,
+ .next_output = tch_afs_7_95_output,
+ .next_state = tch_afs_7_95_state,
+ .next_term_output = tch_afs_7_95_term_output,
+ .next_term_state = tch_afs_7_95_term_state,
+ .puncture = tch_afs_7_95_puncture,
+};
+
+static const uint8_t tch_afs_7_4_state[][2] = {
+ { 0, 1 }, { 3, 2 }, { 5, 4 }, { 6, 7 },
+ { 9, 8 }, { 10, 11 }, { 12, 13 }, { 15, 14 },
+ { 1, 0 }, { 2, 3 }, { 4, 5 }, { 7, 6 },
+ { 8, 9 }, { 11, 10 }, { 13, 12 }, { 14, 15 },
+};
+
+static const uint8_t tch_afs_7_4_output[][2] = {
+ { 0, 7 }, { 2, 5 }, { 4, 3 }, { 6, 1 },
+ { 2, 5 }, { 0, 7 }, { 6, 1 }, { 4, 3 },
+ { 0, 7 }, { 2, 5 }, { 4, 3 }, { 6, 1 },
+ { 2, 5 }, { 0, 7 }, { 6, 1 }, { 4, 3 },
+};
+
+static const uint8_t tch_afs_7_4_term_state[] = {
+ 0, 2, 4, 6, 8, 10, 12, 14, 0, 2, 4, 6,
+ 8, 10, 12, 14,
+};
+
+static const uint8_t tch_afs_7_4_term_output[] = {
+ 0, 5, 3, 6, 5, 0, 6, 3, 7, 2, 4, 1,
+ 2, 7, 1, 4,
+};
+
+static const int tch_afs_7_4_puncture[] = {
+ 0, 355, 361, 367, 373, 379, 385, 391, 397, 403, 409, 415,
+ 421, 427, 433, 439, 445, 451, 457, 460, 463, 466, 468, 469,
+ 471, 472, -1,
+};
+
+/**
+ * TCH/AFS 7.4 kbits convolutional code:
+ * G1/G3 = 1 + D + D3 + D4 / 1 + D + D2 + D3 + D4
+ * G2/G3 = 1 + D2 + D4 / 1 + D + D2 + D3 + D4
+ * G3/G3 = 1
+ */
+const struct osmo_conv_code gsm0503_tch_afs_7_4 = {
+ .N = 3,
+ .K = 5,
+ .len = 154,
+ .next_output = tch_afs_7_4_output,
+ .next_state = tch_afs_7_4_state,
+ .next_term_output = tch_afs_7_4_term_output,
+ .next_term_state = tch_afs_7_4_term_state,
+ .puncture = tch_afs_7_4_puncture,
+};
+
+static const uint8_t tch_afs_6_7_state[][2] = {
+ { 0, 1 }, { 3, 2 }, { 5, 4 }, { 6, 7 },
+ { 9, 8 }, { 10, 11 }, { 12, 13 }, { 15, 14 },
+ { 1, 0 }, { 2, 3 }, { 4, 5 }, { 7, 6 },
+ { 8, 9 }, { 11, 10 }, { 13, 12 }, { 14, 15 },
+};
+
+static const uint8_t tch_afs_6_7_output[][2] = {
+ { 0, 15 }, { 4, 11 }, { 8, 7 }, { 12, 3 },
+ { 4, 11 }, { 0, 15 }, { 12, 3 }, { 8, 7 },
+ { 0, 15 }, { 4, 11 }, { 8, 7 }, { 12, 3 },
+ { 4, 11 }, { 0, 15 }, { 12, 3 }, { 8, 7 },
+};
+
+static const uint8_t tch_afs_6_7_term_state[] = {
+ 0, 2, 4, 6, 8, 10, 12, 14, 0, 2, 4, 6,
+ 8, 10, 12, 14,
+};
+
+static const uint8_t tch_afs_6_7_term_output[] = {
+ 0, 11, 7, 12, 11, 0, 12, 7, 15, 4, 8, 3,
+ 4, 15, 3, 8,
+};
+
+static const int tch_afs_6_7_puncture[] = {
+ 1, 3, 7, 11, 15, 27, 39, 55, 67, 79, 95, 107,
+ 119, 135, 147, 159, 175, 187, 199, 215, 227, 239, 255, 267,
+ 279, 287, 291, 295, 299, 303, 307, 311, 315, 319, 323, 327,
+ 331, 335, 339, 343, 347, 351, 355, 359, 363, 367, 369, 371,
+ 375, 377, 379, 383, 385, 387, 391, 393, 395, 399, 401, 403,
+ 407, 409, 411, 415, 417, 419, 423, 425, 427, 431, 433, 435,
+ 439, 441, 443, 447, 449, 451, 455, 457, 459, 463, 465, 467,
+ 471, 473, 475, 479, 481, 483, 487, 489, 491, 495, 497, 499,
+ 503, 505, 507, 511, 513, 515, 519, 521, 523, 527, 529, 531,
+ 535, 537, 539, 543, 545, 547, 549, 551, 553, 555, 557, 559,
+ 561, 563, 565, 567, 569, 571, 573, 575, -1,
+};
+
+/**
+ * TCH/AFS 6.7 kbits convolutional code:
+ * G1/G3 = 1 + D + D3 + D4 / 1 + D + D2 + D3 + D4
+ * G2/G3 = 1 + D2 + D4 / 1 + D + D2 + D3 + D4
+ * G3/G3 = 1
+ * G3/G3 = 1
+ */
+const struct osmo_conv_code gsm0503_tch_afs_6_7 = {
+ .N = 4,
+ .K = 5,
+ .len = 140,
+ .next_output = tch_afs_6_7_output,
+ .next_state = tch_afs_6_7_state,
+ .next_term_output = tch_afs_6_7_term_output,
+ .next_term_state = tch_afs_6_7_term_state,
+ .puncture = tch_afs_6_7_puncture,
+};
+
+static const uint8_t tch_afs_5_9_state[][2] = {
+ { 0, 1 }, { 3, 2 }, { 5, 4 }, { 6, 7 },
+ { 9, 8 }, { 10, 11 }, { 12, 13 }, { 15, 14 },
+ { 17, 16 }, { 18, 19 }, { 20, 21 }, { 23, 22 },
+ { 24, 25 }, { 27, 26 }, { 29, 28 }, { 30, 31 },
+ { 32, 33 }, { 35, 34 }, { 37, 36 }, { 38, 39 },
+ { 41, 40 }, { 42, 43 }, { 44, 45 }, { 47, 46 },
+ { 49, 48 }, { 50, 51 }, { 52, 53 }, { 55, 54 },
+ { 56, 57 }, { 59, 58 }, { 61, 60 }, { 62, 63 },
+ { 1, 0 }, { 2, 3 }, { 4, 5 }, { 7, 6 },
+ { 8, 9 }, { 11, 10 }, { 13, 12 }, { 14, 15 },
+ { 16, 17 }, { 19, 18 }, { 21, 20 }, { 22, 23 },
+ { 25, 24 }, { 26, 27 }, { 28, 29 }, { 31, 30 },
+ { 33, 32 }, { 34, 35 }, { 36, 37 }, { 39, 38 },
+ { 40, 41 }, { 43, 42 }, { 45, 44 }, { 46, 47 },
+ { 48, 49 }, { 51, 50 }, { 53, 52 }, { 54, 55 },
+ { 57, 56 }, { 58, 59 }, { 60, 61 }, { 63, 62 },
+};
+
+static const uint8_t tch_afs_5_9_output[][2] = {
+ { 0, 15 }, { 8, 7 }, { 4, 11 }, { 12, 3 },
+ { 4, 11 }, { 12, 3 }, { 0, 15 }, { 8, 7 },
+ { 8, 7 }, { 0, 15 }, { 12, 3 }, { 4, 11 },
+ { 12, 3 }, { 4, 11 }, { 8, 7 }, { 0, 15 },
+ { 8, 7 }, { 0, 15 }, { 12, 3 }, { 4, 11 },
+ { 12, 3 }, { 4, 11 }, { 8, 7 }, { 0, 15 },
+ { 0, 15 }, { 8, 7 }, { 4, 11 }, { 12, 3 },
+ { 4, 11 }, { 12, 3 }, { 0, 15 }, { 8, 7 },
+ { 0, 15 }, { 8, 7 }, { 4, 11 }, { 12, 3 },
+ { 4, 11 }, { 12, 3 }, { 0, 15 }, { 8, 7 },
+ { 8, 7 }, { 0, 15 }, { 12, 3 }, { 4, 11 },
+ { 12, 3 }, { 4, 11 }, { 8, 7 }, { 0, 15 },
+ { 8, 7 }, { 0, 15 }, { 12, 3 }, { 4, 11 },
+ { 12, 3 }, { 4, 11 }, { 8, 7 }, { 0, 15 },
+ { 0, 15 }, { 8, 7 }, { 4, 11 }, { 12, 3 },
+ { 4, 11 }, { 12, 3 }, { 0, 15 }, { 8, 7 },
+};
+
+static const uint8_t tch_afs_5_9_term_state[] = {
+ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22,
+ 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46,
+ 48, 50, 52, 54, 56, 58, 60, 62, 0, 2, 4, 6,
+ 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30,
+ 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54,
+ 56, 58, 60, 62,
+};
+
+static const uint8_t tch_afs_5_9_term_output[] = {
+ 0, 7, 11, 12, 11, 12, 0, 7, 7, 0, 12, 11,
+ 12, 11, 7, 0, 8, 15, 3, 4, 3, 4, 8, 15,
+ 15, 8, 4, 3, 4, 3, 15, 8, 15, 8, 4, 3,
+ 4, 3, 15, 8, 8, 15, 3, 4, 3, 4, 8, 15,
+ 7, 0, 12, 11, 12, 11, 7, 0, 0, 7, 11, 12,
+ 11, 12, 0, 7,
+};
+
+static const int tch_afs_5_9_puncture[] = {
+ 0, 1, 3, 5, 7, 11, 15, 31, 47, 63, 79, 95,
+ 111, 127, 143, 159, 175, 191, 207, 223, 239, 255, 271, 287,
+ 303, 319, 327, 331, 335, 343, 347, 351, 359, 363, 367, 375,
+ 379, 383, 391, 395, 399, 407, 411, 415, 423, 427, 431, 439,
+ 443, 447, 455, 459, 463, 467, 471, 475, 479, 483, 487, 491,
+ 495, 499, 503, 507, 509, 511, 512, 513, 515, 516, 517, 519,
+ -1,
+};
+
+/**
+ * TCH/AFS 5.9 kbits convolutional code:
+ * 124 bits
+ * G4/G6 = 1 + D2 + D3 + D5 + D6 / 1 + D + D2 + D3 + D4 + D6
+ * G5/G6 = 1 + D + D4 + D6 / 1 + D + D2 + D3 + D4 + D6
+ * G6/G6 = 1
+ * G6/G6 = 1
+ */
+const struct osmo_conv_code gsm0503_tch_afs_5_9 = {
+ .N = 4,
+ .K = 7,
+ .len = 124,
+ .next_output = tch_afs_5_9_output,
+ .next_state = tch_afs_5_9_state,
+ .next_term_output = tch_afs_5_9_term_output,
+ .next_term_state = tch_afs_5_9_term_state,
+ .puncture = tch_afs_5_9_puncture,
+};
+
+static const uint8_t tch_afs_5_15_state[][2] = {
+ { 0, 1 }, { 3, 2 }, { 5, 4 }, { 6, 7 },
+ { 9, 8 }, { 10, 11 }, { 12, 13 }, { 15, 14 },
+ { 1, 0 }, { 2, 3 }, { 4, 5 }, { 7, 6 },
+ { 8, 9 }, { 11, 10 }, { 13, 12 }, { 14, 15 },
+};
+
+static const uint8_t tch_afs_5_15_output[][2] = {
+ { 0, 31 }, { 4, 27 }, { 24, 7 }, { 28, 3 },
+ { 4, 27 }, { 0, 31 }, { 28, 3 }, { 24, 7 },
+ { 0, 31 }, { 4, 27 }, { 24, 7 }, { 28, 3 },
+ { 4, 27 }, { 0, 31 }, { 28, 3 }, { 24, 7 },
+};
+
+static const uint8_t tch_afs_5_15_term_state[] = {
+ 0, 2, 4, 6, 8, 10, 12, 14, 0, 2, 4, 6,
+ 8, 10, 12, 14,
+};
+
+static const uint8_t tch_afs_5_15_term_output[] = {
+ 0, 27, 7, 28, 27, 0, 28, 7, 31, 4, 24, 3,
+ 4, 31, 3, 24,
+};
+
+static const int tch_afs_5_15_puncture[] = {
+ 0, 4, 5, 9, 10, 14, 15, 20, 25, 30, 35, 40,
+ 50, 60, 70, 80, 90, 100, 110, 120, 130, 140, 150, 160,
+ 170, 180, 190, 200, 210, 220, 230, 240, 250, 260, 270, 280,
+ 290, 300, 310, 315, 320, 325, 330, 334, 335, 340, 344, 345,
+ 350, 354, 355, 360, 364, 365, 370, 374, 375, 380, 384, 385,
+ 390, 394, 395, 400, 404, 405, 410, 414, 415, 420, 424, 425,
+ 430, 434, 435, 440, 444, 445, 450, 454, 455, 460, 464, 465,
+ 470, 474, 475, 480, 484, 485, 490, 494, 495, 500, 504, 505,
+ 510, 514, 515, 520, 524, 525, 529, 530, 534, 535, 539, 540,
+ 544, 545, 549, 550, 554, 555, 559, 560, 564, -1,
+};
+
+/**
+ * TCH/AFS 5.15 kbits convolutional code:
+ * G1/G3 = 1 + D + D3 + D4 / 1 + D + D2 + D3 + D4
+ * G1/G3 = 1 + D + D3 + D4 / 1 + D + D2 + D3 + D4
+ * G2/G3 = 1 + D2 + D4 / 1 + D + D2 + D3 + D4
+ * G3/G3 = 1
+ * G3/G3 = 1
+ */
+const struct osmo_conv_code gsm0503_tch_afs_5_15 = {
+ .N = 5,
+ .K = 5,
+ .len = 109,
+ .next_output = tch_afs_5_15_output,
+ .next_state = tch_afs_5_15_state,
+ .next_term_output = tch_afs_5_15_term_output,
+ .next_term_state = tch_afs_5_15_term_state,
+ .puncture = tch_afs_5_15_puncture,
+};
+
+static const uint8_t tch_afs_4_75_state[][2] = {
+ { 0, 1 }, { 3, 2 }, { 5, 4 }, { 6, 7 },
+ { 9, 8 }, { 10, 11 }, { 12, 13 }, { 15, 14 },
+ { 17, 16 }, { 18, 19 }, { 20, 21 }, { 23, 22 },
+ { 24, 25 }, { 27, 26 }, { 29, 28 }, { 30, 31 },
+ { 32, 33 }, { 35, 34 }, { 37, 36 }, { 38, 39 },
+ { 41, 40 }, { 42, 43 }, { 44, 45 }, { 47, 46 },
+ { 49, 48 }, { 50, 51 }, { 52, 53 }, { 55, 54 },
+ { 56, 57 }, { 59, 58 }, { 61, 60 }, { 62, 63 },
+ { 1, 0 }, { 2, 3 }, { 4, 5 }, { 7, 6 },
+ { 8, 9 }, { 11, 10 }, { 13, 12 }, { 14, 15 },
+ { 16, 17 }, { 19, 18 }, { 21, 20 }, { 22, 23 },
+ { 25, 24 }, { 26, 27 }, { 28, 29 }, { 31, 30 },
+ { 33, 32 }, { 34, 35 }, { 36, 37 }, { 39, 38 },
+ { 40, 41 }, { 43, 42 }, { 45, 44 }, { 46, 47 },
+ { 48, 49 }, { 51, 50 }, { 53, 52 }, { 54, 55 },
+ { 57, 56 }, { 58, 59 }, { 60, 61 }, { 63, 62 },
+};
+
+static const uint8_t tch_afs_4_75_output[][2] = {
+ { 0, 31 }, { 24, 7 }, { 4, 27 }, { 28, 3 },
+ { 4, 27 }, { 28, 3 }, { 0, 31 }, { 24, 7 },
+ { 24, 7 }, { 0, 31 }, { 28, 3 }, { 4, 27 },
+ { 28, 3 }, { 4, 27 }, { 24, 7 }, { 0, 31 },
+ { 24, 7 }, { 0, 31 }, { 28, 3 }, { 4, 27 },
+ { 28, 3 }, { 4, 27 }, { 24, 7 }, { 0, 31 },
+ { 0, 31 }, { 24, 7 }, { 4, 27 }, { 28, 3 },
+ { 4, 27 }, { 28, 3 }, { 0, 31 }, { 24, 7 },
+ { 0, 31 }, { 24, 7 }, { 4, 27 }, { 28, 3 },
+ { 4, 27 }, { 28, 3 }, { 0, 31 }, { 24, 7 },
+ { 24, 7 }, { 0, 31 }, { 28, 3 }, { 4, 27 },
+ { 28, 3 }, { 4, 27 }, { 24, 7 }, { 0, 31 },
+ { 24, 7 }, { 0, 31 }, { 28, 3 }, { 4, 27 },
+ { 28, 3 }, { 4, 27 }, { 24, 7 }, { 0, 31 },
+ { 0, 31 }, { 24, 7 }, { 4, 27 }, { 28, 3 },
+ { 4, 27 }, { 28, 3 }, { 0, 31 }, { 24, 7 },
+};
+
+static const uint8_t tch_afs_4_75_term_state[] = {
+ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22,
+ 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46,
+ 48, 50, 52, 54, 56, 58, 60, 62, 0, 2, 4, 6,
+ 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30,
+ 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54,
+ 56, 58, 60, 62,
+};
+
+static const uint8_t tch_afs_4_75_term_output[] = {
+ 0, 7, 27, 28, 27, 28, 0, 7, 7, 0, 28, 27,
+ 28, 27, 7, 0, 24, 31, 3, 4, 3, 4, 24, 31,
+ 31, 24, 4, 3, 4, 3, 31, 24, 31, 24, 4, 3,
+ 4, 3, 31, 24, 24, 31, 3, 4, 3, 4, 24, 31,
+ 7, 0, 28, 27, 28, 27, 7, 0, 0, 7, 27, 28,
+ 27, 28, 0, 7,
+};
+
+static const int tch_afs_4_75_puncture[] = {
+ 0, 1, 2, 4, 5, 7, 9, 15, 25, 35, 45, 55,
+ 65, 75, 85, 95, 105, 115, 125, 135, 145, 155, 165, 175,
+ 185, 195, 205, 215, 225, 235, 245, 255, 265, 275, 285, 295,
+ 305, 315, 325, 335, 345, 355, 365, 375, 385, 395, 400, 405,
+ 410, 415, 420, 425, 430, 435, 440, 445, 450, 455, 459, 460,
+ 465, 470, 475, 479, 480, 485, 490, 495, 499, 500, 505, 509,
+ 510, 515, 517, 519, 520, 522, 524, 525, 526, 527, 529, 530,
+ 531, 532, 534, -1,
+};
+
+/**
+ * TCH/AFS 4.75 kbits convolutional code:
+ * G4/G6 = 1 + D2 + D3 + D5 + D6 / 1 + D + D2 + D3 + D4 + D6
+ * G4/G6 = 1 + D2 + D3 + D5 + D6 / 1 + D + D2 + D3 + D4 + D6
+ * G5/G6 = 1 + D + D4 + D6 / 1 + D + D2 + D3 + D4 + D6
+ * G6/G6 = 1
+ * G6/G6 = 1
+ */
+const struct osmo_conv_code gsm0503_tch_afs_4_75 = {
+ .N = 5,
+ .K = 7,
+ .len = 101,
+ .next_output = tch_afs_4_75_output,
+ .next_state = tch_afs_4_75_state,
+ .next_term_output = tch_afs_4_75_term_output,
+ .next_term_state = tch_afs_4_75_term_state,
+ .puncture = tch_afs_4_75_puncture,
+};
+
+static const uint8_t tch_fr_state[][2] = {
+ { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 },
+ { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 },
+ { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 },
+ { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 },
+};
+
+static const uint8_t tch_fr_output[][2] = {
+ { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 },
+ { 3, 0 }, { 2, 1 }, { 3, 0 }, { 2, 1 },
+ { 3, 0 }, { 2, 1 }, { 3, 0 }, { 2, 1 },
+ { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 },
+};
+
+/**
+ * TCH/F convolutional code
+ */
+const struct osmo_conv_code gsm0503_tch_fr = {
+ .N = 2,
+ .K = 5,
+ .len = 185,
+ .next_output = tch_fr_output,
+ .next_state = tch_fr_state,
+};
+
+static const uint8_t tch_hr_state[][2] = {
+ { 0, 1 }, { 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 }, { 28, 29 }, { 30, 31 },
+ { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 },
+ { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 },
+ { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 },
+ { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 },
+ { 0, 1 }, { 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 }, { 28, 29 }, { 30, 31 },
+ { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 },
+ { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 },
+ { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 },
+ { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 },
+};
+
+static const uint8_t tch_hr_output[][2] = {
+ { 0, 7 }, { 3, 4 }, { 5, 2 }, { 6, 1 },
+ { 5, 2 }, { 6, 1 }, { 0, 7 }, { 3, 4 },
+ { 3, 4 }, { 0, 7 }, { 6, 1 }, { 5, 2 },
+ { 6, 1 }, { 5, 2 }, { 3, 4 }, { 0, 7 },
+ { 4, 3 }, { 7, 0 }, { 1, 6 }, { 2, 5 },
+ { 1, 6 }, { 2, 5 }, { 4, 3 }, { 7, 0 },
+ { 7, 0 }, { 4, 3 }, { 2, 5 }, { 1, 6 },
+ { 2, 5 }, { 1, 6 }, { 7, 0 }, { 4, 3 },
+ { 7, 0 }, { 4, 3 }, { 2, 5 }, { 1, 6 },
+ { 2, 5 }, { 1, 6 }, { 7, 0 }, { 4, 3 },
+ { 4, 3 }, { 7, 0 }, { 1, 6 }, { 2, 5 },
+ { 1, 6 }, { 2, 5 }, { 4, 3 }, { 7, 0 },
+ { 3, 4 }, { 0, 7 }, { 6, 1 }, { 5, 2 },
+ { 6, 1 }, { 5, 2 }, { 3, 4 }, { 0, 7 },
+ { 0, 7 }, { 3, 4 }, { 5, 2 }, { 6, 1 },
+ { 5, 2 }, { 6, 1 }, { 0, 7 }, { 3, 4 },
+};
+
+static const int tch_hr_puncture[] = {
+ 1, 4, 7, 10, 13, 16, 19, 22, 25, 28, 31, 34,
+ 37, 40, 43, 46, 49, 52, 55, 58, 61, 64, 67, 70,
+ 73, 76, 79, 82, 85, 88, 91, 94, 97, 100, 103, 106,
+ 109, 112, 115, 118, 121, 124, 127, 130, 133, 136, 139, 142,
+ 145, 148, 151, 154, 157, 160, 163, 166, 169, 172, 175, 178,
+ 181, 184, 187, 190, 193, 196, 199, 202, 205, 208, 211, 214,
+ 217, 220, 223, 226, 229, 232, 235, 238, 241, 244, 247, 250,
+ 253, 256, 259, 262, 265, 268, 271, 274, 277, 280, 283, 295,
+ 298, 301, 304, 307, 310, -1,
+};
+
+/**
+ * TCH/H convolutional code
+ */
+const struct osmo_conv_code gsm0503_tch_hr = {
+ .N = 3,
+ .K = 7,
+ .len = 98,
+ .next_output = tch_hr_output,
+ .next_state = tch_hr_state,
+ .puncture = tch_hr_puncture,
+};
+
+static const uint8_t tch_ahs_7_95_state[][2] = {
+ { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 },
+ { 9, 8 }, { 11, 10 }, { 13, 12 }, { 15, 14 },
+ { 1, 0 }, { 3, 2 }, { 5, 4 }, { 7, 6 },
+ { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 },
+};
+
+static const uint8_t tch_ahs_7_95_output[][2] = {
+ { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 },
+ { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 },
+ { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 },
+ { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 },
+};
+
+static const uint8_t tch_ahs_7_95_term_state[] = {
+ 0, 2, 4, 6, 8, 10, 12, 14, 0, 2, 4, 6,
+ 8, 10, 12, 14,
+};
+
+static const uint8_t tch_ahs_7_95_term_output[] = {
+ 0, 1, 0, 1, 3, 2, 3, 2, 3, 2, 3, 2,
+ 0, 1, 0, 1,
+};
+
+static const int tch_ahs_7_95_puncture[] = {
+ 1, 3, 5, 7, 11, 15, 19, 23, 27, 31, 35, 43,
+ 47, 51, 55, 59, 63, 67, 71, 79, 83, 87, 91, 95,
+ 99, 103, 107, 115, 119, 123, 127, 131, 135, 139, 143, 151,
+ 155, 159, 163, 167, 171, 175, 177, 179, 183, 185, 187, 191,
+ 193, 195, 197, 199, 203, 205, 207, 211, 213, 215, 219, 221,
+ 223, 227, 229, 231, 233, 235, 239, 241, 243, 247, 249, 251,
+ 255, 257, 259, 261, 263, 265, -1,
+};
+
+/**
+ * TCH/AHS 7.95 kbits convolutional code
+ */
+const struct osmo_conv_code gsm0503_tch_ahs_7_95 = {
+ .N = 2,
+ .K = 5,
+ .len = 129,
+ .next_output = tch_ahs_7_95_output,
+ .next_state = tch_ahs_7_95_state,
+ .next_term_output = tch_ahs_7_95_term_output,
+ .next_term_state = tch_ahs_7_95_term_state,
+ .puncture = tch_ahs_7_95_puncture,
+};
+
+static const uint8_t tch_ahs_7_4_state[][2] = {
+ { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 },
+ { 9, 8 }, { 11, 10 }, { 13, 12 }, { 15, 14 },
+ { 1, 0 }, { 3, 2 }, { 5, 4 }, { 7, 6 },
+ { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 },
+};
+
+static const uint8_t tch_ahs_7_4_output[][2] = {
+ { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 },
+ { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 },
+ { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 },
+ { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 },
+};
+
+static const uint8_t tch_ahs_7_4_term_state[] = {
+ 0, 2, 4, 6, 8, 10, 12, 14, 0, 2, 4, 6,
+ 8, 10, 12, 14,
+};
+
+static const uint8_t tch_ahs_7_4_term_output[] = {
+ 0, 1, 0, 1, 3, 2, 3, 2, 3, 2, 3, 2,
+ 0, 1, 0, 1,
+};
+
+static const int tch_ahs_7_4_puncture[] = {
+ 1, 3, 7, 11, 19, 23, 27, 35, 39, 43, 51, 55,
+ 59, 67, 71, 75, 83, 87, 91, 99, 103, 107, 115, 119,
+ 123, 131, 135, 139, 143, 147, 151, 155, 159, 163, 167, 171,
+ 175, 179, 183, 187, 191, 195, 199, 203, 207, 211, 215, 219,
+ 221, 223, 227, 229, 231, 235, 237, 239, 243, 245, 247, 251,
+ 253, 255, 257, 259, -1,
+};
+
+/**
+ * TCH/AHS 7.4 kbits convolutional code
+ */
+const struct osmo_conv_code gsm0503_tch_ahs_7_4 = {
+ .N = 2,
+ .K = 5,
+ .len = 126,
+ .next_output = tch_ahs_7_4_output,
+ .next_state = tch_ahs_7_4_state,
+ .next_term_output = tch_ahs_7_4_term_output,
+ .next_term_state = tch_ahs_7_4_term_state,
+ .puncture = tch_ahs_7_4_puncture,
+};
+
+static const uint8_t tch_ahs_6_7_state[][2] = {
+ { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 },
+ { 9, 8 }, { 11, 10 }, { 13, 12 }, { 15, 14 },
+ { 1, 0 }, { 3, 2 }, { 5, 4 }, { 7, 6 },
+ { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 },
+};
+
+static const uint8_t tch_ahs_6_7_output[][2] = {
+ { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 },
+ { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 },
+ { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 },
+ { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 },
+};
+
+static const uint8_t tch_ahs_6_7_term_state[] = {
+ 0, 2, 4, 6, 8, 10, 12, 14, 0, 2, 4, 6,
+ 8, 10, 12, 14,
+};
+
+static const uint8_t tch_ahs_6_7_term_output[] = {
+ 0, 1, 0, 1, 3, 2, 3, 2, 3, 2, 3, 2,
+ 0, 1, 0, 1,
+};
+
+static const int tch_ahs_6_7_puncture[] = {
+ 1, 3, 9, 19, 29, 39, 49, 59, 69, 79, 89, 99,
+ 109, 119, 129, 139, 149, 159, 167, 169, 177, 179, 187, 189,
+ 197, 199, 203, 207, 209, 213, 217, 219, 223, 227, 229, 231,
+ 233, 235, 237, 239, -1,
+};
+
+/**
+ * TCH/AHS 6.7 kbits convolutional code
+ */
+const struct osmo_conv_code gsm0503_tch_ahs_6_7 = {
+ .N = 2,
+ .K = 5,
+ .len = 116,
+ .next_output = tch_ahs_6_7_output,
+ .next_state = tch_ahs_6_7_state,
+ .next_term_output = tch_ahs_6_7_term_output,
+ .next_term_state = tch_ahs_6_7_term_state,
+ .puncture = tch_ahs_6_7_puncture,
+};
+
+static const uint8_t tch_ahs_5_9_state[][2] = {
+ { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 },
+ { 9, 8 }, { 11, 10 }, { 13, 12 }, { 15, 14 },
+ { 1, 0 }, { 3, 2 }, { 5, 4 }, { 7, 6 },
+ { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 },
+};
+
+static const uint8_t tch_ahs_5_9_output[][2] = {
+ { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 },
+ { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 },
+ { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 },
+ { 0, 3 }, { 1, 2 }, { 0, 3 }, { 1, 2 },
+};
+
+static const uint8_t tch_ahs_5_9_term_state[] = {
+ 0, 2, 4, 6, 8, 10, 12, 14, 0, 2, 4, 6,
+ 8, 10, 12, 14,
+};
+
+static const uint8_t tch_ahs_5_9_term_output[] = {
+ 0, 1, 0, 1, 3, 2, 3, 2, 3, 2, 3, 2,
+ 0, 1, 0, 1,
+};
+
+static const int tch_ahs_5_9_puncture[] = {
+ 1, 15, 71, 127, 139, 151, 163, 175, 187, 195, 203, 211,
+ 215, 219, 221, 223, -1,
+};
+
+/**
+ * TCH/AHS 5.9 kbits convolutional code
+ */
+const struct osmo_conv_code gsm0503_tch_ahs_5_9 = {
+ .N = 2,
+ .K = 5,
+ .len = 108,
+ .next_output = tch_ahs_5_9_output,
+ .next_state = tch_ahs_5_9_state,
+ .next_term_output = tch_ahs_5_9_term_output,
+ .next_term_state = tch_ahs_5_9_term_state,
+ .puncture = tch_ahs_5_9_puncture,
+};
+
+static const uint8_t tch_ahs_5_15_state[][2] = {
+ { 0, 1 }, { 3, 2 }, { 5, 4 }, { 6, 7 },
+ { 9, 8 }, { 10, 11 }, { 12, 13 }, { 15, 14 },
+ { 1, 0 }, { 2, 3 }, { 4, 5 }, { 7, 6 },
+ { 8, 9 }, { 11, 10 }, { 13, 12 }, { 14, 15 },
+};
+
+static const uint8_t tch_ahs_5_15_output[][2] = {
+ { 0, 7 }, { 2, 5 }, { 4, 3 }, { 6, 1 },
+ { 2, 5 }, { 0, 7 }, { 6, 1 }, { 4, 3 },
+ { 0, 7 }, { 2, 5 }, { 4, 3 }, { 6, 1 },
+ { 2, 5 }, { 0, 7 }, { 6, 1 }, { 4, 3 },
+};
+
+static const uint8_t tch_ahs_5_15_term_state[] = {
+ 0, 2, 4, 6, 8, 10, 12, 14, 0, 2, 4, 6,
+ 8, 10, 12, 14,
+};
+
+static const uint8_t tch_ahs_5_15_term_output[] = {
+ 0, 5, 3, 6, 5, 0, 6, 3, 7, 2, 4, 1,
+ 2, 7, 1, 4,
+};
+
+static const int tch_ahs_5_15_puncture[] = {
+ 0, 1, 3, 4, 6, 9, 12, 15, 18, 21, 27, 33,
+ 39, 45, 51, 54, 57, 63, 69, 75, 81, 87, 90, 93,
+ 99, 105, 111, 117, 123, 126, 129, 135, 141, 147, 153, 159,
+ 162, 165, 168, 171, 174, 177, 180, 183, 186, 189, 192, 195,
+ 198, 201, 204, 207, 210, 213, 216, 219, 222, 225, 228, 231,
+ 234, 237, 240, 243, 244, 246, 249, 252, 255, 256, 258, 261,
+ 264, 267, 268, 270, 273, 276, 279, 280, 282, 285, 288, 289,
+ 291, 294, 295, 297, 298, 300, 301, -1,
+};
+
+/**
+ * TCH/AHS 5.15 kbits convolutional code
+ */
+const struct osmo_conv_code gsm0503_tch_ahs_5_15 = {
+ .N = 3,
+ .K = 5,
+ .len = 97,
+ .next_output = tch_ahs_5_15_output,
+ .next_state = tch_ahs_5_15_state,
+ .next_term_output = tch_ahs_5_15_term_output,
+ .next_term_state = tch_ahs_5_15_term_state,
+ .puncture = tch_ahs_5_15_puncture,
+};
+
+static const uint8_t tch_ahs_4_75_state[][2] = {
+ { 0, 1 }, { 2, 3 }, { 5, 4 }, { 7, 6 },
+ { 9, 8 }, { 11, 10 }, { 12, 13 }, { 14, 15 },
+ { 16, 17 }, { 18, 19 }, { 21, 20 }, { 23, 22 },
+ { 25, 24 }, { 27, 26 }, { 28, 29 }, { 30, 31 },
+ { 33, 32 }, { 35, 34 }, { 36, 37 }, { 38, 39 },
+ { 40, 41 }, { 42, 43 }, { 45, 44 }, { 47, 46 },
+ { 49, 48 }, { 51, 50 }, { 52, 53 }, { 54, 55 },
+ { 56, 57 }, { 58, 59 }, { 61, 60 }, { 63, 62 },
+ { 1, 0 }, { 3, 2 }, { 4, 5 }, { 6, 7 },
+ { 8, 9 }, { 10, 11 }, { 13, 12 }, { 15, 14 },
+ { 17, 16 }, { 19, 18 }, { 20, 21 }, { 22, 23 },
+ { 24, 25 }, { 26, 27 }, { 29, 28 }, { 31, 30 },
+ { 32, 33 }, { 34, 35 }, { 37, 36 }, { 39, 38 },
+ { 41, 40 }, { 43, 42 }, { 44, 45 }, { 46, 47 },
+ { 48, 49 }, { 50, 51 }, { 53, 52 }, { 55, 54 },
+ { 57, 56 }, { 59, 58 }, { 60, 61 }, { 62, 63 },
+};
+
+static const uint8_t tch_ahs_4_75_output[][2] = {
+ { 0, 7 }, { 3, 4 }, { 2, 5 }, { 1, 6 },
+ { 2, 5 }, { 1, 6 }, { 0, 7 }, { 3, 4 },
+ { 3, 4 }, { 0, 7 }, { 1, 6 }, { 2, 5 },
+ { 1, 6 }, { 2, 5 }, { 3, 4 }, { 0, 7 },
+ { 3, 4 }, { 0, 7 }, { 1, 6 }, { 2, 5 },
+ { 1, 6 }, { 2, 5 }, { 3, 4 }, { 0, 7 },
+ { 0, 7 }, { 3, 4 }, { 2, 5 }, { 1, 6 },
+ { 2, 5 }, { 1, 6 }, { 0, 7 }, { 3, 4 },
+ { 0, 7 }, { 3, 4 }, { 2, 5 }, { 1, 6 },
+ { 2, 5 }, { 1, 6 }, { 0, 7 }, { 3, 4 },
+ { 3, 4 }, { 0, 7 }, { 1, 6 }, { 2, 5 },
+ { 1, 6 }, { 2, 5 }, { 3, 4 }, { 0, 7 },
+ { 3, 4 }, { 0, 7 }, { 1, 6 }, { 2, 5 },
+ { 1, 6 }, { 2, 5 }, { 3, 4 }, { 0, 7 },
+ { 0, 7 }, { 3, 4 }, { 2, 5 }, { 1, 6 },
+ { 2, 5 }, { 1, 6 }, { 0, 7 }, { 3, 4 },
+};
+
+static const uint8_t tch_ahs_4_75_term_state[] = {
+ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22,
+ 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46,
+ 48, 50, 52, 54, 56, 58, 60, 62, 0, 2, 4, 6,
+ 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30,
+ 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54,
+ 56, 58, 60, 62,
+};
+
+static const uint8_t tch_ahs_4_75_term_output[] = {
+ 0, 3, 5, 6, 5, 6, 0, 3, 3, 0, 6, 5,
+ 6, 5, 3, 0, 4, 7, 1, 2, 1, 2, 4, 7,
+ 7, 4, 2, 1, 2, 1, 7, 4, 7, 4, 2, 1,
+ 2, 1, 7, 4, 4, 7, 1, 2, 1, 2, 4, 7,
+ 3, 0, 6, 5, 6, 5, 3, 0, 0, 3, 5, 6,
+ 5, 6, 0, 3,
+};
+
+static const int tch_ahs_4_75_puncture[] = {
+ 1, 2, 4, 5, 7, 8, 10, 13, 16, 22, 28, 34,
+ 40, 46, 52, 58, 64, 70, 76, 82, 88, 94, 100, 106,
+ 112, 118, 124, 130, 136, 142, 148, 151, 154, 160, 163, 166,
+ 172, 175, 178, 184, 187, 190, 196, 199, 202, 208, 211, 214,
+ 220, 223, 226, 232, 235, 238, 241, 244, 247, 250, 253, 256,
+ 259, 262, 265, 268, 271, 274, 275, 277, 278, 280, 281, 283,
+ 284, -1,
+};
+
+/**
+ * TCH/AHS 4.75 kbits convolutional code
+ */
+const struct osmo_conv_code gsm0503_tch_ahs_4_75 = {
+ .N = 3,
+ .K = 7,
+ .len = 89,
+ .next_output = tch_ahs_4_75_output,
+ .next_state = tch_ahs_4_75_state,
+ .next_term_output = tch_ahs_4_75_term_output,
+ .next_term_state = tch_ahs_4_75_term_state,
+ .puncture = tch_ahs_4_75_puncture,
+};
+
+static const uint8_t mcs1_dl_hdr_state[][2] = {
+ { 0, 1 }, { 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 }, { 28, 29 }, { 30, 31 },
+ { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 },
+ { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 },
+ { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 },
+ { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 },
+ { 0, 1 }, { 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 }, { 28, 29 }, { 30, 31 },
+ { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 },
+ { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 },
+ { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 },
+ { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 },
+};
+
+static const uint8_t mcs1_dl_hdr_output[][2] = {
+ { 0, 7 }, { 3, 4 }, { 6, 1 }, { 5, 2 },
+ { 6, 1 }, { 5, 2 }, { 0, 7 }, { 3, 4 },
+ { 1, 6 }, { 2, 5 }, { 7, 0 }, { 4, 3 },
+ { 7, 0 }, { 4, 3 }, { 1, 6 }, { 2, 5 },
+ { 4, 3 }, { 7, 0 }, { 2, 5 }, { 1, 6 },
+ { 2, 5 }, { 1, 6 }, { 4, 3 }, { 7, 0 },
+ { 5, 2 }, { 6, 1 }, { 3, 4 }, { 0, 7 },
+ { 3, 4 }, { 0, 7 }, { 5, 2 }, { 6, 1 },
+ { 7, 0 }, { 4, 3 }, { 1, 6 }, { 2, 5 },
+ { 1, 6 }, { 2, 5 }, { 7, 0 }, { 4, 3 },
+ { 6, 1 }, { 5, 2 }, { 0, 7 }, { 3, 4 },
+ { 0, 7 }, { 3, 4 }, { 6, 1 }, { 5, 2 },
+ { 3, 4 }, { 0, 7 }, { 5, 2 }, { 6, 1 },
+ { 5, 2 }, { 6, 1 }, { 3, 4 }, { 0, 7 },
+ { 2, 5 }, { 1, 6 }, { 4, 3 }, { 7, 0 },
+ { 4, 3 }, { 7, 0 }, { 2, 5 }, { 1, 6 },
+};
+
+/**
+ * EDGE MCS-1 DL header convolutional code:
+ * 42 bits blocks, rate 1/3, k = 7
+ * G4 = 1 + D2 + D3 + D5 + D6
+ * G7 = 1 + D + D2 + D3 + D6
+ * G5 = 1 + D + D4 + D6
+ */
+const struct osmo_conv_code gsm0503_mcs1_dl_hdr = {
+ .N = 3,
+ .K = 7,
+ .len = 36,
+ .next_output = mcs1_dl_hdr_output,
+ .next_state = mcs1_dl_hdr_state,
+ .term = CONV_TERM_TAIL_BITING,
+};
+
+static const uint8_t mcs1_ul_hdr_state[][2] = {
+ { 0, 1 }, { 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 }, { 28, 29 }, { 30, 31 },
+ { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 },
+ { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 },
+ { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 },
+ { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 },
+ { 0, 1 }, { 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 }, { 28, 29 }, { 30, 31 },
+ { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 },
+ { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 },
+ { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 },
+ { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 },
+};
+
+static const uint8_t mcs1_ul_hdr_output[][2] = {
+ { 0, 7 }, { 3, 4 }, { 6, 1 }, { 5, 2 },
+ { 6, 1 }, { 5, 2 }, { 0, 7 }, { 3, 4 },
+ { 1, 6 }, { 2, 5 }, { 7, 0 }, { 4, 3 },
+ { 7, 0 }, { 4, 3 }, { 1, 6 }, { 2, 5 },
+ { 4, 3 }, { 7, 0 }, { 2, 5 }, { 1, 6 },
+ { 2, 5 }, { 1, 6 }, { 4, 3 }, { 7, 0 },
+ { 5, 2 }, { 6, 1 }, { 3, 4 }, { 0, 7 },
+ { 3, 4 }, { 0, 7 }, { 5, 2 }, { 6, 1 },
+ { 7, 0 }, { 4, 3 }, { 1, 6 }, { 2, 5 },
+ { 1, 6 }, { 2, 5 }, { 7, 0 }, { 4, 3 },
+ { 6, 1 }, { 5, 2 }, { 0, 7 }, { 3, 4 },
+ { 0, 7 }, { 3, 4 }, { 6, 1 }, { 5, 2 },
+ { 3, 4 }, { 0, 7 }, { 5, 2 }, { 6, 1 },
+ { 5, 2 }, { 6, 1 }, { 3, 4 }, { 0, 7 },
+ { 2, 5 }, { 1, 6 }, { 4, 3 }, { 7, 0 },
+ { 4, 3 }, { 7, 0 }, { 2, 5 }, { 1, 6 },
+};
+
+/**
+ * EDGE MCS-1 UL header convolutional code:
+ * 45 bits blocks, rate 1/3, k = 7
+ * G4 = 1 + D2 + D3 + D5 + D6
+ * G7 = 1 + D + D2 + D3 + D6
+ * G5 = 1 + D + D4 + D6
+ */
+const struct osmo_conv_code gsm0503_mcs1_ul_hdr = {
+ .N = 3,
+ .K = 7,
+ .len = 39,
+ .next_output = mcs1_ul_hdr_output,
+ .next_state = mcs1_ul_hdr_state,
+ .term = CONV_TERM_TAIL_BITING,
+};
+
+static const uint8_t mcs1_state[][2] = {
+ { 0, 1 }, { 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 }, { 28, 29 }, { 30, 31 },
+ { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 },
+ { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 },
+ { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 },
+ { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 },
+ { 0, 1 }, { 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 }, { 28, 29 }, { 30, 31 },
+ { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 },
+ { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 },
+ { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 },
+ { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 },
+};
+
+static const uint8_t mcs1_output[][2] = {
+ { 0, 7 }, { 3, 4 }, { 6, 1 }, { 5, 2 },
+ { 6, 1 }, { 5, 2 }, { 0, 7 }, { 3, 4 },
+ { 1, 6 }, { 2, 5 }, { 7, 0 }, { 4, 3 },
+ { 7, 0 }, { 4, 3 }, { 1, 6 }, { 2, 5 },
+ { 4, 3 }, { 7, 0 }, { 2, 5 }, { 1, 6 },
+ { 2, 5 }, { 1, 6 }, { 4, 3 }, { 7, 0 },
+ { 5, 2 }, { 6, 1 }, { 3, 4 }, { 0, 7 },
+ { 3, 4 }, { 0, 7 }, { 5, 2 }, { 6, 1 },
+ { 7, 0 }, { 4, 3 }, { 1, 6 }, { 2, 5 },
+ { 1, 6 }, { 2, 5 }, { 7, 0 }, { 4, 3 },
+ { 6, 1 }, { 5, 2 }, { 0, 7 }, { 3, 4 },
+ { 0, 7 }, { 3, 4 }, { 6, 1 }, { 5, 2 },
+ { 3, 4 }, { 0, 7 }, { 5, 2 }, { 6, 1 },
+ { 5, 2 }, { 6, 1 }, { 3, 4 }, { 0, 7 },
+ { 2, 5 }, { 1, 6 }, { 4, 3 }, { 7, 0 },
+ { 4, 3 }, { 7, 0 }, { 2, 5 }, { 1, 6 },
+};
+
+/**
+ * EDGE MCS-1 data convolutional code:
+ * 196 bits blocks, rate 1/3, k = 7
+ * G4 = 1 + D2 + D3 + D5 + D6
+ * G7 = 1 + D + D2 + D3 + D6
+ * G5 = 1 + D + D4 + D6
+ */
+const struct osmo_conv_code gsm0503_mcs1 = {
+ .N = 3,
+ .K = 7,
+ .len = 190,
+ .next_output = mcs1_output,
+ .next_state = mcs1_state,
+};
+
+static const uint8_t mcs2_state[][2] = {
+ { 0, 1 }, { 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 }, { 28, 29 }, { 30, 31 },
+ { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 },
+ { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 },
+ { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 },
+ { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 },
+ { 0, 1 }, { 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 }, { 28, 29 }, { 30, 31 },
+ { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 },
+ { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 },
+ { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 },
+ { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 },
+};
+
+static const uint8_t mcs2_output[][2] = {
+ { 0, 7 }, { 3, 4 }, { 6, 1 }, { 5, 2 },
+ { 6, 1 }, { 5, 2 }, { 0, 7 }, { 3, 4 },
+ { 1, 6 }, { 2, 5 }, { 7, 0 }, { 4, 3 },
+ { 7, 0 }, { 4, 3 }, { 1, 6 }, { 2, 5 },
+ { 4, 3 }, { 7, 0 }, { 2, 5 }, { 1, 6 },
+ { 2, 5 }, { 1, 6 }, { 4, 3 }, { 7, 0 },
+ { 5, 2 }, { 6, 1 }, { 3, 4 }, { 0, 7 },
+ { 3, 4 }, { 0, 7 }, { 5, 2 }, { 6, 1 },
+ { 7, 0 }, { 4, 3 }, { 1, 6 }, { 2, 5 },
+ { 1, 6 }, { 2, 5 }, { 7, 0 }, { 4, 3 },
+ { 6, 1 }, { 5, 2 }, { 0, 7 }, { 3, 4 },
+ { 0, 7 }, { 3, 4 }, { 6, 1 }, { 5, 2 },
+ { 3, 4 }, { 0, 7 }, { 5, 2 }, { 6, 1 },
+ { 5, 2 }, { 6, 1 }, { 3, 4 }, { 0, 7 },
+ { 2, 5 }, { 1, 6 }, { 4, 3 }, { 7, 0 },
+ { 4, 3 }, { 7, 0 }, { 2, 5 }, { 1, 6 },
+};
+
+/**
+ * EDGE MCS-2 data convolutional code:
+ * 244 bits blocks, rate 1/3, k = 7
+ * G4 = 1 + D2 + D3 + D5 + D6
+ * G7 = 1 + D + D2 + D3 + D6
+ * G5 = 1 + D + D4 + D6
+ */
+const struct osmo_conv_code gsm0503_mcs2 = {
+ .N = 3,
+ .K = 7,
+ .len = 238,
+ .next_output = mcs2_output,
+ .next_state = mcs2_state,
+};
+
+static const uint8_t mcs3_state[][2] = {
+ { 0, 1 }, { 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 }, { 28, 29 }, { 30, 31 },
+ { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 },
+ { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 },
+ { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 },
+ { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 },
+ { 0, 1 }, { 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 }, { 28, 29 }, { 30, 31 },
+ { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 },
+ { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 },
+ { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 },
+ { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 },
+};
+
+static const uint8_t mcs3_output[][2] = {
+ { 0, 7 }, { 3, 4 }, { 6, 1 }, { 5, 2 },
+ { 6, 1 }, { 5, 2 }, { 0, 7 }, { 3, 4 },
+ { 1, 6 }, { 2, 5 }, { 7, 0 }, { 4, 3 },
+ { 7, 0 }, { 4, 3 }, { 1, 6 }, { 2, 5 },
+ { 4, 3 }, { 7, 0 }, { 2, 5 }, { 1, 6 },
+ { 2, 5 }, { 1, 6 }, { 4, 3 }, { 7, 0 },
+ { 5, 2 }, { 6, 1 }, { 3, 4 }, { 0, 7 },
+ { 3, 4 }, { 0, 7 }, { 5, 2 }, { 6, 1 },
+ { 7, 0 }, { 4, 3 }, { 1, 6 }, { 2, 5 },
+ { 1, 6 }, { 2, 5 }, { 7, 0 }, { 4, 3 },
+ { 6, 1 }, { 5, 2 }, { 0, 7 }, { 3, 4 },
+ { 0, 7 }, { 3, 4 }, { 6, 1 }, { 5, 2 },
+ { 3, 4 }, { 0, 7 }, { 5, 2 }, { 6, 1 },
+ { 5, 2 }, { 6, 1 }, { 3, 4 }, { 0, 7 },
+ { 2, 5 }, { 1, 6 }, { 4, 3 }, { 7, 0 },
+ { 4, 3 }, { 7, 0 }, { 2, 5 }, { 1, 6 },
+};
+
+/**
+ * EDGE MCS-3 data convolutional code:
+ * 316 bits blocks, rate 1/3, k = 7
+ * G4 = 1 + D2 + D3 + D5 + D6
+ * G7 = 1 + D + D2 + D3 + D6
+ * G5 = 1 + D + D4 + D6
+ */
+const struct osmo_conv_code gsm0503_mcs3 = {
+ .N = 3,
+ .K = 7,
+ .len = 310,
+ .next_output = mcs3_output,
+ .next_state = mcs3_state,
+};
+
+static const uint8_t mcs4_state[][2] = {
+ { 0, 1 }, { 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 }, { 28, 29 }, { 30, 31 },
+ { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 },
+ { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 },
+ { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 },
+ { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 },
+ { 0, 1 }, { 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 }, { 28, 29 }, { 30, 31 },
+ { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 },
+ { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 },
+ { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 },
+ { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 },
+};
+
+static const uint8_t mcs4_output[][2] = {
+ { 0, 7 }, { 3, 4 }, { 6, 1 }, { 5, 2 },
+ { 6, 1 }, { 5, 2 }, { 0, 7 }, { 3, 4 },
+ { 1, 6 }, { 2, 5 }, { 7, 0 }, { 4, 3 },
+ { 7, 0 }, { 4, 3 }, { 1, 6 }, { 2, 5 },
+ { 4, 3 }, { 7, 0 }, { 2, 5 }, { 1, 6 },
+ { 2, 5 }, { 1, 6 }, { 4, 3 }, { 7, 0 },
+ { 5, 2 }, { 6, 1 }, { 3, 4 }, { 0, 7 },
+ { 3, 4 }, { 0, 7 }, { 5, 2 }, { 6, 1 },
+ { 7, 0 }, { 4, 3 }, { 1, 6 }, { 2, 5 },
+ { 1, 6 }, { 2, 5 }, { 7, 0 }, { 4, 3 },
+ { 6, 1 }, { 5, 2 }, { 0, 7 }, { 3, 4 },
+ { 0, 7 }, { 3, 4 }, { 6, 1 }, { 5, 2 },
+ { 3, 4 }, { 0, 7 }, { 5, 2 }, { 6, 1 },
+ { 5, 2 }, { 6, 1 }, { 3, 4 }, { 0, 7 },
+ { 2, 5 }, { 1, 6 }, { 4, 3 }, { 7, 0 },
+ { 4, 3 }, { 7, 0 }, { 2, 5 }, { 1, 6 },
+};
+
+/**
+ * EDGE MCS-4 data convolutional code:
+ * 372 bits blocks, rate 1/3, k = 7
+ * G4 = 1 + D2 + D3 + D5 + D6
+ * G7 = 1 + D + D2 + D3 + D6
+ * G5 = 1 + D + D4 + D6
+ */
+const struct osmo_conv_code gsm0503_mcs4 = {
+ .N = 3,
+ .K = 7,
+ .len = 366,
+ .next_output = mcs4_output,
+ .next_state = mcs4_state,
+};
+
+static const uint8_t mcs5_dl_hdr_state[][2] = {
+ { 0, 1 }, { 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 }, { 28, 29 }, { 30, 31 },
+ { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 },
+ { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 },
+ { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 },
+ { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 },
+ { 0, 1 }, { 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 }, { 28, 29 }, { 30, 31 },
+ { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 },
+ { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 },
+ { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 },
+ { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 },
+};
+
+static const uint8_t mcs5_dl_hdr_output[][2] = {
+ { 0, 7 }, { 3, 4 }, { 6, 1 }, { 5, 2 },
+ { 6, 1 }, { 5, 2 }, { 0, 7 }, { 3, 4 },
+ { 1, 6 }, { 2, 5 }, { 7, 0 }, { 4, 3 },
+ { 7, 0 }, { 4, 3 }, { 1, 6 }, { 2, 5 },
+ { 4, 3 }, { 7, 0 }, { 2, 5 }, { 1, 6 },
+ { 2, 5 }, { 1, 6 }, { 4, 3 }, { 7, 0 },
+ { 5, 2 }, { 6, 1 }, { 3, 4 }, { 0, 7 },
+ { 3, 4 }, { 0, 7 }, { 5, 2 }, { 6, 1 },
+ { 7, 0 }, { 4, 3 }, { 1, 6 }, { 2, 5 },
+ { 1, 6 }, { 2, 5 }, { 7, 0 }, { 4, 3 },
+ { 6, 1 }, { 5, 2 }, { 0, 7 }, { 3, 4 },
+ { 0, 7 }, { 3, 4 }, { 6, 1 }, { 5, 2 },
+ { 3, 4 }, { 0, 7 }, { 5, 2 }, { 6, 1 },
+ { 5, 2 }, { 6, 1 }, { 3, 4 }, { 0, 7 },
+ { 2, 5 }, { 1, 6 }, { 4, 3 }, { 7, 0 },
+ { 4, 3 }, { 7, 0 }, { 2, 5 }, { 1, 6 },
+};
+
+/**
+ * EDGE MCS-5 DL header convolutional code:
+ * 39 bits blocks, rate 1/3, k = 7
+ * G4 = 1 + D2 + D3 + D5 + D6
+ * G7 = 1 + D + D2 + D3 + D6
+ * G5 = 1 + D + D4 + D6
+ */
+const struct osmo_conv_code gsm0503_mcs5_dl_hdr = {
+ .N = 3,
+ .K = 7,
+ .len = 33,
+ .next_output = mcs5_dl_hdr_output,
+ .next_state = mcs5_dl_hdr_state,
+ .term = CONV_TERM_TAIL_BITING,
+};
+
+static const uint8_t mcs5_ul_hdr_state[][2] = {
+ { 0, 1 }, { 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 }, { 28, 29 }, { 30, 31 },
+ { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 },
+ { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 },
+ { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 },
+ { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 },
+ { 0, 1 }, { 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 }, { 28, 29 }, { 30, 31 },
+ { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 },
+ { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 },
+ { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 },
+ { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 },
+};
+
+static const uint8_t mcs5_ul_hdr_output[][2] = {
+ { 0, 7 }, { 3, 4 }, { 6, 1 }, { 5, 2 },
+ { 6, 1 }, { 5, 2 }, { 0, 7 }, { 3, 4 },
+ { 1, 6 }, { 2, 5 }, { 7, 0 }, { 4, 3 },
+ { 7, 0 }, { 4, 3 }, { 1, 6 }, { 2, 5 },
+ { 4, 3 }, { 7, 0 }, { 2, 5 }, { 1, 6 },
+ { 2, 5 }, { 1, 6 }, { 4, 3 }, { 7, 0 },
+ { 5, 2 }, { 6, 1 }, { 3, 4 }, { 0, 7 },
+ { 3, 4 }, { 0, 7 }, { 5, 2 }, { 6, 1 },
+ { 7, 0 }, { 4, 3 }, { 1, 6 }, { 2, 5 },
+ { 1, 6 }, { 2, 5 }, { 7, 0 }, { 4, 3 },
+ { 6, 1 }, { 5, 2 }, { 0, 7 }, { 3, 4 },
+ { 0, 7 }, { 3, 4 }, { 6, 1 }, { 5, 2 },
+ { 3, 4 }, { 0, 7 }, { 5, 2 }, { 6, 1 },
+ { 5, 2 }, { 6, 1 }, { 3, 4 }, { 0, 7 },
+ { 2, 5 }, { 1, 6 }, { 4, 3 }, { 7, 0 },
+ { 4, 3 }, { 7, 0 }, { 2, 5 }, { 1, 6 },
+};
+
+/**
+ * EDGE MCS-5 UL header convolutional code:
+ * 51 bits blocks, rate 1/3, k = 7
+ * G4 = 1 + D2 + D3 + D5 + D6
+ * G7 = 1 + D + D2 + D3 + D6
+ * G5 = 1 + D + D4 + D6
+ */
+const struct osmo_conv_code gsm0503_mcs5_ul_hdr = {
+ .N = 3,
+ .K = 7,
+ .len = 45,
+ .next_output = mcs5_ul_hdr_output,
+ .next_state = mcs5_ul_hdr_state,
+ .term = CONV_TERM_TAIL_BITING,
+};
+
+static const uint8_t mcs5_state[][2] = {
+ { 0, 1 }, { 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 }, { 28, 29 }, { 30, 31 },
+ { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 },
+ { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 },
+ { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 },
+ { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 },
+ { 0, 1 }, { 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 }, { 28, 29 }, { 30, 31 },
+ { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 },
+ { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 },
+ { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 },
+ { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 },
+};
+
+static const uint8_t mcs5_output[][2] = {
+ { 0, 7 }, { 3, 4 }, { 6, 1 }, { 5, 2 },
+ { 6, 1 }, { 5, 2 }, { 0, 7 }, { 3, 4 },
+ { 1, 6 }, { 2, 5 }, { 7, 0 }, { 4, 3 },
+ { 7, 0 }, { 4, 3 }, { 1, 6 }, { 2, 5 },
+ { 4, 3 }, { 7, 0 }, { 2, 5 }, { 1, 6 },
+ { 2, 5 }, { 1, 6 }, { 4, 3 }, { 7, 0 },
+ { 5, 2 }, { 6, 1 }, { 3, 4 }, { 0, 7 },
+ { 3, 4 }, { 0, 7 }, { 5, 2 }, { 6, 1 },
+ { 7, 0 }, { 4, 3 }, { 1, 6 }, { 2, 5 },
+ { 1, 6 }, { 2, 5 }, { 7, 0 }, { 4, 3 },
+ { 6, 1 }, { 5, 2 }, { 0, 7 }, { 3, 4 },
+ { 0, 7 }, { 3, 4 }, { 6, 1 }, { 5, 2 },
+ { 3, 4 }, { 0, 7 }, { 5, 2 }, { 6, 1 },
+ { 5, 2 }, { 6, 1 }, { 3, 4 }, { 0, 7 },
+ { 2, 5 }, { 1, 6 }, { 4, 3 }, { 7, 0 },
+ { 4, 3 }, { 7, 0 }, { 2, 5 }, { 1, 6 },
+};
+
+/**
+ * EDGE MCS-5 data convolutional code:
+ * 468 bits blocks, rate 1/3, k = 7
+ * G4 = 1 + D2 + D3 + D5 + D6
+ * G7 = 1 + D + D2 + D3 + D6
+ * G5 = 1 + D + D4 + D6
+ */
+const struct osmo_conv_code gsm0503_mcs5 = {
+ .N = 3,
+ .K = 7,
+ .len = 462,
+ .next_output = mcs5_output,
+ .next_state = mcs5_state,
+};
+
+static const uint8_t mcs6_state[][2] = {
+ { 0, 1 }, { 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 }, { 28, 29 }, { 30, 31 },
+ { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 },
+ { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 },
+ { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 },
+ { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 },
+ { 0, 1 }, { 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 }, { 28, 29 }, { 30, 31 },
+ { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 },
+ { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 },
+ { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 },
+ { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 },
+};
+
+static const uint8_t mcs6_output[][2] = {
+ { 0, 7 }, { 3, 4 }, { 6, 1 }, { 5, 2 },
+ { 6, 1 }, { 5, 2 }, { 0, 7 }, { 3, 4 },
+ { 1, 6 }, { 2, 5 }, { 7, 0 }, { 4, 3 },
+ { 7, 0 }, { 4, 3 }, { 1, 6 }, { 2, 5 },
+ { 4, 3 }, { 7, 0 }, { 2, 5 }, { 1, 6 },
+ { 2, 5 }, { 1, 6 }, { 4, 3 }, { 7, 0 },
+ { 5, 2 }, { 6, 1 }, { 3, 4 }, { 0, 7 },
+ { 3, 4 }, { 0, 7 }, { 5, 2 }, { 6, 1 },
+ { 7, 0 }, { 4, 3 }, { 1, 6 }, { 2, 5 },
+ { 1, 6 }, { 2, 5 }, { 7, 0 }, { 4, 3 },
+ { 6, 1 }, { 5, 2 }, { 0, 7 }, { 3, 4 },
+ { 0, 7 }, { 3, 4 }, { 6, 1 }, { 5, 2 },
+ { 3, 4 }, { 0, 7 }, { 5, 2 }, { 6, 1 },
+ { 5, 2 }, { 6, 1 }, { 3, 4 }, { 0, 7 },
+ { 2, 5 }, { 1, 6 }, { 4, 3 }, { 7, 0 },
+ { 4, 3 }, { 7, 0 }, { 2, 5 }, { 1, 6 },
+};
+
+/**
+ * EDGE MCS-6 data convolutional code:
+ * 612 bits blocks, rate 1/3, k = 7
+ * G4 = 1 + D2 + D3 + D5 + D6
+ * G7 = 1 + D + D2 + D3 + D6
+ * G5 = 1 + D + D4 + D6
+ */
+const struct osmo_conv_code gsm0503_mcs6 = {
+ .N = 3,
+ .K = 7,
+ .len = 606,
+ .next_output = mcs6_output,
+ .next_state = mcs6_state,
+};
+
+static const uint8_t mcs7_dl_hdr_state[][2] = {
+ { 0, 1 }, { 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 }, { 28, 29 }, { 30, 31 },
+ { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 },
+ { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 },
+ { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 },
+ { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 },
+ { 0, 1 }, { 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 }, { 28, 29 }, { 30, 31 },
+ { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 },
+ { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 },
+ { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 },
+ { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 },
+};
+
+static const uint8_t mcs7_dl_hdr_output[][2] = {
+ { 0, 7 }, { 3, 4 }, { 6, 1 }, { 5, 2 },
+ { 6, 1 }, { 5, 2 }, { 0, 7 }, { 3, 4 },
+ { 1, 6 }, { 2, 5 }, { 7, 0 }, { 4, 3 },
+ { 7, 0 }, { 4, 3 }, { 1, 6 }, { 2, 5 },
+ { 4, 3 }, { 7, 0 }, { 2, 5 }, { 1, 6 },
+ { 2, 5 }, { 1, 6 }, { 4, 3 }, { 7, 0 },
+ { 5, 2 }, { 6, 1 }, { 3, 4 }, { 0, 7 },
+ { 3, 4 }, { 0, 7 }, { 5, 2 }, { 6, 1 },
+ { 7, 0 }, { 4, 3 }, { 1, 6 }, { 2, 5 },
+ { 1, 6 }, { 2, 5 }, { 7, 0 }, { 4, 3 },
+ { 6, 1 }, { 5, 2 }, { 0, 7 }, { 3, 4 },
+ { 0, 7 }, { 3, 4 }, { 6, 1 }, { 5, 2 },
+ { 3, 4 }, { 0, 7 }, { 5, 2 }, { 6, 1 },
+ { 5, 2 }, { 6, 1 }, { 3, 4 }, { 0, 7 },
+ { 2, 5 }, { 1, 6 }, { 4, 3 }, { 7, 0 },
+ { 4, 3 }, { 7, 0 }, { 2, 5 }, { 1, 6 },
+};
+
+/**
+ * EDGE MCS-7 DL header convolutional code:
+ * 51 bits blocks, rate 1/3, k = 7
+ * G4 = 1 + D2 + D3 + D5 + D6
+ * G7 = 1 + D + D2 + D3 + D6
+ * G5 = 1 + D + D4 + D6
+ */
+const struct osmo_conv_code gsm0503_mcs7_dl_hdr = {
+ .N = 3,
+ .K = 7,
+ .len = 45,
+ .next_output = mcs7_dl_hdr_output,
+ .next_state = mcs7_dl_hdr_state,
+ .term = CONV_TERM_TAIL_BITING,
+};
+
+static const uint8_t mcs7_ul_hdr_state[][2] = {
+ { 0, 1 }, { 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 }, { 28, 29 }, { 30, 31 },
+ { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 },
+ { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 },
+ { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 },
+ { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 },
+ { 0, 1 }, { 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 }, { 28, 29 }, { 30, 31 },
+ { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 },
+ { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 },
+ { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 },
+ { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 },
+};
+
+static const uint8_t mcs7_ul_hdr_output[][2] = {
+ { 0, 7 }, { 3, 4 }, { 6, 1 }, { 5, 2 },
+ { 6, 1 }, { 5, 2 }, { 0, 7 }, { 3, 4 },
+ { 1, 6 }, { 2, 5 }, { 7, 0 }, { 4, 3 },
+ { 7, 0 }, { 4, 3 }, { 1, 6 }, { 2, 5 },
+ { 4, 3 }, { 7, 0 }, { 2, 5 }, { 1, 6 },
+ { 2, 5 }, { 1, 6 }, { 4, 3 }, { 7, 0 },
+ { 5, 2 }, { 6, 1 }, { 3, 4 }, { 0, 7 },
+ { 3, 4 }, { 0, 7 }, { 5, 2 }, { 6, 1 },
+ { 7, 0 }, { 4, 3 }, { 1, 6 }, { 2, 5 },
+ { 1, 6 }, { 2, 5 }, { 7, 0 }, { 4, 3 },
+ { 6, 1 }, { 5, 2 }, { 0, 7 }, { 3, 4 },
+ { 0, 7 }, { 3, 4 }, { 6, 1 }, { 5, 2 },
+ { 3, 4 }, { 0, 7 }, { 5, 2 }, { 6, 1 },
+ { 5, 2 }, { 6, 1 }, { 3, 4 }, { 0, 7 },
+ { 2, 5 }, { 1, 6 }, { 4, 3 }, { 7, 0 },
+ { 4, 3 }, { 7, 0 }, { 2, 5 }, { 1, 6 },
+};
+
+/**
+ * EDGE MCS-7 UL header convolutional code:
+ * 60 bits blocks, rate 1/3, k = 7
+ * G4 = 1 + D2 + D3 + D5 + D6
+ * G7 = 1 + D + D2 + D3 + D6
+ * G5 = 1 + D + D4 + D6
+ */
+const struct osmo_conv_code gsm0503_mcs7_ul_hdr = {
+ .N = 3,
+ .K = 7,
+ .len = 54,
+ .next_output = mcs7_ul_hdr_output,
+ .next_state = mcs7_ul_hdr_state,
+ .term = CONV_TERM_TAIL_BITING,
+};
+
+static const uint8_t mcs7_state[][2] = {
+ { 0, 1 }, { 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 }, { 28, 29 }, { 30, 31 },
+ { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 },
+ { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 },
+ { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 },
+ { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 },
+ { 0, 1 }, { 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 }, { 28, 29 }, { 30, 31 },
+ { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 },
+ { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 },
+ { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 },
+ { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 },
+};
+
+static const uint8_t mcs7_output[][2] = {
+ { 0, 7 }, { 3, 4 }, { 6, 1 }, { 5, 2 },
+ { 6, 1 }, { 5, 2 }, { 0, 7 }, { 3, 4 },
+ { 1, 6 }, { 2, 5 }, { 7, 0 }, { 4, 3 },
+ { 7, 0 }, { 4, 3 }, { 1, 6 }, { 2, 5 },
+ { 4, 3 }, { 7, 0 }, { 2, 5 }, { 1, 6 },
+ { 2, 5 }, { 1, 6 }, { 4, 3 }, { 7, 0 },
+ { 5, 2 }, { 6, 1 }, { 3, 4 }, { 0, 7 },
+ { 3, 4 }, { 0, 7 }, { 5, 2 }, { 6, 1 },
+ { 7, 0 }, { 4, 3 }, { 1, 6 }, { 2, 5 },
+ { 1, 6 }, { 2, 5 }, { 7, 0 }, { 4, 3 },
+ { 6, 1 }, { 5, 2 }, { 0, 7 }, { 3, 4 },
+ { 0, 7 }, { 3, 4 }, { 6, 1 }, { 5, 2 },
+ { 3, 4 }, { 0, 7 }, { 5, 2 }, { 6, 1 },
+ { 5, 2 }, { 6, 1 }, { 3, 4 }, { 0, 7 },
+ { 2, 5 }, { 1, 6 }, { 4, 3 }, { 7, 0 },
+ { 4, 3 }, { 7, 0 }, { 2, 5 }, { 1, 6 },
+};
+
+/**
+ * EDGE MCS-7 data convolutional code:
+ * 468 bits blocks, rate 1/3, k = 7
+ * G4 = 1 + D2 + D3 + D5 + D6
+ * G7 = 1 + D + D2 + D3 + D6
+ * G5 = 1 + D + D4 + D6
+ */
+const struct osmo_conv_code gsm0503_mcs7 = {
+ .N = 3,
+ .K = 7,
+ .len = 462,
+ .next_output = mcs7_output,
+ .next_state = mcs7_state,
+};
+
+static const uint8_t mcs8_state[][2] = {
+ { 0, 1 }, { 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 }, { 28, 29 }, { 30, 31 },
+ { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 },
+ { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 },
+ { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 },
+ { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 },
+ { 0, 1 }, { 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 }, { 28, 29 }, { 30, 31 },
+ { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 },
+ { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 },
+ { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 },
+ { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 },
+};
+
+static const uint8_t mcs8_output[][2] = {
+ { 0, 7 }, { 3, 4 }, { 6, 1 }, { 5, 2 },
+ { 6, 1 }, { 5, 2 }, { 0, 7 }, { 3, 4 },
+ { 1, 6 }, { 2, 5 }, { 7, 0 }, { 4, 3 },
+ { 7, 0 }, { 4, 3 }, { 1, 6 }, { 2, 5 },
+ { 4, 3 }, { 7, 0 }, { 2, 5 }, { 1, 6 },
+ { 2, 5 }, { 1, 6 }, { 4, 3 }, { 7, 0 },
+ { 5, 2 }, { 6, 1 }, { 3, 4 }, { 0, 7 },
+ { 3, 4 }, { 0, 7 }, { 5, 2 }, { 6, 1 },
+ { 7, 0 }, { 4, 3 }, { 1, 6 }, { 2, 5 },
+ { 1, 6 }, { 2, 5 }, { 7, 0 }, { 4, 3 },
+ { 6, 1 }, { 5, 2 }, { 0, 7 }, { 3, 4 },
+ { 0, 7 }, { 3, 4 }, { 6, 1 }, { 5, 2 },
+ { 3, 4 }, { 0, 7 }, { 5, 2 }, { 6, 1 },
+ { 5, 2 }, { 6, 1 }, { 3, 4 }, { 0, 7 },
+ { 2, 5 }, { 1, 6 }, { 4, 3 }, { 7, 0 },
+ { 4, 3 }, { 7, 0 }, { 2, 5 }, { 1, 6 },
+};
+
+/**
+ * EDGE MCS-8 data convolutional code:
+ * 564 bits blocks, rate 1/3, k = 7
+ * G4 = 1 + D2 + D3 + D5 + D6
+ * G7 = 1 + D + D2 + D3 + D6
+ * G5 = 1 + D + D4 + D6
+ */
+const struct osmo_conv_code gsm0503_mcs8 = {
+ .N = 3,
+ .K = 7,
+ .len = 558,
+ .next_output = mcs8_output,
+ .next_state = mcs8_state,
+};
+
+static const uint8_t mcs9_state[][2] = {
+ { 0, 1 }, { 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 }, { 28, 29 }, { 30, 31 },
+ { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 },
+ { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 },
+ { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 },
+ { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 },
+ { 0, 1 }, { 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 }, { 28, 29 }, { 30, 31 },
+ { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 },
+ { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 },
+ { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 },
+ { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 },
+};
+
+static const uint8_t mcs9_output[][2] = {
+ { 0, 7 }, { 3, 4 }, { 6, 1 }, { 5, 2 },
+ { 6, 1 }, { 5, 2 }, { 0, 7 }, { 3, 4 },
+ { 1, 6 }, { 2, 5 }, { 7, 0 }, { 4, 3 },
+ { 7, 0 }, { 4, 3 }, { 1, 6 }, { 2, 5 },
+ { 4, 3 }, { 7, 0 }, { 2, 5 }, { 1, 6 },
+ { 2, 5 }, { 1, 6 }, { 4, 3 }, { 7, 0 },
+ { 5, 2 }, { 6, 1 }, { 3, 4 }, { 0, 7 },
+ { 3, 4 }, { 0, 7 }, { 5, 2 }, { 6, 1 },
+ { 7, 0 }, { 4, 3 }, { 1, 6 }, { 2, 5 },
+ { 1, 6 }, { 2, 5 }, { 7, 0 }, { 4, 3 },
+ { 6, 1 }, { 5, 2 }, { 0, 7 }, { 3, 4 },
+ { 0, 7 }, { 3, 4 }, { 6, 1 }, { 5, 2 },
+ { 3, 4 }, { 0, 7 }, { 5, 2 }, { 6, 1 },
+ { 5, 2 }, { 6, 1 }, { 3, 4 }, { 0, 7 },
+ { 2, 5 }, { 1, 6 }, { 4, 3 }, { 7, 0 },
+ { 4, 3 }, { 7, 0 }, { 2, 5 }, { 1, 6 },
+};
+
+/**
+ * EDGE MCS-9 data convolutional code:
+ * 612 bits blocks, rate 1/3, k = 7
+ * G4 = 1 + D2 + D3 + D5 + D6
+ * G7 = 1 + D + D2 + D3 + D6
+ * G5 = 1 + D + D4 + D6
+ */
+const struct osmo_conv_code gsm0503_mcs9 = {
+ .N = 3,
+ .K = 7,
+ .len = 606,
+ .next_output = mcs9_output,
+ .next_state = mcs9_state,
+};
+
diff --git a/lib/decoding/osmocom/coding/gsm0503_interleaving.c b/lib/decoding/osmocom/coding/gsm0503_interleaving.c
new file mode 100644
index 0000000..333e105
--- /dev/null
+++ b/lib/decoding/osmocom/coding/gsm0503_interleaving.c
@@ -0,0 +1,573 @@
+/*
+ * (C) 2013 by Andreas Eversberg <jolly@eversberg.eu>
+ * (C) 2016 by Tom Tsou <tom.tsou@ettus.com>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdint.h>
+#include <string.h>
+
+#include <osmocom/core/bits.h>
+#include "gsm0503_tables.h"
+#include "gsm0503_interleaving.h"
+
+/*
+ * GSM xCCH interleaving and burst mapping
+ *
+ * Interleaving:
+ *
+ * Given 456 coded input bits, form 4 blocks of 114 bits:
+ *
+ * i(B, j) = c(n, k) k = 0, ..., 455
+ * n = 0, ..., N, N + 1, ...
+ * B = B_0 + 4n + (k mod 4)
+ * j = 2(49k mod 57) + ((k mod 8) div 4)
+ *
+ * Mapping on Burst:
+ *
+ * e(B, j) = i(B, j)
+ * e(B, 59 + j) = i(B, 57 + j) j = 0, ..., 56
+ * e(B, 57) = h_l(B)
+ * e(B, 58) = h_n(B)
+ *
+ * Where hl(B) and hn(B) are bits in burst B indicating flags.
+ */
+
+void gsm0503_xcch_deinterleave(sbit_t *cB, const sbit_t *iB)
+{
+ int j, k, B;
+
+ for (k = 0; k < 456; k++) {
+ B = k & 3;
+ j = 2 * ((49 * k) % 57) + ((k & 7) >> 2);
+ cB[k] = iB[B * 114 + j];
+ }
+}
+
+void gsm0503_xcch_interleave(ubit_t *cB, ubit_t *iB)
+{
+ int j, k, B;
+
+ for (k = 0; k < 456; k++) {
+ B = k & 3;
+ j = 2 * ((49 * k) % 57) + ((k & 7) >> 2);
+ iB[B * 114 + j] = cB[k];
+ }
+}
+
+void gsm0503_mcs1_dl_deinterleave(sbit_t *u, sbit_t *hc,
+ sbit_t *dc, const sbit_t *iB)
+{
+ int k;
+ sbit_t c[452];
+ sbit_t cp[456];
+
+ gsm0503_xcch_deinterleave(cp, iB);
+
+ for (k = 0; k < 25; k++)
+ c[k] = cp[k];
+ for (k = 26; k < 82; k++)
+ c[k - 1] = cp[k];
+ for (k = 83; k < 139; k++)
+ c[k - 2] = cp[k];
+ for (k = 140; k < 424; k++)
+ c[k - 3] = cp[k];
+ for (k = 425; k < 456; k++)
+ c[k - 4] = cp[k];
+
+ if (u) {
+ for (k = 0; k < 12; k++)
+ u[k] = c[k];
+ }
+
+ if (hc) {
+ for (k = 12; k < 80; k++)
+ hc[k - 12] = c[k];
+ }
+
+ if (dc) {
+ for (k = 80; k < 452; k++)
+ dc[k - 80] = c[k];
+ }
+}
+
+void gsm0503_mcs1_dl_interleave(const ubit_t *up, const ubit_t *hc,
+ const ubit_t *dc, ubit_t *iB)
+{
+ int k;
+ ubit_t c[452];
+ ubit_t cp[456];
+
+ for (k = 0; k < 12; k++)
+ c[k] = up[k];
+ for (k = 12; k < 80; k++)
+ c[k] = hc[k - 12];
+ for (k = 80; k < 452; k++)
+ c[k] = dc[k - 80];
+
+ for (k = 0; k < 25; k++)
+ cp[k] = c[k];
+ for (k = 26; k < 82; k++)
+ cp[k] = c[k - 1];
+ for (k = 83; k < 139; k++)
+ cp[k] = c[k - 2];
+ for (k = 140; k < 424; k++)
+ cp[k] = c[k - 3];
+ for (k = 425; k < 456; k++)
+ cp[k] = c[k - 4];
+
+ cp[25] = 0;
+ cp[82] = 0;
+ cp[139] = 0;
+ cp[424] = 0;
+
+ gsm0503_xcch_interleave(cp, iB);
+}
+
+void gsm0503_mcs1_ul_deinterleave(sbit_t *hc, sbit_t *dc, const sbit_t *iB)
+{
+ int k;
+ sbit_t c[452];
+ sbit_t cp[456];
+
+ gsm0503_xcch_deinterleave(cp, iB);
+
+ for (k = 0; k < 25; k++)
+ c[k] = cp[k];
+ for (k = 26; k < 82; k++)
+ c[k - 1] = cp[k];
+ for (k = 83; k < 139; k++)
+ c[k - 2] = cp[k];
+ for (k = 140; k < 424; k++)
+ c[k - 3] = cp[k];
+ for (k = 425; k < 456; k++)
+ c[k - 4] = cp[k];
+
+ if (hc) {
+ for (k = 0; k < 80; k++)
+ hc[k] = c[k];
+ }
+
+ if (dc) {
+ for (k = 80; k < 452; k++)
+ dc[k - 80] = c[k];
+ }
+}
+
+void gsm0503_mcs1_ul_interleave(const ubit_t *hc, const ubit_t *dc, ubit_t *iB)
+{
+ int k;
+ ubit_t c[452];
+ ubit_t cp[456];
+
+ for (k = 0; k < 80; k++)
+ c[k] = hc[k];
+ for (k = 80; k < 452; k++)
+ c[k] = dc[k - 80];
+
+ for (k = 0; k < 25; k++)
+ cp[k] = c[k];
+ for (k = 26; k < 82; k++)
+ cp[k] = c[k - 1];
+ for (k = 83; k < 139; k++)
+ cp[k] = c[k - 2];
+ for (k = 140; k < 424; k++)
+ cp[k] = c[k - 3];
+ for (k = 425; k < 456; k++)
+ cp[k] = c[k - 4];
+
+ cp[25] = 0;
+ cp[82] = 0;
+ cp[139] = 0;
+ cp[424] = 0;
+
+ gsm0503_xcch_interleave(cp, iB);
+}
+
+void gsm0503_mcs5_ul_interleave(const ubit_t *hc, const ubit_t *dc,
+ ubit_t *hi, ubit_t *di)
+{
+ int j, k;
+
+ /* Header */
+ for (k = 0; k < 136; k++) {
+ j = 34 * (k % 4) + 2 * (11 * k % 17) + k % 8 / 4;
+ hi[j] = hc[k];
+ }
+
+ /* Data */
+ for (k = 0; k < 1248; k++) {
+ j = gsm0503_interleave_mcs5[k];
+ di[j] = dc[k];
+ }
+}
+
+void gsm0503_mcs5_ul_deinterleave(sbit_t *hc, sbit_t *dc,
+ const sbit_t *hi, const sbit_t *di)
+{
+ int j, k;
+
+ /* Header */
+ if (hc) {
+ for (k = 0; k < 136; k++) {
+ j = 34 * (k % 4) + 2 * (11 * k % 17) + k % 8 / 4;
+ hc[k] = hi[j];
+ }
+ }
+
+ /* Data */
+ if (dc) {
+ for (k = 0; k < 1248; k++) {
+ j = gsm0503_interleave_mcs5[k];
+ dc[k] = di[j];
+ }
+ }
+}
+
+void gsm0503_mcs5_dl_interleave(const ubit_t *hc, const ubit_t *dc,
+ ubit_t *hi, ubit_t *di)
+{
+ int j, k;
+
+ /* Header */
+ for (k = 0; k < 100; k++) {
+ j = 25 * (k % 4) + ((17 * k) % 25);
+ hi[j] = hc[k];
+ }
+
+ /* Data */
+ for (k = 0; k < 1248; k++) {
+ j = gsm0503_interleave_mcs5[k];
+ di[j] = dc[k];
+ }
+}
+
+void gsm0503_mcs5_dl_deinterleave(sbit_t *hc, sbit_t *dc,
+ const sbit_t *hi, const sbit_t *di)
+{
+ int j, k;
+
+ /* Header */
+ if (hc) {
+ for (k = 0; k < 100; k++) {
+ j = 25 * (k % 4) + ((17 * k) % 25);
+ hc[k] = hi[j];
+ }
+ }
+
+ /* Data */
+ if (dc) {
+ for (k = 0; k < 1248; k++) {
+ j = gsm0503_interleave_mcs5[k];
+ dc[k] = di[j];
+ }
+ }
+}
+
+void gsm0503_mcs7_dl_interleave(const ubit_t *hc, const ubit_t *c1,
+ const ubit_t *c2, ubit_t *hi, ubit_t *di)
+{
+ int j, k;
+ ubit_t dc[1224];
+
+ /* Header */
+ for (k = 0; k < 124; k++) {
+ j = 31 * (k % 4) + ((17 * k) % 31);
+ hi[j] = hc[k];
+ }
+
+ memcpy(&dc[0], c1, 612);
+ memcpy(&dc[612], c2, 612);
+
+ /* Data */
+ for (k = 0; k < 1224; k++) {
+ j = 306 * (k % 4) + 3 * (44 * k % 102 + k / 4 % 2) +
+ (k + 2 - k / 408) % 3;
+ di[j] = dc[k];
+ }
+}
+
+
+void gsm0503_mcs7_dl_deinterleave(sbit_t *hc, sbit_t *c1, sbit_t *c2,
+ const sbit_t *hi, const sbit_t *di)
+{
+ int j, k;
+ ubit_t dc[1224];
+
+ /* Header */
+ if (hc) {
+ for (k = 0; k < 124; k++) {
+ j = 31 * (k % 4) + ((17 * k) % 31);
+ hc[k] = hi[j];
+ }
+ }
+
+ /* Data */
+ if (c1 && c2) {
+ for (k = 0; k < 1224; k++) {
+ j = 306 * (k % 4) + 3 * (44 * k % 102 + k / 4 % 2) +
+ (k + 2 - k / 408) % 3;
+ dc[k] = di[j];
+ }
+
+ memcpy(c1, &dc[0], 612);
+ memcpy(c2, &dc[612], 612);
+ }
+}
+
+void gsm0503_mcs7_ul_interleave(const ubit_t *hc, const ubit_t *c1,
+ const ubit_t *c2, ubit_t *hi, ubit_t *di)
+{
+ int j, k;
+ ubit_t dc[1224];
+
+ /* Header */
+ for (k = 0; k < 160; k++) {
+ j = 40 * (k % 4) + 2 * (13 * (k / 8) % 20) + k % 8 / 4;
+ hi[j] = hc[k];
+ }
+
+ memcpy(&dc[0], c1, 612);
+ memcpy(&dc[612], c2, 612);
+
+ /* Data */
+ for (k = 0; k < 1224; k++) {
+ j = 306 * (k % 4) + 3 * (44 * k % 102 + k / 4 % 2) +
+ (k + 2 - k / 408) % 3;
+ di[j] = dc[k];
+ }
+}
+
+void gsm0503_mcs7_ul_deinterleave(sbit_t *hc, sbit_t *c1, sbit_t *c2,
+ const sbit_t *hi, const sbit_t *di)
+{
+ int j, k;
+ ubit_t dc[1224];
+
+ /* Header */
+ if (hc) {
+ for (k = 0; k < 160; k++) {
+ j = 40 * (k % 4) + 2 * (13 * (k / 8) % 20) + k % 8 / 4;
+ hc[k] = hi[j];
+ }
+ }
+
+ /* Data */
+ if (c1 && c2) {
+ for (k = 0; k < 1224; k++) {
+ j = 306 * (k % 4) + 3 * (44 * k % 102 + k / 4 % 2) +
+ (k + 2 - k / 408) % 3;
+ dc[k] = di[j];
+ }
+
+ memcpy(c1, &dc[0], 612);
+ memcpy(c2, &dc[612], 612);
+ }
+}
+
+void gsm0503_mcs8_ul_interleave(const ubit_t *hc, const ubit_t *c1,
+ const ubit_t *c2, ubit_t *hi, ubit_t *di)
+{
+ int j, k;
+ ubit_t dc[1224];
+
+ /* Header */
+ for (k = 0; k < 160; k++) {
+ j = 40 * (k % 4) + 2 * (13 * (k / 8) % 20) + k % 8 / 4;
+ hi[j] = hc[k];
+ }
+
+ memcpy(&dc[0], c1, 612);
+ memcpy(&dc[612], c2, 612);
+
+ /* Data */
+ for (k = 0; k < 1224; k++) {
+ j = 306 * (2 * (k / 612) + (k % 2)) +
+ 3 * (74 * k % 102 + k / 2 % 2) + (k + 2 - k / 204) % 3;
+ di[j] = dc[k];
+ }
+}
+
+void gsm0503_mcs8_ul_deinterleave(sbit_t *hc, sbit_t *c1, sbit_t *c2,
+ const sbit_t *hi, const sbit_t *di)
+{
+ int j, k;
+ ubit_t dc[1224];
+
+ /* Header */
+ if (hc) {
+ for (k = 0; k < 160; k++) {
+ j = 40 * (k % 4) + 2 * (13 * (k / 8) % 20) + k % 8 / 4;
+ hc[k] = hi[j];
+ }
+ }
+
+ /* Data */
+ if (c1 && c2) {
+ for (k = 0; k < 1224; k++) {
+ j = 306 * (2 * (k / 612) + (k % 2)) +
+ 3 * (74 * k % 102 + k / 2 % 2) + (k + 2 - k / 204) % 3;
+ dc[k] = di[j];
+ }
+
+ memcpy(c1, &dc[0], 612);
+ memcpy(c2, &dc[612], 612);
+ }
+}
+
+void gsm0503_mcs8_dl_interleave(const ubit_t *hc, const ubit_t *c1,
+ const ubit_t *c2, ubit_t *hi, ubit_t *di)
+{
+ int j, k;
+ ubit_t dc[1224];
+
+ /* Header */
+ for (k = 0; k < 124; k++) {
+ j = 31 * (k % 4) + ((17 * k) % 31);
+ hi[j] = hc[k];
+ }
+
+ memcpy(&dc[0], c1, 612);
+ memcpy(&dc[612], c2, 612);
+
+ /* Data */
+ for (k = 0; k < 1224; k++) {
+ j = 306 * (2 * (k / 612) + (k % 2)) +
+ 3 * (74 * k % 102 + k / 2 % 2) + (k + 2 - k / 204) % 3;
+ di[j] = dc[k];
+ }
+}
+
+void gsm0503_mcs8_dl_deinterleave(sbit_t *hc, sbit_t *c1, sbit_t *c2,
+ const sbit_t *hi, const sbit_t *di)
+{
+ int j, k;
+ ubit_t dc[1224];
+
+ /* Header */
+ if (hc) {
+ for (k = 0; k < 124; k++) {
+ j = 31 * (k % 4) + ((17 * k) % 31);
+ hc[k] = hi[j];
+ }
+ }
+
+ /* Data */
+ if (c1 && c2) {
+ for (k = 0; k < 1224; k++) {
+ j = 306 * (2 * (k / 612) + (k % 2)) +
+ 3 * (74 * k % 102 + k / 2 % 2) + (k + 2 - k / 204) % 3;
+ dc[k] = di[j];
+ }
+
+ memcpy(c1, &dc[0], 612);
+ memcpy(c2, &dc[612], 612);
+ }
+}
+
+/*
+ * GSM TCH FR/EFR/AFS interleaving and burst mapping
+ *
+ * Interleaving:
+ *
+ * Given 456 coded input bits, form 8 blocks of 114 bits,
+ * where even bits of the first 4 blocks and odd bits of the last 4 blocks
+ * are used:
+ *
+ * i(B, j) = c(n, k) k = 0, ..., 455
+ * n = 0, ..., N, N + 1, ...
+ * B = B_0 + 4n + (k mod 8)
+ * j = 2(49k mod 57) + ((k mod 8) div 4)
+ *
+ * Mapping on Burst:
+ *
+ * e(B, j) = i(B, j)
+ * e(B, 59 + j) = i(B, 57 + j) j = 0, ..., 56
+ * e(B, 57) = h_l(B)
+ * e(B, 58) = h_n(B)
+ *
+ * Where hl(B) and hn(B) are bits in burst B indicating flags.
+ */
+
+void gsm0503_tch_fr_deinterleave(sbit_t *cB, sbit_t *iB)
+{
+ int j, k, B;
+
+ for (k = 0; k < 456; k++) {
+ B = k & 7;
+ j = 2 * ((49 * k) % 57) + ((k & 7) >> 2);
+ cB[k] = iB[B * 114 + j];
+ }
+}
+
+void gsm0503_tch_fr_interleave(ubit_t *cB, ubit_t *iB)
+{
+ int j, k, B;
+
+ for (k = 0; k < 456; k++) {
+ B = k & 7;
+ j = 2 * ((49 * k) % 57) + ((k & 7) >> 2);
+ iB[B * 114 + j] = cB[k];
+ }
+}
+
+/*
+ * GSM TCH HR/AHS interleaving and burst mapping
+ *
+ * Interleaving:
+ *
+ * Given 288 coded input bits, form 4 blocks of 114 bits,
+ * where even bits of the first 2 blocks and odd bits of the last 2 blocks
+ * are used:
+ *
+ * i(B, j) = c(n, k) k = 0, ..., 227
+ * n = 0, ..., N, N + 1, ...
+ * B = B_0 + 2n + b
+ * j, b = table[k];
+ *
+ * Mapping on Burst:
+ *
+ * e(B, j) = i(B, j)
+ * e(B, 59 + j) = i(B, 57 + j) j = 0, ..., 56
+ * e(B, 57) = h_l(B)
+ * e(B, 58) = h_n(B)
+ *
+ * Where hl(B) and hn(B) are bits in burst B indicating flags.
+ */
+
+void gsm0503_tch_hr_deinterleave(sbit_t *cB, sbit_t *iB)
+{
+ int j, k, B;
+
+ for (k = 0; k < 228; k++) {
+ B = gsm0503_tch_hr_interleaving[k][1];
+ j = gsm0503_tch_hr_interleaving[k][0];
+ cB[k] = iB[B * 114 + j];
+ }
+}
+
+void gsm0503_tch_hr_interleave(ubit_t *cB, ubit_t *iB)
+{
+ int j, k, B;
+
+ for (k = 0; k < 228; k++) {
+ B = gsm0503_tch_hr_interleaving[k][1];
+ j = gsm0503_tch_hr_interleaving[k][0];
+ iB[B * 114 + j] = cB[k];
+ }
+}
diff --git a/lib/decoding/osmocom/coding/gsm0503_interleaving.h b/lib/decoding/osmocom/coding/gsm0503_interleaving.h
new file mode 100644
index 0000000..05c0365
--- /dev/null
+++ b/lib/decoding/osmocom/coding/gsm0503_interleaving.h
@@ -0,0 +1,73 @@
+/*
+ * (C) 2013 by Andreas Eversberg <jolly@eversberg.eu>
+ * (C) 2016 by Tom Tsou <tom.tsou@ettus.com>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+
+#pragma once
+
+#include <osmocom/core/bits.h>
+
+void gsm0503_xcch_deinterleave(sbit_t *cB, const sbit_t *iB);
+void gsm0503_xcch_interleave(ubit_t *cB, ubit_t *iB);
+
+void gsm0503_tch_fr_deinterleave(sbit_t *cB, sbit_t *iB);
+void gsm0503_tch_fr_interleave(ubit_t *cB, ubit_t *iB);
+
+void gsm0503_tch_hr_deinterleave(sbit_t *cB, sbit_t *iB);
+void gsm0503_tch_hr_interleave(ubit_t *cB, ubit_t *iB);
+
+void gsm0503_mcs1_ul_deinterleave(sbit_t *hc, sbit_t *dc, const sbit_t *iB);
+void gsm0503_mcs1_ul_interleave(const ubit_t *hc,
+ const ubit_t *dc, ubit_t *iB);
+
+void gsm0503_mcs1_dl_deinterleave(sbit_t *u, sbit_t *hc,
+ sbit_t *dc, const sbit_t *iB);
+void gsm0503_mcs1_dl_interleave(const ubit_t *up, const ubit_t *hc,
+ const ubit_t *dc, ubit_t *iB);
+
+void gsm0503_mcs5_ul_deinterleave(sbit_t *hc, sbit_t *dc,
+ const sbit_t *hi, const sbit_t *di);
+void gsm0503_mcs5_ul_interleave(const ubit_t *hc, const ubit_t *dc,
+ ubit_t *hi, ubit_t *di);
+
+void gsm0503_mcs5_dl_deinterleave(sbit_t *hc, sbit_t *dc,
+ const sbit_t *hi, const sbit_t *di);
+void gsm0503_mcs5_dl_interleave(const ubit_t *hc, const ubit_t *dc,
+ ubit_t *hi, ubit_t *di);
+
+void gsm0503_mcs7_ul_deinterleave(sbit_t *hc, sbit_t *c1, sbit_t *c2,
+ const sbit_t *hi, const sbit_t *di);
+void gsm0503_mcs7_ul_interleave(const ubit_t *hc, const ubit_t *c1,
+ const ubit_t *c2, ubit_t *hi, ubit_t *di);
+
+void gsm0503_mcs7_dl_deinterleave(sbit_t *hc, sbit_t *c1, sbit_t *c2,
+ const sbit_t *hi, const sbit_t *di);
+void gsm0503_mcs7_dl_interleave(const ubit_t *hc, const ubit_t *c1,
+ const ubit_t *c2, ubit_t *hi, ubit_t *di);
+
+void gsm0503_mcs8_ul_deinterleave(sbit_t *hc, sbit_t *c1, sbit_t *c2,
+ const sbit_t *hi, const sbit_t *di);
+void gsm0503_mcs8_ul_interleave(const ubit_t *hc, const ubit_t *c1,
+ const ubit_t *c2, ubit_t *hi, ubit_t *di);
+
+void gsm0503_mcs8_dl_deinterleave(sbit_t *hc, sbit_t *c1, sbit_t *c2,
+ const sbit_t *hi, const sbit_t *di);
+void gsm0503_mcs8_dl_interleave(const ubit_t *hc, const ubit_t *c1,
+ const ubit_t *c2, ubit_t *hi, ubit_t *di);
diff --git a/lib/decoding/osmocom/coding/gsm0503_mapping.c b/lib/decoding/osmocom/coding/gsm0503_mapping.c
new file mode 100644
index 0000000..45275bf
--- /dev/null
+++ b/lib/decoding/osmocom/coding/gsm0503_mapping.c
@@ -0,0 +1,291 @@
+/*
+ * (C) 2013 by Andreas Eversberg <jolly@eversberg.eu>
+ * (C) 2016 by Tom Tsou <tom.tsou@ettus.com>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdint.h>
+#include <string.h>
+
+#include <osmocom/core/bits.h>
+#include "gsm0503_mapping.h"
+
+void gsm0503_xcch_burst_unmap(sbit_t *iB, const sbit_t *eB,
+ sbit_t *hl, sbit_t *hn)
+{
+ memcpy(iB, eB, 57);
+ memcpy(iB + 57, eB + 59, 57);
+
+ if (hl)
+ *hl = eB[57];
+
+ if (hn)
+ *hn = eB[58];
+}
+
+void gsm0503_xcch_burst_map(ubit_t *iB, ubit_t *eB, const ubit_t *hl,
+ const ubit_t *hn)
+{
+ memcpy(eB, iB, 57);
+ memcpy(eB + 59, iB + 57, 57);
+
+ if (hl)
+ eB[57] = *hl;
+ if (hn)
+ eB[58] = *hn;
+}
+
+void gsm0503_tch_burst_unmap(sbit_t *iB, sbit_t *eB, sbit_t *h, int odd)
+{
+ int i;
+
+ /* brainfuck: only copy even or odd bits */
+ if (iB) {
+ for (i = odd; i < 57; i += 2)
+ iB[i] = eB[i];
+ for (i = 58 - odd; i < 114; i += 2)
+ iB[i] = eB[i + 2];
+ }
+
+ if (h) {
+ if (!odd)
+ *h = eB[58];
+ else
+ *h = eB[57];
+ }
+}
+
+void gsm0503_tch_burst_map(ubit_t *iB, ubit_t *eB, const ubit_t *h, int odd)
+{
+ int i;
+
+ /* brainfuck: only copy even or odd bits */
+ if (eB) {
+ for (i = odd; i < 57; i += 2)
+ eB[i] = iB[i];
+ for (i = 58 - odd; i < 114; i += 2)
+ eB[i + 2] = iB[i];
+ }
+
+ if (h) {
+ if (!odd)
+ eB[58] = *h;
+ else
+ eB[57] = *h;
+ }
+}
+
+void gsm0503_mcs5_dl_burst_map(const ubit_t *di, ubit_t *eB,
+ const ubit_t *hi, const ubit_t *up, int B)
+{
+ int j;
+ int q[8] = { 0, 0, 0, 0, 0, 0, 0, 0, };
+
+ for (j = 0; j < 156; j++)
+ eB[j] = di[312 * B + j];
+ for (j = 156; j < 168; j++)
+ eB[j] = hi[25 * B + j - 156];
+ for (j = 168; j < 174; j++)
+ eB[j] = up[9 * B + j - 168];
+ for (j = 174; j < 176; j++)
+ eB[j] = q[2 * B + j - 174];
+ for (j = 176; j < 179; j++)
+ eB[j] = up[9 * B + j - 170];
+ for (j = 179; j < 192; j++)
+ eB[j] = hi[25 * B + j - 167];
+ for (j = 192; j < 348; j++)
+ eB[j] = di[312 * B + j - 36];
+}
+
+void gsm0503_mcs5_dl_burst_unmap(sbit_t *di, const sbit_t *eB,
+ sbit_t *hi, sbit_t *up, int B)
+{
+ int j;
+
+ for (j = 0; j < 156; j++)
+ di[312 * B + j] = eB[j];
+ for (j = 156; j < 168; j++)
+ hi[25 * B + j - 156] = eB[j];
+ for (j = 168; j < 174; j++)
+ up[9 * B + j - 168] = eB[j];
+
+ for (j = 176; j < 179; j++)
+ up[9 * B + j - 170] = eB[j];
+ for (j = 179; j < 192; j++)
+ hi[25 * B + j - 167] = eB[j];
+ for (j = 192; j < 348; j++)
+ di[312 * B + j - 36] = eB[j];
+}
+
+void gsm0503_mcs5_ul_burst_map(const ubit_t *di, ubit_t *eB,
+ const ubit_t *hi, int B)
+{
+ int j;
+
+ for (j = 0; j < 156; j++)
+ eB[j] = di[312 * B + j];
+ for (j = 156; j < 174; j++)
+ eB[j] = hi[34 * B + j - 156];
+ for (j = 174; j < 176; j++)
+ eB[j] = 0;
+ for (j = 176; j < 192; j++)
+ eB[j] = hi[34 * B + j - 158];
+ for (j = 192; j < 348; j++)
+ eB[j] = di[312 * B + j - 36];
+}
+
+void gsm0503_mcs5_ul_burst_unmap(sbit_t *di, const sbit_t *eB,
+ sbit_t *hi, int B)
+{
+ int j;
+
+ for (j = 0; j < 156; j++)
+ di[312 * B + j] = eB[j];
+ for (j = 156; j < 174; j++)
+ hi[34 * B + j - 156] = eB[j];
+ for (j = 176; j < 192; j++)
+ hi[34 * B + j - 158] = eB[j];
+ for (j = 192; j < 348; j++)
+ di[312 * B + j - 36] = eB[j];
+}
+
+void gsm0503_mcs7_dl_burst_map(const ubit_t *di, ubit_t *eB,
+ const ubit_t *hi, const ubit_t *up, int B)
+{
+ int j;
+ int q[8] = { 1, 1, 1, 0, 0, 1, 1, 1, };
+
+ for (j = 0; j < 153; j++)
+ eB[j] = di[306 * B + j];
+ for (j = 153; j < 168; j++)
+ eB[j] = hi[31 * B + j - 153];
+ for (j = 168; j < 174; j++)
+ eB[j] = up[9 * B + j - 168];
+ for (j = 174; j < 176; j++)
+ eB[j] = q[2 * B + j - 174];
+ for (j = 176; j < 179; j++)
+ eB[j] = up[9 * B + j - 170];
+ for (j = 179; j < 195; j++)
+ eB[j] = hi[31 * B + j - 164];
+ for (j = 195; j < 348; j++)
+ eB[j] = di[306 * B + j - 42];
+}
+
+void gsm0503_mcs7_dl_burst_unmap(sbit_t *di, const sbit_t *eB,
+ sbit_t *hi, sbit_t *up, int B)
+{
+ int j;
+
+ for (j = 0; j < 153; j++)
+ di[306 * B + j] = eB[j];
+ for (j = 153; j < 168; j++)
+ hi[31 * B + j - 153] = eB[j];
+ for (j = 168; j < 174; j++)
+ up[9 * B + j - 168] = eB[j];
+
+ for (j = 176; j < 179; j++)
+ up[9 * B + j - 170] = eB[j];
+ for (j = 179; j < 195; j++)
+ hi[31 * B + j - 164] = eB[j];
+ for (j = 195; j < 348; j++)
+ di[306 * B + j - 42] = eB[j];
+}
+
+void gsm0503_mcs7_ul_burst_map(const ubit_t *di, ubit_t *eB,
+ const ubit_t *hi, int B)
+{
+ int j;
+ int q[8] = { 1, 1, 1, 0, 0, 1, 1, 1, };
+
+ for (j = 0; j < 153; j++)
+ eB[j] = di[306 * B + j];
+ for (j = 153; j < 174; j++)
+ eB[j] = hi[40 * B + j - 153];
+ for (j = 174; j < 176; j++)
+ eB[j] = q[2 * B + j - 174];
+ for (j = 176; j < 195; j++)
+ eB[j] = hi[40 * B + j - 155];
+ for (j = 195; j < 348; j++)
+ eB[j] = di[306 * B + j - 42];
+}
+
+void gsm0503_mcs7_ul_burst_unmap(sbit_t *di, const sbit_t *eB,
+ sbit_t *hi, int B)
+{
+ int j;
+
+ for (j = 0; j < 153; j++)
+ di[306 * B + j] = eB[j];
+ for (j = 153; j < 174; j++)
+ hi[40 * B + j - 153] = eB[j];
+
+ for (j = 176; j < 195; j++)
+ hi[40 * B + j - 155] = eB[j];
+ for (j = 195; j < 348; j++)
+ di[306 * B + j - 42] = eB[j];
+}
+
+void gsm0503_mcs5_burst_swap(sbit_t *eB)
+{
+ sbit_t t[14];
+
+ t[0] = eB[155];
+ t[1] = eB[158];
+ t[2] = eB[161];
+ t[3] = eB[164];
+ t[4] = eB[167];
+ t[5] = eB[170];
+ t[6] = eB[173];
+ t[7] = eB[195];
+ t[8] = eB[196];
+ t[9] = eB[198];
+ t[10] = eB[199];
+ t[11] = eB[201];
+ t[12] = eB[202];
+ t[13] = eB[204];
+
+ eB[155] = eB[142];
+ eB[158] = eB[144];
+ eB[161] = eB[145];
+ eB[164] = eB[147];
+ eB[167] = eB[148];
+ eB[170] = eB[150];
+ eB[173] = eB[151];
+ eB[195] = eB[176];
+ eB[196] = eB[179];
+ eB[198] = eB[182];
+ eB[199] = eB[185];
+ eB[201] = eB[188];
+ eB[202] = eB[191];
+ eB[204] = eB[194];
+
+ eB[142] = t[0];
+ eB[144] = t[1];
+ eB[145] = t[2];
+ eB[147] = t[3];
+ eB[148] = t[4];
+ eB[150] = t[5];
+ eB[151] = t[6];
+ eB[176] = t[7];
+ eB[179] = t[8];
+ eB[182] = t[9];
+ eB[185] = t[10];
+ eB[188] = t[11];
+ eB[191] = t[12];
+ eB[194] = t[13];
+}
diff --git a/lib/decoding/osmocom/coding/gsm0503_mapping.h b/lib/decoding/osmocom/coding/gsm0503_mapping.h
new file mode 100644
index 0000000..417a94f
--- /dev/null
+++ b/lib/decoding/osmocom/coding/gsm0503_mapping.h
@@ -0,0 +1,54 @@
+/*
+ * (C) 2013 by Andreas Eversberg <jolly@eversberg.eu>
+ * (C) 2016 by Tom Tsou <tom.tsou@ettus.com>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#pragma once
+
+#include <osmocom/core/bits.h>
+
+void gsm0503_xcch_burst_unmap(sbit_t *iB, const sbit_t *eB,
+ sbit_t *hl, sbit_t *hn);
+void gsm0503_xcch_burst_map(ubit_t *iB, ubit_t *eB, const ubit_t *hl,
+ const ubit_t *hn);
+
+void gsm0503_tch_burst_unmap(sbit_t *iB, sbit_t *eB, sbit_t *h, int odd);
+void gsm0503_tch_burst_map(ubit_t *iB, ubit_t *eB, const ubit_t *h, int odd);
+
+void gsm0503_mcs5_ul_burst_map(const ubit_t *di, ubit_t *eB,
+ const ubit_t *hi, int B);
+void gsm0503_mcs5_ul_burst_unmap(sbit_t *di, const sbit_t *eB,
+ sbit_t *hi, int B);
+
+void gsm0503_mcs7_ul_burst_map(const ubit_t *di, ubit_t *eB,
+ const ubit_t *hi, int B);
+void gsm0503_mcs7_ul_burst_unmap(sbit_t *di, const sbit_t *eB,
+ sbit_t *hi, int B);
+
+void gsm0503_mcs5_dl_burst_map(const ubit_t *di, ubit_t *eB,
+ const ubit_t *hi, const ubit_t *up, int B);
+void gsm0503_mcs5_dl_burst_unmap(sbit_t *di, const sbit_t *eB,
+ sbit_t *hi, sbit_t *up, int B);
+
+void gsm0503_mcs7_dl_burst_map(const ubit_t *di, ubit_t *eB,
+ const ubit_t *hi, const ubit_t *up, int B);
+void gsm0503_mcs7_dl_burst_unmap(sbit_t *di, const sbit_t *eB,
+ sbit_t *hi, sbit_t *up, int B);
+
+void gsm0503_mcs5_burst_swap(sbit_t *eB);
diff --git a/lib/decoding/osmocom/coding/gsm0503_parity.c b/lib/decoding/osmocom/coding/gsm0503_parity.c
new file mode 100644
index 0000000..50977f7
--- /dev/null
+++ b/lib/decoding/osmocom/coding/gsm0503_parity.c
@@ -0,0 +1,132 @@
+/*
+ * (C) 2013 by Andreas Eversberg <jolly@eversberg.eu>
+ * (C) 2016 by Tom Tsou <tom.tsou@ettus.com>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdint.h>
+
+#include <osmocom/core/crcgen.h>
+#include "gsm0503_parity.h"
+
+/*
+ * GSM (SACCH) parity (FIRE code)
+ *
+ * g(x) = (x^23 + 1)(x^17 + x^3 + 1)
+ * = x^40 + x^26 + x^23 + x^17 + x^3 + a1
+ */
+const struct osmo_crc64gen_code gsm0503_fire_crc40 = {
+ .bits = 40,
+ .poly = 0x0004820009ULL,
+ .init = 0x0000000000ULL,
+ .remainder = 0xffffffffffULL,
+};
+
+/*
+ * GSM PDTCH CS-2, CS-3, CS-4 parity
+ *
+ * g(x) = x^16 + x^12 + x^5 + 1
+ */
+const struct osmo_crc16gen_code gsm0503_cs234_crc16 = {
+ .bits = 16,
+ .poly = 0x1021,
+ .init = 0x0000,
+ .remainder = 0xffff,
+};
+
+/*
+ * EDGE MCS header parity
+ *
+ */
+const struct osmo_crc8gen_code gsm0503_mcs_crc8_hdr = {
+ .bits = 8,
+ .poly = 0x49,
+ .init = 0x00,
+ .remainder = 0xff,
+};
+
+/*
+ * EDGE MCS data parity
+ *
+ */
+const struct osmo_crc16gen_code gsm0503_mcs_crc12 = {
+ .bits = 12,
+ .poly = 0x0d31,
+ .init = 0x0000,
+ .remainder = 0x0fff,
+};
+
+/*
+ * GSM RACH parity
+ *
+ * g(x) = x^6 + x^5 + x^3 + x^2 + x^1 + 1
+ */
+const struct osmo_crc8gen_code gsm0503_rach_crc6 = {
+ .bits = 6,
+ .poly = 0x2f,
+ .init = 0x00,
+ .remainder = 0x3f,
+};
+
+/*
+ * GSM SCH parity
+ *
+ * g(x) = x^10 + x^8 + x^6 + x^5 + x^4 + x^2 + 1
+ */
+const struct osmo_crc16gen_code gsm0503_sch_crc10 = {
+ .bits = 10,
+ .poly = 0x175,
+ .init = 0x000,
+ .remainder = 0x3ff,
+};
+
+/*
+ * GSM TCH FR/HR/EFR parity
+ *
+ * g(x) = x^3 + x + 1
+ */
+const struct osmo_crc8gen_code gsm0503_tch_fr_crc3 = {
+ .bits = 3,
+ .poly = 0x3,
+ .init = 0x0,
+ .remainder = 0x7,
+};
+
+/*
+ * GSM TCH EFR parity
+ *
+ * g(x) = x^8 + x^4 + x^3 + x^2 + 1
+ */
+const struct osmo_crc8gen_code gsm0503_tch_efr_crc8 = {
+ .bits = 8,
+ .poly = 0x1d,
+ .init = 0x00,
+ .remainder = 0x00,
+};
+
+/*
+ * GSM AMR parity
+ *
+ * g(x) = x^6 + x^5 + x^3 + x^2 + x^1 + 1
+ */
+const struct osmo_crc8gen_code gsm0503_amr_crc6 = {
+ .bits = 6,
+ .poly = 0x2f,
+ .init = 0x00,
+ .remainder = 0x3f,
+};
diff --git a/lib/decoding/osmocom/coding/gsm0503_parity.h b/lib/decoding/osmocom/coding/gsm0503_parity.h
new file mode 100644
index 0000000..6d8a062
--- /dev/null
+++ b/lib/decoding/osmocom/coding/gsm0503_parity.h
@@ -0,0 +1,34 @@
+/*
+ * (C) 2013 by Andreas Eversberg <jolly@eversberg.eu>
+ * (C) 2016 by Tom Tsou <tom.tsou@ettus.com>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#pragma once
+
+#include <osmocom/core/crcgen.h>
+
+const struct osmo_crc64gen_code gsm0503_fire_crc40;
+const struct osmo_crc16gen_code gsm0503_cs234_crc16;
+const struct osmo_crc8gen_code gsm0503_mcs_crc8_hdr;
+const struct osmo_crc16gen_code gsm0503_mcs_crc12;
+const struct osmo_crc8gen_code gsm0503_rach_crc6;
+const struct osmo_crc16gen_code gsm0503_sch_crc10;
+const struct osmo_crc8gen_code gsm0503_tch_fr_crc3;
+const struct osmo_crc8gen_code gsm0503_tch_efr_crc8;
+const struct osmo_crc8gen_code gsm0503_amr_crc6;
diff --git a/lib/decoding/osmocom/coding/gsm0503_tables.c b/lib/decoding/osmocom/coding/gsm0503_tables.c
new file mode 100644
index 0000000..d4cabcc
--- /dev/null
+++ b/lib/decoding/osmocom/coding/gsm0503_tables.c
@@ -0,0 +1,1732 @@
+/*
+ * (C) 2013 by Andreas Eversberg <jolly@eversberg.eu>
+ * (C) 2016 by Tom Tsou <tom.tsou@ettus.com>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <stdint.h>
+
+#include <osmocom/core/bits.h>
+#include "gsm0503_tables.h"
+
+const ubit_t gsm0503_pdtch_hl_hn_ubit[4][8] = {
+ { 1,1, 1,1, 1,1, 1,1 },
+ { 1,1, 0,0, 1,0, 0,0 },
+ { 0,0, 1,0, 0,0, 0,1 },
+ { 0,0, 0,1, 0,1, 1,0 },
+};
+
+const ubit_t gsm0503_pdtch_edge_hl_hn_ubit[3][8] = {
+ { 0,0, 0,1, 0,1, 1,0 },
+ { 0,0, 0,0, 0,0, 0,0 },
+ { 1,1, 1,0, 0,1, 1,1 },
+};
+
+const sbit_t gsm0503_pdtch_hl_hn_sbit[4][8] = {
+ { -127,-127, -127,-127, -127,-127, -127,-127 },
+ { -127,-127, 127, 127, -127, 127, 127, 127 },
+ { 127, 127, -127, 127, 127, 127, 127,-127 },
+ { 127, 127, 127,-127, 127,-127, -127, 127 },
+};
+
+const sbit_t gsm0503_pdtch_edge_hl_hn_sbit[3][8] = {
+ { 127, 127, 127,-127, 127,-127, -127, 127 },
+ { 127, 127, 127, 127, 127, 127, 127, 127 },
+ { -127,-127, -127, 127, 127,-127, -127,-127 },
+};
+
+const ubit_t gsm0503_usf2six[8][6] = {
+ { 0,0,0, 0,0,0 },
+ { 1,0,0, 1,0,1 },
+ { 0,1,0, 1,1,0 },
+ { 1,1,0, 0,1,1 },
+ { 0,0,1, 0,1,1 },
+ { 1,0,1, 1,1,0 },
+ { 0,1,1, 1,0,1 },
+ { 1,1,1, 0,0,0 },
+};
+
+const ubit_t gsm0503_usf2twelve_ubit[8][12] = {
+ { 0,0,0, 0,0,0, 0,0,0, 0,0,0 },
+ { 1,1,0, 1,0,0, 0,0,1, 0,1,1 },
+ { 0,0,1, 1,0,1, 1,1,0, 1,1,0 },
+ { 1,1,1, 0,0,1, 1,1,1, 1,0,1 },
+ { 0,0,0, 0,1,1, 0,1,1, 1,0,1 },
+ { 1,1,0, 1,1,1, 0,1,0, 1,1,0 },
+ { 0,0,1, 1,1,0, 1,0,1, 0,1,1 },
+ { 1,1,1, 0,1,0, 1,0,0, 0,0,0 },
+};
+
+const sbit_t gsm0503_usf2twelve_sbit[8][12] = {
+ { 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127 },
+ { -127,-127, 127, -127, 127, 127, 127, 127,-127, 127,-127,-127 },
+ { 127, 127,-127, -127, 127,-127, -127,-127, 127, -127,-127, 127 },
+ { -127,-127,-127, 127, 127,-127, -127,-127,-127, -127, 127,-127 },
+ { 127, 127, 127, 127,-127,-127, 127,-127,-127, -127, 127,-127 },
+ { -127,-127, 127, -127,-127,-127, 127,-127, 127, -127,-127, 127 },
+ { 127, 127,-127, -127,-127, 127, -127, 127,-127, 127,-127,-127 },
+ { -127,-127,-127, 127,-127, 127, -127, 127, 127, 127, 127, 127 },
+};
+
+const uint8_t gsm0503_puncture_cs2[588] = {
+ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1,
+ 0,0,0,1, 0,0,0,0, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1,
+ 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,0, 0,0,0,1, 0,0,0,1,
+ 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1,
+ 0,0,0,1, 0,0,0,0, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1,
+ 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,0, 0,0,0,1, 0,0,0,1,
+ 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1,
+ 0,0,0,1, 0,0,0,0, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1,
+ 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,0, 0,0,0,1, 0,0,0,1,
+ 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1,
+ 0,0,0,1, 0,0,0,0, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1,
+ 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,0, 0,0,0,1, 0,0,0,1,
+ 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1,
+ 0,0,0,1, 0,0,0,0, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1,
+ 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,0, 0,0,0,1, 0,0,0,1,
+ 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1,
+ 0,0,0,1, 0,0,0,0, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1,
+ 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,1, 0,0,0,0, 0,0,0,1, 0,0,0,1,
+ 0,0,0,1, 0,0,0,1, 0,0,0,1
+};
+
+const uint8_t gsm0503_puncture_cs3[676] = {
+ 0,0,0,0,0,0, 0,0,0,0,0,0, 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1,
+ 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1,
+ 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1,
+ 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1,
+ 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1,
+ 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1,
+ 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1,
+ 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1,
+ 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1,
+ 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1,
+ 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1,
+ 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1,
+ 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1,
+ 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1,
+ 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1,
+ 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1,
+ 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1,
+ 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1,
+ 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1,
+ 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1,
+ 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1,
+ 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,1,0,1,
+ 0,0,0,1,0,1, 0,0,0,1,0,1, 0,0,0,0
+};
+
+const uint8_t gsm0503_puncture_mcs1_dl_hdr[108] = {
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,1,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,1,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,1,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,1,1,
+};
+
+const uint8_t gsm0503_puncture_mcs1_ul_hdr[117] = {
+ 0,0,0,0,0,1,0,0,1,0,0,1,
+ 0,0,0,0,0,1,0,0,1,0,0,1,
+ 0,0,1,0,0,1,0,0,1,0,0,1,
+ 0,0,1,0,0,1,0,0,1,0,0,1,
+ 0,0,1,0,0,1,0,0,1,0,0,1,
+ 0,0,1,0,0,1,0,0,1,0,0,1,
+ 0,0,1,0,0,1,0,0,1,0,0,1,
+ 0,0,1,0,0,1,0,0,1,0,0,1,
+ 0,0,1,0,0,1,0,0,1,0,0,1,
+ 0,0,1,0,0,1,0,0,1,
+};
+
+const uint8_t gsm0503_puncture_mcs1_p1[588] = {
+ 0,0,1,0,0,1,0,0,1,0,1,1,0,0,1,0,0,1,0,0,1,
+ 0,0,1,0,0,1,0,0,1,0,1,1,0,0,1,0,0,1,0,0,1,
+ 0,0,1,0,0,1,0,0,1,0,1,1,0,0,1,0,0,1,0,0,1,
+ 0,0,1,0,0,1,0,0,0,0,1,1,0,0,1,0,0,1,0,0,1,
+ 0,0,1,0,0,1,0,0,1,0,1,1,0,0,1,0,0,1,0,0,1,
+ 0,0,1,0,0,1,0,0,1,0,1,1,0,0,1,0,0,1,0,0,1,
+ 0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,
+ 0,0,1,0,0,1,0,0,1,0,1,1,0,0,1,0,0,1,0,0,1,
+ 0,0,1,0,0,1,0,0,1,0,1,1,0,0,1,0,0,1,0,0,1,
+ 0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,
+ 0,0,1,0,0,1,0,0,1,0,1,1,0,0,1,0,0,1,0,0,1,
+ 0,0,1,0,0,1,0,0,1,0,1,1,0,0,1,0,0,1,0,0,1,
+ 0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,
+ 0,0,1,0,0,1,0,0,1,0,1,1,0,0,1,0,0,1,0,0,1,
+ 0,0,1,0,0,1,0,0,1,0,1,1,0,0,1,0,0,1,0,0,1,
+ 0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,
+ 0,0,1,0,0,1,0,0,1,0,1,1,0,0,1,0,0,1,0,0,1,
+ 0,0,1,0,0,1,0,0,1,0,1,1,0,0,1,0,0,1,0,0,1,
+ 0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,
+ 0,0,1,0,0,1,0,0,1,0,1,1,0,0,1,0,0,1,0,0,1,
+ 0,0,1,0,0,1,0,0,1,0,1,1,0,0,1,0,0,1,0,0,1,
+ 0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,
+ 0,0,1,0,0,1,0,0,1,0,1,1,0,0,1,0,0,1,0,0,1,
+ 0,0,1,0,0,1,0,0,1,0,1,1,0,0,1,0,0,1,0,0,1,
+ 0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,0,0,1,
+ 0,0,1,0,0,1,0,0,1,0,1,1,0,0,1,0,0,1,0,0,1,
+ 0,0,1,0,0,1,0,0,1,0,1,1,0,0,1,0,0,1,0,0,1,
+ 0,0,1,0,0,1,0,0,1,0,1,1,0,0,1,0,0,1,0,0,1,
+};
+
+const uint8_t gsm0503_puncture_mcs1_p2[588] = {
+ 0,1,0,0,1,0,0,1,0,1,0,0,0,1,0,1,1,0,0,1,0,
+ 0,1,0,0,1,0,0,1,0,1,0,0,0,1,0,1,1,0,0,1,0,
+ 0,1,0,0,1,0,0,1,0,1,0,0,0,1,0,1,1,0,0,1,0,
+ 0,1,0,0,1,0,0,1,0,1,0,0,0,1,0,0,1,0,0,1,0,
+ 0,1,0,0,1,0,0,1,0,1,0,0,0,1,0,1,1,0,0,1,0,
+ 0,1,0,0,1,0,0,1,0,1,0,0,0,1,0,1,1,0,0,1,0,
+ 0,1,0,0,1,0,0,1,0,1,0,0,0,1,0,0,1,0,0,1,0,
+ 0,1,0,0,1,0,0,1,0,1,0,0,0,1,0,1,1,0,0,1,0,
+ 0,1,0,0,1,0,0,1,0,1,0,0,0,1,0,1,1,0,0,1,0,
+ 0,1,0,0,1,0,0,1,0,1,0,0,0,1,0,0,1,0,0,1,0,
+ 0,1,0,0,1,0,0,1,0,1,0,0,0,1,0,1,1,0,0,1,0,
+ 0,1,0,0,1,0,0,1,0,1,0,0,0,1,0,1,1,0,0,1,0,
+ 0,1,0,0,1,0,0,1,0,1,0,0,0,1,0,0,1,0,0,1,0,
+ 0,1,0,0,1,0,0,1,0,1,0,0,0,1,0,1,1,0,0,1,0,
+ 0,1,0,0,1,0,0,1,0,1,0,0,0,1,0,1,1,0,0,1,0,
+ 0,1,0,0,1,0,0,1,0,1,0,0,0,1,0,0,1,0,0,1,0,
+ 0,1,0,0,1,0,0,1,0,1,0,0,0,1,0,1,1,0,0,1,0,
+ 0,1,0,0,1,0,0,1,0,1,0,0,0,1,0,1,1,0,0,1,0,
+ 0,1,0,0,1,0,0,1,0,1,0,0,0,1,0,0,1,0,0,1,0,
+ 0,1,0,0,1,0,0,1,0,1,0,0,0,1,0,1,1,0,0,1,0,
+ 0,1,0,0,1,0,0,1,0,1,0,0,0,1,0,1,1,0,0,1,0,
+ 0,1,0,0,1,0,0,1,0,1,0,0,0,1,0,0,1,0,0,1,0,
+ 0,1,0,0,1,0,0,1,0,1,0,0,0,1,0,1,1,0,0,1,0,
+ 0,1,0,0,1,0,0,1,0,1,0,0,0,1,0,1,1,0,0,1,0,
+ 0,1,0,0,1,0,0,1,0,1,0,0,0,1,0,0,1,0,0,1,0,
+ 0,1,0,0,1,0,0,1,0,1,0,0,0,1,0,1,1,0,0,1,0,
+ 0,1,0,0,1,0,0,1,0,1,0,0,0,1,0,1,1,0,0,1,0,
+ 0,1,0,0,1,0,0,1,0,1,0,0,0,1,0,1,1,0,0,1,0,
+};
+
+const uint8_t gsm0503_puncture_mcs2_p1[732] = {
+ 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0,
+ 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,0,1,0,
+ 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0,
+ 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0,
+ 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0,
+ 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,0,1,0, 0,0,1,1,1,0,
+ 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0,
+ 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0,
+ 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0,
+ 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,0,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0,
+ 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0,
+ 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0,
+ 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0,
+ 0,0,1,1,1,0, 0,0,1,0,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0,
+ 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0,
+ 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0,
+ 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0,
+ 0,0,1,0,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0,
+ 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0,
+ 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0,
+ 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,0,1,0,
+ 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0,
+ 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0,
+ 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0, 0,0,1,1,1,0,
+ 0,0,1,1,1,0, 0,0,1,1,1,0,
+};
+
+const uint8_t gsm0503_puncture_mcs2_p2[732] = {
+ 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1,
+ 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1,
+ 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1,
+ 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1, 0,1,0,0,0,1, 1,1,0,0,0,1,
+ 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1,
+ 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1,
+ 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1,
+ 1,1,0,0,0,1, 1,1,0,0,0,1, 0,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1,
+ 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1,
+ 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1,
+ 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1,
+ 1,1,0,0,0,1, 0,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1,
+ 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1,
+ 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1,
+ 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1,
+ 0,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1,
+ 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1,
+ 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1,
+ 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1, 0,1,0,0,0,1,
+ 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1,
+ 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1,
+ 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1,
+ 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1, 0,1,0,0,0,1, 1,1,0,0,0,1,
+ 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1, 1,1,0,0,0,1,
+ 1,1,0,0,0,1, 1,1,0,0,0,1,
+};
+
+const uint8_t gsm0503_puncture_mcs3_p1[948] = {
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,1,1,0,1,1,0,
+ 0,0,1,0,1,1,0,1,1,1,0,1,
+};
+
+const uint8_t gsm0503_puncture_mcs3_p2[948] = {
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,
+};
+
+const uint8_t gsm0503_puncture_mcs3_p3[948] = {
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,
+};
+
+const uint8_t gsm0503_puncture_mcs4_p1[1116] = {
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1,
+};
+
+const uint8_t gsm0503_puncture_mcs4_p2[1116] = {
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1,
+};
+
+const uint8_t gsm0503_puncture_mcs4_p3[1116] = {
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0,
+};
+
+const uint8_t gsm0503_puncture_mcs5_p1[1404] = {
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0, 0,0,1,0,0,1,0,0,1, 0,0,1,0,0,1,0,0,1,
+};
+
+const uint8_t gsm0503_puncture_mcs5_p2[1404] = {
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0, 0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0, 0,1,0,0,1,0,0,1,0, 0,1,0,0,1,0,0,1,0,
+};
+
+const uint8_t gsm0503_puncture_mcs6_p1[1836] = {
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,0, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,0, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,0, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,0, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,0, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,0, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,0, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,0, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,0, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,0, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,0, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,0, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,0, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,0, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,0, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,0, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,0, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,0, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,0, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,0, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,0, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,0, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,0, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,0, 0,0,1, 0,0,1, 0,0,1, 0,0,1, 0,0,1,
+ 0,0,1, 0,0,1,
+};
+
+const uint8_t gsm0503_puncture_mcs6_p2[1836] = {
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,0,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,0,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,0,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,0,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,0,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,0,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,0,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,0,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,0,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,0,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,0,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,0,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,0,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,0,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,0,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,0,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,0,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,0,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,0,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,0,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,0,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,0,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,0,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,0,0,
+ 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0, 0,1,0,
+ 0,1,0, 0,1,0,
+};
+
+const uint8_t gsm0503_puncture_mcs7_dl_hdr[135] = {
+ 0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,1,0,0,0,0,0,
+ 0,0,0,1,0,0,0,0,0,0,
+ 0,0,0,1,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,
+ 1,0,0,0,0,0,0,0,0,1,
+ 0,0,0,0,0,0,0,0,0,1,
+ 0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,1,0,0,0,
+ 0,0,0,0,0,1,0,0,0,0,
+ 0,0,0,0,0,1,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,
+ 0,0,1,0,0,0,0,0,0,0,
+ 0,1,0,0,0,
+};
+
+const uint8_t gsm0503_puncture_mcs7_ul_hdr[162] = {
+ 0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,1,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,
+ 0,1,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,
+ 0,0,
+};
+
+const uint8_t gsm0503_puncture_mcs7_p1[1404] = {
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,0,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+ 0,1,1,1,0,1,1,1,0,1,1,0,0,0,1,0,1,1,
+};
+
+const uint8_t gsm0503_puncture_mcs7_p2[1404] = {
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,1,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,1,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,1,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,1,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,1,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,1,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,1,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,1,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,1,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,0,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,1,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,1,0,
+ 1,1,0,0,1,0,0,1,1,1,0,1,1,1,0,1,1,0,
+};
+
+const uint8_t gsm0503_puncture_mcs7_p3[1404] = {
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,0,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+ 1,1,0,1,1,0,0,0,1,0,1,1,0,1,1,1,0,1,
+};
+
+const uint8_t gsm0503_puncture_mcs8_p1[1692] = {
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,0,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+ 0,1,0,1,1,0,0,1,1,1,0,1,1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,1,1,0,1,1,1,0,
+};
+
+const uint8_t gsm0503_puncture_mcs8_p2[1692] = {
+ 1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+ 1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+ 1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+ 1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+ 1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+ 1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+ 1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+ 1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+ 1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+ 1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+ 1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+ 1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+ 1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+ 1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+ 1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+ 1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+ 1,0,1,1,0,1,0,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+ 1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+ 1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+ 1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+ 1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+ 1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+ 1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+ 1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+ 1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+ 1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+ 1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+ 1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+ 1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+ 1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+ 1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+ 1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+ 1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+ 1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+ 1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+ 1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+ 1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+ 1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+ 1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+ 1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+ 1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+ 1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+ 1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+ 1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+ 1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+ 1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+ 1,0,1,1,0,1,1,1,0,1,1,0,0,1,1,0,1,0,1,0,1,1,0,1,1,0,1,1,0,1,0,1,1,0,1,1,
+};
+
+const uint8_t gsm0503_puncture_mcs8_p3[1692] = {
+ 1,1,0,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+ 1,1,0,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+ 1,1,0,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+ 1,1,0,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+ 1,1,0,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+ 1,1,0,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+ 1,1,0,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+ 1,1,0,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+ 1,1,0,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+ 1,1,0,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+ 1,1,0,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+ 1,1,0,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+ 1,1,0,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+ 1,1,0,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+ 1,1,0,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+ 1,1,0,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+ 1,1,0,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+ 1,1,0,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+ 1,1,0,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+ 1,1,0,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+ 1,1,0,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+ 1,1,0,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+ 1,1,0,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+ 1,1,0,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+ 1,1,0,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+ 1,1,0,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+ 1,1,0,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+ 1,1,0,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+ 1,1,0,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+ 1,1,0,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+ 1,1,0,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+ 1,1,0,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+ 1,1,0,0,0,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+ 1,1,0,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+ 1,1,0,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+ 1,1,0,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+ 1,1,0,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+ 1,1,0,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+ 1,1,0,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+ 1,1,0,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+ 1,1,0,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+ 1,1,0,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+ 1,1,0,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+ 1,1,0,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+ 1,1,0,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+ 1,1,0,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+ 1,1,0,0,1,1,1,0,1,0,1,1,1,1,0,1,1,0,0,1,1,0,1,1,1,1,0,0,1,0,1,1,0,1,0,1,
+};
+
+const uint8_t gsm0503_puncture_mcs9_p1[1836] = {
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+ 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1, 0,1,1,
+};
+
+const uint8_t gsm0503_puncture_mcs9_p2[1836] = {
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+ 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1, 1,0,1,
+};
+
+const uint8_t gsm0503_puncture_mcs9_p3[1836] = {
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+ 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0, 1,1,0,
+};
+
+const uint16_t gsm0503_interleave_mcs5[1248] = {
+ 0, 463, 890, 1038, 220, 371, 795, 946, 582, 733, 1160, 63, 490, 641, 277, 428,
+ 852, 1003, 185, 333, 1223, 120, 547, 698, 1122, 28, 915, 1066, 242, 390, 817, 968,
+ 610, 761, 1185, 85, 512, 660, 305, 453, 880, 1031, 204, 355, 782, 1242, 148, 575,
+ 723, 1150, 50, 474, 625, 1088, 267, 418, 845, 993, 169, 320, 1207, 113, 537, 688,
+ 1115, 12, 902, 1050, 232, 383, 807, 958, 594, 745, 1172, 75, 502, 653, 289, 440,
+ 864, 1015, 197, 345, 1235, 132, 559, 710, 1134, 40, 927, 1078, 254, 402, 829, 980,
+ 159, 622, 773, 1197, 97, 524, 672, 1099, 5, 465, 892, 1043, 216, 367, 794, 942,
+ 587, 735, 1162, 62, 486, 637, 279, 430, 857, 1005, 181, 332, 1219, 125, 549, 700,
+ 1127, 24, 914, 1062, 244, 395, 819, 970, 606, 757, 1184, 87, 514, 665, 301, 452,
+ 876, 1027, 209, 357, 784, 1247, 144, 571, 722, 1146, 52, 479, 627, 1090, 266, 414,
+ 841, 992, 171, 322, 1209, 109, 536, 684, 1111, 17, 904, 1055, 228, 379, 806, 954,
+ 599, 747, 1174, 74, 498, 649, 291, 442, 869, 1017, 193, 344, 1231, 137, 561, 712,
+ 1139, 36, 926, 1074, 256, 407, 831, 982, 158, 618, 769, 1196, 99, 526, 677, 1101,
+ 7, 458, 894, 1033, 227, 363, 802, 941, 577, 740, 1152, 70, 485, 645, 284, 420,
+ 859, 998, 189, 328, 1215, 127, 542, 702, 1117, 35, 922, 1061, 246, 385, 824, 960,
+ 605, 765, 1180, 92, 504, 667, 309, 448, 887, 1023, 211, 350, 786, 1237, 155, 567,
+ 730, 1145, 54, 469, 632, 1080, 274, 413, 849, 988, 176, 312, 1202, 117, 532, 695,
+ 1107, 19, 906, 1045, 239, 375, 814, 953, 589, 752, 1164, 82, 497, 657, 296, 432,
+ 871, 1010, 201, 340, 1227, 139, 554, 714, 1129, 47, 934, 1073, 258, 397, 836, 972,
+ 166, 617, 777, 1192, 104, 516, 679, 1094, 9, 460, 899, 1035, 223, 362, 798, 937,
+ 579, 742, 1157, 66, 481, 644, 286, 425, 861, 1000, 188, 324, 1214, 129, 544, 707,
+ 1119, 31, 918, 1057, 251, 387, 826, 965, 601, 764, 1176, 94, 509, 669, 308, 444,
+ 883, 1022, 213, 352, 791, 1239, 151, 566, 726, 1141, 59, 471, 634, 1085, 270, 409,
+ 848, 984, 178, 317, 1204, 116, 528, 691, 1106, 21, 911, 1047, 235, 374, 810, 949,
+ 591, 754, 1169, 78, 493, 656, 298, 437, 873, 1012, 200, 336, 1226, 141, 556, 719,
+ 1131, 43, 930, 1069, 263, 399, 838, 977, 162, 613, 776, 1188, 106, 521, 681, 1096,
+ 2, 462, 889, 1040, 219, 370, 797, 945, 584, 732, 1159, 65, 489, 640, 276, 427,
+ 854, 1002, 184, 335, 1222, 122, 546, 697, 1124, 27, 917, 1065, 241, 392, 816, 967,
+ 609, 760, 1187, 84, 511, 662, 304, 455, 879, 1030, 206, 354, 781, 1244, 147, 574,
+ 725, 1149, 49, 476, 624, 1087, 269, 417, 844, 995, 168, 319, 1206, 112, 539, 687,
+ 1114, 14, 901, 1052, 231, 382, 809, 957, 596, 744, 1171, 77, 501, 652, 288, 439,
+ 866, 1014, 196, 347, 1234, 134, 558, 709, 1136, 39, 929, 1077, 253, 404, 828, 979,
+ 161, 621, 772, 1199, 96, 523, 674, 1098, 4, 467, 891, 1042, 218, 366, 793, 944,
+ 586, 737, 1161, 61, 488, 636, 281, 429, 856, 1007, 180, 331, 1218, 124, 551, 699,
+ 1126, 26, 913, 1064, 243, 394, 821, 969, 608, 756, 1183, 89, 513, 664, 300, 451,
+ 878, 1026, 208, 359, 783, 1246, 146, 570, 721, 1148, 51, 478, 629, 1089, 265, 416,
+ 840, 991, 173, 321, 1211, 108, 535, 686, 1110, 16, 903, 1054, 230, 378, 805, 956,
+ 598, 749, 1173, 73, 500, 648, 293, 441, 868, 1019, 192, 343, 1230, 136, 563, 711,
+ 1138, 38, 925, 1076, 255, 406, 833, 981, 157, 620, 768, 1195, 101, 525, 676, 1103,
+ 6, 457, 896, 1032, 226, 365, 801, 940, 576, 739, 1154, 69, 484, 647, 283, 422,
+ 858, 997, 191, 327, 1217, 126, 541, 704, 1116, 34, 921, 1060, 248, 384, 823, 962,
+ 604, 767, 1179, 91, 506, 666, 311, 447, 886, 1025, 210, 349, 788, 1236, 154, 569,
+ 729, 1144, 56, 468, 631, 1082, 273, 412, 851, 987, 175, 314, 1201, 119, 531, 694,
+ 1109, 18, 908, 1044, 238, 377, 813, 952, 588, 751, 1166, 81, 496, 659, 295, 434,
+ 870, 1009, 203, 339, 1229, 138, 553, 716, 1128, 46, 933, 1072, 260, 396, 835, 974,
+ 165, 616, 779, 1191, 103, 518, 678, 1093, 11, 459, 898, 1037, 222, 361, 800, 936,
+ 581, 741, 1156, 68, 480, 643, 285, 424, 863, 999, 187, 326, 1213, 131, 543, 706,
+ 1121, 30, 920, 1056, 250, 389, 825, 964, 600, 763, 1178, 93, 508, 671, 307, 446,
+ 882, 1021, 215, 351, 790, 1241, 150, 565, 728, 1140, 58, 473, 633, 1084, 272, 408,
+ 847, 986, 177, 316, 1203, 115, 530, 690, 1105, 23, 910, 1049, 234, 373, 812, 948,
+ 593, 753, 1168, 80, 492, 655, 297, 436, 875, 1011, 199, 338, 1225, 143, 555, 718,
+ 1133, 42, 932, 1068, 262, 401, 837, 976, 164, 612, 775, 1190, 105, 520, 683, 1095,
+ 1, 464, 888, 1039, 221, 369, 796, 947, 583, 734, 1158, 64, 491, 639, 278, 426,
+ 853, 1004, 183, 334, 1221, 121, 548, 696, 1123, 29, 916, 1067, 240, 391, 818, 966,
+ 611, 759, 1186, 86, 510, 661, 303, 454, 881, 1029, 205, 356, 780, 1243, 149, 573,
+ 724, 1151, 48, 475, 626, 1086, 268, 419, 843, 994, 170, 318, 1208, 111, 538, 689,
+ 1113, 13, 900, 1051, 233, 381, 808, 959, 595, 746, 1170, 76, 503, 651, 290, 438,
+ 865, 1016, 195, 346, 1233, 133, 560, 708, 1135, 41, 928, 1079, 252, 403, 830, 978,
+ 160, 623, 771, 1198, 98, 522, 673, 1100, 3, 466, 893, 1041, 217, 368, 792, 943,
+ 585, 736, 1163, 60, 487, 638, 280, 431, 855, 1006, 182, 330, 1220, 123, 550, 701,
+ 1125, 25, 912, 1063, 245, 393, 820, 971, 607, 758, 1182, 88, 515, 663, 302, 450,
+ 877, 1028, 207, 358, 785, 1245, 145, 572, 720, 1147, 53, 477, 628, 1091, 264, 415,
+ 842, 990, 172, 323, 1210, 110, 534, 685, 1112, 15, 905, 1053, 229, 380, 804, 955,
+ 597, 748, 1175, 72, 499, 650, 292, 443, 867, 1018, 194, 342, 1232, 135, 562, 713,
+ 1137, 37, 924, 1075, 257, 405, 832, 983, 156, 619, 770, 1194, 100, 527, 675, 1102,
+ 8, 456, 895, 1034, 225, 364, 803, 939, 578, 738, 1153, 71, 483, 646, 282, 421,
+ 860, 996, 190, 329, 1216, 128, 540, 703, 1118, 33, 923, 1059, 247, 386, 822, 961,
+ 603, 766, 1181, 90, 505, 668, 310, 449, 885, 1024, 212, 348, 787, 1238, 153, 568,
+ 731, 1143, 55, 470, 630, 1081, 275, 411, 850, 989, 174, 313, 1200, 118, 533, 693,
+ 1108, 20, 907, 1046, 237, 376, 815, 951, 590, 750, 1165, 83, 495, 658, 294, 433,
+ 872, 1008, 202, 341, 1228, 140, 552, 715, 1130, 45, 935, 1071, 259, 398, 834, 973,
+ 167, 615, 778, 1193, 102, 517, 680, 1092, 10, 461, 897, 1036, 224, 360, 799, 938,
+ 580, 743, 1155, 67, 482, 642, 287, 423, 862, 1001, 186, 325, 1212, 130, 545, 705,
+ 1120, 32, 919, 1058, 249, 388, 827, 963, 602, 762, 1177, 95, 507, 670, 306, 445,
+ 884, 1020, 214, 353, 789, 1240, 152, 564, 727, 1142, 57, 472, 635, 1083, 271, 410,
+ 846, 985, 179, 315, 1205, 114, 529, 692, 1104, 22, 909, 1048, 236, 372, 811, 950,
+ 592, 755, 1167, 79, 494, 654, 299, 435, 874, 1013, 198, 337, 1224, 142, 557, 717,
+ 1132, 44, 931, 1070, 261, 400, 839, 975, 163, 614, 774, 1189, 107, 519, 682, 1097,
+};
+
+/* this corresponds to the bit-lengths of the individual codec
+ * parameters as indicated in Table 1.1 of TS 06.10 */
+const uint8_t gsm0503_gsm_fr_map[76] = {
+ 6, 6, 5, 5, 4, 4, 3, 3, 7, 2, 2, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 7, 2, 2, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 2, 2, 6, 3, 3,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 2, 2, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 3, 3, 3, 3
+};
+
+/* this table describes the 65 most importaint bits from EFR coded
+ * bits as indicated in TS 05.03 (3.1.1.1) */
+const uint8_t gsm0503_gsm_efr_protected_bits[65] = {
+ 39, 40, 41, 42, 43, 44, 48, 87, 45, 2,
+ 3, 8, 10, 18, 19, 24, 46, 47,142,143,
+ 144,145,146,147, 92, 93,195,196, 98,137,
+ 148, 94,197,149,150, 95,198, 4, 5, 11,
+ 12, 16, 9, 6, 7, 13, 17, 20, 96,199,
+ 1, 14, 15, 21, 25, 26, 28,151,201,190,
+ 240, 88,138,191,241
+};
+
+/* Encoded in-band data for speech frames */
+const ubit_t gsm0503_afs_ic_ubit[4][8] = {
+ { 0,0,0,0,0,0,0,0 },
+ { 0,1,0,1,1,1,0,1 },
+ { 1,0,1,1,1,0,1,0 },
+ { 1,1,1,0,0,1,1,1 },
+};
+
+const sbit_t gsm0503_afs_ic_sbit[4][8] = {
+ { 127, 127, 127, 127, 127, 127, 127, 127 },
+ { 127,-127, 127,-127,-127,-127, 127,-127 },
+ { -127, 127,-127,-127,-127, 127,-127, 127 },
+ { -127,-127,-127, 127, 127,-127,-127,-127 },
+};
+
+const ubit_t gsm0503_ahs_ic_ubit[4][4] = {
+ { 0,0,0,0 },
+ { 1,0,0,1 },
+ { 1,1,1,0 },
+ { 0,1,1,1 },
+};
+
+const sbit_t gsm0503_ahs_ic_sbit[4][4] = {
+ { 127, 127, 127, 127 },
+ { -127, 127, 127,-127 },
+ { -127,-127,-127, 127 },
+ { 127,-127,-127,-127 },
+};
+
+const uint8_t gsm0503_tch_hr_interleaving[228][2] = {
+ { 0 ,0 }, { 1 ,2 }, { 78 ,1 }, { 79 ,3 }, { 48 ,0 }, { 49 ,2 },
+ { 54 ,1 }, { 55 ,3 }, { 24 ,0 }, { 25 ,2 }, { 30 ,1 }, { 31 ,3 },
+ { 72 ,0 }, { 73 ,2 }, { 6 ,1 }, { 7 ,3 }, { 96 ,0 }, { 97 ,2 },
+ { 12 ,0 }, { 13 ,2 }, { 102,1 }, { 103,3 }, { 60 ,0 }, { 61 ,2 },
+ { 66 ,1 }, { 67 ,3 }, { 90 ,1 }, { 91 ,3 }, { 36 ,0 }, { 37 ,2 },
+ { 42 ,1 }, { 43 ,3 }, { 18 ,1 }, { 19 ,3 }, { 84 ,0 }, { 85 ,2 },
+ { 108,0 }, { 109,2 }, { 2 ,0 }, { 3 ,2 }, { 80 ,1 }, { 81 ,3 },
+ { 50 ,0 }, { 51 ,2 }, { 56 ,1 }, { 57 ,3 }, { 26 ,0 }, { 27 ,2 },
+ { 32 ,1 }, { 33 ,3 }, { 74 ,0 }, { 75 ,2 }, { 8 ,1 }, { 9 ,3 },
+ { 98 ,0 }, { 99 ,2 }, { 14 ,0 }, { 15 ,2 }, { 104,1 }, { 105,3 },
+ { 62 ,0 }, { 63 ,2 }, { 68 ,1 }, { 69 ,3 }, { 92 ,1 }, { 93 ,3 },
+ { 38 ,0 }, { 39 ,2 }, { 44 ,1 }, { 45 ,3 }, { 20 ,1 }, { 21 ,3 },
+ { 86 ,0 }, { 87 ,2 }, { 110,0 }, { 111,2 }, { 4 ,0 }, { 5 ,2 },
+ { 82 ,1 }, { 83 ,3 }, { 52 ,0 }, { 53 ,2 }, { 58 ,1 }, { 59 ,3 },
+ { 28 ,0 }, { 29 ,2 }, { 34 ,1 }, { 35 ,3 }, { 76 ,0 }, { 77 ,2 },
+ { 10 ,1 }, { 12 ,3 }, { 100,0 }, { 101,2 }, { 16 ,0 }, { 17 ,2 },
+ { 106,1 }, { 107,3 }, { 64 ,0 }, { 65 ,2 }, { 70 ,1 }, { 71 ,3 },
+ { 94 ,1 }, { 95 ,3 }, { 40 ,0 }, { 41 ,2 }, { 46 ,1 }, { 47 ,3 },
+ { 22 ,1 }, { 23 ,3 }, { 88 ,0 }, { 89 ,2 }, { 112,0 }, { 113,2 },
+ { 6 ,0 }, { 7 ,2 }, { 84 ,1 }, { 85 ,3 }, { 54 ,0 }, { 55 ,2 },
+ { 60 ,1 }, { 61 ,3 }, { 30 ,0 }, { 31 ,2 }, { 36 ,1 }, { 37 ,3 },
+ { 78 ,0 }, { 79 ,2 }, { 12 ,1 }, { 13 ,3 }, { 102,0 }, { 103,2 },
+ { 18 ,0 }, { 19 ,2 }, { 108,1 }, { 109,3 }, { 66 ,0 }, { 67 ,2 },
+ { 72 ,1 }, { 73 ,3 }, { 96 ,1 }, { 97 ,3 }, { 42 ,0 }, { 43 ,2 },
+ { 48 ,1 }, { 49 ,3 }, { 24 ,1 }, { 25 ,3 }, { 90 ,0 }, { 91 ,2 },
+ { 0 ,1 }, { 1 ,3 }, { 8 ,0 }, { 9 ,2 }, { 86 ,1 }, { 87 ,3 },
+ { 56 ,0 }, { 57 ,2 }, { 62 ,1 }, { 63 ,3 }, { 32 ,0 }, { 33 ,2 },
+ { 38 ,1 }, { 39 ,3 }, { 80 ,0 }, { 81 ,2 }, { 14 ,1 }, { 15 ,3 },
+ { 104,0 }, { 105,2 }, { 20 ,0 }, { 21 ,2 }, { 110,1 }, { 111,3 },
+ { 68 ,0 }, { 69 ,2 }, { 74 ,1 }, { 75 ,3 }, { 98 ,1 }, { 99 ,3 },
+ { 44 ,0 }, { 45 ,2 }, { 50 ,1 }, { 51 ,3 }, { 26 ,1 }, { 27 ,3 },
+ { 92 ,0 }, { 93 ,2 }, { 2 ,1 }, { 3 ,3 }, { 10 ,0 }, { 11 ,2 },
+ { 88 ,1 }, { 89 ,3 }, { 58 ,0 }, { 59 ,2 }, { 64 ,1 }, { 65 ,3 },
+ { 34 ,0 }, { 35 ,2 }, { 40 ,1 }, { 41 ,3 }, { 82 ,0 }, { 83 ,2 },
+ { 16 ,1 }, { 17 ,3 }, { 106,0 }, { 107,2 }, { 22 ,0 }, { 23 ,2 },
+ { 112,1 }, { 113,3 }, { 70 ,0 }, { 71 ,2 }, { 76 ,1 }, { 77 ,3 },
+ { 100,1 }, { 101,3 }, { 46 ,0 }, { 47 ,2 }, { 52 ,1 }, { 53 ,3 },
+ { 28 ,1 }, { 29 ,3 }, { 94 ,0 }, { 95 ,2 }, { 4 ,1 }, { 5 ,3 },
+};
+
+/*
+ * 3GPP TS 05.03 5.1.9.1.2 "USF precoding"
+ */
+const ubit_t gsm0503_mcs5_usf_precode_table[8][36] = {
+ { 0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0, },
+ { 1,1,1,1,1,0,0,0,0, 1,1,1,1,0,0,0,0,0, 1,1,1,1,1,1,0,0,0, 1,1,1,1,1,0,0,0,1, },
+ { 1,1,1,0,0,1,1,1,0, 1,1,1,0,1,1,1,0,0, 1,1,0,0,0,0,1,1,0, 1,1,0,0,0,1,1,0,0, },
+ { 1,0,0,1,1,1,1,0,0, 1,1,0,0,0,0,0,1,1, 1,0,1,1,1,0,1,1,1, 0,0,1,0,0,1,1,1,1, },
+ { 0,0,0,1,1,0,0,1,1, 0,0,1,0,1,1,0,1,0, 1,0,0,0,0,1,1,0,1, 1,1,1,1,1,1,1,1,0, },
+ { 1,1,0,1,0,1,0,1,1, 0,0,0,1,1,0,1,0,1, 0,1,1,1,0,1,0,1,1, 1,0,0,1,0,1,0,1,1, },
+ { 0,0,1,0,0,1,1,0,1, 1,0,1,1,1,1,1,1,1, 0,1,1,0,1,0,0,0,1, 0,0,1,1,1,0,1,0,0, },
+ { 0,1,1,0,1,0,1,1,1, 0,1,0,1,0,1,1,1,1, 0,0,0,1,1,1,1,1,0, 0,1,0,0,1,0,0,1,1, },
+};
diff --git a/lib/decoding/osmocom/coding/gsm0503_tables.h b/lib/decoding/osmocom/coding/gsm0503_tables.h
new file mode 100644
index 0000000..4976c81
--- /dev/null
+++ b/lib/decoding/osmocom/coding/gsm0503_tables.h
@@ -0,0 +1,71 @@
+/*
+ * (C) 2013 by Andreas Eversberg <jolly@eversberg.eu>
+ * (C) 2016 by Tom Tsou <tom.tsou@ettus.com>
+ *
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#pragma once
+
+#include <stdint.h>
+#include <osmocom/core/bits.h>
+
+extern const ubit_t gsm0503_pdtch_hl_hn_ubit[4][8];
+extern const ubit_t gsm0503_pdtch_edge_hl_hn_ubit[3][8];
+extern const sbit_t gsm0503_pdtch_hl_hn_sbit[4][8];
+extern const sbit_t gsm0503_pdtch_edge_hl_hn_sbit[3][8];
+extern const ubit_t gsm0503_usf2six[8][6];
+extern const ubit_t gsm0503_usf2twelve_ubit[8][12];
+extern const sbit_t gsm0503_usf2twelve_sbit[8][12];
+extern const uint8_t gsm0503_puncture_cs2[588];
+extern const uint8_t gsm0503_puncture_cs3[676];
+extern const uint8_t gsm0503_puncture_mcs1_dl_hdr[108];
+extern const uint8_t gsm0503_puncture_mcs1_ul_hdr[117];
+extern const uint8_t gsm0503_puncture_mcs1_p1[588];
+extern const uint8_t gsm0503_puncture_mcs1_p2[588];
+extern const uint8_t gsm0503_puncture_mcs2_p1[732];
+extern const uint8_t gsm0503_puncture_mcs2_p2[732];
+extern const uint8_t gsm0503_puncture_mcs3_p1[948];
+extern const uint8_t gsm0503_puncture_mcs3_p2[948];
+extern const uint8_t gsm0503_puncture_mcs3_p3[948];
+extern const uint8_t gsm0503_puncture_mcs4_p1[1116];
+extern const uint8_t gsm0503_puncture_mcs4_p2[1116];
+extern const uint8_t gsm0503_puncture_mcs4_p3[1116];
+extern const uint8_t gsm0503_puncture_mcs5_p1[1404];
+extern const uint8_t gsm0503_puncture_mcs5_p2[1404];
+extern const uint8_t gsm0503_puncture_mcs6_p1[1836];
+extern const uint8_t gsm0503_puncture_mcs6_p2[1836];
+extern const uint8_t gsm0503_puncture_mcs7_dl_hdr[135];
+extern const uint8_t gsm0503_puncture_mcs7_ul_hdr[162];
+extern const uint8_t gsm0503_puncture_mcs7_p1[1404];
+extern const uint8_t gsm0503_puncture_mcs7_p2[1404];
+extern const uint8_t gsm0503_puncture_mcs7_p3[1404];
+extern const uint8_t gsm0503_puncture_mcs8_p1[1692];
+extern const uint8_t gsm0503_puncture_mcs8_p2[1692];
+extern const uint8_t gsm0503_puncture_mcs8_p3[1692];
+extern const uint8_t gsm0503_puncture_mcs9_p1[1836];
+extern const uint8_t gsm0503_puncture_mcs9_p2[1836];
+extern const uint8_t gsm0503_puncture_mcs9_p3[1836];
+extern const uint16_t gsm0503_interleave_mcs5[1248];
+extern const uint8_t gsm0503_gsm_fr_map[76];
+extern const uint8_t gsm0503_gsm_efr_protected_bits[65];
+extern const ubit_t gsm0503_afs_ic_ubit[4][8];
+extern const sbit_t gsm0503_afs_ic_sbit[4][8];
+extern const ubit_t gsm0503_ahs_ic_ubit[4][4];
+extern const sbit_t gsm0503_ahs_ic_sbit[4][4];
+extern const uint8_t gsm0503_tch_hr_interleaving[228][2];
+extern const ubit_t gsm0503_mcs5_usf_precode_table[8][36];
diff --git a/lib/decoding/sch.c b/lib/decoding/sch.c
new file mode 100644
index 0000000..6d2e3eb
--- /dev/null
+++ b/lib/decoding/sch.c
@@ -0,0 +1,132 @@
+/* -*- c++ -*- */
+/*
+ * @file
+ * @author (C) 2014 by Piotr Krysik <ptrkrysik@gmail.com>
+ * @section LICENSE
+ *
+ * Gr-gsm is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * Gr-gsm is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with gr-gsm; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <string.h>
+#include "gsm_constants.h"
+
+#include "osmocom/coding/gsm0503_coding.h"
+#include <osmocom/core/utils.h>
+
+static int ubits2sbits(ubit_t *ubits, sbit_t *sbits, int count)
+{
+ int i;
+
+ for (i = 0; i < count; i++) {
+ if (*ubits == 0x23) {
+ ubits++;
+ sbits++;
+ continue;
+ }
+ if ((*ubits++) & 1)
+ *sbits++ = -127;
+ else
+ *sbits++ = 127;
+ }
+
+ return count;
+}
+
+int decode_sch(const unsigned char *buf, int * t1_o, int * t2_o, int * t3_o, int * ncc_o, int * bcc_o)
+{
+
+ int t1, t2, t3p, t3, ncc, bcc;
+
+ uint8_t result[4];
+ ubit_t bursts_u[SCH_DATA_LEN*2];
+ sbit_t bursts_s[SCH_DATA_LEN*2];
+
+ // extract encoded data from synchronization burst
+ /* buf, 39 bit */
+ /* buf + 39 + 64 = 103, 39 */
+ memcpy(bursts_u, buf, SCH_DATA_LEN);
+ memcpy(bursts_u + SCH_DATA_LEN, buf + SCH_DATA_LEN + N_SYNC_BITS, SCH_DATA_LEN);
+
+ ubits2sbits(bursts_u, bursts_s, SCH_DATA_LEN*2);
+ if(gsm0503_sch_decode(result, bursts_s)==-1){
+ return 1;
+ }
+
+ // Synchronization channel information, 44.018 page 171. (V7.2.0)
+ uint8_t decoded_data[25];
+ osmo_pbit2ubit_ext(decoded_data, 0, result, 0, 25, 1);
+ ncc =
+ (decoded_data[ 7] << 2) |
+ (decoded_data[ 6] << 1) |
+ (decoded_data[ 5] << 0);
+ bcc =
+ (decoded_data[ 4] << 2) |
+ (decoded_data[ 3] << 1) |
+ (decoded_data[ 2] << 0);
+ t1 =
+ (decoded_data[ 1] << 10) |
+ (decoded_data[ 0] << 9) |
+ (decoded_data[15] << 8) |
+ (decoded_data[14] << 7) |
+ (decoded_data[13] << 6) |
+ (decoded_data[12] << 5) |
+ (decoded_data[11] << 4) |
+ (decoded_data[10] << 3) |
+ (decoded_data[ 9] << 2) |
+ (decoded_data[ 8] << 1) |
+ (decoded_data[23] << 0);
+ t2 =
+ (decoded_data[22] << 4) |
+ (decoded_data[21] << 3) |
+ (decoded_data[20] << 2) |
+ (decoded_data[19] << 1) |
+ (decoded_data[18] << 0);
+ t3p =
+ (decoded_data[17] << 2) |
+ (decoded_data[16] << 1) |
+ (decoded_data[24] << 0);
+
+ t3 = 10 * t3p + 1;
+
+ // modulo arithmetic t3 - t2 mod 26
+// tt = ((t3 + 26) - t2) % 26;
+
+// fn = (51 * 26 * t1) + (51 * tt) + t3;
+
+ /*
+ * BSIC: Base Station Identification Code
+ * BCC: Base station Color Code
+ * NCC: Network Color Code
+ *
+ * FN: Frame Number
+ */
+
+// printf("bsic: %x (bcc: %u; ncc: %u)\tFN: %u\n", bsic, bsic & 7,
+// (bsic >> 3) & 7, fn);
+
+// if (fn_o)
+// *fn_o = fn;
+// if (bsic_o)
+ if (t1_o && t2_o && t3_o && ncc_o && bcc_o) {
+ *t1_o = t1;
+ *t2_o = t2;
+ *t3_o = t3;
+ *bcc_o = bcc;
+ *ncc_o = ncc;
+ }
+
+ return 0;
+}
diff --git a/lib/decoding/tch_f_decoder_impl.cc b/lib/decoding/tch_f_decoder_impl.cc
index 41e5f53..1f22cf2 100644
--- a/lib/decoding/tch_f_decoder_impl.cc
+++ b/lib/decoding/tch_f_decoder_impl.cc
@@ -1,7 +1,8 @@
/* -*- c++ -*- */
/*
* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
+ * (C) 2017 by Piotr Krysik <ptrkrysik@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
@@ -29,11 +30,34 @@
#include "stdio.h"
#include "tch_f_decoder_impl.h"
+extern "C" {
+ #include "osmocom/coding/gsm0503_coding.h"
+}
+
#define DATA_BYTES 23
namespace gr {
namespace gsm {
+ static int ubits2sbits(ubit_t *ubits, sbit_t *sbits, int count)
+ {
+ int i;
+
+ for (i = 0; i < count; i++) {
+ if (*ubits == 0x23) {
+ ubits++;
+ sbits++;
+ continue;
+ }
+ if ((*ubits++) & 1)
+ *sbits++ = -127;
+ else
+ *sbits++ = 127;
+ }
+
+ return count;
+ }
+
tch_f_decoder::sptr
tch_f_decoder::make(tch_mode mode, bool boundary_check)
{
@@ -107,6 +131,7 @@
if (d_collected_bursts_num == 8)
{
+ ubit_t bursts_u[116 * 8];
d_collected_bursts_num = 0;
// reorganize data
@@ -115,6 +140,9 @@
pmt::pmt_t header_plus_burst = pmt::cdr(d_bursts[ii]);
int8_t * burst_bits = (int8_t *)(pmt::blob_data(header_plus_burst))+sizeof(gsmtap_hdr);
+ memcpy(&bursts_u[ii*116], &burst_bits[3],58);
+ memcpy(&bursts_u[ii*116+58], &burst_bits[3+57+1+26],58);
+
for (int jj = 0; jj < 57; jj++)
{
iBLOCK[ii*114+jj] = burst_bits[jj + 3];
@@ -271,23 +299,17 @@
if (good)
{
- unsigned char frameBuffer[33];
+ uint8_t frameBuffer[33];
+ sbit_t bursts_s[116 * 8];
+ int n_errors, n_bits_total;
unsigned int mTCHFrameLength;
+ ubits2sbits(bursts_u, bursts_s, 116 * 8);
if (d_tch_mode == TCH_FS) // GSM-FR
{
- unsigned char mFrameHeader = 0x0d;
mTCHFrameLength = 33;
-
- // Undo Um's importance-sorted bit ordering.
- // See GSM 05.03 3.1 and Table 2.
- BitVector frFrame(260 + 4); // FR has a frameheader of 4 bits only
- frFrame.fillField(0, mFrameHeader, 4);
- BitVector payload = frFrame.tail(4);
-
- mTCHD.unmap(GSM::g610BitOrder, 260, payload);
- frFrame.pack(frameBuffer);
-
+ gsm0503_tch_fr_decode(frameBuffer, bursts_s, 1, 0, &n_errors, &n_bits_total);
+ //std::cout << "Errors: " << n_errors << std::endl;
}
else if (d_tch_mode == TCH_EFR) // GSM-EFR
{
@@ -327,7 +349,8 @@
// Put the whole frame (hdr + payload)
mTCHFrameLength = 32;
amrFrame.pack(frameBuffer);
-
+ //when itegrating with libosmocore lines above can be removed and line below uncommented, efr decoding with libosmocore need to be tested however
+ //gsm0503_tch_fr_decode(frameBuffer, bursts_s, 1, 1, &n_errors, &n_bits_total);
}
message_port_pub(pmt::mp("voice"), pmt::cons(pmt::PMT_NIL, pmt::make_blob(frameBuffer,mTCHFrameLength)));
}
diff --git a/lib/decoding/tch_f_decoder_impl.h b/lib/decoding/tch_f_decoder_impl.h
index 0119b5a..cac245a 100644
--- a/lib/decoding/tch_f_decoder_impl.h
+++ b/lib/decoding/tch_f_decoder_impl.h
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
@@ -23,12 +23,12 @@
#ifndef INCLUDED_GSM_TCH_F_DECODER_IMPL_H
#define INCLUDED_GSM_TCH_F_DECODER_IMPL_H
-#include "AmrCoder.h"
-#include "BitVector.h"
-#include "GSM503Tables.h"
-#include "GSM610Tables.h"
-#include "GSM660Tables.h"
-#include "ViterbiR204.h"
+#include "openbts/AmrCoder.h"
+#include "openbts/BitVector.h"
+#include "openbts/GSM503Tables.h"
+#include "openbts/GSM610Tables.h"
+#include "openbts/GSM660Tables.h"
+#include "openbts/ViterbiR204.h"
#include <grgsm/decoding/tch_f_decoder.h>
diff --git a/lib/decryption/decryption_impl.cc b/lib/decryption/decryption_impl.cc
index 9e6112b..551afa4 100644
--- a/lib/decryption/decryption_impl.cc
+++ b/lib/decryption/decryption_impl.cc
@@ -1,19 +1,22 @@
/* -*- c++ -*- */
/*
- * Copyright 2014 <+YOU OR YOUR COMPANY+>.
+ * @file
+ * @author (C) 2014 by Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
+ * @section LICENSE
*
- * This is free software; you can redistribute it and/or modify
+ * Gr-gsm is free software; you can redistribute it and/or modify
* it under the 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 software is distributed in the hope that it will be useful,
+ * Gr-gsm is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 software; see the file COPYING. If not, write to
+ * along with gr-gsm; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
@@ -57,7 +60,6 @@
set_a5_version(a5_version);
validate_k_c();
-// std::cout << "Be careful with decryption block - it wasn't tested yet!" << std::endl;
message_port_register_in(pmt::mp("bursts"));
set_msg_handler(pmt::mp("bursts"), boost::bind(&decryption_impl::decrypt, this, _1));
message_port_register_out(pmt::mp("bursts"));
@@ -138,7 +140,7 @@
for (int i = 0; i < 3; i++) {
decrypted_data[i] = burst_binary[i];
}
- //encrypt first part of the burst
+ //decrypt first part of the burst
for (int i = 0; i < 57; i++) {
decrypted_data[i+3] = keystream[i] ^ burst_binary[i+3];
}
@@ -146,7 +148,7 @@
for (int i = 60; i < 88; i++) {
decrypted_data[i] = burst_binary[i];
}
- //encrypt second part of the burst
+ //decrypt second part of the burst
for (int i = 0; i < 57; i++) {
decrypted_data[i+88] = keystream[i+57] ^ burst_binary[i+88];
}
diff --git a/lib/decryption/decryption_impl.h b/lib/decryption/decryption_impl.h
index 68fbb9c..aa6e5ac 100644
--- a/lib/decryption/decryption_impl.h
+++ b/lib/decryption/decryption_impl.h
@@ -1,19 +1,21 @@
/* -*- c++ -*- */
/*
- * Copyright 2014 <+YOU OR YOUR COMPANY+>.
+ * @file
+ * @author (C) 2014 by Piotr Krysik <ptrkrysik@gmail.com>
+ * @section LICENSE
*
- * This is free software; you can redistribute it and/or modify
+ * Gr-gsm is free software; you can redistribute it and/or modify
* it under the 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 software is distributed in the hope that it will be useful,
+ * Gr-gsm is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR 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 software; see the file COPYING. If not, write to
+ * along with gr-gsm; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
diff --git a/lib/demapping/tch_f_chans_demapper_impl.cc b/lib/demapping/tch_f_chans_demapper_impl.cc
index 53f46fb..bf1ff8f 100644
--- a/lib/demapping/tch_f_chans_demapper_impl.cc
+++ b/lib/demapping/tch_f_chans_demapper_impl.cc
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/demapping/tch_f_chans_demapper_impl.h b/lib/demapping/tch_f_chans_demapper_impl.h
index 01c97fa..fe3bdf2 100644
--- a/lib/demapping/tch_f_chans_demapper_impl.h
+++ b/lib/demapping/tch_f_chans_demapper_impl.h
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/demapping/universal_ctrl_chans_demapper_impl.cc b/lib/demapping/universal_ctrl_chans_demapper_impl.cc
index dc1670d..98bcc9c 100644
--- a/lib/demapping/universal_ctrl_chans_demapper_impl.cc
+++ b/lib/demapping/universal_ctrl_chans_demapper_impl.cc
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2016 by Piotr Krysik <ptrkrysik@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/demapping/universal_ctrl_chans_demapper_impl.h b/lib/demapping/universal_ctrl_chans_demapper_impl.h
index 9545ab6..6ba4973 100644
--- a/lib/demapping/universal_ctrl_chans_demapper_impl.h
+++ b/lib/demapping/universal_ctrl_chans_demapper_impl.h
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2016 by Piotr Krysik <ptrkrysik@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/flow_control/burst_fnr_filter_impl.cc b/lib/flow_control/burst_fnr_filter_impl.cc
index 5d1ffbc..49ddc4c 100644
--- a/lib/flow_control/burst_fnr_filter_impl.cc
+++ b/lib/flow_control/burst_fnr_filter_impl.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/flow_control/burst_fnr_filter_impl.h b/lib/flow_control/burst_fnr_filter_impl.h
index 9d13825..5abd1c2 100644
--- a/lib/flow_control/burst_fnr_filter_impl.h
+++ b/lib/flow_control/burst_fnr_filter_impl.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/flow_control/burst_sdcch_subslot_filter_impl.cc b/lib/flow_control/burst_sdcch_subslot_filter_impl.cc
index 80e7c89..cc72f99 100644
--- a/lib/flow_control/burst_sdcch_subslot_filter_impl.cc
+++ b/lib/flow_control/burst_sdcch_subslot_filter_impl.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/flow_control/burst_sdcch_subslot_filter_impl.h b/lib/flow_control/burst_sdcch_subslot_filter_impl.h
index 85a392f..b5ac5ae 100644
--- a/lib/flow_control/burst_sdcch_subslot_filter_impl.h
+++ b/lib/flow_control/burst_sdcch_subslot_filter_impl.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/flow_control/burst_sdcch_subslot_splitter_impl.cc b/lib/flow_control/burst_sdcch_subslot_splitter_impl.cc
index 46177c1..267f6b4 100644
--- a/lib/flow_control/burst_sdcch_subslot_splitter_impl.cc
+++ b/lib/flow_control/burst_sdcch_subslot_splitter_impl.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/flow_control/burst_sdcch_subslot_splitter_impl.h b/lib/flow_control/burst_sdcch_subslot_splitter_impl.h
index 50aa028..9eac070 100644
--- a/lib/flow_control/burst_sdcch_subslot_splitter_impl.h
+++ b/lib/flow_control/burst_sdcch_subslot_splitter_impl.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/flow_control/burst_timeslot_filter_impl.cc b/lib/flow_control/burst_timeslot_filter_impl.cc
index c93bc60..4fcd847 100644
--- a/lib/flow_control/burst_timeslot_filter_impl.cc
+++ b/lib/flow_control/burst_timeslot_filter_impl.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/flow_control/burst_timeslot_filter_impl.h b/lib/flow_control/burst_timeslot_filter_impl.h
index fa54ef4..eb1953c 100644
--- a/lib/flow_control/burst_timeslot_filter_impl.h
+++ b/lib/flow_control/burst_timeslot_filter_impl.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/flow_control/burst_timeslot_splitter_impl.cc b/lib/flow_control/burst_timeslot_splitter_impl.cc
index 99964b7..1f1572c 100644
--- a/lib/flow_control/burst_timeslot_splitter_impl.cc
+++ b/lib/flow_control/burst_timeslot_splitter_impl.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/flow_control/burst_timeslot_splitter_impl.h b/lib/flow_control/burst_timeslot_splitter_impl.h
index 47a9115..6abcb00 100644
--- a/lib/flow_control/burst_timeslot_splitter_impl.h
+++ b/lib/flow_control/burst_timeslot_splitter_impl.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/flow_control/dummy_burst_filter_impl.cc b/lib/flow_control/dummy_burst_filter_impl.cc
index 4241111..4621187 100644
--- a/lib/flow_control/dummy_burst_filter_impl.cc
+++ b/lib/flow_control/dummy_burst_filter_impl.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/flow_control/dummy_burst_filter_impl.h b/lib/flow_control/dummy_burst_filter_impl.h
index 953ae94..3433313 100644
--- a/lib/flow_control/dummy_burst_filter_impl.h
+++ b/lib/flow_control/dummy_burst_filter_impl.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/flow_control/uplink_downlink_splitter_impl.cc b/lib/flow_control/uplink_downlink_splitter_impl.cc
index e98c668..691feb3 100644
--- a/lib/flow_control/uplink_downlink_splitter_impl.cc
+++ b/lib/flow_control/uplink_downlink_splitter_impl.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2016 by Piotr Krysik <ptrkrysik@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/flow_control/uplink_downlink_splitter_impl.h b/lib/flow_control/uplink_downlink_splitter_impl.h
index bc4368a..fb8b2b8 100644
--- a/lib/flow_control/uplink_downlink_splitter_impl.h
+++ b/lib/flow_control/uplink_downlink_splitter_impl.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2016 by Piotr Krysik <ptrkrysik@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/misc_utils/burst_file_sink_impl.cc b/lib/misc_utils/burst_file_sink_impl.cc
index 25a262e..9990d86 100644
--- a/lib/misc_utils/burst_file_sink_impl.cc
+++ b/lib/misc_utils/burst_file_sink_impl.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/misc_utils/burst_file_sink_impl.h b/lib/misc_utils/burst_file_sink_impl.h
index 898c609..3d8dbe4 100644
--- a/lib/misc_utils/burst_file_sink_impl.h
+++ b/lib/misc_utils/burst_file_sink_impl.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/misc_utils/burst_file_source_impl.cc b/lib/misc_utils/burst_file_source_impl.cc
index 4661dfb..4367150 100644
--- a/lib/misc_utils/burst_file_source_impl.cc
+++ b/lib/misc_utils/burst_file_source_impl.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/misc_utils/burst_file_source_impl.h b/lib/misc_utils/burst_file_source_impl.h
index 383dc90..8856520 100644
--- a/lib/misc_utils/burst_file_source_impl.h
+++ b/lib/misc_utils/burst_file_source_impl.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/misc_utils/bursts_printer_impl.cc b/lib/misc_utils/bursts_printer_impl.cc
index ab134aa..744d6ca 100644
--- a/lib/misc_utils/bursts_printer_impl.cc
+++ b/lib/misc_utils/bursts_printer_impl.cc
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2014 by Piotr Krysik <ptrkrysik@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/misc_utils/bursts_printer_impl.h b/lib/misc_utils/bursts_printer_impl.h
index e438c37..e475b0f 100644
--- a/lib/misc_utils/bursts_printer_impl.h
+++ b/lib/misc_utils/bursts_printer_impl.h
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2014 by Piotr Krysik <ptrkrysik@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/misc_utils/collect_system_info_impl.cc b/lib/misc_utils/collect_system_info_impl.cc
old mode 100755
new mode 100644
index 76b3288..2f46041
--- a/lib/misc_utils/collect_system_info_impl.cc
+++ b/lib/misc_utils/collect_system_info_impl.cc
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2017 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/misc_utils/collect_system_info_impl.h b/lib/misc_utils/collect_system_info_impl.h
old mode 100755
new mode 100644
index df017f6..b320b5e
--- a/lib/misc_utils/collect_system_info_impl.h
+++ b/lib/misc_utils/collect_system_info_impl.h
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2017 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/misc_utils/controlled_fractional_resampler_cc_impl.cc b/lib/misc_utils/controlled_fractional_resampler_cc_impl.cc
index cf15a04..3376c67 100644
--- a/lib/misc_utils/controlled_fractional_resampler_cc_impl.cc
+++ b/lib/misc_utils/controlled_fractional_resampler_cc_impl.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2016 by Piotr Krysik <ptrkrysik@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/misc_utils/controlled_fractional_resampler_cc_impl.h b/lib/misc_utils/controlled_fractional_resampler_cc_impl.h
index de32c34..24e00ed 100644
--- a/lib/misc_utils/controlled_fractional_resampler_cc_impl.h
+++ b/lib/misc_utils/controlled_fractional_resampler_cc_impl.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2016 by Piotr Krysik <ptrkrysik@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/misc_utils/controlled_rotator_cc_impl.cc b/lib/misc_utils/controlled_rotator_cc_impl.cc
index a91fd08..e5ead1c 100644
--- a/lib/misc_utils/controlled_rotator_cc_impl.cc
+++ b/lib/misc_utils/controlled_rotator_cc_impl.cc
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2014 by Piotr Krysik <ptrkrysik@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/misc_utils/controlled_rotator_cc_impl.h b/lib/misc_utils/controlled_rotator_cc_impl.h
index fb29356..13bc6fc 100644
--- a/lib/misc_utils/controlled_rotator_cc_impl.h
+++ b/lib/misc_utils/controlled_rotator_cc_impl.h
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2014 by Piotr Krysik <ptrkrysik@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/misc_utils/extract_cmc_impl.cc b/lib/misc_utils/extract_cmc_impl.cc
old mode 100755
new mode 100644
index 5fa6a6b..96e04d6
--- a/lib/misc_utils/extract_cmc_impl.cc
+++ b/lib/misc_utils/extract_cmc_impl.cc
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2016 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/misc_utils/extract_cmc_impl.h b/lib/misc_utils/extract_cmc_impl.h
old mode 100755
new mode 100644
index fe03bc8..b62cadc
--- a/lib/misc_utils/extract_cmc_impl.h
+++ b/lib/misc_utils/extract_cmc_impl.h
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2016 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/misc_utils/extract_immediate_assignment_impl.cc b/lib/misc_utils/extract_immediate_assignment_impl.cc
index 75a1edf..125b7e8 100644
--- a/lib/misc_utils/extract_immediate_assignment_impl.cc
+++ b/lib/misc_utils/extract_immediate_assignment_impl.cc
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/misc_utils/extract_immediate_assignment_impl.h b/lib/misc_utils/extract_immediate_assignment_impl.h
index cf007e2..44a3830 100644
--- a/lib/misc_utils/extract_immediate_assignment_impl.h
+++ b/lib/misc_utils/extract_immediate_assignment_impl.h
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/misc_utils/extract_system_info_impl.cc b/lib/misc_utils/extract_system_info_impl.cc
index b406418..2de544e 100644
--- a/lib/misc_utils/extract_system_info_impl.cc
+++ b/lib/misc_utils/extract_system_info_impl.cc
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2014 by Piotr Krysik <ptrkrysik@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/misc_utils/extract_system_info_impl.h b/lib/misc_utils/extract_system_info_impl.h
index 20f5adc..2ddc84d 100644
--- a/lib/misc_utils/extract_system_info_impl.h
+++ b/lib/misc_utils/extract_system_info_impl.h
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2014 by Piotr Krysik <ptrkrysik@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/misc_utils/message_file_sink_impl.cc b/lib/misc_utils/message_file_sink_impl.cc
index 7e52993..7857e6b 100644
--- a/lib/misc_utils/message_file_sink_impl.cc
+++ b/lib/misc_utils/message_file_sink_impl.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/misc_utils/message_file_sink_impl.h b/lib/misc_utils/message_file_sink_impl.h
index 6757e69..9f05a0b 100644
--- a/lib/misc_utils/message_file_sink_impl.h
+++ b/lib/misc_utils/message_file_sink_impl.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/misc_utils/message_file_source_impl.cc b/lib/misc_utils/message_file_source_impl.cc
index 540fe9e..8164f92 100644
--- a/lib/misc_utils/message_file_source_impl.cc
+++ b/lib/misc_utils/message_file_source_impl.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/misc_utils/message_file_source_impl.h b/lib/misc_utils/message_file_source_impl.h
index 42f65cb..312174d 100644
--- a/lib/misc_utils/message_file_source_impl.h
+++ b/lib/misc_utils/message_file_source_impl.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/misc_utils/message_printer_impl.cc b/lib/misc_utils/message_printer_impl.cc
index 7d19830..e8aa2d3 100644
--- a/lib/misc_utils/message_printer_impl.cc
+++ b/lib/misc_utils/message_printer_impl.cc
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2014 by Piotr Krysik <ptrkrysik@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/misc_utils/message_printer_impl.h b/lib/misc_utils/message_printer_impl.h
index 86d27d7..8fdcdfd 100644
--- a/lib/misc_utils/message_printer_impl.h
+++ b/lib/misc_utils/message_printer_impl.h
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2014 by Piotr Krysik <ptrkrysik@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/misc_utils/msg_to_tag_impl.cc b/lib/misc_utils/msg_to_tag_impl.cc
index e572864..0ab65e7 100644
--- a/lib/misc_utils/msg_to_tag_impl.cc
+++ b/lib/misc_utils/msg_to_tag_impl.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2016 by Piotr Krysik <ptrkrysik@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/misc_utils/msg_to_tag_impl.h b/lib/misc_utils/msg_to_tag_impl.h
index 4af794c..39c6ca3 100644
--- a/lib/misc_utils/msg_to_tag_impl.h
+++ b/lib/misc_utils/msg_to_tag_impl.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2016 by Piotr Krysik <ptrkrysik@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/misc_utils/tmsi_dumper_impl.cc b/lib/misc_utils/tmsi_dumper_impl.cc
index e53aad3..043d935 100644
--- a/lib/misc_utils/tmsi_dumper_impl.cc
+++ b/lib/misc_utils/tmsi_dumper_impl.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2015 by Piotr Krysik <ptrkrysik@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/misc_utils/tmsi_dumper_impl.h b/lib/misc_utils/tmsi_dumper_impl.h
index 8b5a038..3019587 100644
--- a/lib/misc_utils/tmsi_dumper_impl.h
+++ b/lib/misc_utils/tmsi_dumper_impl.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2015 by Piotr Krysik <ptrkrysik@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/qa_utils/burst_sink_impl.cc b/lib/qa_utils/burst_sink_impl.cc
index 5f1ae64..102c5be 100644
--- a/lib/qa_utils/burst_sink_impl.cc
+++ b/lib/qa_utils/burst_sink_impl.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/qa_utils/burst_sink_impl.h b/lib/qa_utils/burst_sink_impl.h
index 42e1e4a..1035430 100644
--- a/lib/qa_utils/burst_sink_impl.h
+++ b/lib/qa_utils/burst_sink_impl.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/qa_utils/burst_source_impl.cc b/lib/qa_utils/burst_source_impl.cc
index 7391872..db3d85a 100644
--- a/lib/qa_utils/burst_source_impl.cc
+++ b/lib/qa_utils/burst_source_impl.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/qa_utils/burst_source_impl.h b/lib/qa_utils/burst_source_impl.h
index 969faf9..cc7d9b4 100644
--- a/lib/qa_utils/burst_source_impl.h
+++ b/lib/qa_utils/burst_source_impl.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/qa_utils/message_sink_impl.cc b/lib/qa_utils/message_sink_impl.cc
index 269cada..c16f133 100644
--- a/lib/qa_utils/message_sink_impl.cc
+++ b/lib/qa_utils/message_sink_impl.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/qa_utils/message_sink_impl.h b/lib/qa_utils/message_sink_impl.h
index dd11819..b7458af 100644
--- a/lib/qa_utils/message_sink_impl.h
+++ b/lib/qa_utils/message_sink_impl.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/qa_utils/message_source_impl.cc b/lib/qa_utils/message_source_impl.cc
index 2e71ba4..a2f28d1 100644
--- a/lib/qa_utils/message_source_impl.cc
+++ b/lib/qa_utils/message_source_impl.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/qa_utils/message_source_impl.h b/lib/qa_utils/message_source_impl.h
index 9856f78..b5ffdcb 100644
--- a/lib/qa_utils/message_source_impl.h
+++ b/lib/qa_utils/message_source_impl.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Roman Khassraf <rkhassraf@gmail.com>
+ * @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/receiver/clock_offset_control_impl.cc b/lib/receiver/clock_offset_control_impl.cc
index 4115707..868cbc2 100644
--- a/lib/receiver/clock_offset_control_impl.cc
+++ b/lib/receiver/clock_offset_control_impl.cc
@@ -1,8 +1,7 @@
-
/* -*- c++ -*- */
/*
* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2015-2017 Piotr Krysik <ptrkrysik@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/receiver/clock_offset_control_impl.h b/lib/receiver/clock_offset_control_impl.h
index 60c3df6..fc90f45 100644
--- a/lib/receiver/clock_offset_control_impl.h
+++ b/lib/receiver/clock_offset_control_impl.h
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2015-2017 by Piotr Krysik <ptrkrysik@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/receiver/cx_channel_hopper_impl.cc b/lib/receiver/cx_channel_hopper_impl.cc
index 27a0cae..e5be27a 100644
--- a/lib/receiver/cx_channel_hopper_impl.cc
+++ b/lib/receiver/cx_channel_hopper_impl.cc
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2015 by Pieter Robyns <pieter.robyns@uhasselt.be>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/receiver/cx_channel_hopper_impl.h b/lib/receiver/cx_channel_hopper_impl.h
index 2e630db..7ac9bf4 100644
--- a/lib/receiver/cx_channel_hopper_impl.h
+++ b/lib/receiver/cx_channel_hopper_impl.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2015 by Pieter Robyns <pieter.robyns@uhasselt.be>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/receiver/gsm_constants.h b/lib/receiver/gsm_constants.h
index 131d923..9052290 100644
--- a/lib/receiver/gsm_constants.h
+++ b/lib/receiver/gsm_constants.h
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2014 by Piotr Krysik <ptrkrysik@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/receiver/receiver_config.cc b/lib/receiver/receiver_config.cc
index 44e3b6c..b5745ed 100644
--- a/lib/receiver/receiver_config.cc
+++ b/lib/receiver/receiver_config.cc
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2009-2017 by Piotr Krysik <ptrkrysik@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/receiver/receiver_config.h b/lib/receiver/receiver_config.h
index 17b98c8..f68e3f6 100644
--- a/lib/receiver/receiver_config.h
+++ b/lib/receiver/receiver_config.h
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2009-2017 by Piotr Krysik <ptrkrysik@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/receiver/receiver_impl.cc b/lib/receiver/receiver_impl.cc
index e69183f..b7c5be2 100644
--- a/lib/receiver/receiver_impl.cc
+++ b/lib/receiver/receiver_impl.cc
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2009-2017 by Piotr Krysik <ptrkrysik@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
@@ -26,884 +26,1073 @@
#include <gnuradio/io_signature.h>
#include <gnuradio/math.h>
-#include <math.h>
-#include <boost/circular_buffer.hpp>
+
#include <algorithm>
-#include <numeric>
-#include <vector>
-#include <viterbi_detector.h>
#include <string.h>
#include <iostream>
-//#include <iomanip>
-#include <boost/scoped_ptr.hpp>
+#include <numeric>
+#include <math.h>
+#include <vector>
-#include <sch.h>
-#include "receiver_impl.h"
+#include <boost/circular_buffer.hpp>
+#include <boost/scoped_ptr.hpp>
#include <grgsm/endian.h>
-//files included for debuging
-//#include "plotting/plotting.hpp"
-//#include <pthread.h>
+#include "receiver_impl.h"
+#include "viterbi_detector.h"
+#include "sch.h"
+
+#if 0
+/* Files included for debuging */
+#include "plotting/plotting.hpp"
+#include <pthread.h>
+#include <iomanip>
+#endif
#define SYNC_SEARCH_RANGE 30
namespace gr
{
-namespace gsm
-{
-receiver::sptr
-receiver::make(int osr, const std::vector<int> &cell_allocation, const std::vector<int> &tseq_nums, bool process_uplink)
-{
- return gnuradio::get_initial_sptr
- (new receiver_impl(osr, cell_allocation, tseq_nums, process_uplink));
-}
+ namespace gsm
+ {
-/*
- * The private constructor
- */
-receiver_impl::receiver_impl(int osr, const std::vector<int> &cell_allocation, const std::vector<int> &tseq_nums, bool process_uplink)
- : gr::sync_block("receiver",
- gr::io_signature::make(1, -1, sizeof(gr_complex)),
- gr::io_signature::make(0, 0, 0)),
- d_OSR(osr),
- d_process_uplink(process_uplink),
- d_chan_imp_length(CHAN_IMP_RESP_LENGTH),
- d_counter(0),
- d_fcch_start_pos(0),
- d_freq_offset_setting(0),
- d_state(fcch_search),
- d_burst_nr(osr),
- d_failed_sch(0),
- d_signal_dbm(-120),
- d_tseq_nums(tseq_nums),
- d_cell_allocation(cell_allocation),
- d_last_time(0.0)
-{
- int i;
- //don't send samples to the receiver until there are at least samples for one
- set_output_multiple(floor((TS_BITS + 2 * GUARD_PERIOD) * d_OSR)); // burst and two gurad periods (one gurard period is an arbitrary overlap)
- gmsk_mapper(SYNC_BITS, N_SYNC_BITS, d_sch_training_seq, gr_complex(0.0, -1.0));
- for (i = 0; i < TRAIN_SEQ_NUM; i++)
+ /* The public constructor */
+ receiver::sptr
+ receiver::make(
+ int osr, const std::vector<int> &cell_allocation,
+ const std::vector<int> &tseq_nums, bool process_uplink)
{
- gr_complex startpoint = (train_seq[i][0]==0) ? gr_complex(1.0, 0.0) : gr_complex(-1.0, 0.0); //if first bit of the seqeunce ==0 first symbol ==1
- //if first bit of the seqeunce ==1 first symbol ==-1
- gmsk_mapper(train_seq[i], N_TRAIN_BITS, d_norm_training_seq[i], startpoint);
+ return gnuradio::get_initial_sptr
+ (new receiver_impl(osr, cell_allocation,
+ tseq_nums, process_uplink));
}
- message_port_register_out(pmt::mp("C0"));
- message_port_register_out(pmt::mp("CX"));
- message_port_register_out(pmt::mp("measurements"));
- configure_receiver(); //configure the receiver - tell it where to find which burst type
-}
-/*
- * Our virtual destructor.
- */
-receiver_impl::~receiver_impl()
-{
-}
-
-int
-receiver_impl::work(int noutput_items,
- gr_vector_const_void_star &input_items,
- gr_vector_void_star &output_items)
-{
-// std::vector<const gr_complex *> iii = (std::vector<const gr_complex *>) input_items; // jak zrobić to rzutowanie poprawnie
- gr_complex * input = (gr_complex *) input_items[0];
- std::vector<tag_t> freq_offset_tags;
- uint64_t start = nitems_read(0);
- uint64_t stop = start + noutput_items;
-
- float current_time = static_cast<float>(start)/(GSM_SYMBOL_RATE*d_OSR);
- if((current_time - d_last_time) > 0.1)
+ /* The private constructor */
+ receiver_impl::receiver_impl(
+ int osr, const std::vector<int> &cell_allocation,
+ const std::vector<int> &tseq_nums, bool process_uplink
+ ) : gr::sync_block("receiver",
+ gr::io_signature::make(1, -1, sizeof(gr_complex)),
+ gr::io_signature::make(0, 0, 0)),
+ d_OSR(osr),
+ d_process_uplink(process_uplink),
+ d_chan_imp_length(CHAN_IMP_RESP_LENGTH),
+ d_counter(0),
+ d_fcch_start_pos(0),
+ d_freq_offset_setting(0),
+ d_state(fcch_search),
+ d_burst_nr(osr),
+ d_failed_sch(0),
+ d_signal_dbm(-120),
+ d_tseq_nums(tseq_nums),
+ d_cell_allocation(cell_allocation),
+ d_last_time(0.0)
{
- pmt::pmt_t msg = pmt::make_tuple(pmt::mp("current_time"),pmt::from_double(current_time));
+ /**
+ * Don't send samples to the receiver
+ * until there are at least samples for one
+ */
+ set_output_multiple(floor((TS_BITS + 2 * GUARD_PERIOD) * d_OSR));
+
+ /**
+ * Prepare SCH sequence bits
+ *
+ * (TS_BITS + 2 * GUARD_PERIOD)
+ * Burst and two guard periods
+ * (one guard period is an arbitrary overlap)
+ */
+ gmsk_mapper(SYNC_BITS, N_SYNC_BITS,
+ d_sch_training_seq, gr_complex(0.0, -1.0));
+
+ /* Prepare bits of training sequences */
+ for (int i = 0; i < TRAIN_SEQ_NUM; i++) {
+ /**
+ * If first bit of the sequence is 0
+ * => first symbol is 1, else -1
+ */
+ gr_complex startpoint = train_seq[i][0] == 0 ?
+ gr_complex(1.0, 0.0) : gr_complex(-1.0, 0.0);
+ gmsk_mapper(train_seq[i], N_TRAIN_BITS,
+ d_norm_training_seq[i], startpoint);
+ }
+
+ /* Register output ports */
+ message_port_register_out(pmt::mp("C0"));
+ message_port_register_out(pmt::mp("CX"));
+ message_port_register_out(pmt::mp("measurements"));
+
+ /**
+ * Configure the receiver,
+ * i.e. tell it where to find which burst type
+ */
+ configure_receiver();
+ }
+
+ /* Our virtual destructor */
+ receiver_impl::~receiver_impl() {}
+
+ int
+ receiver_impl::work(
+ int noutput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+ {
+ gr_complex *input = (gr_complex *) input_items[0];
+ uint64_t start = nitems_read(0);
+ uint64_t stop = start + noutput_items;
+ d_freq_offset_tag_in_fcch = false;
+
+#if 0
+ /* FIXME: jak zrobić to rzutowanie poprawnie */
+ std::vector<const gr_complex *> iii =
+ (std::vector<const gr_complex *>) input_items;
+#endif
+
+ /* Time synchronization loop */
+ float current_time =
+ static_cast<float>(start / (GSM_SYMBOL_RATE * d_OSR));
+ if ((current_time - d_last_time) > 0.1) {
+ pmt::pmt_t msg = pmt::make_tuple(pmt::mp("current_time"),
+ pmt::from_double(current_time));
message_port_pub(pmt::mp("measurements"), msg);
d_last_time = current_time;
- }
+ }
- pmt::pmt_t key = pmt::string_to_symbol("setting_freq_offset");
- get_tags_in_range(freq_offset_tags, 0, start, stop, key);
- bool freq_offset_tag_in_fcch = false;
-
- if(!freq_offset_tags.empty()){
+ /* Frequency correction loop */
+ std::vector<tag_t> freq_offset_tags;
+ pmt::pmt_t key = pmt::string_to_symbol("setting_freq_offset");
+ get_tags_in_range(freq_offset_tags, 0, start, stop, key);
+
+ if (!freq_offset_tags.empty()) {
tag_t freq_offset_tag = freq_offset_tags[0];
uint64_t tag_offset = freq_offset_tag.offset - start;
-
- burst_type b_type = d_channel_conf.get_burst_type(d_burst_nr);
- if(d_state == synchronized && b_type == fcch_burst){
- uint64_t last_sample_nr = ceil((GUARD_PERIOD + 2.0 * TAIL_BITS + 156.25) * d_OSR) + 1;
- if(tag_offset < last_sample_nr){
- freq_offset_tag_in_fcch = true;
- }
- }
d_freq_offset_setting = pmt::to_double(freq_offset_tag.value);
- }
-
- switch (d_state)
- {
- //bootstrapping
- case fcch_search:
- {
- double freq_offset_tmp;
- if (find_fcch_burst(input, noutput_items,freq_offset_tmp))
- {
- pmt::pmt_t msg = pmt::make_tuple(pmt::mp("freq_offset"),pmt::from_double(freq_offset_tmp-d_freq_offset_setting),pmt::mp("fcch_search"));
- message_port_pub(pmt::mp("measurements"), msg);
- d_state = sch_search;
+ burst_type b_type = d_channel_conf.get_burst_type(d_burst_nr);
+ if (d_state == synchronized && b_type == fcch_burst){
+ uint64_t last_sample_nr =
+ ceil((GUARD_PERIOD + 2.0 * TAIL_BITS + 156.25) * d_OSR) + 1;
+ d_freq_offset_tag_in_fcch = tag_offset < last_sample_nr;
}
- else
- {
- d_state = fcch_search;
- }
+ }
+
+ /* Main state machine */
+ switch (d_state) {
+ case fcch_search:
+ fcch_search_handler(input, noutput_items);
break;
- }
-
- case sch_search:
- {
- std::vector<gr_complex> channel_imp_resp(CHAN_IMP_RESP_LENGTH*d_OSR);
- int t1, t2, t3;
- int burst_start = 0;
- unsigned char output_binary[BURST_SIZE];
-
- if (reach_sch_burst(noutput_items)) //wait for a SCH burst
- {
- burst_start = get_sch_chan_imp_resp(input, &channel_imp_resp[0]); //get channel impulse response from it
- detect_burst(input, &channel_imp_resp[0], burst_start, output_binary); //detect bits using MLSE detection
- if (decode_sch(&output_binary[3], &t1, &t2, &t3, &d_ncc, &d_bcc) == 0) //decode SCH burst
- {
- d_burst_nr.set(t1, t2, t3, 0); //set counter of bursts value
- d_burst_nr++;
-
- consume_each(burst_start + BURST_SIZE * d_OSR + 4*d_OSR); //consume samples up to next guard period
- d_state = synchronized;
- }
- else
- {
- d_state = fcch_search; //if there is error in the sch burst go back to fcch search phase
- }
- }
- else
- {
- d_state = sch_search;
- }
+ case sch_search:
+ sch_search_handler(input, noutput_items);
break;
+ case synchronized:
+ synchronized_handler(input, input_items, noutput_items);
+ break;
+ }
+
+ return 0;
}
- //in this state receiver is synchronized and it processes bursts according to burst type for given burst number
- case synchronized:
+
+ void
+ receiver_impl::fcch_search_handler(gr_complex *input, int noutput_items)
{
- std::vector<gr_complex> channel_imp_resp(CHAN_IMP_RESP_LENGTH*d_OSR);
- int offset = 0;
- int to_consume = 0;
- unsigned char output_binary[BURST_SIZE];
- burst_type b_type;
- unsigned int inputs_to_process=d_cell_allocation.size();
-
- if(d_process_uplink)
- {
- inputs_to_process = 2*inputs_to_process;
- }
-
- for(int input_nr=0; input_nr<inputs_to_process; input_nr++)
- {
- double signal_pwr = 0;
- input = (gr_complex *)input_items[input_nr];
-
- for(int ii=GUARD_PERIOD;ii<TS_BITS;ii++)
- {
- signal_pwr += abs(input[ii])*abs(input[ii]);
- }
- signal_pwr = signal_pwr/(TS_BITS);
- d_signal_dbm = round(10*log10(signal_pwr/50));
- if(input_nr==0){
- d_c0_signal_dbm = d_signal_dbm;
- }
-
- if(input_nr==0) //for c0 channel burst type is controlled by channel configuration
- {
- b_type = d_channel_conf.get_burst_type(d_burst_nr); //get burst type for given burst number
- }
- else
- {
- b_type = normal_or_noise; //for the rest it can be only normal burst or noise (at least at this moment of development)
- }
-
- switch (b_type)
- {
- case fcch_burst: //if it's FCCH burst
- {
- if(freq_offset_tag_in_fcch==false)
- {
- const unsigned first_sample = ceil((GUARD_PERIOD + 2 * TAIL_BITS) * d_OSR) + 1;
- const unsigned last_sample = first_sample + USEFUL_BITS * d_OSR - TAIL_BITS * d_OSR;
- double freq_offset_tmp = compute_freq_offset(input, first_sample, last_sample); //extract frequency offset from it
- send_burst(d_burst_nr, fc_fb, GSMTAP_BURST_FCCH, input_nr);
+ double freq_offset_tmp;
- pmt::pmt_t msg = pmt::make_tuple(pmt::mp("freq_offset"),pmt::from_double(freq_offset_tmp-d_freq_offset_setting),pmt::mp("synchronized"));
- message_port_pub(pmt::mp("measurements"), msg);
- }
- break;
- }
- case sch_burst: //if it's SCH burst
- {
- int t1, t2, t3, d_ncc, d_bcc;
- d_c0_burst_start = get_sch_chan_imp_resp(input, &channel_imp_resp[0]); //get channel impulse response
-
- detect_burst(input, &channel_imp_resp[0], d_c0_burst_start, output_binary); //MLSE detection of bits
- send_burst(d_burst_nr, output_binary, GSMTAP_BURST_SCH, input_nr);
- if (decode_sch(&output_binary[3], &t1, &t2, &t3, &d_ncc, &d_bcc) == 0) //and decode SCH data
- {
- // d_burst_nr.set(t1, t2, t3, 0); //but only to check if burst_start value is correct
- d_failed_sch = 0;
- offset = d_c0_burst_start - floor((GUARD_PERIOD) * d_OSR); //compute offset from burst_start - burst should start after a guard period
- to_consume += offset; //adjust with offset number of samples to be consumed
- }
- else
- {
- d_failed_sch++;
- if (d_failed_sch >= MAX_SCH_ERRORS)
- {
- d_state = fcch_search;
- pmt::pmt_t msg = pmt::make_tuple(pmt::mp("freq_offset"),pmt::from_double(0.0),pmt::mp("sync_loss"));
- message_port_pub(pmt::mp("measurements"), msg);
- //DCOUT("Re-Synchronization!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
- }
- }
- break;
- }
- case normal_burst:
- {
- float normal_corr_max; //if it's normal burst
- d_c0_burst_start = get_norm_chan_imp_resp(input, &channel_imp_resp[0], &normal_corr_max, d_bcc); //get channel impulse response for given training sequence number - d_bcc
- detect_burst(input, &channel_imp_resp[0], d_c0_burst_start, output_binary); //MLSE detection of bits
- send_burst(d_burst_nr, output_binary, GSMTAP_BURST_NORMAL, input_nr);
- break;
- }
- case dummy_or_normal:
- {
- unsigned int normal_burst_start, dummy_burst_start;
- float dummy_corr_max, normal_corr_max;
+ /* Check if received samples is a FCCN burst */
+ if (!find_fcch_burst(input, noutput_items, freq_offset_tmp))
+ return;
- dummy_burst_start = get_norm_chan_imp_resp(input, &channel_imp_resp[0], &dummy_corr_max, TS_DUMMY);
- normal_burst_start = get_norm_chan_imp_resp(input, &channel_imp_resp[0], &normal_corr_max, d_bcc);
+ /* We found it, compose a message */
+ pmt::pmt_t msg = pmt::make_tuple(
+ pmt::mp("freq_offset"),
+ pmt::from_double(freq_offset_tmp - d_freq_offset_setting),
+ pmt::mp("fcch_search")
+ );
- if (normal_corr_max > dummy_corr_max)
- {
- d_c0_burst_start = normal_burst_start;
- detect_burst(input, &channel_imp_resp[0], normal_burst_start, output_binary);
- send_burst(d_burst_nr, output_binary, GSMTAP_BURST_NORMAL, input_nr);
- }
- else
- {
- d_c0_burst_start = dummy_burst_start;
- send_burst(d_burst_nr, dummy_burst, GSMTAP_BURST_DUMMY, input_nr);
- }
- break;
- }
- case rach_burst:
- break;
- case dummy:
- send_burst(d_burst_nr, dummy_burst, GSMTAP_BURST_DUMMY, input_nr);
- break;
- case normal_or_noise:
- {
- unsigned int burst_start;
- float normal_corr_max_tmp;
- float normal_corr_max=-1e6;
- int max_tn;
- std::vector<gr_complex> v(input, input + noutput_items);
- //if(d_signal_dbm>=d_c0_signal_dbm-13)
- {
- if(d_tseq_nums.size()==0) //there is no information about training sequence
- { //however the receiver can detect it
- get_norm_chan_imp_resp(input, &channel_imp_resp[0], &normal_corr_max, 0);
- float ts_max=normal_corr_max; //with use of a very simple algorithm based on finding
- int ts_max_num=0; //maximum correlation
- for(int ss=1; ss<=7; ss++)
- {
- get_norm_chan_imp_resp(input, &channel_imp_resp[0], &normal_corr_max, ss);
- if(ts_max<normal_corr_max)
- {
- ts_max = normal_corr_max;
- ts_max_num = ss;
- }
- }
- d_tseq_nums.push_back(ts_max_num);
- }
- int tseq_num;
- if(input_nr<=d_tseq_nums.size())
- {
- tseq_num = d_tseq_nums[input_nr-1];
- } else
- {
- tseq_num = d_tseq_nums.back();
- }
- burst_start = get_norm_chan_imp_resp(input, &channel_imp_resp[0], &normal_corr_max, tseq_num);
-// if(abs(d_c0_burst_start-burst_start)<=2){ //unused check/filter based on timing
- // if((normal_corr_max/sqrt(signal_pwr))>=0.9)
- {
- detect_burst(input, &channel_imp_resp[0], burst_start, output_binary);
- send_burst(d_burst_nr, output_binary, GSMTAP_BURST_NORMAL, input_nr);
- }
- }
- break;
- }
- case empty: //if it's empty burst
- break; //do nothing
- }
-
- if(input_nr==input_items.size()-1)
- {
- d_burst_nr++; //go to next burst
- to_consume += TS_BITS * d_OSR + d_burst_nr.get_offset(); //consume samples of the burst up to next guard period
- consume_each(to_consume);
- }
- //and add offset which is introduced by
- //0.25 fractional part of a guard period
- }
+ /* Notify FCCH loop */
+ message_port_pub(pmt::mp("measurements"), msg);
+
+ /* Update current state */
+ d_state = sch_search;
}
- break;
+
+ void
+ receiver_impl::sch_search_handler(gr_complex *input, int noutput_items)
+ {
+ std::vector<gr_complex> channel_imp_resp(CHAN_IMP_RESP_LENGTH * d_OSR);
+ unsigned char burst_buf[BURST_SIZE];
+ int rc, t1, t2, t3;
+ int burst_start;
+
+ /* Wait until we get a SCH burst */
+ if (!reach_sch_burst(noutput_items))
+ return;
+
+ /* Get channel impulse response from it */
+ burst_start = get_sch_chan_imp_resp(input, &channel_imp_resp[0]);
+
+ /* Detect bits using MLSE detection */
+ detect_burst(input, &channel_imp_resp[0], burst_start, burst_buf);
+
+ /* Attempt to decode BSIC and frame number */
+ rc = decode_sch(&burst_buf[3], &t1, &t2, &t3, &d_ncc, &d_bcc);
+ if (rc) {
+ /**
+ * There is error in the SCH burst,
+ * go back to the FCCH search state
+ */
+ d_state = fcch_search;
+ return;
+ }
+
+ /* Set counter of bursts value */
+ d_burst_nr.set(t1, t2, t3, 0);
+ d_burst_nr++;
+
+ /* Consume samples up to the next guard period */
+ consume_each(burst_start + BURST_SIZE * d_OSR + 4 * d_OSR);
+
+ /* Update current state */
+ d_state = synchronized;
}
- return 0;
-}
-bool receiver_impl::find_fcch_burst(const gr_complex *input, const int nitems, double & computed_freq_offset)
-{
- boost::circular_buffer<float> phase_diff_buffer(FCCH_HITS_NEEDED * d_OSR); //circular buffer used to scan throug signal to find
- //best match for FCCH burst
- float phase_diff = 0;
- gr_complex conjprod;
- int start_pos = -1;
- int hit_count = 0;
- int miss_count = 0;
- float min_phase_diff;
- float max_phase_diff;
- double best_sum = 0;
- float lowest_max_min_diff = 99999;
-
- int to_consume = 0;
- int sample_number = 0;
- bool end = false;
- bool result = false;
- boost::circular_buffer<float>::iterator buffer_iter;
-
- /**@name Possible states of FCCH search algorithm*/
- //@{
- enum states
+ void
+ receiver_impl::synchronized_handler(gr_complex *input,
+ gr_vector_const_void_star &input_items, int noutput_items)
{
- init, ///< initialize variables
- search, ///< search for positive samples
- found_something, ///< search for FCCH and the best position of it
- fcch_found, ///< when FCCH was found
- search_fail ///< when there is no FCCH in the input vector
- } fcch_search_state;
- //@}
+ /**
+ * In this state receiver is synchronized and it processes
+ * bursts according to burst type for given burst number
+ */
+ std::vector<gr_complex> channel_imp_resp(CHAN_IMP_RESP_LENGTH * d_OSR);
+ unsigned int inputs_to_process = d_cell_allocation.size();
+ unsigned char output_binary[BURST_SIZE];
+ burst_type b_type;
+ int to_consume = 0;
+ int offset = 0;
- fcch_search_state = init;
+ if (d_process_uplink)
+ inputs_to_process *= 2;
- while (!end)
- {
- switch (fcch_search_state)
+ /* Process all connected inputs */
+ for (int input_nr = 0; input_nr < inputs_to_process; input_nr++) {
+ input = (gr_complex *) input_items[input_nr];
+ double signal_pwr = 0;
+
+ for (int ii = GUARD_PERIOD; ii < TS_BITS; ii++)
+ signal_pwr += abs(input[ii]) * abs(input[ii]);
+
+ signal_pwr = signal_pwr / (TS_BITS);
+ d_signal_dbm = round(10 * log10(signal_pwr / 50));
+
+ if (input_nr == 0)
+ d_c0_signal_dbm = d_signal_dbm;
+
+ /* Get burst type for given burst number */
+ b_type = input_nr == 0 ?
+ d_channel_conf.get_burst_type(d_burst_nr) : normal_or_noise;
+
+ /* Process burst according to its type */
+ switch (b_type) {
+ case fcch_burst:
{
-
- case init: //initialize variables
- hit_count = 0;
- miss_count = 0;
- start_pos = -1;
- lowest_max_min_diff = 99999;
- phase_diff_buffer.clear();
- fcch_search_state = search;
-
+ if (d_freq_offset_tag_in_fcch)
break;
- case search: // search for positive samples
- sample_number++;
+ /* Send all-zero sequence message */
+ send_burst(d_burst_nr, fc_fb, GSMTAP_BURST_FCCH, input_nr);
- if (sample_number > nitems - FCCH_HITS_NEEDED * d_OSR) //if it isn't possible to find FCCH because
- {
- //there's too few samples left to look into,
- to_consume = sample_number; //don't do anything with those samples which are left
- //and consume only those which were checked
- fcch_search_state = search_fail;
- }
- else
- {
- phase_diff = compute_phase_diff(input[sample_number], input[sample_number-1]);
+ /* Extract frequency offset */
+ const unsigned first_sample =
+ ceil((GUARD_PERIOD + 2 * TAIL_BITS) * d_OSR) + 1;
+ const unsigned last_sample =
+ first_sample + USEFUL_BITS * d_OSR - TAIL_BITS * d_OSR;
+ double freq_offset_tmp =
+ compute_freq_offset(input, first_sample, last_sample);
- if (phase_diff > 0) //if a positive phase difference was found
- {
- to_consume = sample_number;
- fcch_search_state = found_something; //switch to state in which searches for FCCH
- }
- else
- {
- fcch_search_state = search;
- }
+ /* Frequency correction loop */
+ pmt::pmt_t msg = pmt::make_tuple(
+ pmt::mp("freq_offset"),
+ pmt::from_double(freq_offset_tmp - d_freq_offset_setting),
+ pmt::mp("synchronized"));
+ message_port_pub(pmt::mp("measurements"), msg);
+
+ break;
+ }
+
+ case sch_burst:
+ {
+ int d_ncc, d_bcc;
+ int t1, t2, t3;
+ int rc;
+
+ /* Get channel impulse response */
+ d_c0_burst_start = get_sch_chan_imp_resp(input,
+ &channel_imp_resp[0]);
+
+ /* Perform MLSE detection */
+ detect_burst(input, &channel_imp_resp[0],
+ d_c0_burst_start, output_binary);
+
+ /* Compose a message with GSMTAP header and bits */
+ send_burst(d_burst_nr, output_binary,
+ GSMTAP_BURST_SCH, input_nr);
+
+ /* Attempt to decode SCH burst */
+ rc = decode_sch(&output_binary[3], &t1, &t2, &t3, &d_ncc, &d_bcc);
+ if (rc) {
+ if (++d_failed_sch >= MAX_SCH_ERRORS) {
+ /* We have to resynchronize, change state */
+ d_state = fcch_search;
+
+ /* Frequency correction loop */
+ pmt::pmt_t msg = pmt::make_tuple(pmt::mp("freq_offset"),
+ pmt::from_double(0.0),pmt::mp("sync_loss"));
+ message_port_pub(pmt::mp("measurements"), msg);
}
break;
+ }
- case found_something: // search for FCCH and the best position of it
- {
- if (phase_diff > 0)
- {
- hit_count++; //positive phase differencies increases hits_count
- }
- else
- {
- miss_count++; //negative increases miss_count
- }
+ /**
+ * Decoding was successful, now
+ * compute offset from burst_start,
+ * burst should start after a guard period.
+ */
+ offset = d_c0_burst_start - floor((GUARD_PERIOD) * d_OSR);
+ to_consume += offset;
+ d_failed_sch = 0;
- if ((miss_count >= FCCH_MAX_MISSES * d_OSR) && (hit_count <= FCCH_HITS_NEEDED * d_OSR))
- {
- //if miss_count exceeds limit before hit_count
- fcch_search_state = init; //go to init
- continue;
- }
- else if (((miss_count >= FCCH_MAX_MISSES * d_OSR) && (hit_count > FCCH_HITS_NEEDED * d_OSR)) || (hit_count > 2 * FCCH_HITS_NEEDED * d_OSR))
- {
- //if hit_count and miss_count exceeds limit then FCCH was found
- fcch_search_state = fcch_found;
- continue;
- }
- else if ((miss_count < FCCH_MAX_MISSES * d_OSR) && (hit_count > FCCH_HITS_NEEDED * d_OSR))
- {
- //find difference between minimal and maximal element in the buffer
- //for FCCH this value should be low
- //this part is searching for a region where this value is lowest
- min_phase_diff = * (min_element(phase_diff_buffer.begin(), phase_diff_buffer.end()));
- max_phase_diff = * (max_element(phase_diff_buffer.begin(), phase_diff_buffer.end()));
-
- if (lowest_max_min_diff > max_phase_diff - min_phase_diff)
- {
- lowest_max_min_diff = max_phase_diff - min_phase_diff;
- start_pos = sample_number - FCCH_HITS_NEEDED * d_OSR - FCCH_MAX_MISSES * d_OSR; //store start pos
- best_sum = 0;
-
- for (buffer_iter = phase_diff_buffer.begin();
- buffer_iter != (phase_diff_buffer.end());
- buffer_iter++)
- {
- best_sum += *buffer_iter - (M_PI / 2) / d_OSR; //store best value of phase offset sum
- }
- }
- }
-
- sample_number++;
-
- if (sample_number >= nitems) //if there's no single sample left to check
- {
- fcch_search_state = search_fail;//FCCH search failed
- continue;
- }
-
- phase_diff = compute_phase_diff(input[sample_number], input[sample_number-1]);
- phase_diff_buffer.push_back(phase_diff);
- fcch_search_state = found_something;
+ break;
}
- break;
+
+ case normal_burst:
+ {
+ float normal_corr_max;
+ /**
+ * Get channel impulse response for given
+ * training sequence number - d_bcc
+ */
+ d_c0_burst_start = get_norm_chan_imp_resp(input,
+ &channel_imp_resp[0], &normal_corr_max, d_bcc);
+
+ /* Perform MLSE detection */
+ detect_burst(input, &channel_imp_resp[0],
+ d_c0_burst_start, output_binary);
+
+ /* Compose a message with GSMTAP header and bits */
+ send_burst(d_burst_nr, output_binary,
+ GSMTAP_BURST_NORMAL, input_nr);
+
+ break;
+ }
+
+ case dummy_or_normal:
+ {
+ unsigned int normal_burst_start, dummy_burst_start;
+ float dummy_corr_max, normal_corr_max;
+
+ dummy_burst_start = get_norm_chan_imp_resp(input,
+ &channel_imp_resp[0], &dummy_corr_max, TS_DUMMY);
+ normal_burst_start = get_norm_chan_imp_resp(input,
+ &channel_imp_resp[0], &normal_corr_max, d_bcc);
+
+ if (normal_corr_max > dummy_corr_max) {
+ d_c0_burst_start = normal_burst_start;
+
+ /* Perform MLSE detection */
+ detect_burst(input, &channel_imp_resp[0],
+ normal_burst_start, output_binary);
+
+ /* Compose a message with GSMTAP header and bits */
+ send_burst(d_burst_nr, output_binary,
+ GSMTAP_BURST_NORMAL, input_nr);
+ } else {
+ d_c0_burst_start = dummy_burst_start;
+
+ /* Compose a message with GSMTAP header and bits */
+ send_burst(d_burst_nr, dummy_burst,
+ GSMTAP_BURST_DUMMY, input_nr);
+ }
+
+ break;
+ }
+
+ case normal_or_noise:
+ {
+ std::vector<gr_complex> v(input, input + noutput_items);
+ float normal_corr_max = -1e6;
+ float normal_corr_max_tmp;
+ unsigned int burst_start;
+ int max_tn, tseq_num;
+
+ if (d_tseq_nums.size() == 0) {
+ /**
+ * There is no information about training sequence,
+ * however the receiver can detect it with use of a
+ * very simple algorithm based on finding
+ */
+ get_norm_chan_imp_resp(input, &channel_imp_resp[0],
+ &normal_corr_max, 0);
+
+ float ts_max = normal_corr_max;
+ int ts_max_num = 0;
+
+ for (int ss = 1; ss <= 7; ss++) {
+ get_norm_chan_imp_resp(input, &channel_imp_resp[0],
+ &normal_corr_max, ss);
+
+ if (ts_max < normal_corr_max) {
+ ts_max = normal_corr_max;
+ ts_max_num = ss;
+ }
+ }
+
+ d_tseq_nums.push_back(ts_max_num);
+ }
+
+ /* Choose proper training sequence number */
+ tseq_num = input_nr <= d_tseq_nums.size() ?
+ d_tseq_nums[input_nr - 1] : d_tseq_nums.back();
+
+ /* Get channel impulse response */
+ burst_start = get_norm_chan_imp_resp(input, &channel_imp_resp[0],
+ &normal_corr_max, tseq_num);
+
+ /* Perform MLSE detection */
+ detect_burst(input, &channel_imp_resp[0],
+ burst_start, output_binary);
+
+ /* Compose a message with GSMTAP header and bits */
+ send_burst(d_burst_nr, output_binary, GSMTAP_BURST_NORMAL, input_nr);
+
+ break;
+ }
+
+ case dummy:
+ send_burst(d_burst_nr, dummy_burst, GSMTAP_BURST_DUMMY, input_nr);
+ break;
+
+ case rach_burst:
+ case empty:
+ /* Do nothing */
+ break;
+ }
+
+ if (input_nr == input_items.size() - 1) {
+ /* Go to the next burst */
+ d_burst_nr++;
+
+ /* Consume samples of the burst up to next guard period */
+ to_consume += TS_BITS * d_OSR + d_burst_nr.get_offset();
+ consume_each(to_consume);
+ }
+ }
+ }
+
+ bool
+ receiver_impl::find_fcch_burst(const gr_complex *input,
+ const int nitems, double &computed_freq_offset)
+ {
+ /* Circular buffer used to scan through signal to find */
+ boost::circular_buffer<float>
+ phase_diff_buffer(FCCH_HITS_NEEDED * d_OSR);
+ boost::circular_buffer<float>::iterator buffer_iter;
+
+ float lowest_max_min_diff;
+ float phase_diff; /* Best match for FCCH burst */
+ float min_phase_diff;
+ float max_phase_diff;
+ double best_sum = 0;
+ gr_complex conjprod;
+ int start_pos;
+ int hit_count;
+ int miss_count;
+
+ int sample_number = 0;
+ int to_consume = 0;
+ bool result = false;
+ bool end = false;
+
+ /* Possible states of FCCH search algorithm */
+ enum states
+ {
+ init, /* initialize variables */
+ search, /* search for positive samples */
+ found_something, /* search for FCCH and the best position of it */
+ fcch_found, /* when FCCH was found */
+ search_fail /* when there is no FCCH in the input vector */
+ } fcch_search_state;
+
+ /* Set initial state */
+ fcch_search_state = init;
+
+ while (!end)
+ {
+ switch (fcch_search_state) {
+ case init:
+ {
+ hit_count = 0;
+ miss_count = 0;
+ start_pos = -1;
+ lowest_max_min_diff = 99999;
+ phase_diff_buffer.clear();
+
+ /* Change current state */
+ fcch_search_state = search;
+
+ break;
+ }
+
+ case search:
+ {
+ sample_number++;
+
+ if (sample_number > nitems - FCCH_HITS_NEEDED * d_OSR) {
+ /**
+ * If it isn't possible to find FCCH, because
+ * there is too few samples left to look into,
+ * don't do anything with those samples which are left
+ * and consume only those which were checked
+ */
+ to_consume = sample_number;
+ fcch_search_state = search_fail;
+ break;
+ }
+
+ phase_diff = compute_phase_diff(input[sample_number],
+ input[sample_number - 1]);
+
+ /**
+ * If a positive phase difference was found
+ * switch to state in which searches for FCCH
+ */
+ if (phase_diff > 0) {
+ to_consume = sample_number;
+ fcch_search_state = found_something;
+ } else {
+ fcch_search_state = search;
+ }
+
+ break;
+ }
+
+ case found_something:
+ {
+ if (phase_diff > 0)
+ hit_count++;
+ else
+ miss_count++;
+
+ if ((miss_count >= FCCH_MAX_MISSES * d_OSR)
+ && (hit_count <= FCCH_HITS_NEEDED * d_OSR))
+ {
+ /* If miss_count exceeds limit before hit_count */
+ fcch_search_state = init;
+ continue;
+ }
+
+ if (((miss_count >= FCCH_MAX_MISSES * d_OSR)
+ && (hit_count > FCCH_HITS_NEEDED * d_OSR))
+ || (hit_count > 2 * FCCH_HITS_NEEDED * d_OSR))
+ {
+ /**
+ * If hit_count and miss_count exceeds
+ * limit then FCCH was found
+ */
+ fcch_search_state = fcch_found;
+ continue;
+ }
+
+ if ((miss_count < FCCH_MAX_MISSES * d_OSR)
+ && (hit_count > FCCH_HITS_NEEDED * d_OSR))
+ {
+ /**
+ * Find difference between minimal and maximal
+ * element in the buffer. For FCCH this value
+ * should be low. This part is searching for
+ * a region where this value is lowest.
+ */
+ min_phase_diff = *(min_element(phase_diff_buffer.begin(),
+ phase_diff_buffer.end()));
+ max_phase_diff = *(max_element(phase_diff_buffer.begin(),
+ phase_diff_buffer.end()));
+
+ if (lowest_max_min_diff > max_phase_diff - min_phase_diff) {
+ lowest_max_min_diff = max_phase_diff - min_phase_diff;
+ start_pos = sample_number - FCCH_HITS_NEEDED
+ * d_OSR - FCCH_MAX_MISSES * d_OSR;
+ best_sum = 0;
+
+ for (buffer_iter = phase_diff_buffer.begin();
+ buffer_iter != (phase_diff_buffer.end());
+ buffer_iter++) {
+ /* Store best value of phase offset sum */
+ best_sum += *buffer_iter - (M_PI / 2) / d_OSR;
+ }
+ }
+ }
+
+ /* If there is no single sample left to check */
+ if (++sample_number >= nitems) {
+ fcch_search_state = search_fail;
+ continue;
+ }
+
+ phase_diff = compute_phase_diff(input[sample_number],
+ input[sample_number-1]);
+ phase_diff_buffer.push_back(phase_diff);
+ fcch_search_state = found_something;
+
+ break;
+ }
case fcch_found:
{
- to_consume = start_pos + FCCH_HITS_NEEDED * d_OSR + 1; //consume one FCCH burst
+ /* Consume one FCCH burst */
+ to_consume = start_pos + FCCH_HITS_NEEDED * d_OSR + 1;
+ d_fcch_start_pos = d_counter + start_pos;
- d_fcch_start_pos = d_counter + start_pos;
+ /**
+ * Compute frequency offset
+ *
+ * 1625000.0 / 6 - GMSK symbol rate in GSM
+ */
+ double phase_offset = best_sum / FCCH_HITS_NEEDED;
+ double freq_offset = phase_offset * 1625000.0 / 6 / (2 * M_PI);
+ computed_freq_offset = freq_offset;
- //compute frequency offset
- double phase_offset = best_sum / FCCH_HITS_NEEDED;
- double freq_offset = phase_offset * 1625000.0/6 / (2 * M_PI); //1625000.0/6 - GMSK symbol rate in GSM
- computed_freq_offset = freq_offset;
+ end = true;
+ result = true;
- end = true;
- result = true;
- break;
+ break;
}
case search_fail:
- end = true;
- result = false;
- break;
+ end = true;
+ result = false;
+ break;
}
+ }
+
+ d_counter += to_consume;
+ consume_each(to_consume);
+
+ return result;
}
- d_counter += to_consume;
- consume_each(to_consume);
-
- return result;
-}
-
-double receiver_impl::compute_freq_offset(const gr_complex * input, unsigned first_sample, unsigned last_sample)
-{
- double phase_sum = 0;
- unsigned ii;
-
- for (ii = first_sample; ii < last_sample; ii++)
+ double
+ receiver_impl::compute_freq_offset(const gr_complex * input,
+ unsigned first_sample, unsigned last_sample)
{
- double phase_diff = compute_phase_diff(input[ii], input[ii-1]) - (M_PI / 2) / d_OSR;
+ double phase_sum = 0;
+ unsigned ii;
+
+ for (ii = first_sample; ii < last_sample; ii++)
+ {
+ double phase_diff = compute_phase_diff(input[ii],
+ input[ii-1]) - (M_PI / 2) / d_OSR;
phase_sum += phase_diff;
+ }
+
+ double phase_offset = phase_sum / (last_sample - first_sample);
+ double freq_offset = phase_offset * 1625000.0 / (12.0 * M_PI);
+
+ return freq_offset;
}
- double phase_offset = phase_sum / (last_sample - first_sample);
- double freq_offset = phase_offset * 1625000.0 / (12.0 * M_PI);
- return freq_offset;
-}
-
-inline float receiver_impl::compute_phase_diff(gr_complex val1, gr_complex val2)
-{
- gr_complex conjprod = val1 * conj(val2);
- return fast_atan2f(imag(conjprod), real(conjprod));
-}
-
-bool receiver_impl::reach_sch_burst(const int nitems)
-{
- //it just consumes samples to get near to a SCH burst
- int to_consume = 0;
- bool result = false;
- unsigned sample_nr_near_sch_start = d_fcch_start_pos + (FRAME_BITS - SAFETY_MARGIN) * d_OSR;
-
- //consume samples until d_counter will be equal to sample_nr_near_sch_start
- if (d_counter < sample_nr_near_sch_start)
+ inline float
+ receiver_impl::compute_phase_diff(gr_complex val1, gr_complex val2)
{
- if (d_counter + nitems >= sample_nr_near_sch_start)
- {
- to_consume = sample_nr_near_sch_start - d_counter;
- }
- else
- {
- to_consume = nitems;
- }
- result = false;
+ gr_complex conjprod = val1 * conj(val2);
+ return fast_atan2f(imag(conjprod), real(conjprod));
}
- else
+
+ bool
+ receiver_impl::reach_sch_burst(const int nitems)
{
+ /* It just consumes samples to get near to a SCH burst */
+ int to_consume = 0;
+ bool result = false;
+ unsigned sample_nr = d_fcch_start_pos
+ + (FRAME_BITS - SAFETY_MARGIN) * d_OSR;
+
+ /* Consume samples until d_counter will be equal to sample_nr */
+ if (d_counter < sample_nr) {
+ to_consume = d_counter + nitems >= sample_nr ?
+ sample_nr - d_counter : nitems;
+ } else {
to_consume = 0;
result = true;
+ }
+
+ d_counter += to_consume;
+ consume_each(to_consume);
+
+ return result;
}
- d_counter += to_consume;
- consume_each(to_consume);
- return result;
-}
-
-int receiver_impl::get_sch_chan_imp_resp(const gr_complex *input, gr_complex * chan_imp_resp)
-{
- std::vector<gr_complex> correlation_buffer;
- std::vector<float> power_buffer;
- std::vector<float> window_energy_buffer;
-
- int strongest_window_nr;
- int burst_start = 0;
- int chan_imp_resp_center = 0;
- float max_correlation = 0;
- float energy = 0;
-
- for (int ii = SYNC_POS * d_OSR; ii < (SYNC_POS + SYNC_SEARCH_RANGE) *d_OSR; ii++)
+ int
+ receiver_impl::get_sch_chan_imp_resp(const gr_complex *input,
+ gr_complex * chan_imp_resp)
{
- gr_complex correlation = correlate_sequence(&d_sch_training_seq[5], N_SYNC_BITS - 10, &input[ii]);
+ std::vector<gr_complex> correlation_buffer;
+ std::vector<float> window_energy_buffer;
+ std::vector<float> power_buffer;
+
+ int chan_imp_resp_center = 0;
+ int strongest_window_nr;
+ int burst_start;
+ float energy = 0;
+
+ int len = (SYNC_POS + SYNC_SEARCH_RANGE) * d_OSR;
+ for (int ii = SYNC_POS * d_OSR; ii < len; ii++) {
+ gr_complex correlation = correlate_sequence(&d_sch_training_seq[5],
+ N_SYNC_BITS - 10, &input[ii]);
correlation_buffer.push_back(correlation);
power_buffer.push_back(std::pow(abs(correlation), 2));
- }
- //compute window energies
- std::vector<float>::iterator iter = power_buffer.begin();
- bool loop_end = false;
- while (iter != power_buffer.end())
- {
+ }
+
+ /* Compute window energies */
+ std::vector<float>::iterator iter = power_buffer.begin();
+ while (iter != power_buffer.end()) {
std::vector<float>::iterator iter_ii = iter;
+ bool loop_end = false;
energy = 0;
- for (int ii = 0; ii < (d_chan_imp_length) *d_OSR; ii++, iter_ii++)
- {
- if (iter_ii == power_buffer.end())
- {
- loop_end = true;
- break;
- }
- energy += (*iter_ii);
- }
- if (loop_end)
- {
+ for (int ii = 0; ii < (d_chan_imp_length) * d_OSR; ii++, iter_ii++) {
+ if (iter_ii == power_buffer.end()) {
+ loop_end = true;
break;
+ }
+
+ energy += (*iter_ii);
}
- iter++;
+
+ if (loop_end)
+ break;
+
window_energy_buffer.push_back(energy);
- }
+ iter++;
+ }
- strongest_window_nr = max_element(window_energy_buffer.begin(), window_energy_buffer.end()) - window_energy_buffer.begin();
- // d_channel_imp_resp.clear();
+ strongest_window_nr = max_element(window_energy_buffer.begin(),
+ window_energy_buffer.end()) - window_energy_buffer.begin();
- max_correlation = 0;
- for (int ii = 0; ii < (d_chan_imp_length) *d_OSR; ii++)
- {
+#if 0
+ d_channel_imp_resp.clear();
+#endif
+
+ float max_correlation = 0;
+ for (int ii = 0; ii < (d_chan_imp_length) * d_OSR; ii++) {
gr_complex correlation = correlation_buffer[strongest_window_nr + ii];
- if (abs(correlation) > max_correlation)
- {
- chan_imp_resp_center = ii;
- max_correlation = abs(correlation);
+ if (abs(correlation) > max_correlation) {
+ chan_imp_resp_center = ii;
+ max_correlation = abs(correlation);
}
- // d_channel_imp_resp.push_back(correlation);
+
+#if 0
+ d_channel_imp_resp.push_back(correlation);
+#endif
+
chan_imp_resp[ii] = correlation;
+ }
+
+ burst_start = strongest_window_nr + chan_imp_resp_center
+ - 48 * d_OSR - 2 * d_OSR + 2 + SYNC_POS * d_OSR;
+ return burst_start;
}
- burst_start = strongest_window_nr + chan_imp_resp_center - 48 * d_OSR - 2 * d_OSR + 2 + SYNC_POS * d_OSR;
- return burst_start;
-}
-
-void receiver_impl::detect_burst(const gr_complex * input, gr_complex * chan_imp_resp, int burst_start, unsigned char * output_binary)
-{
- float output[BURST_SIZE];
- std::vector<gr_complex> rhh_temp(CHAN_IMP_RESP_LENGTH*d_OSR);
- gr_complex rhh[CHAN_IMP_RESP_LENGTH];
- gr_complex filtered_burst[BURST_SIZE];
- int start_state = 3;
- unsigned int stop_states[2] = {4, 12};
-
- autocorrelation(chan_imp_resp, &rhh_temp[0], d_chan_imp_length*d_OSR);
- for (int ii = 0; ii < (d_chan_imp_length); ii++)
+ void
+ receiver_impl::detect_burst(const gr_complex * input,
+ gr_complex * chan_imp_resp, int burst_start,
+ unsigned char * output_binary)
{
+ std::vector<gr_complex> rhh_temp(CHAN_IMP_RESP_LENGTH * d_OSR);
+ unsigned int stop_states[2] = {4, 12};
+ gr_complex filtered_burst[BURST_SIZE];
+ gr_complex rhh[CHAN_IMP_RESP_LENGTH];
+ float output[BURST_SIZE];
+ int start_state = 3;
+
+ autocorrelation(chan_imp_resp, &rhh_temp[0], d_chan_imp_length*d_OSR);
+ for (int ii = 0; ii < d_chan_imp_length; ii++)
rhh[ii] = conj(rhh_temp[ii*d_OSR]);
+
+ mafi(&input[burst_start], BURST_SIZE, chan_imp_resp,
+ d_chan_imp_length * d_OSR, filtered_burst);
+
+ viterbi_detector(filtered_burst, BURST_SIZE, rhh,
+ start_state, stop_states, 2, output);
+
+ for (int i = 0; i < BURST_SIZE; i++)
+ output_binary[i] = output[i] > 0;
}
- mafi(&input[burst_start], BURST_SIZE, chan_imp_resp, d_chan_imp_length*d_OSR, filtered_burst);
-
- viterbi_detector(filtered_burst, BURST_SIZE, rhh, start_state, stop_states, 2, output);
-
- for (int i = 0; i < BURST_SIZE ; i++)
+ void
+ receiver_impl::gmsk_mapper(const unsigned char * input,
+ int nitems, gr_complex * gmsk_output, gr_complex start_point)
{
- output_binary[i] = (output[i] > 0);
- }
-}
+ gr_complex j = gr_complex(0.0, 1.0);
+ gmsk_output[0] = start_point;
-void receiver_impl::gmsk_mapper(const unsigned char * input, int nitems, gr_complex * gmsk_output, gr_complex start_point)
-{
- gr_complex j = gr_complex(0.0, 1.0);
+ int previous_symbol = 2 * input[0] - 1;
+ int current_symbol;
+ int encoded_symbol;
- int current_symbol;
- int encoded_symbol;
- int previous_symbol = 2 * input[0] - 1;
- gmsk_output[0] = start_point;
-
- for (int i = 1; i < nitems; i++)
- {
- //change bits representation to NRZ
+ for (int i = 1; i < nitems; i++) {
+ /* Change bits representation to NRZ */
current_symbol = 2 * input[i] - 1;
- //differentially encode
+
+ /* Differentially encode */
encoded_symbol = current_symbol * previous_symbol;
- //and do gmsk mapping
- gmsk_output[i] = j * gr_complex(encoded_symbol, 0.0) * gmsk_output[i-1];
+
+ /* And do GMSK mapping */
+ gmsk_output[i] = j * gr_complex(encoded_symbol, 0.0)
+ * gmsk_output[i-1];
+
previous_symbol = current_symbol;
- }
-}
-
-gr_complex receiver_impl::correlate_sequence(const gr_complex * sequence, int length, const gr_complex * input)
-{
- gr_complex result(0.0, 0.0);
- int sample_number = 0;
-
- for (int ii = 0; ii < length; ii++)
- {
- sample_number = (ii * d_OSR) ;
- result += sequence[ii] * conj(input[sample_number]);
+ }
}
- result = result / gr_complex(length, 0);
- return result;
-}
-
-//computes autocorrelation for positive arguments
-inline void receiver_impl::autocorrelation(const gr_complex * input, gr_complex * out, int nitems)
-{
- int i, k;
- for (k = nitems - 1; k >= 0; k--)
+ gr_complex
+ receiver_impl::correlate_sequence(const gr_complex * sequence,
+ int length, const gr_complex * input)
{
+ gr_complex result(0.0, 0.0);
+
+ for (int ii = 0; ii < length; ii++)
+ result += sequence[ii] * conj(input[ii * d_OSR]);
+
+ return result / gr_complex(length, 0);
+ }
+
+ /* Computes autocorrelation for positive arguments */
+ inline void
+ receiver_impl::autocorrelation(const gr_complex * input,
+ gr_complex * out, int nitems)
+ {
+ for (int k = nitems - 1; k >= 0; k--) {
out[k] = gr_complex(0, 0);
- for (i = k; i < nitems; i++)
- {
- out[k] += input[i] * conj(input[i-k]);
- }
+ for (int i = k; i < nitems; i++)
+ out[k] += input[i] * conj(input[i - k]);
+ }
}
-}
-inline void receiver_impl::mafi(const gr_complex * input, int nitems, gr_complex * filter, int filter_length, gr_complex * output)
-{
- int ii = 0, n, a;
-
- for (n = 0; n < nitems; n++)
+ inline void
+ receiver_impl::mafi(const gr_complex * input, int nitems,
+ gr_complex * filter, int filter_length, gr_complex * output)
{
- a = n * d_OSR;
+ for (int n = 0; n < nitems; n++) {
+ int a = n * d_OSR;
output[n] = 0;
- ii = 0;
- while (ii < filter_length)
- {
- if ((a + ii) >= nitems*d_OSR){
- break;
- }
- output[n] += input[a+ii] * filter[ii];
- ii++;
- }
- }
-}
-
-//especially computations of strongest_window_nr
-int receiver_impl::get_norm_chan_imp_resp(const gr_complex *input, gr_complex * chan_imp_resp, float *corr_max, int bcc)
-{
- std::vector<gr_complex> correlation_buffer;
- std::vector<float> power_buffer;
- std::vector<float> window_energy_buffer;
-
- int strongest_window_nr;
- int burst_start = 0;
- int chan_imp_resp_center = 0;
- float max_correlation = 0;
- float energy = 0;
-
- int search_center = (int)((TRAIN_POS + GUARD_PERIOD) * d_OSR);
- int search_start_pos = search_center + 1 - 5*d_OSR;
- // int search_start_pos = search_center - d_chan_imp_length * d_OSR;
- int search_stop_pos = search_center + d_chan_imp_length * d_OSR + 5 * d_OSR;
-
- for(int ii = search_start_pos; ii < search_stop_pos; ii++)
- {
- gr_complex correlation = correlate_sequence(&d_norm_training_seq[bcc][TRAIN_BEGINNING], N_TRAIN_BITS - 10, &input[ii]);
- correlation_buffer.push_back(correlation);
- power_buffer.push_back(std::pow(abs(correlation), 2));
- }
-// plot(power_buffer);
- //compute window energies
- std::vector<float>::iterator iter = power_buffer.begin();
- bool loop_end = false;
- while (iter != power_buffer.end())
- {
- std::vector<float>::iterator iter_ii = iter;
- energy = 0;
-
- for (int ii = 0; ii < (d_chan_imp_length)*d_OSR; ii++, iter_ii++)
- {
- if (iter_ii == power_buffer.end())
- {
- loop_end = true;
- break;
- }
- energy += (*iter_ii);
- }
- if (loop_end)
- {
+ for (int ii = 0; ii < filter_length; ii++) {
+ if ((a + ii) >= nitems * d_OSR)
break;
+
+ output[n] += input[a + ii] * filter[ii];
}
- iter++;
+ }
+ }
+
+ /* Especially computations of strongest_window_nr */
+ int
+ receiver_impl::get_norm_chan_imp_resp(const gr_complex *input,
+ gr_complex *chan_imp_resp, float *corr_max, int bcc)
+ {
+ std::vector<gr_complex> correlation_buffer;
+ std::vector<float> window_energy_buffer;
+ std::vector<float> power_buffer;
+
+ int search_center = (int) (TRAIN_POS + GUARD_PERIOD) * d_OSR;
+ int search_start_pos = search_center + 1 - 5 * d_OSR;
+ int search_stop_pos = search_center
+ + d_chan_imp_length * d_OSR + 5 * d_OSR;
+
+ for (int ii = search_start_pos; ii < search_stop_pos; ii++) {
+ gr_complex correlation = correlate_sequence(
+ &d_norm_training_seq[bcc][TRAIN_BEGINNING],
+ N_TRAIN_BITS - 10, &input[ii]);
+ correlation_buffer.push_back(correlation);
+ power_buffer.push_back(std::pow(abs(correlation), 2));
+ }
+
+#if 0
+ plot(power_buffer);
+#endif
+
+ /* Compute window energies */
+ std::vector<float>::iterator iter = power_buffer.begin();
+ while (iter != power_buffer.end()) {
+ std::vector<float>::iterator iter_ii = iter;
+ bool loop_end = false;
+ float energy = 0;
+
+ int len = d_chan_imp_length * d_OSR;
+ for (int ii = 0; ii < len; ii++, iter_ii++) {
+ if (iter_ii == power_buffer.end()) {
+ loop_end = true;
+ break;
+ }
+
+ energy += (*iter_ii);
+ }
+
+ if (loop_end)
+ break;
window_energy_buffer.push_back(energy);
- }
+ iter++;
+ }
- strongest_window_nr = max_element(window_energy_buffer.begin(), window_energy_buffer.end()-((d_chan_imp_length)*d_OSR)) - window_energy_buffer.begin();
- //strongest_window_nr = strongest_window_nr-d_OSR;
- if(strongest_window_nr<0){
- strongest_window_nr = 0;
- }
-
- max_correlation = 0;
- for (int ii = 0; ii < (d_chan_imp_length)*d_OSR; ii++)
- {
+ /* Calculate the strongest window number */
+ int strongest_window_nr = max_element(window_energy_buffer.begin(),
+ window_energy_buffer.end() - d_chan_imp_length * d_OSR)
+ - window_energy_buffer.begin();
+
+ if (strongest_window_nr < 0)
+ strongest_window_nr = 0;
+
+ float max_correlation = 0;
+ for (int ii = 0; ii < d_chan_imp_length * d_OSR; ii++) {
gr_complex correlation = correlation_buffer[strongest_window_nr + ii];
if (abs(correlation) > max_correlation)
- {
- chan_imp_resp_center = ii;
- max_correlation = abs(correlation);
- }
- // d_channel_imp_resp.push_back(correlation);
+ max_correlation = abs(correlation);
+
+#if 0
+ d_channel_imp_resp.push_back(correlation);
+#endif
+
chan_imp_resp[ii] = correlation;
+ }
+
+ *corr_max = max_correlation;
+
+ /**
+ * Compute first sample position, which corresponds
+ * to the first sample of the impulse response
+ */
+ return search_start_pos + strongest_window_nr - TRAIN_POS * d_OSR;
}
-
- *corr_max = max_correlation;
-
- //DCOUT("strongest_window_nr_new: " << strongest_window_nr);
- burst_start = search_start_pos + strongest_window_nr - TRAIN_POS * d_OSR; //compute first sample posiiton which corresponds to the first sample of the impulse response
-
- //DCOUT("burst_start: " << burst_start);
- return burst_start;
-}
-void receiver_impl::send_burst(burst_counter burst_nr, const unsigned char * burst_binary, uint8_t burst_type, unsigned int input_nr)
-{
- boost::scoped_ptr<gsmtap_hdr> tap_header(new gsmtap_hdr());
-
- tap_header->version = GSMTAP_VERSION;
- tap_header->hdr_len = sizeof(gsmtap_hdr)/4;
- tap_header->type = GSMTAP_TYPE_UM_BURST;
- tap_header->sub_type = burst_type;
- bool uplink_burst = (input_nr >= d_cell_allocation.size());
- if(!uplink_burst) // downlink burst
+ void
+ receiver_impl::send_burst(burst_counter burst_nr,
+ const unsigned char * burst_binary, uint8_t burst_type,
+ unsigned int input_nr)
{
- tap_header->timeslot = static_cast<uint8_t>(d_burst_nr.get_timeslot_nr());
- tap_header->frame_number = htobe32(d_burst_nr.get_frame_nr());
- tap_header->arfcn = htobe16(d_cell_allocation[input_nr]) ;
- }
- else //uplink burst
- {
- tap_header->timeslot = static_cast<uint8_t>(d_burst_nr.subtract_timeslots(3).get_timeslot_nr());
- tap_header->frame_number = htobe32(d_burst_nr.subtract_timeslots(3).get_frame_nr());
- input_nr = input_nr - d_cell_allocation.size();
- tap_header->arfcn = htobe16(d_cell_allocation[input_nr] | 0x4000);
- }
- tap_header->signal_dbm = static_cast<int8_t>(d_signal_dbm);
- tap_header->snr_db = 0;
+ /* Buffer for GSMTAP header and burst */
+ uint8_t buf[sizeof(gsmtap_hdr) + BURST_SIZE];
+ uint32_t frame_number;
+ uint16_t arfcn;
+ uint8_t tn;
- int8_t header_plus_burst[sizeof(gsmtap_hdr)+BURST_SIZE];
- memcpy(header_plus_burst, tap_header.get(), sizeof(gsmtap_hdr));
- memcpy(header_plus_burst+sizeof(gsmtap_hdr), burst_binary, BURST_SIZE);
-
- pmt::pmt_t blob_header_plus_burst = pmt::make_blob(header_plus_burst,sizeof(gsmtap_hdr)+BURST_SIZE);
- pmt::pmt_t msg = pmt::cons(pmt::PMT_NIL, blob_header_plus_burst);
-
- if(input_nr==0){
+ /* Set pointers to GSMTAP header and burst inside buffer */
+ struct gsmtap_hdr *tap_header = (struct gsmtap_hdr *) buf;
+ uint8_t *burst = buf + sizeof(gsmtap_hdr);
+
+ tap_header->version = GSMTAP_VERSION;
+ tap_header->hdr_len = sizeof(gsmtap_hdr) / 4;
+ tap_header->type = GSMTAP_TYPE_UM_BURST;
+ tap_header->sub_type = burst_type;
+
+ bool dl_burst = !(input_nr >= d_cell_allocation.size());
+ if (dl_burst) {
+ tn = static_cast<uint8_t>(d_burst_nr.get_timeslot_nr());
+ frame_number = htobe32(d_burst_nr.get_frame_nr());
+ arfcn = htobe16(d_cell_allocation[input_nr]);
+ } else {
+ input_nr -= d_cell_allocation.size();
+ tn = static_cast<uint8_t>
+ (d_burst_nr.subtract_timeslots(3).get_timeslot_nr());
+ frame_number = htobe32(
+ d_burst_nr.subtract_timeslots(3).get_frame_nr());
+ arfcn = htobe16(
+ d_cell_allocation[input_nr] | GSMTAP_ARFCN_F_UPLINK);
+ }
+
+ tap_header->frame_number = frame_number;
+ tap_header->timeslot = tn;
+ tap_header->arfcn = arfcn;
+
+ tap_header->signal_dbm = static_cast<int8_t>(d_signal_dbm);
+ tap_header->snr_db = 0; /* FIXME: Can we calculate this? */
+
+ /* Copy burst to the buffer */
+ memcpy(burst, burst_binary, BURST_SIZE);
+
+ /* Allocate a new message */
+ pmt::pmt_t blob = pmt::make_blob(buf, sizeof(gsmtap_hdr) + BURST_SIZE);
+ pmt::pmt_t msg = pmt::cons(pmt::PMT_NIL, blob);
+
+ /* Send message */
+ if (input_nr == 0)
message_port_pub(pmt::mp("C0"), msg);
- } else {
+ else
message_port_pub(pmt::mp("CX"), msg);
}
-}
-void receiver_impl::configure_receiver()
-{
- d_channel_conf.set_multiframe_type(TIMESLOT0, multiframe_51);
- d_channel_conf.set_burst_types(TIMESLOT0, TEST51, sizeof(TEST51) / sizeof(unsigned), dummy_or_normal);
+ void
+ receiver_impl::configure_receiver(void)
+ {
+ d_channel_conf.set_multiframe_type(TIMESLOT0, multiframe_51);
+ d_channel_conf.set_burst_types(TIMESLOT0, TEST51,
+ sizeof(TEST51) / sizeof(unsigned), dummy_or_normal);
+ d_channel_conf.set_burst_types(TIMESLOT0, TEST_CCH_FRAMES,
+ sizeof(TEST_CCH_FRAMES) / sizeof(unsigned), dummy_or_normal);
+ d_channel_conf.set_burst_types(TIMESLOT0, FCCH_FRAMES,
+ sizeof(FCCH_FRAMES) / sizeof(unsigned), fcch_burst);
+ d_channel_conf.set_burst_types(TIMESLOT0, SCH_FRAMES,
+ sizeof(SCH_FRAMES) / sizeof(unsigned), sch_burst);
- d_channel_conf.set_burst_types(TIMESLOT0, TEST_CCH_FRAMES, sizeof(TEST_CCH_FRAMES) / sizeof(unsigned), dummy_or_normal);
- d_channel_conf.set_burst_types(TIMESLOT0, FCCH_FRAMES, sizeof(FCCH_FRAMES) / sizeof(unsigned), fcch_burst);
- d_channel_conf.set_burst_types(TIMESLOT0, SCH_FRAMES, sizeof(SCH_FRAMES) / sizeof(unsigned), sch_burst);
+ d_channel_conf.set_multiframe_type(TIMESLOT1, multiframe_51);
+ d_channel_conf.set_burst_types(TIMESLOT1, TEST51,
+ sizeof(TEST51) / sizeof(unsigned), dummy_or_normal);
- d_channel_conf.set_multiframe_type(TIMESLOT1, multiframe_51);
- d_channel_conf.set_burst_types(TIMESLOT1, TEST51, sizeof(TEST51) / sizeof(unsigned), dummy_or_normal);
- d_channel_conf.set_multiframe_type(TIMESLOT2, multiframe_51);
- d_channel_conf.set_burst_types(TIMESLOT2, TEST51, sizeof(TEST51) / sizeof(unsigned), dummy_or_normal);
- d_channel_conf.set_multiframe_type(TIMESLOT3, multiframe_51);
- d_channel_conf.set_burst_types(TIMESLOT3, TEST51, sizeof(TEST51) / sizeof(unsigned), dummy_or_normal);
- d_channel_conf.set_multiframe_type(TIMESLOT4, multiframe_51);
- d_channel_conf.set_burst_types(TIMESLOT4, TEST51, sizeof(TEST51) / sizeof(unsigned), dummy_or_normal);
- d_channel_conf.set_multiframe_type(TIMESLOT5, multiframe_51);
- d_channel_conf.set_burst_types(TIMESLOT5, TEST51, sizeof(TEST51) / sizeof(unsigned), dummy_or_normal);
- d_channel_conf.set_multiframe_type(TIMESLOT6, multiframe_51);
- d_channel_conf.set_burst_types(TIMESLOT6, TEST51, sizeof(TEST51) / sizeof(unsigned), dummy_or_normal);
- d_channel_conf.set_multiframe_type(TIMESLOT7, multiframe_51);
- d_channel_conf.set_burst_types(TIMESLOT7, TEST51, sizeof(TEST51) / sizeof(unsigned), dummy_or_normal);
-}
+ d_channel_conf.set_multiframe_type(TIMESLOT2, multiframe_51);
+ d_channel_conf.set_burst_types(TIMESLOT2, TEST51,
+ sizeof(TEST51) / sizeof(unsigned), dummy_or_normal);
-void receiver_impl::set_cell_allocation(const std::vector<int> &cell_allocation)
-{
- d_cell_allocation = cell_allocation;
-}
+ d_channel_conf.set_multiframe_type(TIMESLOT3, multiframe_51);
+ d_channel_conf.set_burst_types(TIMESLOT3, TEST51,
+ sizeof(TEST51) / sizeof(unsigned), dummy_or_normal);
-void receiver_impl::set_tseq_nums(const std::vector<int> & tseq_nums)
-{
- d_tseq_nums = tseq_nums;
-}
+ d_channel_conf.set_multiframe_type(TIMESLOT4, multiframe_51);
+ d_channel_conf.set_burst_types(TIMESLOT4, TEST51,
+ sizeof(TEST51) / sizeof(unsigned), dummy_or_normal);
-void receiver_impl::reset()
-{
- d_state = fcch_search;
-}
+ d_channel_conf.set_multiframe_type(TIMESLOT5, multiframe_51);
+ d_channel_conf.set_burst_types(TIMESLOT5, TEST51,
+ sizeof(TEST51) / sizeof(unsigned), dummy_or_normal);
-} /* namespace gsm */
+ d_channel_conf.set_multiframe_type(TIMESLOT6, multiframe_51);
+ d_channel_conf.set_burst_types(TIMESLOT6, TEST51,
+ sizeof(TEST51) / sizeof(unsigned), dummy_or_normal);
+
+ d_channel_conf.set_multiframe_type(TIMESLOT7, multiframe_51);
+ d_channel_conf.set_burst_types(TIMESLOT7, TEST51,
+ sizeof(TEST51) / sizeof(unsigned), dummy_or_normal);
+ }
+
+ void
+ receiver_impl::set_cell_allocation(
+ const std::vector<int> &cell_allocation)
+ {
+ d_cell_allocation = cell_allocation;
+ }
+
+ void
+ receiver_impl::set_tseq_nums(const std::vector<int> &tseq_nums)
+ {
+ d_tseq_nums = tseq_nums;
+ }
+
+ void
+ receiver_impl::reset(void)
+ {
+ d_state = fcch_search;
+ }
+
+ } /* namespace gsm */
} /* namespace gr */
-
diff --git a/lib/receiver/receiver_impl.h b/lib/receiver/receiver_impl.h
index 6074dd5..6831bf1 100644
--- a/lib/receiver/receiver_impl.h
+++ b/lib/receiver/receiver_impl.h
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2009-2017 by Piotr Krysik <ptrkrysik@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
@@ -63,6 +63,7 @@
/**@name Variables used to store result of the find_fcch_burst fuction */
//@{
+ bool d_freq_offset_tag_in_fcch; ///< frequency offset tag presence
unsigned d_fcch_start_pos; ///< position of the first sample of the fcch burst
float d_freq_offset_setting; ///< frequency offset set in frequency shifter located upstream
//@}
@@ -200,9 +201,13 @@
* Configures burst types in different channels
*/
void configure_receiver();
-
-
+ /* State machine handlers */
+ void fcch_search_handler(gr_complex *input, int noutput_items);
+ void sch_search_handler(gr_complex *input, int noutput_items);
+ void synchronized_handler(gr_complex *input,
+ gr_vector_const_void_star &input_items, int noutput_items);
+
public:
receiver_impl(int osr, const std::vector<int> &cell_allocation, const std::vector<int> &tseq_nums, bool process_uplink);
~receiver_impl();
diff --git a/lib/receiver/sch.c b/lib/receiver/sch.c
deleted file mode 100644
index 3273237..0000000
--- a/lib/receiver/sch.c
+++ /dev/null
@@ -1,339 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include "gsm_constants.h"
-
-#define DEBUGF(a...) { \
- fprintf(stderr, "%s:%d ", __FILE__, __LINE__); \
- fprintf(stderr, a); \
-} while (0)
-
-
-
-/*
- * Synchronization channel.
- *
- * Timeslot Repeat length Frame Number (mod repeat length)
- * 0 51 1, 11, 21, 31, 41
- */
-
-/*
- * Parity (FIRE) for the GSM SCH.
- *
- * g(x) = x^10 + x^8 + x^6 + x^5 + x^4 + x^2 + 1
- */
-#define DATA_BLOCK_SIZE 25
-#define PARITY_SIZE 10
-#define TAIL_BITS_SIZE 4
-#define PARITY_OUTPUT_SIZE (DATA_BLOCK_SIZE + PARITY_SIZE + TAIL_BITS_SIZE)
-
-static const unsigned char parity_polynomial[PARITY_SIZE + 1] = {
- 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1
-};
-
-static const unsigned char parity_remainder[PARITY_SIZE] = {
- 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
-};
-
-
-static void parity_encode(unsigned char *d, unsigned char *p)
-{
-
- unsigned int i;
- unsigned char buf[DATA_BLOCK_SIZE + PARITY_SIZE], *q;
-
- memcpy(buf, d, DATA_BLOCK_SIZE);
- memset(buf + DATA_BLOCK_SIZE, 0, PARITY_SIZE);
-
- for (q = buf; q < buf + DATA_BLOCK_SIZE; q++)
- if (*q)
- for (i = 0; i < PARITY_SIZE + 1; i++)
- q[i] ^= parity_polynomial[i];
- for (i = 0; i < PARITY_SIZE; i++)
- p[i] = !buf[DATA_BLOCK_SIZE + i];
-}
-
-
-static int parity_check(unsigned char *d)
-{
-
- unsigned int i;
- unsigned char buf[DATA_BLOCK_SIZE + PARITY_SIZE], *q;
-
- memcpy(buf, d, DATA_BLOCK_SIZE + PARITY_SIZE);
-
- for (q = buf; q < buf + DATA_BLOCK_SIZE; q++)
- if (*q)
- for (i = 0; i < PARITY_SIZE + 1; i++)
- q[i] ^= parity_polynomial[i];
- return memcmp(buf + DATA_BLOCK_SIZE, parity_remainder, PARITY_SIZE);
-}
-
-
-/*
- * Convolutional encoding and Viterbi decoding for the GSM SCH.
- * (Equivalent to the GSM SACCH.)
- *
- * G_0 = 1 + x^3 + x^4
- * G_1 = 1 + x + x^3 + x^4
- *
- * i.e.,
- *
- * c_{2k} = u_k + u_{k - 3} + u_{k - 4}
- * c_{2k + 1} = u_k + u_{k - 1} + u_{k - 3} + u_{k - 4}
- */
-#define CONV_INPUT_SIZE PARITY_OUTPUT_SIZE
-#define CONV_SIZE (2 * CONV_INPUT_SIZE)
-#define K 5
-#define MAX_ERROR (2 * CONV_INPUT_SIZE + 1)
-
-
-/*
- * Given the current state and input bit, what are the output bits?
- *
- * encode[current_state][input_bit]
- */
-static const unsigned int encode[1 << (K - 1)][2] = {
- {0, 3}, {3, 0}, {3, 0}, {0, 3},
- {0, 3}, {3, 0}, {3, 0}, {0, 3},
- {1, 2}, {2, 1}, {2, 1}, {1, 2},
- {1, 2}, {2, 1}, {2, 1}, {1, 2}
-};
-
-
-/*
- * Given the current state and input bit, what is the next state?
- *
- * next_state[current_state][input_bit]
- */
-static const unsigned int next_state[1 << (K - 1)][2] = {
- {0, 8}, {0, 8}, {1, 9}, {1, 9},
- {2, 10}, {2, 10}, {3, 11}, {3, 11},
- {4, 12}, {4, 12}, {5, 13}, {5, 13},
- {6, 14}, {6, 14}, {7, 15}, {7, 15}
-};
-
-
-/*
- * Given the previous state and the current state, what input bit caused
- * the transition? If it is impossible to transition between the two
- * states, the value is 2.
- *
- * prev_next_state[previous_state][current_state]
- */
-static const unsigned int prev_next_state[1 << (K - 1)][1 << (K - 1)] = {
- { 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2},
- { 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2},
- { 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2},
- { 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2},
- { 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2},
- { 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2},
- { 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2},
- { 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2},
- { 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2},
- { 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2},
- { 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2},
- { 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2},
- { 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2},
- { 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2},
- { 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1},
- { 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1}
-};
-
-
-static inline unsigned int hamming_distance2(unsigned int w)
-{
-
- return (w & 1) + !!(w & 2);
-}
-
-
-static void conv_encode(unsigned char *data, unsigned char *output)
-{
-
- unsigned int i, state = 0, o;
-
- // encode data
- for (i = 0; i < CONV_INPUT_SIZE; i++) {
- o = encode[state][data[i]];
- state = next_state[state][data[i]];
- *output++ = !!(o & 2);
- *output++ = o & 1;
- }
-}
-
-
-static int conv_decode(unsigned char *data, unsigned char *output)
-{
-
- int i, t;
- unsigned int rdata, state, nstate, b, o, distance, accumulated_error,
- min_state, min_error, cur_state;
-
- unsigned int ae[1 << (K - 1)];
- unsigned int nae[1 << (K - 1)]; // next accumulated error
- unsigned int state_history[1 << (K - 1)][CONV_INPUT_SIZE + 1];
-
- // initialize accumulated error, assume starting state is 0
- for (i = 0; i < (1 << (K - 1)); i++)
- ae[i] = nae[i] = MAX_ERROR;
- ae[0] = 0;
-
- // build trellis
- for (t = 0; t < CONV_INPUT_SIZE; t++) {
-
- // get received data symbol
- rdata = (data[2 * t] << 1) | data[2 * t + 1];
-
- // for each state
- for (state = 0; state < (1 << (K - 1)); state++) {
-
- // make sure this state is possible
- if (ae[state] >= MAX_ERROR)
- continue;
-
- // find all states we lead to
- for (b = 0; b < 2; b++) {
-
- // get next state given input bit b
- nstate = next_state[state][b];
-
- // find output for this transition
- o = encode[state][b];
-
- // calculate distance from received data
- distance = hamming_distance2(rdata ^ o);
-
- // choose surviving path
- accumulated_error = ae[state] + distance;
- if (accumulated_error < nae[nstate]) {
-
- // save error for surviving state
- nae[nstate] = accumulated_error;
-
- // update state history
- state_history[nstate][t + 1] = state;
- }
- }
- }
-
- // get accumulated error ready for next time slice
- for (i = 0; i < (1 << (K - 1)); i++) {
- ae[i] = nae[i];
- nae[i] = MAX_ERROR;
- }
- }
-
- // the final state is the state with the fewest errors
- min_state = (unsigned int) - 1;
- min_error = MAX_ERROR;
- for (i = 0; i < (1 << (K - 1)); i++) {
- if (ae[i] < min_error) {
- min_state = i;
- min_error = ae[i];
- }
- }
-
- // trace the path
- cur_state = min_state;
- for (t = CONV_INPUT_SIZE; t >= 1; t--) {
- min_state = cur_state;
- cur_state = state_history[cur_state][t]; // get previous
- output[t - 1] = prev_next_state[cur_state][min_state];
- }
-
- // return the number of errors detected (hard-decision)
- return min_error;
-}
-
-
-int decode_sch(const unsigned char *buf, int * t1_o, int * t2_o, int * t3_o, int * ncc_o, int * bcc_o)
-{
-
- int errors, t1, t2, t3p, t3, ncc, bcc;
- unsigned char data[CONV_SIZE], decoded_data[PARITY_OUTPUT_SIZE];
-
- // extract encoded data from synchronization burst
- /* buf, 39 bit */
- /* buf + 39 + 64 = 103, 39 */
- memcpy(data, buf, SCH_DATA_LEN);
- memcpy(data + SCH_DATA_LEN, buf + SCH_DATA_LEN + N_SYNC_BITS, SCH_DATA_LEN);
-
- // Viterbi decode
- if ((errors = conv_decode(data, decoded_data))) {
- // fprintf(stderr, "error: sch: conv_decode (%d)\n", errors);
- //DEBUGF("ERR: conv_decode %d\n", errors);
- //return errors;
- }
-
- // check parity
- if (parity_check(decoded_data)) {
- // fprintf(stderr, "error: sch: parity failed\n");
- //DEBUGF("ERR: parity_check failed\n");
- return 1;
- }
-
- // Synchronization channel information, 44.018 page 171. (V7.2.0)
- ncc =
- (decoded_data[ 7] << 2) |
- (decoded_data[ 6] << 1) |
- (decoded_data[ 5] << 0);
- bcc =
- (decoded_data[ 4] << 2) |
- (decoded_data[ 3] << 1) |
- (decoded_data[ 2] << 0);
- t1 =
- (decoded_data[ 1] << 10) |
- (decoded_data[ 0] << 9) |
- (decoded_data[15] << 8) |
- (decoded_data[14] << 7) |
- (decoded_data[13] << 6) |
- (decoded_data[12] << 5) |
- (decoded_data[11] << 4) |
- (decoded_data[10] << 3) |
- (decoded_data[ 9] << 2) |
- (decoded_data[ 8] << 1) |
- (decoded_data[23] << 0);
- t2 =
- (decoded_data[22] << 4) |
- (decoded_data[21] << 3) |
- (decoded_data[20] << 2) |
- (decoded_data[19] << 1) |
- (decoded_data[18] << 0);
- t3p =
- (decoded_data[17] << 2) |
- (decoded_data[16] << 1) |
- (decoded_data[24] << 0);
-
- t3 = 10 * t3p + 1;
-
- // modulo arithmetic t3 - t2 mod 26
-// tt = ((t3 + 26) - t2) % 26;
-
-// fn = (51 * 26 * t1) + (51 * tt) + t3;
-
- /*
- * BSIC: Base Station Identification Code
- * BCC: Base station Color Code
- * NCC: Network Color Code
- *
- * FN: Frame Number
- */
-
-// printf("bsic: %x (bcc: %u; ncc: %u)\tFN: %u\n", bsic, bsic & 7,
-// (bsic >> 3) & 7, fn);
-
-// if (fn_o)
-// *fn_o = fn;
-// if (bsic_o)
- if (t1_o && t2_o && t3_o && ncc_o && bcc_o) {
- *t1_o = t1;
- *t2_o = t2;
- *t3_o = t3;
- *bcc_o = bcc;
- *ncc_o = ncc;
- }
-
- return 0;
-}
diff --git a/lib/receiver/sch.h b/lib/receiver/sch.h
index 7b5a657..5eaf554 100644
--- a/lib/receiver/sch.h
+++ b/lib/receiver/sch.h
@@ -1,3 +1,24 @@
+/* -*- c++ -*- */
+/*
+ * @file
+ * @author (C) 2014 by Piotr Krysik <ptrkrysik@gmail.com>
+ * @section LICENSE
+ *
+ * Gr-gsm is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * Gr-gsm is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with gr-gsm; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
#ifndef __SCH_H__
#define __SCH_H__ 1
diff --git a/lib/receiver/viterbi_detector.cc b/lib/receiver/viterbi_detector.cc
index c3a54fe..4e8fb3a 100644
--- a/lib/receiver/viterbi_detector.cc
+++ b/lib/receiver/viterbi_detector.cc
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2009 by Piotr Krysik <ptrkrysik@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/lib/receiver/viterbi_detector.h b/lib/receiver/viterbi_detector.h
index ef74cd0..a823003 100644
--- a/lib/receiver/viterbi_detector.h
+++ b/lib/receiver/viterbi_detector.h
@@ -1,7 +1,7 @@
/* -*- c++ -*- */
/*
* @file
- * @author Piotr Krysik <ptrkrysik@gmail.com>
+ * @author (C) 2009 Piotr Krysik <ptrkrysik@gmail.com>
* @section LICENSE
*
* Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/python/demapping/gsm_bcch_ccch_demapper.py b/python/demapping/gsm_bcch_ccch_demapper.py
index d7b5218..5bafba7 100644
--- a/python/demapping/gsm_bcch_ccch_demapper.py
+++ b/python/demapping/gsm_bcch_ccch_demapper.py
@@ -1,4 +1,24 @@
+#!/usr/bin/env python2
# -*- coding: utf-8 -*-
+# @file
+# @author (C) 2016 by Piotr Krysik <ptrkrysik@gmail.com>
+# @section LICENSE
+#
+# Gr-gsm is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# Gr-gsm is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with gr-gsm; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
##################################################
# GNU Radio Python Flow Graph
# Title: BCCH + CCCH demapper
diff --git a/python/demapping/gsm_bcch_ccch_sdcch4_demapper.py b/python/demapping/gsm_bcch_ccch_sdcch4_demapper.py
index 9234408..7b6a04d 100644
--- a/python/demapping/gsm_bcch_ccch_sdcch4_demapper.py
+++ b/python/demapping/gsm_bcch_ccch_sdcch4_demapper.py
@@ -1,4 +1,24 @@
+#!/usr/bin/env python2
# -*- coding: utf-8 -*-
+# @file
+# @author (C) 2016 by Piotr Krysik <ptrkrysik@gmail.com>
+# @section LICENSE
+#
+# Gr-gsm is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# Gr-gsm is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with gr-gsm; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
##################################################
# GNU Radio Python Flow Graph
# Title: BCCH + CCCH + SDCCH/4 demapper
diff --git a/python/demapping/gsm_sdcch8_demapper.py b/python/demapping/gsm_sdcch8_demapper.py
index 9c1e485..3d3a5a0 100644
--- a/python/demapping/gsm_sdcch8_demapper.py
+++ b/python/demapping/gsm_sdcch8_demapper.py
@@ -1,4 +1,24 @@
+#!/usr/bin/env python2
# -*- coding: utf-8 -*-
+# @file
+# @author (C) 2016 by Piotr Krysik <ptrkrysik@gmail.com>
+# @section LICENSE
+#
+# Gr-gsm is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# Gr-gsm is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with gr-gsm; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
##################################################
# GNU Radio Python Flow Graph
# Title: SDCCH/8 demapper
diff --git a/python/misc_utils/arfcn.py b/python/misc_utils/arfcn.py
index 8836501..bf227b4 100644
--- a/python/misc_utils/arfcn.py
+++ b/python/misc_utils/arfcn.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @file
-# @author Roman Khassraf <rkhassraf@gmail.com>
+# @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
# @section LICENSE
#
# Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/python/misc_utils/clock_offset_corrector_tagged.py b/python/misc_utils/clock_offset_corrector_tagged.py
index bf4b455..be55212 100644
--- a/python/misc_utils/clock_offset_corrector_tagged.py
+++ b/python/misc_utils/clock_offset_corrector_tagged.py
@@ -1,4 +1,24 @@
+#!/usr/bin/env python2
# -*- coding: utf-8 -*-
+# @file
+# @author (C) 2016 by Piotr Krysik <ptrkrysik@gmail.com>
+# @section LICENSE
+#
+# Gr-gsm is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# Gr-gsm is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with gr-gsm; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
##################################################
# GNU Radio Python Flow Graph
# Title: Clock Offset Corrector Tagged
diff --git a/python/misc_utils/hier_block.py b/python/misc_utils/hier_block.py
index a3ca1e6..0dc9c78 100644
--- a/python/misc_utils/hier_block.py
+++ b/python/misc_utils/hier_block.py
@@ -1,3 +1,25 @@
+#!/usr/bin/env python2
+# -*- coding: utf-8 -*-
+# @file
+# @author (C) 2016 by Piotr Krysik <ptrkrysik@gmail.com>
+# @section LICENSE
+#
+# Gr-gsm is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# Gr-gsm is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with gr-gsm; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
from gnuradio import gr
from distutils.version import LooseVersion as version
diff --git a/python/qa_arfcn.py b/python/qa_arfcn.py
index 358d436..1b7fb73 100755
--- a/python/qa_arfcn.py
+++ b/python/qa_arfcn.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @file
-# @author Roman Khassraf <rkhassraf@gmail.com>
+# @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
# @section LICENSE
#
# Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/python/qa_burst_fnr_filter.py b/python/qa_burst_fnr_filter.py
index 93152df..4602ec7 100755
--- a/python/qa_burst_fnr_filter.py
+++ b/python/qa_burst_fnr_filter.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @file
-# @author Roman Khassraf <rkhassraf@gmail.com>
+# @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
# @section LICENSE
#
# Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/python/qa_burst_printer.py b/python/qa_burst_printer.py
index 49c89e4..a3d50d5 100755
--- a/python/qa_burst_printer.py
+++ b/python/qa_burst_printer.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @file
-# @author Roman Khassraf <rkhassraf@gmail.com>
+# @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
# @section LICENSE
#
# Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/python/qa_burst_sdcch_subslot_filter.py b/python/qa_burst_sdcch_subslot_filter.py
index 9cb3cd5..4940286 100755
--- a/python/qa_burst_sdcch_subslot_filter.py
+++ b/python/qa_burst_sdcch_subslot_filter.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @file
-# @author Roman Khassraf <rkhassraf@gmail.com>
+# @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
# @section LICENSE
#
# Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/python/qa_burst_sdcch_subslot_splitter.py b/python/qa_burst_sdcch_subslot_splitter.py
index 1800137..7d8b8e0 100755
--- a/python/qa_burst_sdcch_subslot_splitter.py
+++ b/python/qa_burst_sdcch_subslot_splitter.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @file
-# @author Roman Khassraf <rkhassraf@gmail.com>
+# @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
# @section LICENSE
#
# Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/python/qa_burst_timeslot_filter.py b/python/qa_burst_timeslot_filter.py
index 4c0f655..16001f0 100755
--- a/python/qa_burst_timeslot_filter.py
+++ b/python/qa_burst_timeslot_filter.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @file
-# @author Roman Khassraf <rkhassraf@gmail.com>
+# @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
# @section LICENSE
#
# Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/python/qa_burst_timeslot_splitter.py b/python/qa_burst_timeslot_splitter.py
index cac9ae1..2f8738b 100755
--- a/python/qa_burst_timeslot_splitter.py
+++ b/python/qa_burst_timeslot_splitter.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @file
-# @author Roman Khassraf <rkhassraf@gmail.com>
+# @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
# @section LICENSE
#
# Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/python/qa_controlled_fractional_resampler_cc.py b/python/qa_controlled_fractional_resampler_cc.py
index 417ab5b..e00f6bc 100755
--- a/python/qa_controlled_fractional_resampler_cc.py
+++ b/python/qa_controlled_fractional_resampler_cc.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @file
-# @author Piotr Krysik <ptrkrysik@gmail.com>
+# @author (C) 2016 by Piotr Krysik <ptrkrysik@gmail.com>
# @section LICENSE
#
# Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/python/qa_decryption.py b/python/qa_decryption.py
index 71feb62..663471c 100755
--- a/python/qa_decryption.py
+++ b/python/qa_decryption.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @file
-# @author Piotr Krysik <ptrkrysik@gmail.com>
+# @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
# @section LICENSE
#
# Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/python/qa_dummy_burst_filter.py b/python/qa_dummy_burst_filter.py
index a86a0e5..3215b12 100755
--- a/python/qa_dummy_burst_filter.py
+++ b/python/qa_dummy_burst_filter.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @file
-# @author Roman Khassraf <rkhassraf@gmail.com>
+# @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
# @section LICENSE
#
# Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/python/qa_message_printer.py b/python/qa_message_printer.py
index 4e54df1..6bc9a20 100755
--- a/python/qa_message_printer.py
+++ b/python/qa_message_printer.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @file
-# @author Roman Khassraf <rkhassraf@gmail.com>
+# @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
# @section LICENSE
#
# Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/python/qa_message_source_sink.py b/python/qa_message_source_sink.py
index a82b16f..1638345 100755
--- a/python/qa_message_source_sink.py
+++ b/python/qa_message_source_sink.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @file
-# @author Roman Khassraf <rkhassraf@gmail.com>
+# @author (C) 2015 by Roman Khassraf <rkhassraf@gmail.com>
# @section LICENSE
#
# Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/python/qa_msg_to_tag.py b/python/qa_msg_to_tag.py
index eb206b1..f4b6829 100755
--- a/python/qa_msg_to_tag.py
+++ b/python/qa_msg_to_tag.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @file
-# @author Piotr Krysik <ptrkrysik@gmail.com>
+# @author (C) 2016 by Piotr Krysik <ptrkrysik@gmail.com>
# @section LICENSE
#
# Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/python/qa_uplink_downlink_splitter.py b/python/qa_uplink_downlink_splitter.py
index 1b9020f..681331b 100755
--- a/python/qa_uplink_downlink_splitter.py
+++ b/python/qa_uplink_downlink_splitter.py
@@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @file
-# @author Piotr Krysik <ptrkrysik@gmail.com>
+# @author (C) 2016 by Piotr Krysik <ptrkrysik@gmail.com>
# @section LICENSE
#
# Gr-gsm is free software; you can redistribute it and/or modify
diff --git a/python/receiver/fcch_burst_tagger.py b/python/receiver/fcch_burst_tagger.py
index fdea81c..04b1986 100644
--- a/python/receiver/fcch_burst_tagger.py
+++ b/python/receiver/fcch_burst_tagger.py
@@ -1,7 +1,8 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
# -*- coding: utf-8 -*-
-#
-# Copyright 2014 Piotr Krysik <ptrkrysik@gmail.com>
+# @file
+# @author (C) 2014 by Piotr Krysik <ptrkrysik@gmail.com>
+# @section LICENSE
#
# This is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
diff --git a/python/receiver/fcch_detector.py b/python/receiver/fcch_detector.py
index 2f2a4ab..81438e2 100644
--- a/python/receiver/fcch_detector.py
+++ b/python/receiver/fcch_detector.py
@@ -1,4 +1,25 @@
-#!/usr/bin/env python
+#!/usr/bin/env python2
+# -*- coding: utf-8 -*-
+# @file
+# @author (C) 2014 by Piotr Krysik <ptrkrysik@gmail.com>
+# @section LICENSE
+#
+# Gr-gsm is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# Gr-gsm is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with gr-gsm; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
##################################################
# Gnuradio Python Flow Graph
# Title: FCCH Bursts Detector
diff --git a/python/receiver/gsm_input.py b/python/receiver/gsm_input.py
index af5d4c3..8c4ad51 100644
--- a/python/receiver/gsm_input.py
+++ b/python/receiver/gsm_input.py
@@ -1,4 +1,24 @@
+#!/usr/bin/env python2
# -*- coding: utf-8 -*-
+# @file
+# @author (C) 2014 by Piotr Krysik <ptrkrysik@gmail.com>
+# @section LICENSE
+#
+# Gr-gsm is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# Gr-gsm is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with gr-gsm; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
##################################################
# GNU Radio Python Flow Graph
# Title: GSM input adaptor
diff --git a/python/receiver/sch_detector.py b/python/receiver/sch_detector.py
index d5d05b0..d3587d1 100644
--- a/python/receiver/sch_detector.py
+++ b/python/receiver/sch_detector.py
@@ -1,7 +1,8 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
-#
-# Copyright 2014 Piotr Krysik <ptrkrysik@gmail.com>
+# @file
+# @author (C) 2014 by Piotr Krysik <ptrkrysik@gmail.com>
+# @section LICENSE
#
# This is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
diff --git a/swig/grgsm_swig.i b/swig/grgsm_swig.i
index eab179c..9d6636a 100644
--- a/swig/grgsm_swig.i
+++ b/swig/grgsm_swig.i
@@ -1,4 +1,25 @@
/* -*- c++ -*- */
+/*
+ * @file
+ * @author (C) 2014 by Piotr Krysik <ptrkrysik@gmail.com>
+ * @section LICENSE
+ *
+ * Gr-gsm is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * Gr-gsm is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with gr-gsm; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
#define GRGSM_API