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