summaryrefslogtreecommitdiff
path: root/gsm-receiver
diff options
context:
space:
mode:
authorPiotr Krysik <perper@o2.pl>2009-06-30 23:10:11 +0200
committerPiotr Krysik <perper@o2.pl>2009-06-30 23:10:11 +0200
commit3f91ce4f1c4a047a94497041b82c77c815d52a1f (patch)
treeed787719fb4e89670cc2161ecd4136c554834686 /gsm-receiver
parent26a95cc318fcc8022a42f679d81b41d949771b8d (diff)
parent8d2bc49fb9e0c9a5fbd75aa3cad207608e72bf99 (diff)
Merge branch 'moving_to_airprobe'
Diffstat (limited to 'gsm-receiver')
-rw-r--r--gsm-receiver/.gitignore25
-rw-r--r--gsm-receiver/AUTHORS1
-rw-r--r--gsm-receiver/CHANGELOG0
-rw-r--r--gsm-receiver/COPYING674
-rw-r--r--gsm-receiver/ChangeLog0
-rw-r--r--gsm-receiver/Doxyfile316
-rw-r--r--gsm-receiver/INSTALL13
-rw-r--r--gsm-receiver/Makefile.am13
-rw-r--r--gsm-receiver/Makefile.common57
-rw-r--r--gsm-receiver/NEWS0
-rw-r--r--gsm-receiver/README5
-rwxr-xr-xgsm-receiver/bootstrap32
-rw-r--r--gsm-receiver/config/.gitignore5
-rw-r--r--gsm-receiver/config/Makefile.am70
-rw-r--r--gsm-receiver/config/acx_pthread.m4190
-rw-r--r--gsm-receiver/config/bnv_have_qt.m4404
-rw-r--r--gsm-receiver/config/cppunit.m480
-rw-r--r--gsm-receiver/config/gr_boost.m4111
-rw-r--r--gsm-receiver/config/gr_check_createfilemapping.m452
-rw-r--r--gsm-receiver/config/gr_check_mc4020.m437
-rw-r--r--gsm-receiver/config/gr_check_shm_open.m429
-rw-r--r--gsm-receiver/config/gr_check_usrp.m432
-rw-r--r--gsm-receiver/config/gr_doxygen.m459
-rw-r--r--gsm-receiver/config/gr_gprof.m472
-rw-r--r--gsm-receiver/config/gr_libgnuradio_core_extra_ldflags.m440
-rw-r--r--gsm-receiver/config/gr_no_undefined.m444
-rw-r--r--gsm-receiver/config/gr_omnithread.m451
-rw-r--r--gsm-receiver/config/gr_pwin32.m4146
-rw-r--r--gsm-receiver/config/gr_python.m4111
-rw-r--r--gsm-receiver/config/gr_require_mc4020.m433
-rw-r--r--gsm-receiver/config/gr_scripting.m430
-rw-r--r--gsm-receiver/config/gr_set_md_cpu.m444
-rw-r--r--gsm-receiver/config/gr_swig.m485
-rw-r--r--gsm-receiver/config/gr_sysv_shm.m436
-rw-r--r--gsm-receiver/config/gr_x86_64.m439
-rw-r--r--gsm-receiver/config/lf_cc.m442
-rw-r--r--gsm-receiver/config/lf_cxx.m4121
-rw-r--r--gsm-receiver/config/lf_warnings.m4128
-rw-r--r--gsm-receiver/config/lf_x11.m439
-rw-r--r--gsm-receiver/config/mkstemp.m489
-rw-r--r--gsm-receiver/config/onceonly.m463
-rw-r--r--gsm-receiver/config/pkg.m468
-rw-r--r--gsm-receiver/config/usrp_fusb_tech.m456
-rw-r--r--gsm-receiver/config/usrp_libusb.m443
-rw-r--r--gsm-receiver/config/usrp_sdcc.m467
-rw-r--r--gsm-receiver/configure.ac120
-rw-r--r--gsm-receiver/gsm-receiver.pc.in11
-rwxr-xr-xgsm-receiver/py-compile146
-rw-r--r--gsm-receiver/src/Makefile.am23
-rw-r--r--gsm-receiver/src/lib/Assert.h67
-rw-r--r--gsm-receiver/src/lib/Makefile.am109
-rw-r--r--gsm-receiver/src/lib/decoder/AUTHORS1
-rw-r--r--gsm-receiver/src/lib/decoder/Makefile.am56
-rw-r--r--gsm-receiver/src/lib/decoder/a5-1-2.h453
-rw-r--r--gsm-receiver/src/lib/decoder/burst_types.h214
-rw-r--r--gsm-receiver/src/lib/decoder/cch.c482
-rw-r--r--gsm-receiver/src/lib/decoder/cch.h56
-rw-r--r--gsm-receiver/src/lib/decoder/fire_crc.c179
-rw-r--r--gsm-receiver/src/lib/decoder/fire_crc.h47
-rw-r--r--gsm-receiver/src/lib/decoder/gsmstack.c206
-rw-r--r--gsm-receiver/src/lib/decoder/gsmstack.h43
-rw-r--r--gsm-receiver/src/lib/decoder/gsmtap.h41
-rw-r--r--gsm-receiver/src/lib/decoder/interleave.c47
-rw-r--r--gsm-receiver/src/lib/decoder/interleave.h19
-rw-r--r--gsm-receiver/src/lib/decoder/openbtsstuff/AUTHORS173
-rw-r--r--gsm-receiver/src/lib/decoder/openbtsstuff/Assert.h49
-rw-r--r--gsm-receiver/src/lib/decoder/openbtsstuff/BitVector.cpp513
-rw-r--r--gsm-receiver/src/lib/decoder/openbtsstuff/BitVector.h427
-rw-r--r--gsm-receiver/src/lib/decoder/openbtsstuff/GSM610Tables.cpp492
-rw-r--r--gsm-receiver/src/lib/decoder/openbtsstuff/GSM610Tables.h37
-rw-r--r--gsm-receiver/src/lib/decoder/openbtsstuff/GSMCommon.cpp315
-rw-r--r--gsm-receiver/src/lib/decoder/openbtsstuff/GSMCommon.h537
-rw-r--r--gsm-receiver/src/lib/decoder/openbtsstuff/GSML1FEC.cpp256
-rw-r--r--gsm-receiver/src/lib/decoder/openbtsstuff/GSML1FEC.h146
-rw-r--r--gsm-receiver/src/lib/decoder/openbtsstuff/GSMTDMA.cpp337
-rw-r--r--gsm-receiver/src/lib/decoder/openbtsstuff/GSMTDMA.h358
-rw-r--r--gsm-receiver/src/lib/decoder/openbtsstuff/Makefile.am49
-rw-r--r--gsm-receiver/src/lib/decoder/openbtsstuff/RxBurst.h69
-rw-r--r--gsm-receiver/src/lib/decoder/openbtsstuff/Threads.cpp106
-rw-r--r--gsm-receiver/src/lib/decoder/openbtsstuff/Threads.h150
-rw-r--r--gsm-receiver/src/lib/decoder/openbtsstuff/Timeval.cpp93
-rw-r--r--gsm-receiver/src/lib/decoder/openbtsstuff/Timeval.h96
-rw-r--r--gsm-receiver/src/lib/decoder/openbtsstuff/Vector.h257
-rw-r--r--gsm-receiver/src/lib/decoder/openbtsstuff/VocoderFrame.h25
-rw-r--r--gsm-receiver/src/lib/decoder/out_pcap.c111
-rw-r--r--gsm-receiver/src/lib/decoder/out_pcap.h9
-rw-r--r--gsm-receiver/src/lib/decoder/sch.c333
-rw-r--r--gsm-receiver/src/lib/decoder/sch.h17
-rw-r--r--gsm-receiver/src/lib/decoder/system.h11
-rw-r--r--gsm-receiver/src/lib/decoder/tun.c125
-rw-r--r--gsm-receiver/src/lib/decoder/tun.h4
-rw-r--r--gsm-receiver/src/lib/gsm.i49
-rw-r--r--gsm-receiver/src/lib/gsm_constants.h150
-rw-r--r--gsm-receiver/src/lib/gsm_receiver_cf.cc853
-rw-r--r--gsm-receiver/src/lib/gsm_receiver_cf.h254
-rw-r--r--gsm-receiver/src/lib/gsm_receiver_config.cc84
-rw-r--r--gsm-receiver/src/lib/gsm_receiver_config.h164
-rw-r--r--gsm-receiver/src/lib/viterbi_detector.cc554
-rw-r--r--gsm-receiver/src/lib/viterbi_detector.h63
-rw-r--r--gsm-receiver/src/python/Makefile.am24
-rwxr-xr-xgsm-receiver/src/python/capture.sh45
-rw-r--r--gsm-receiver/src/python/cfilebin0 -> 640000 bytes
-rwxr-xr-xgsm-receiver/src/python/go.sh12
-rwxr-xr-xgsm-receiver/src/python/gsm_receive.py117
-rwxr-xr-xgsm-receiver/src/python/gsm_receive_usrp.py141
-rwxr-xr-xgsm-receiver/src/python/test.sh16
106 files changed, 13593 insertions, 0 deletions
diff --git a/gsm-receiver/.gitignore b/gsm-receiver/.gitignore
new file mode 100644
index 0000000..91f0ff0
--- /dev/null
+++ b/gsm-receiver/.gitignore
@@ -0,0 +1,25 @@
+configure
+Makefile.in
+config.log
+config.h
+config.sub
+config.guess
+ltmain.sh
+Makefile
+config.status
+stamp-h1
+config.h.in
+autom4te.cache
+libtool
+missing
+aclocal.m4
+install-sh
+depcomp
+compile
+build
+*~
+autom4te.cache
+debug
+html
+latex
+xml
diff --git a/gsm-receiver/AUTHORS b/gsm-receiver/AUTHORS
new file mode 100644
index 0000000..944ad20
--- /dev/null
+++ b/gsm-receiver/AUTHORS
@@ -0,0 +1 @@
+Piotr Krysik <perper@o2.pl> \ No newline at end of file
diff --git a/gsm-receiver/CHANGELOG b/gsm-receiver/CHANGELOG
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/gsm-receiver/CHANGELOG
diff --git a/gsm-receiver/COPYING b/gsm-receiver/COPYING
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/gsm-receiver/COPYING
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 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 General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <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 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/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/gsm-receiver/ChangeLog b/gsm-receiver/ChangeLog
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/gsm-receiver/ChangeLog
diff --git a/gsm-receiver/Doxyfile b/gsm-receiver/Doxyfile
new file mode 100644
index 0000000..2c5110c
--- /dev/null
+++ b/gsm-receiver/Doxyfile
@@ -0,0 +1,316 @@
+# Doxyfile 1.5.6-KDevelop
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+DOXYFILE_ENCODING = UTF-8
+PROJECT_NAME = gsm_receiver
+PROJECT_NUMBER = 0.0.1
+OUTPUT_DIRECTORY =
+CREATE_SUBDIRS = NO
+OUTPUT_LANGUAGE = English
+BRIEF_MEMBER_DESC = YES
+REPEAT_BRIEF = YES
+ABBREVIATE_BRIEF = "The $name class" \
+ "The $name widget" \
+ "The $name file" \
+ is \
+ provides \
+ specifies \
+ contains \
+ represents \
+ a \
+ an \
+ the
+ALWAYS_DETAILED_SEC = NO
+INLINE_INHERITED_MEMB = NO
+FULL_PATH_NAMES = YES
+STRIP_FROM_PATH = /home/piotr/
+STRIP_FROM_INC_PATH =
+SHORT_NAMES = NO
+JAVADOC_AUTOBRIEF = YES
+QT_AUTOBRIEF = NO
+MULTILINE_CPP_IS_BRIEF = NO
+DETAILS_AT_TOP = NO
+INHERIT_DOCS = YES
+SEPARATE_MEMBER_PAGES = NO
+TAB_SIZE = 8
+ALIASES =
+OPTIMIZE_OUTPUT_FOR_C = NO
+OPTIMIZE_OUTPUT_JAVA = NO
+OPTIMIZE_FOR_FORTRAN = NO
+OPTIMIZE_OUTPUT_VHDL = NO
+BUILTIN_STL_SUPPORT = NO
+CPP_CLI_SUPPORT = NO
+SIP_SUPPORT = NO
+IDL_PROPERTY_SUPPORT = YES
+DISTRIBUTE_GROUP_DOC = NO
+SUBGROUPING = YES
+TYPEDEF_HIDES_STRUCT = NO
+SYMBOL_CACHE_SIZE = 0
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+EXTRACT_ALL = NO
+EXTRACT_PRIVATE = YES
+EXTRACT_STATIC = YES
+EXTRACT_LOCAL_CLASSES = YES
+EXTRACT_LOCAL_METHODS = NO
+EXTRACT_ANON_NSPACES = NO
+HIDE_UNDOC_MEMBERS = NO
+HIDE_UNDOC_CLASSES = NO
+HIDE_FRIEND_COMPOUNDS = NO
+HIDE_IN_BODY_DOCS = NO
+INTERNAL_DOCS = NO
+CASE_SENSE_NAMES = YES
+HIDE_SCOPE_NAMES = NO
+SHOW_INCLUDE_FILES = YES
+INLINE_INFO = YES
+SORT_MEMBER_DOCS = YES
+SORT_BRIEF_DOCS = NO
+SORT_GROUP_NAMES = NO
+SORT_BY_SCOPE_NAME = NO
+GENERATE_TODOLIST = YES
+GENERATE_TESTLIST = YES
+GENERATE_BUGLIST = YES
+GENERATE_DEPRECATEDLIST= YES
+ENABLED_SECTIONS =
+MAX_INITIALIZER_LINES = 30
+SHOW_USED_FILES = YES
+SHOW_DIRECTORIES = NO
+SHOW_FILES = YES
+SHOW_NAMESPACES = YES
+FILE_VERSION_FILTER =
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+QUIET = NO
+WARNINGS = YES
+WARN_IF_UNDOCUMENTED = YES
+WARN_IF_DOC_ERROR = YES
+WARN_NO_PARAMDOC = NO
+WARN_FORMAT = "$file:$line: $text"
+WARN_LOGFILE =
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+INPUT = /home/piotr/MiejscePracy/gsm-receiver
+INPUT_ENCODING = UTF-8
+FILE_PATTERNS = *.c \
+ *.cc \
+ *.cxx \
+ *.cpp \
+ *.c++ \
+ *.d \
+ *.java \
+ *.ii \
+ *.ixx \
+ *.ipp \
+ *.i++ \
+ *.inl \
+ *.h \
+ *.hh \
+ *.hxx \
+ *.hpp \
+ *.h++ \
+ *.idl \
+ *.odl \
+ *.cs \
+ *.php \
+ *.php3 \
+ *.inc \
+ *.m \
+ *.mm \
+ *.dox \
+ *.py \
+ *.f90 \
+ *.f \
+ *.vhd \
+ *.vhdl \
+ *.C \
+ *.CC \
+ *.C++ \
+ *.II \
+ *.I++ \
+ *.H \
+ *.HH \
+ *.H++ \
+ *.CS \
+ *.PHP \
+ *.PHP3 \
+ *.M \
+ *.MM \
+ *.PY \
+ *.F90 \
+ *.F \
+ *.VHD \
+ *.VHDL \
+ *.C \
+ *.H \
+ *.tlh \
+ *.diff \
+ *.patch \
+ *.moc \
+ *.xpm \
+ *.dox
+RECURSIVE = yes
+EXCLUDE =
+EXCLUDE_SYMLINKS = NO
+EXCLUDE_PATTERNS =
+EXCLUDE_SYMBOLS =
+EXAMPLE_PATH =
+EXAMPLE_PATTERNS = *
+EXAMPLE_RECURSIVE = NO
+IMAGE_PATH =
+INPUT_FILTER =
+FILTER_PATTERNS =
+FILTER_SOURCE_FILES = NO
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+SOURCE_BROWSER = NO
+INLINE_SOURCES = NO
+STRIP_CODE_COMMENTS = YES
+REFERENCED_BY_RELATION = NO
+REFERENCES_RELATION = NO
+REFERENCES_LINK_SOURCE = YES
+USE_HTAGS = NO
+VERBATIM_HEADERS = YES
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+ALPHABETICAL_INDEX = NO
+COLS_IN_ALPHA_INDEX = 5
+IGNORE_PREFIX =
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+GENERATE_HTML = YES
+HTML_OUTPUT = html
+HTML_FILE_EXTENSION = .html
+HTML_HEADER =
+HTML_FOOTER =
+HTML_STYLESHEET =
+HTML_ALIGN_MEMBERS = YES
+GENERATE_HTMLHELP = NO
+GENERATE_DOCSET = NO
+DOCSET_FEEDNAME = "Doxygen generated docs"
+DOCSET_BUNDLE_ID = org.doxygen.Project
+HTML_DYNAMIC_SECTIONS = NO
+CHM_FILE =
+HHC_LOCATION =
+QTHELP_FILE =
+QTHELP_CONFIG =
+DOXYGEN2QTHELP_LOC =
+GENERATE_CHI = NO
+CHM_INDEX_ENCODING =
+BINARY_TOC = NO
+TOC_EXPAND = NO
+DISABLE_INDEX = NO
+ENUM_VALUES_PER_LINE = 4
+GENERATE_TREEVIEW = NONE
+TREEVIEW_WIDTH = 250
+FORMULA_FONTSIZE = 10
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+GENERATE_LATEX = YES
+LATEX_OUTPUT = latex
+LATEX_CMD_NAME = latex
+MAKEINDEX_CMD_NAME = makeindex
+COMPACT_LATEX = NO
+PAPER_TYPE = a4wide
+EXTRA_PACKAGES =
+LATEX_HEADER =
+PDF_HYPERLINKS = YES
+USE_PDFLATEX = YES
+LATEX_BATCHMODE = NO
+LATEX_HIDE_INDICES = NO
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+GENERATE_RTF = NO
+RTF_OUTPUT = rtf
+COMPACT_RTF = NO
+RTF_HYPERLINKS = NO
+RTF_STYLESHEET_FILE =
+RTF_EXTENSIONS_FILE =
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+GENERATE_MAN = NO
+MAN_OUTPUT = man
+MAN_EXTENSION = .3
+MAN_LINKS = NO
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+GENERATE_XML = yes
+XML_OUTPUT = xml
+XML_SCHEMA =
+XML_DTD =
+XML_PROGRAMLISTING = YES
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+GENERATE_AUTOGEN_DEF = NO
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+GENERATE_PERLMOD = NO
+PERLMOD_LATEX = NO
+PERLMOD_PRETTY = YES
+PERLMOD_MAKEVAR_PREFIX =
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+ENABLE_PREPROCESSING = YES
+MACRO_EXPANSION = NO
+EXPAND_ONLY_PREDEF = NO
+SEARCH_INCLUDES = YES
+INCLUDE_PATH =
+INCLUDE_FILE_PATTERNS =
+PREDEFINED =
+EXPAND_AS_DEFINED =
+SKIP_FUNCTION_MACROS = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+TAGFILES =
+GENERATE_TAGFILE = gsm_receiver.tag
+ALLEXTERNALS = NO
+EXTERNAL_GROUPS = YES
+PERL_PATH = /usr/bin/perl
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+CLASS_DIAGRAMS = YES
+MSCGEN_PATH =
+HIDE_UNDOC_RELATIONS = YES
+HAVE_DOT = NO
+DOT_FONTNAME = FreeSans
+DOT_FONTPATH =
+CLASS_GRAPH = YES
+COLLABORATION_GRAPH = YES
+GROUP_GRAPHS = YES
+UML_LOOK = NO
+TEMPLATE_RELATIONS = NO
+INCLUDE_GRAPH = YES
+INCLUDED_BY_GRAPH = YES
+CALL_GRAPH = NO
+CALLER_GRAPH = NO
+GRAPHICAL_HIERARCHY = YES
+DIRECTORY_GRAPH = YES
+DOT_IMAGE_FORMAT = png
+DOT_PATH =
+DOTFILE_DIRS =
+DOT_GRAPH_MAX_NODES = 50
+MAX_DOT_GRAPH_DEPTH = 1000
+DOT_TRANSPARENT = YES
+DOT_MULTI_TARGETS = NO
+GENERATE_LEGEND = YES
+DOT_CLEANUP = YES
+#---------------------------------------------------------------------------
+# Configuration::additions related to the search engine
+#---------------------------------------------------------------------------
+SEARCHENGINE = NO
diff --git a/gsm-receiver/INSTALL b/gsm-receiver/INSTALL
new file mode 100644
index 0000000..314b196
--- /dev/null
+++ b/gsm-receiver/INSTALL
@@ -0,0 +1,13 @@
+Under Ubuntu 9.04 install:
+ -add following lines to /etc/apt/sources.list
+ deb http://gnuradio.org/ubuntu stable main
+ deb-src http://gnuradio.org/ubuntu stable main
+ -type
+ $ sudo apt-get update
+ $ sudo apt-get install gnuradio libtool automake
+
+To build the GSM Receiver use:
+ $ ./bootstrap
+ $ cd debug
+ $ ../configure
+ $ make
diff --git a/gsm-receiver/Makefile.am b/gsm-receiver/Makefile.am
new file mode 100644
index 0000000..734941a
--- /dev/null
+++ b/gsm-receiver/Makefile.am
@@ -0,0 +1,13 @@
+include $(top_srcdir)/Makefile.common
+
+SUBDIRS = src config
+DIST_SUBDIRS = src config
+
+EXTRA_DIST = \
+ configure \
+ gsm-receiver.pc.in \
+ config.h.in
+# bootstrap
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = gsm-receiver.pc
diff --git a/gsm-receiver/Makefile.common b/gsm-receiver/Makefile.common
new file mode 100644
index 0000000..0b88813
--- /dev/null
+++ b/gsm-receiver/Makefile.common
@@ -0,0 +1,57 @@
+# -*- Makefile -*-
+#
+# Copyright 2004,2006 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+#!! remove this
+TCH_DECODER_INCLUDEDIR = $(top_srcdir)/src/lib/decoder/openbtsstuff
+
+MAIN_INCLUDEDIR = $(top_srcdir)/src/lib
+DECODER_INCLUDEDIR = $(top_srcdir)/src/lib/decoder
+DECODER_LA = $(top_builddir)/src/lib/decoder/libdecoder.la
+
+STD_DEFINES_AND_INCLUDES = \
+ -I$(DECODER_INCLUDEDIR) \
+ -I$(MAIN_INCLUDEDIR) \
+ -I$(GNURADIO_CORE_INCLUDEDIR) \
+ -I$(TCH_DECODER_INCLUDEDIR)
+
+# includes
+grincludedir = $(includedir)/gnuradio
+
+# swig includes
+swigincludedir = $(grincludedir)/swig
+
+# Install this stuff in the appropriate subdirectory
+# This usually ends up at:
+# ${prefix}/lib/python${python_version}/site-packages/gnuradio
+
+grpythondir = $(pythondir)/gnuradio
+grpyexecdir = $(pyexecdir)/gnuradio
+
+# swig flags
+SWIGPYTHONFLAGS = -fvirtual -python -modern
+SWIGGRFLAGS = -I$(GNURADIO_CORE_INCLUDEDIR)/swig -I$(GNURADIO_CORE_INCLUDEDIR)
+
+# Don't assume that make predefines $(RM), because BSD make does
+# not. We define it now in configure.ac using AM_PATH_PROG, but now
+# here have to add a -f to be like GNU make.
+RM=$(RM_PROG) -f
+
diff --git a/gsm-receiver/NEWS b/gsm-receiver/NEWS
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/gsm-receiver/NEWS
diff --git a/gsm-receiver/README b/gsm-receiver/README
new file mode 100644
index 0000000..96b560b
--- /dev/null
+++ b/gsm-receiver/README
@@ -0,0 +1,5 @@
+Usage:
+ -capture cfile with usrp:
+ $ capture.sh <frequency>
+ -run go.sh on this file:
+ $ go.sh <file.cfile>
diff --git a/gsm-receiver/bootstrap b/gsm-receiver/bootstrap
new file mode 100755
index 0000000..7e0a2eb
--- /dev/null
+++ b/gsm-receiver/bootstrap
@@ -0,0 +1,32 @@
+#!/bin/sh
+
+# Copyright 2001,2005 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+
+rm -fr config.cache autom4te*.cache
+
+aclocal -I config
+autoconf
+autoheader
+libtoolize --automake
+automake --add-missing
+if test ! -d debug; then
+ mkdir debug
+fi
diff --git a/gsm-receiver/config/.gitignore b/gsm-receiver/config/.gitignore
new file mode 100644
index 0000000..38066dd
--- /dev/null
+++ b/gsm-receiver/config/.gitignore
@@ -0,0 +1,5 @@
+libtool.m4
+ltoptions.m4
+ltsugar.m4
+ltversion.m4
+lt~obsolete.m4
diff --git a/gsm-receiver/config/Makefile.am b/gsm-receiver/config/Makefile.am
new file mode 100644
index 0000000..1c99d68
--- /dev/null
+++ b/gsm-receiver/config/Makefile.am
@@ -0,0 +1,70 @@
+#
+# Copyright 2001 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+include $(top_srcdir)/Makefile.common
+
+# Install m4 macros in this directory
+m4datadir = $(datadir)/aclocal
+
+# List your m4 macros here
+m4macros = \
+ acx_pthread.m4 \
+ bnv_have_qt.m4 \
+ cppunit.m4 \
+ gr_boost.m4 \
+ gr_check_createfilemapping.m4 \
+ gr_check_usrp.m4 \
+ gr_check_mc4020.m4 \
+ gr_check_shm_open.m4 \
+ gr_doxygen.m4 \
+ gr_gprof.m4 \
+ gr_libgnuradio_core_extra_ldflags.m4 \
+ gr_no_undefined.m4 \
+ gr_omnithread.m4 \
+ gr_pwin32.m4 \
+ gr_python.m4 \
+ gr_require_mc4020.m4 \
+ gr_scripting.m4 \
+ gr_set_md_cpu.m4 \
+ gr_swig.m4 \
+ gr_sysv_shm.m4 \
+ gr_x86_64.m4 \
+ lf_cc.m4 \
+ lf_cxx.m4 \
+ lf_warnings.m4 \
+ lf_x11.m4 \
+ mkstemp.m4 \
+ onceonly.m4 \
+ pkg.m4 \
+ usrp_fusb_tech.m4 \
+ usrp_libusb.m4 \
+ usrp_sdcc.m4
+
+
+# Don't install m4 macros anymore
+# m4data_DATA = $(m4macros)
+
+EXTRA_DIST = $(m4macros) \
+ libtool.m4 \
+ lt~obsolete.m4 \
+ ltsugar.m4 \
+ ltversion.m4 \
+ ltoptions.m4
diff --git a/gsm-receiver/config/acx_pthread.m4 b/gsm-receiver/config/acx_pthread.m4
new file mode 100644
index 0000000..d318ab0
--- /dev/null
+++ b/gsm-receiver/config/acx_pthread.m4
@@ -0,0 +1,190 @@
+dnl Available from the GNU Autoconf Macro Archive at:
+dnl http://www.gnu.org/software/ac-archive/htmldoc/acx_pthread.html
+dnl
+AC_DEFUN([ACX_PTHREAD], [
+AC_REQUIRE([AC_CANONICAL_HOST])
+AC_LANG_SAVE
+AC_LANG_C
+acx_pthread_ok=no
+
+# We used to check for pthread.h first, but this fails if pthread.h
+# requires special compiler flags (e.g. on True64 or Sequent).
+# It gets checked for in the link test anyway.
+
+# First of all, check if the user has set any of the PTHREAD_LIBS,
+# etcetera environment variables, and if threads linking works using
+# them:
+if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+ save_LIBS="$LIBS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
+ AC_TRY_LINK_FUNC(pthread_join, acx_pthread_ok=yes)
+ AC_MSG_RESULT($acx_pthread_ok)
+ if test x"$acx_pthread_ok" = xno; then
+ PTHREAD_LIBS=""
+ PTHREAD_CFLAGS=""
+ fi
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+fi
+
+# We must check for the threads library under a number of different
+# names; the ordering is very important because some systems
+# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
+# libraries is broken (non-POSIX).
+
+# Create a list of thread flags to try. Items starting with a "-" are
+# C compiler flags, and other items are library names, except for "none"
+# which indicates that we try without any flags at all.
+
+acx_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt"
+
+# The ordering *is* (sometimes) important. Some notes on the
+# individual items follow:
+
+# pthreads: AIX (must check this before -lpthread)
+# none: in case threads are in libc; should be tried before -Kthread and
+# other compiler flags to prevent continual compiler warnings
+# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
+# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
+# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
+# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
+# -pthreads: Solaris/gcc
+# -mthreads: Mingw32/gcc, Lynx/gcc
+# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
+# doesn't hurt to check since this sometimes defines pthreads too;
+# also defines -D_REENTRANT)
+# pthread: Linux, etcetera
+# --thread-safe: KAI C++
+
+case "${host_cpu}-${host_os}" in
+ *solaris*)
+
+ # On Solaris (at least, for some versions), libc contains stubbed
+ # (non-functional) versions of the pthreads routines, so link-based
+ # tests will erroneously succeed. (We need to link with -pthread or
+ # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
+ # a function called by this macro, so we could check for that, but
+ # who knows whether they'll stub that too in a future libc.) So,
+ # we'll just look for -pthreads and -lpthread first:
+
+ acx_pthread_flags="-pthread -pthreads pthread -mt $acx_pthread_flags"
+ ;;
+esac
+
+if test x"$acx_pthread_ok" = xno; then
+for flag in $acx_pthread_flags; do
+
+ case $flag in
+ none)
+ AC_MSG_CHECKING([whether pthreads work without any flags])
+ ;;
+
+ -*)
+ AC_MSG_CHECKING([whether pthreads work with $flag])
+ PTHREAD_CFLAGS="$flag"
+ ;;
+
+ *)
+ AC_MSG_CHECKING([for the pthreads library -l$flag])
+ PTHREAD_LIBS="-l$flag"
+ ;;
+ esac
+
+ save_LIBS="$LIBS"
+ save_CFLAGS="$CFLAGS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+ # Check for various functions. We must include pthread.h,
+ # since some functions may be macros. (On the Sequent, we
+ # need a special flag -Kthread to make this header compile.)
+ # We check for pthread_join because it is in -lpthread on IRIX
+ # while pthread_create is in libc. We check for pthread_attr_init
+ # due to DEC craziness with -lpthreads. We check for
+ # pthread_cleanup_push because it is one of the few pthread
+ # functions on Solaris that doesn't have a non-functional libc stub.
+ # We try pthread_create on general principles.
+ AC_TRY_LINK([#include <pthread.h>],
+ [pthread_t th; pthread_join(th, 0);
+ pthread_attr_init(0); pthread_cleanup_push(0, 0);
+ pthread_create(0,0,0,0); pthread_cleanup_pop(0); ],
+ [acx_pthread_ok=yes])
+
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+
+ AC_MSG_RESULT($acx_pthread_ok)
+ if test "x$acx_pthread_ok" = xyes; then
+ break;
+ fi
+
+ PTHREAD_LIBS=""
+ PTHREAD_CFLAGS=""
+done
+fi
+
+# Various other checks:
+if test "x$acx_pthread_ok" = xyes; then
+ save_LIBS="$LIBS"
+ LIBS="$PTHREAD_LIBS $LIBS"
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
+ # Detect AIX lossage: threads are created detached by default
+ # and the JOINABLE attribute has a nonstandard name (UNDETACHED).
+ AC_MSG_CHECKING([for joinable pthread attribute])
+ AC_TRY_LINK([#include <pthread.h>],
+ [int attr=PTHREAD_CREATE_JOINABLE;],
+ ok=PTHREAD_CREATE_JOINABLE, ok=unknown)
+ if test x"$ok" = xunknown; then
+ AC_TRY_LINK([#include <pthread.h>],
+ [int attr=PTHREAD_CREATE_UNDETACHED;],
+ ok=PTHREAD_CREATE_UNDETACHED, ok=unknown)
+ fi
+ if test x"$ok" != xPTHREAD_CREATE_JOINABLE; then
+ AC_DEFINE(PTHREAD_CREATE_JOINABLE, $ok,
+ [Define to the necessary symbol if this constant
+ uses a non-standard name on your system.])
+ fi
+ AC_MSG_RESULT(${ok})
+ if test x"$ok" = xunknown; then
+ AC_MSG_WARN([we do not know how to create joinable pthreads])
+ fi
+
+ AC_MSG_CHECKING([if more special flags are required for pthreads])
+ flag=no
+ case "${host_cpu}-${host_os}" in
+ *-aix* | *-freebsd*) flag="-D_THREAD_SAFE";;
+ *solaris* | *-osf* | *-hpux*) flag="-D_REENTRANT";;
+ esac
+ AC_MSG_RESULT(${flag})
+ if test "x$flag" != xno; then
+ PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
+ fi
+
+ LIBS="$save_LIBS"
+ CFLAGS="$save_CFLAGS"
+
+ # More AIX lossage: must compile with cc_r
+ AC_CHECK_PROG(PTHREAD_CC, cc_r, cc_r, ${CC})
+else
+ PTHREAD_CC="$CC"
+fi
+
+AC_SUBST(PTHREAD_LIBS)
+AC_SUBST(PTHREAD_CFLAGS)
+AC_SUBST(PTHREAD_CC)
+
+# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
+if test x"$acx_pthread_ok" = xyes; then
+ ifelse([$1],,AC_DEFINE(HAVE_PTHREAD,1,[Define if you have POSIX threads libraries and header files.]),[$1])
+ :
+else
+ acx_pthread_ok=no
+ $2
+fi
+AC_LANG_RESTORE
+])dnl ACX_PTHREAD
diff --git a/gsm-receiver/config/bnv_have_qt.m4 b/gsm-receiver/config/bnv_have_qt.m4
new file mode 100644
index 0000000..1469bfb
--- /dev/null
+++ b/gsm-receiver/config/bnv_have_qt.m4
@@ -0,0 +1,404 @@
+dnl Available from the GNU Autoconf Macro Archive at:
+dnl http://www.gnu.org/software/ac-archive/htmldoc/bnv_have_qt.html
+dnl
+AC_DEFUN([BNV_HAVE_QT],
+[
+ dnl THANKS! This code includes bug fixes by:
+ dnl Tim McClarren.
+
+ AC_REQUIRE([AC_PROG_CXX])
+ AC_REQUIRE([AC_PATH_X])
+ AC_REQUIRE([AC_PATH_XTRA])
+
+ AC_MSG_CHECKING(for Qt)
+
+ AC_ARG_WITH([Qt-dir],
+ [ --with-Qt-dir=DIR DIR is equal to \$QTDIR if you have followed the
+ installation instructions of Trolltech. Header
+ files are in DIR/include, binary utilities are
+ in DIR/bin and the library is in DIR/lib])
+ AC_ARG_WITH([Qt-include-dir],
+ [ --with-Qt-include-dir=DIR
+ Qt header files are in DIR])
+ AC_ARG_WITH([Qt-bin-dir],
+ [ --with-Qt-bin-dir=DIR Qt utilities such as moc and uic are in DIR])
+ AC_ARG_WITH([Qt-lib-dir],
+ [ --with-Qt-lib-dir=DIR The Qt library is in DIR])
+ AC_ARG_WITH([Qt-lib],
+ [ --with-Qt-lib=LIB Use -lLIB to link with the Qt library])
+ if test x"$with_Qt_dir" = x"no" ||
+ test x"$with_Qt_include-dir" = x"no" ||
+ test x"$with_Qt_bin_dir" = x"no" ||
+ test x"$with_Qt_lib_dir" = x"no" ||
+ test x"$with_Qt_lib" = x"no"; then
+ # user disabled Qt. Leave cache alone.
+ have_qt="User disabled Qt."
+ else
+ # "yes" is a bogus option
+ if test x"$with_Qt_dir" = xyes; then
+ with_Qt_dir=
+ fi
+ if test x"$with_Qt_include_dir" = xyes; then
+ with_Qt_include_dir=
+ fi
+ if test x"$with_Qt_bin_dir" = xyes; then
+ with_Qt_bin_dir=
+ fi
+ if test x"$with_Qt_lib_dir" = xyes; then
+ with_Qt_lib_dir=
+ fi
+ if test x"$with_Qt_lib" = xyes; then
+ with_Qt_lib=
+ fi
+ # No Qt unless we discover otherwise
+ have_qt=no
+ # Check whether we are requested to link with a specific version
+ if test x"$with_Qt_lib" != x; then
+ bnv_qt_lib="$with_Qt_lib"
+ fi
+ # Check whether we were supplied with an answer already
+ if test x"$with_Qt_dir" != x; then
+ have_qt=yes
+ bnv_qt_dir="$with_Qt_dir"
+ bnv_qt_include_dir="$with_Qt_dir/include"
+ bnv_qt_bin_dir="$with_Qt_dir/bin"
+ bnv_qt_lib_dir="$with_Qt_dir/lib"
+ # Only search for the lib if the user did not define one already
+ if test x"$bnv_qt_lib" = x; then
+ bnv_qt_lib="`ls $bnv_qt_lib_dir/libqt* | sed -n 1p |
+ sed s@$bnv_qt_lib_dir/lib@@ | [sed s@[.].*@@]`"
+ fi
+ bnv_qt_LIBS="-L$bnv_qt_lib_dir -l$bnv_qt_lib $X_PRE_LIBS $X_LIBS -lX11 -lXext -lXmu -lXt -lXi $X_EXTRA_LIBS"
+ else
+ # Use cached value or do search, starting with suggestions from
+ # the command line
+ AC_CACHE_VAL(bnv_cv_have_qt,
+ [
+ # We are not given a solution and there is no cached value.
+ bnv_qt_dir=NO
+ bnv_qt_include_dir=NO
+ bnv_qt_lib_dir=NO
+ if test x"$bnv_qt_lib" = x; then
+ bnv_qt_lib=NO
+ fi
+ BNV_PATH_QT_DIRECT
+ if test "$bnv_qt_dir" = NO ||
+ test "$bnv_qt_include_dir" = NO ||
+ test "$bnv_qt_lib_dir" = NO ||
+ test "$bnv_qt_lib" = NO; then
+ # Problem with finding complete Qt. Cache the known absence of Qt.
+ bnv_cv_have_qt="have_qt=no"
+ else
+ # Record where we found Qt for the cache.
+ bnv_cv_have_qt="have_qt=yes \
+ bnv_qt_dir=$bnv_qt_dir \
+ bnv_qt_include_dir=$bnv_qt_include_dir \
+ bnv_qt_bin_dir=$bnv_qt_bin_dir \
+ bnv_qt_LIBS=\"$bnv_qt_LIBS\""
+ fi
+ ])dnl
+ eval "$bnv_cv_have_qt"
+ fi # all $bnv_qt_* are set
+ fi # $have_qt reflects the system status
+ if test x"$have_qt" = xyes; then
+ QT_CXXFLAGS="-I$bnv_qt_include_dir"
+ QT_DIR="$bnv_qt_dir"
+ QT_LIBS="$bnv_qt_LIBS"
+ # If bnv_qt_dir is defined, utilities are expected to be in the
+ # bin subdirectory
+ if test x"$bnv_qt_dir" != x; then
+ if test -x "$bnv_qt_dir/bin/uic"; then
+ QT_UIC="$bnv_qt_dir/bin/uic"
+ else
+ # Old versions of Qt don't have uic
+ QT_UIC=
+ fi
+ QT_MOC="$bnv_qt_dir/bin/moc"
+ else
+ # Or maybe we are told where to look for the utilities
+ if test x"$bnv_qt_bin_dir" != x; then
+ if test -x "$bnv_qt_bin_dir/uic"; then
+ QT_UIC="$bnv_qt_bin_dir/uic"
+ else
+ # Old versions of Qt don't have uic
+ QT_UIC=
+ fi
+ QT_MOC="$bnv_qt_bin_dir/moc"
+ else
+ # Last possibility is that they are in $PATH
+ QT_UIC="`which uic`"
+ QT_MOC="`which moc`"
+ fi
+ fi
+ # All variables are defined, report the result
+ AC_MSG_RESULT([$have_qt:
+ QT_CXXFLAGS=$QT_CXXFLAGS
+ QT_DIR=$QT_DIR
+ QT_LIBS=$QT_LIBS
+ QT_UIC=$QT_UIC
+ QT_MOC=$QT_MOC])
+ else
+ # Qt was not found
+ QT_CXXFLAGS=
+ QT_DIR=
+ QT_LIBS=
+ QT_UIC=
+ QT_MOC=
+ AC_MSG_RESULT($have_qt)
+ fi
+ AC_SUBST(QT_CXXFLAGS)
+ AC_SUBST(QT_DIR)
+ AC_SUBST(QT_LIBS)
+ AC_SUBST(QT_UIC)
+ AC_SUBST(QT_MOC)
+
+ #### Being paranoid:
+ if test x"$have_qt" = xyes; then
+ AC_MSG_CHECKING(correct functioning of Qt installation)
+ AC_CACHE_VAL(bnv_cv_qt_test_result,
+ [
+ cat > bnv_qt_test.h << EOF
+#include <qobject.h>
+class Test : public QObject
+{
+Q_OBJECT
+public:
+ Test() {}
+ ~Test() {}
+public slots:
+ void receive() {}
+signals:
+ void send();
+};
+EOF
+
+ cat > bnv_qt_main.$ac_ext << EOF
+#include "bnv_qt_test.h"
+#include <qapplication.h>
+int main( int argc, char **argv )
+{
+ QApplication app( argc, argv );
+ Test t;
+ QObject::connect( &t, SIGNAL(send()), &t, SLOT(receive()) );
+}
+EOF
+
+ bnv_cv_qt_test_result="failure"
+ bnv_try_1="$QT_MOC bnv_qt_test.h -o moc_bnv_qt_test.$ac_ext >/dev/null 2>bnv_qt_test_1.out"
+ AC_TRY_EVAL(bnv_try_1)
+ bnv_err_1=`grep -v '^ *+' bnv_qt_test_1.out | grep -v "^bnv_qt_test.h\$"`
+ if test x"$bnv_err_1" != x; then
+ echo "$bnv_err_1" >&AC_FD_CC
+ echo "configure: could not run $QT_MOC on:" >&AC_FD_CC
+ cat bnv_qt_test.h >&AC_FD_CC
+ else
+ bnv_try_2="$CXX $QT_CXXFLAGS -c $CXXFLAGS -o moc_bnv_qt_test.o moc_bnv_qt_test.$ac_ext >/dev/null 2>bnv_qt_test_2.out"
+ AC_TRY_EVAL(bnv_try_2)
+ bnv_err_2=`grep -v '^ *+' bnv_qt_test_2.out | grep -v "^bnv_qt_test.{$ac_ext}\$"`
+ if test x"$bnv_err_2" != x; then
+ echo "$bnv_err_2" >&AC_FD_CC
+ echo "configure: could not compile:" >&AC_FD_CC
+ cat bnv_qt_test.$ac_ext >&AC_FD_CC
+ else
+ bnv_try_3="$CXX $QT_CXXFLAGS -c $CXXFLAGS -o bnv_qt_main.o bnv_qt_main.$ac_ext >/dev/null 2>bnv_qt_test_3.out"
+ AC_TRY_EVAL(bnv_try_3)
+ bnv_err_3=`grep -v '^ *+' bnv_qt_test_3.out | grep -v "^bnv_qt_main.{$ac_ext}\$"`
+ if test x"$bnv_err_3" != x; then
+ echo "$bnv_err_3" >&AC_FD_CC
+ echo "configure: could not compile:" >&AC_FD_CC
+ cat bnv_qt_main.$ac_ext >&AC_FD_CC
+ else
+ bnv_try_4="$CXX $QT_LIBS $LIBS -o bnv_qt_main bnv_qt_main.o moc_bnv_qt_test.o >/dev/null 2>bnv_qt_test_4.out"
+ AC_TRY_EVAL(bnv_try_4)
+ bnv_err_4=`grep -v '^ *+' bnv_qt_test_4.out`
+ if test x"$bnv_err_4" != x; then
+ echo "$bnv_err_4" >&AC_FD_CC
+ else
+ bnv_cv_qt_test_result="success"
+ fi
+ fi
+ fi
+ fi
+ ])dnl AC_CACHE_VAL bnv_cv_qt_test_result
+ AC_MSG_RESULT([$bnv_cv_qt_test_result]);
+ if test x"$bnv_cv_qt_test_result" = "xfailure"; then
+ # working Qt was not found
+ QT_CXXFLAGS=
+ QT_DIR=
+ QT_LIBS=
+ QT_UIC=
+ QT_MOC=
+ have_qt=no
+ AC_MSG_WARN([Failed to find matching components of a complete
+ Qt installation. Try using more options,
+ see ./configure --help.])
+ fi
+
+ rm -f bnv_qt_test.h moc_bnv_qt_test.$ac_ext moc_bnv_qt_test.o \
+ bnv_qt_main.$ac_ext bnv_qt_main.o bnv_qt_main \
+ bnv_qt_test_1.out bnv_qt_test_2.out bnv_qt_test_3.out bnv_qt_test_4.out
+ fi
+])
+
+dnl Internal subroutine of BNV_HAVE_QT
+dnl Set bnv_qt_dir bnv_qt_include_dir bnv_qt_bin_dir bnv_qt_lib_dir bnv_qt_lib
+dnl Copyright 2001 Bastiaan N. Veelo <Bastiaan.N.Veelo@immtek.ntnu.no>
+AC_DEFUN([BNV_PATH_QT_DIRECT],
+[
+ ## Binary utilities ##
+ if test x"$with_Qt_bin_dir" != x; then
+ bnv_qt_bin_dir=$with_Qt_bin_dir
+ fi
+ ## Look for header files ##
+ if test x"$with_Qt_include_dir" != x; then
+ bnv_qt_include_dir="$with_Qt_include_dir"
+ else
+ # The following header file is expected to define QT_VERSION.
+ qt_direct_test_header=qglobal.h
+ # Look for the header file in a standard set of common directories.
+ bnv_include_path_list="
+ /usr/include
+ `ls -dr /usr/include/qt* 2>/dev/null`
+ `ls -dr /usr/lib/qt*/include 2>/dev/null`
+ `ls -dr /usr/local/qt*/include 2>/dev/null`
+ `ls -dr /opt/qt*/include 2>/dev/null`
+ "
+ for bnv_dir in $bnv_include_path_list; do
+ if test -r "$bnv_dir/$qt_direct_test_header"; then
+ bnv_dirs="$bnv_dirs $bnv_dir"
+ fi
+ done
+ # Now look for the newest in this list
+ bnv_prev_ver=0
+ for bnv_dir in $bnv_dirs; do
+ bnv_this_ver=`egrep -w '#define QT_VERSION' $bnv_dir/$qt_direct_test_header | sed s/'#define QT_VERSION'//`
+ if expr $bnv_this_ver '>' $bnv_prev_ver > /dev/null; then
+ bnv_qt_include_dir=$bnv_dir
+ bnv_prev_ver=$bnv_this_ver
+ fi
+ done
+ fi dnl Found header files.
+
+ # Are these headers located in a traditional Trolltech installation?
+ # That would be $bnv_qt_include_dir stripped from its last element:
+ bnv_possible_qt_dir=`dirname $bnv_qt_include_dir`
+ if test -x $bnv_possible_qt_dir/bin/moc &&
+ ls $bnv_possible_qt_dir/lib/libqt* > /dev/null; then
+ # Then the rest is a piece of cake
+ bnv_qt_dir=$bnv_possible_qt_dir
+ bnv_qt_bin_dir="$bnv_qt_dir/bin"
+ bnv_qt_lib_dir="$bnv_qt_dir/lib"
+ # Only look for lib if the user did not supply it already
+ if test x"$bnv_qt_lib" = xNO; then
+ bnv_qt_lib="`ls $bnv_qt_lib_dir/libqt* | sed -n 1p |
+ sed s@$bnv_qt_lib_dir/lib@@ | [sed s@[.].*@@]`"
+ fi
+ bnv_qt_LIBS="-L$bnv_qt_lib_dir -l$bnv_qt_lib $X_PRE_LIBS $X_LIBS -lX11 -lXext -lXmu -lXt -lXi $X_EXTRA_LIBS"
+ else
+ # There is no valid definition for $QTDIR as Trolltech likes to see it
+ bnv_qt_dir=
+ ## Look for Qt library ##
+ if test x"$with_Qt_lib_dir" != x; then
+ bnv_qt_lib_dir="$with_Qt_lib_dir"
+ # Only look for lib if the user did not supply it already
+ if test x"$bnv_qt_lib" = xNO; then
+ bnv_qt_lib="`ls $bnv_qt_lib_dir/libqt* | sed -n 1p |
+ sed s@$bnv_qt_lib_dir/lib@@ | [sed s@[.].*@@]`"
+ fi
+ bnv_qt_LIBS="-L$bnv_qt_lib_dir -l$bnv_qt_lib $X_PRE_LIBS $X_LIBS -lX11 -lXext -lXmu -lXt -lXi $X_EXTRA_LIBS"
+ else
+ # Normally, when there is no traditional Trolltech installation,
+ # the library is installed in a place where the linker finds it
+ # automatically.
+ # If the user did not define the library name, try with qt
+ if test x"$bnv_qt_lib" = xNO; then
+ bnv_qt_lib=qt
+ fi
+ qt_direct_test_header=qapplication.h
+ qt_direct_test_main="
+ int argc;
+ char ** argv;
+ QApplication app(argc,argv);
+ "
+ # See if we find the library without any special options.
+ # Don't add top $LIBS permanently yet
+ bnv_save_LIBS="$LIBS"
+ LIBS="-l$bnv_qt_lib $X_PRE_LIBS $X_LIBS -lX11 -lXext -lXmu -lXt -lXi $X_EXTRA_LIBS"
+ bnv_qt_LIBS="$LIBS"
+ bnv_save_CXXFLAGS="$CXXFLAGS"
+ CXXFLAGS="-I$bnv_qt_include_dir"
+ AC_TRY_LINK([#include <$qt_direct_test_header>],
+ $qt_direct_test_main,
+ [
+ # Success.
+ # We can link with no special library directory.
+ bnv_qt_lib_dir=
+ ], [
+ # That did not work. Try the multi-threaded version
+ echo "Non-critical error, please neglect the above." >&AC_FD_CC
+ bnv_qt_lib=qt-mt
+ LIBS="-l$bnv_qt_lib $X_PRE_LIBS $X_LIBS -lX11 -lXext -lXmu -lXt -lXi $X_EXTRA_LIBS"
+ AC_TRY_LINK([#include <$qt_direct_test_header>],
+ $qt_direct_test_main,
+ [
+ # Success.
+ # We can link with no special library directory.
+ bnv_qt_lib_dir=
+ ], [
+ # That did not work. Try the OpenGL version
+ echo "Non-critical error, please neglect the above." >&AC_FD_CC
+ bnv_qt_lib=qt-gl
+ LIBS="-l$bnv_qt_lib $X_PRE_LIBS $X_LIBS -lX11 -lXext -lXmu -lXt -lXi $X_EXTRA_LIBS"
+ AC_TRY_LINK([#include <$qt_direct_test_header>],
+ $qt_direct_test_main,
+ [
+ # Succes.
+ # We can link with no special library directory.
+ bnv_qt_lib_dir=
+ ], [
+ # That did not work. Maybe a library version I don't know about?
+ echo "Non-critical error, please neglect the above." >&AC_FD_CC
+ # Look for some Qt lib in a standard set of common directories.
+ bnv_dir_list="
+ `echo $bnv_qt_includes | sed ss/includess`
+ /lib
+ /usr/lib
+ /usr/local/lib
+ /opt/lib
+ `ls -dr /usr/lib/qt* 2>/dev/null`
+ `ls -dr /usr/local/qt* 2>/dev/null`
+ `ls -dr /opt/qt* 2>/dev/null`
+ "
+ for bnv_dir in $bnv_dir_list; do
+ if ls $bnv_dir/libqt*; then
+ # Gamble that it's the first one...
+ bnv_qt_lib="`ls $bnv_dir/libqt* | sed -n 1p |
+ sed s@$bnv_dir/lib@@ | sed s/[.].*//`"
+ bnv_qt_lib_dir="$bnv_dir"
+ break
+ fi
+ done
+ # Try with that one
+ LIBS="-l$bnv_qt_lib $X_PRE_LIBS $X_LIBS -lX11 -lXext -lXmu -lXt -lXi $X_EXTRA_LIBS"
+ AC_TRY_LINK([#include <$qt_direct_test_header>],
+ $qt_direct_test_main,
+ [
+ # Succes.
+ # We can link with no special library directory.
+ bnv_qt_lib_dir=
+ ], [
+ # Leave bnv_qt_lib_dir defined
+ ])
+ ])
+ ])
+ ])
+ if test x"$bnv_qt_lib_dir" != x; then
+ bnv_qt_LIBS="-l$bnv_qt_lib_dir $LIBS"
+ else
+ bnv_qt_LIBS="$LIBS"
+ fi
+ LIBS="$bnv_save_LIBS"
+ CXXFLAGS="$bnv_save_CXXFLAGS"
+ fi dnl $with_Qt_lib_dir was not given
+ fi dnl Done setting up for non-traditional Trolltech installation
+])
diff --git a/gsm-receiver/config/cppunit.m4 b/gsm-receiver/config/cppunit.m4
new file mode 100644
index 0000000..0991d51
--- /dev/null
+++ b/gsm-receiver/config/cppunit.m4
@@ -0,0 +1,80 @@
+dnl
+dnl AM_PATH_CPPUNIT(MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]])
+dnl
+AC_DEFUN([AM_PATH_CPPUNIT],
+[
+
+AC_ARG_WITH(cppunit-prefix,[ --with-cppunit-prefix=PFX Prefix where CppUnit is installed (optional)],
+ cppunit_config_prefix="$withval", cppunit_config_prefix="")
+AC_ARG_WITH(cppunit-exec-prefix,[ --with-cppunit-exec-prefix=PFX Exec prefix where CppUnit is installed (optional)],
+ cppunit_config_exec_prefix="$withval", cppunit_config_exec_prefix="")
+
+ if test x$cppunit_config_exec_prefix != x ; then
+ cppunit_config_args="$cppunit_config_args --exec-prefix=$cppunit_config_exec_prefix"
+ if test x${CPPUNIT_CONFIG+set} != xset ; then
+ CPPUNIT_CONFIG=$cppunit_config_exec_prefix/bin/cppunit-config
+ fi
+ fi
+ if test x$cppunit_config_prefix != x ; then
+ cppunit_config_args="$cppunit_config_args --prefix=$cppunit_config_prefix"
+ if test x${CPPUNIT_CONFIG+set} != xset ; then
+ CPPUNIT_CONFIG=$cppunit_config_prefix/bin/cppunit-config
+ fi
+ fi
+
+ AC_PATH_PROG(CPPUNIT_CONFIG, cppunit-config, no)
+ cppunit_version_min=$1
+
+ AC_MSG_CHECKING(for Cppunit - version >= $cppunit_version_min)
+ no_cppunit=""
+ if test "$CPPUNIT_CONFIG" = "no" ; then
+ no_cppunit=yes
+ else
+ CPPUNIT_CFLAGS=`$CPPUNIT_CONFIG --cflags`
+ CPPUNIT_LIBS=`$CPPUNIT_CONFIG --libs`
+ cppunit_version=`$CPPUNIT_CONFIG --version`
+
+ cppunit_major_version=`echo $cppunit_version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
+ cppunit_minor_version=`echo $cppunit_version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
+ cppunit_micro_version=`echo $cppunit_version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
+
+ cppunit_major_min=`echo $cppunit_version_min | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
+ cppunit_minor_min=`echo $cppunit_version_min | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
+ cppunit_micro_min=`echo $cppunit_version_min | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
+
+ cppunit_version_proper=`expr \
+ $cppunit_major_version \> $cppunit_major_min \| \
+ $cppunit_major_version \= $cppunit_major_min \& \
+ $cppunit_minor_version \> $cppunit_minor_min \| \
+ $cppunit_major_version \= $cppunit_major_min \& \
+ $cppunit_minor_version \= $cppunit_minor_min \& \
+ $cppunit_micro_version \>= $cppunit_micro_min `
+
+ if test "$cppunit_version_proper" = "1" ; then
+ AC_MSG_RESULT([$cppunit_major_version.$cppunit_minor_version.$cppunit_micro_version])
+ else
+ AC_MSG_RESULT(no)
+ no_cppunit=yes
+ fi
+ fi
+
+ if test "x$no_cppunit" = x ; then
+ ifelse([$2], , :, [$2])
+ else
+ CPPUNIT_CFLAGS=""
+ CPPUNIT_LIBS=""
+ ifelse([$3], , :, [$3])
+ fi
+
+ AC_SUBST(CPPUNIT_CFLAGS)
+ AC_SUBST(CPPUNIT_LIBS)
+])
+
+
+
diff --git a/gsm-receiver/config/gr_boost.m4 b/gsm-receiver/config/gr_boost.m4
new file mode 100644
index 0000000..0664d36
--- /dev/null
+++ b/gsm-receiver/config/gr_boost.m4
@@ -0,0 +1,111 @@
+dnl
+dnl Copyright 2004,2005 Free Software Foundation, Inc.
+dnl
+dnl This file is part of GNU Radio
+dnl
+dnl GNU Radio is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 3, or (at your option)
+dnl any later version.
+dnl
+dnl GNU Radio is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with GNU Radio; see the file COPYING. If not, write to
+dnl the Free Software Foundation, Inc., 51 Franklin Street,
+dnl Boston, MA 02110-1301, USA.
+dnl
+
+dnl This tries to do the "right thing" to locate the boost include files.
+dnl If the user explicitly specified --with-boost-include-dir=<foo>
+dnl we believe them and use it. Otherwise,
+dnl
+dnl We look for boost/shared_ptr.hpp in the "normal places". That is,
+dnl wherever AC_CHECK_HEADER looks. If the boost includes are in /usr/local/include
+dnl this step will find them.
+dnl
+dnl Otherwise, we check to see if the boost stuff was installed in a version-specific
+dnl directory under /usr/local/include. These look like: /usr/local/include/boost-1_33_1
+dnl If there's more than one version installed, we select the
+dnl lexicographically greatest one.
+dnl
+dnl If none of these work, we bail.
+
+AC_DEFUN([GR_REQUIRE_BOOST_INCLUDES],
+[
+ AC_LANG_PUSH(C++)
+ gr_boost_include_dir=
+ AC_ARG_WITH([boost-include-dir],
+ AC_HELP_STRING([--with-boost-include-dir=<path>],
+ [path to boost c++ include files]),
+ [
+ # "yes" and "no" are bogus answers
+ if test x"$with_boost_include_dir" = xyes ||
+ test x"$with_boost_include_dir" = xno; then
+ gr_boost_include_dir=
+ else
+ gr_boost_include_dir=$with_boost_include_dir
+ fi
+ ])
+ echo "gr_boost_include_dir = $gr_boost_include_dir"
+ if test x$gr_boost_include_dir != x; then
+ #
+ # If the user specified a directory, then we use it
+ #
+ OLD_CPPFLAGS=$CPPFLAGS
+ CPPFLAGS="$CPPFLAGS -I$gr_boost_include_dir"
+ AC_CHECK_HEADER([boost/shared_ptr.hpp],
+ [BOOST_CFLAGS="-I$gr_boost_include_dir"],
+ [AC_MSG_ERROR(
+ [Failed to locate boost/shared_ptr.hpp.
+Try using --with-boost-include-dir=<path>,
+E.g., --with-boost-include-dir=/usr/local/include/boost-1_33_1])])
+ CPPFLAGS=$OLD_CPPFLAGS
+ else
+ #
+ # Otherwise we check in the default places
+ #
+ AC_CHECK_HEADER([boost/shared_ptr.hpp],
+ [BOOST_CFLAGS=""],
+ [ # Nope, look for latest version if any in $prefix/include/boost-*
+
+ # Wipe out cached value. KLUDGE: AC should have API for this
+ unset AS_TR_SH([ac_cv_header_boost/shared_ptr.hpp])
+
+ boost_last_match(){
+ #echo "boost_last_match: [$]*"
+ pattern="[$]1"
+ shift
+ if test "[$]pattern" = "[$]1"
+ then
+ LM=''
+ else
+ shift `expr [$]# - 1`
+ LM=[$]1
+ fi
+ #echo "LM(1)='[$]LM'"
+ }
+
+ pattern="/usr/local/include/boost-*"
+ boost_last_match "$pattern" $pattern
+ #echo "LM(2)='$LM'"
+
+ OLD_CPPFLAGS=$CPP_FLAGS
+ CPPFLAGS="$CPPFLAGS -I$LM"
+ AC_CHECK_HEADER([boost/shared_ptr.hpp],
+ [BOOST_CFLAGS="-I$LM"],
+ [AC_MSG_ERROR(
+ [Failed to locate boost/shared_ptr.hpp.
+Try using --with-boost-include-dir=<path>,
+E.g., --with-boost-include-dir=/usr/local/include/boost-1_33_1])])
+ CPPFLAGS=$OLD_CPPFLAGS
+ ])
+
+ fi
+ unset boost_last_match LM
+ AC_LANG_POP
+ AC_SUBST(BOOST_CFLAGS)
+])
diff --git a/gsm-receiver/config/gr_check_createfilemapping.m4 b/gsm-receiver/config/gr_check_createfilemapping.m4
new file mode 100644
index 0000000..5f9b4a4
--- /dev/null
+++ b/gsm-receiver/config/gr_check_createfilemapping.m4
@@ -0,0 +1,52 @@
+dnl
+dnl Copyright 2005 Free Software Foundation, Inc.
+dnl
+dnl This file is part of GNU Radio
+dnl
+dnl GNU Radio is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 3, or (at your option)
+dnl any later version.
+dnl
+dnl GNU Radio is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with GNU Radio; see the file COPYING. If not, write to
+dnl the Free Software Foundation, Inc., 51 Franklin Street,
+dnl Boston, MA 02110-1301, USA.
+
+dnl AC_DEFUN([GR_CHECK_CREATEFILEMAPPING],
+dnl [
+dnl AC_CHECK_FUNCS([CreateFileMapping])
+dnl ])
+
+AC_DEFUN([GR_CHECK_CREATEFILEMAPPING],[
+ AC_MSG_CHECKING([for CreateFileMapping function])
+ AC_COMPILE_IFELSE([
+#include <windows.h>
+int main (int argc, char **argv)
+{
+ HANDLE handle;
+ int size;
+ char seg_name[[1024]];
+ handle = CreateFileMapping(
+ INVALID_HANDLE_VALUE, // use paging file
+ NULL, // default security
+ PAGE_READWRITE, // read/write access
+ 0, // max. object size
+ size, // buffer size
+ seg_name); // name of mapping object
+ return 0;
+}
+],[HAVE_CREATEFILEMAPPING=yes
+ AC_DEFINE(HAVE_CREATEFILEMAPPING,[1],[Define if you have the CreateFilemapping function(win32).])],
+ [HAVE_CREATEFILEMAPPING=no])
+
+ AC_MSG_RESULT($HAVE_CREATEFILEMAPPING)
+ AM_CONDITIONAL(HAVE_CREATEFILEMAPPING, test x$HAVE_CREATEFILEMAPPING = xyes)
+])
+
+
diff --git a/gsm-receiver/config/gr_check_mc4020.m4 b/gsm-receiver/config/gr_check_mc4020.m4
new file mode 100644
index 0000000..28987c2
--- /dev/null
+++ b/gsm-receiver/config/gr_check_mc4020.m4
@@ -0,0 +1,37 @@
+dnl
+dnl Copyright 2003 Free Software Foundation, Inc.
+dnl
+dnl This file is part of GNU Radio
+dnl
+dnl GNU Radio is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 3, or (at your option)
+dnl any later version.
+dnl
+dnl GNU Radio is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with GNU Radio; see the file COPYING. If not, write to
+dnl the Free Software Foundation, Inc., 51 Franklin Street,
+dnl Boston, MA 02110-1301, USA.
+dnl
+
+AC_DEFUN([GR_CHECK_MC4020],[
+ AC_MSG_CHECKING([for mc4020 A/D driver include file])
+ AC_COMPILE_IFELSE([
+#include <mc4020.h>
+int main (int argc, char **argv)
+{
+ return 0;
+}
+],[HAVE_MC4020=yes
+ AC_DEFINE(HAVE_MC4020,[1],[Define if you have a Measurement Computing PCI-DAS4020/12 A/D])],
+ [HAVE_MC4020=no])
+
+ AC_MSG_RESULT($HAVE_MC4020)
+ AM_CONDITIONAL(HAVE_MC4020, test x$HAVE_MC4020 = xyes)
+])
+
diff --git a/gsm-receiver/config/gr_check_shm_open.m4 b/gsm-receiver/config/gr_check_shm_open.m4
new file mode 100644
index 0000000..83d260b
--- /dev/null
+++ b/gsm-receiver/config/gr_check_shm_open.m4
@@ -0,0 +1,29 @@
+dnl
+dnl Copyright 2003 Free Software Foundation, Inc.
+dnl
+dnl This file is part of GNU Radio
+dnl
+dnl GNU Radio is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 3, or (at your option)
+dnl any later version.
+dnl
+dnl GNU Radio is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with GNU Radio; see the file COPYING. If not, write to
+dnl the Free Software Foundation, Inc., 51 Franklin Street,
+dnl Boston, MA 02110-1301, USA.
+
+AC_DEFUN([GR_CHECK_SHM_OPEN],
+[
+ SHM_OPEN_LIBS=""
+ save_LIBS="$LIBS"
+ AC_SEARCH_LIBS([shm_open], [rt], [SHM_OPEN_LIBS="$LIBS"])
+ AC_CHECK_FUNCS([shm_open])
+ LIBS="$save_LIBS"
+ AC_SUBST(SHM_OPEN_LIBS)
+])
diff --git a/gsm-receiver/config/gr_check_usrp.m4 b/gsm-receiver/config/gr_check_usrp.m4
new file mode 100644
index 0000000..12a5d1c
--- /dev/null
+++ b/gsm-receiver/config/gr_check_usrp.m4
@@ -0,0 +1,32 @@
+dnl
+dnl Copyright 2003 Free Software Foundation, Inc.
+dnl
+dnl This file is part of GNU Radio
+dnl
+dnl GNU Radio is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 3, or (at your option)
+dnl any later version.
+dnl
+dnl GNU Radio is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with GNU Radio; see the file COPYING. If not, write to
+dnl the Free Software Foundation, Inc., 51 Franklin Street,
+dnl Boston, MA 02110-1301, USA.
+dnl
+
+dnl Check for Universal Software Radio Peripheral
+
+AC_DEFUN([GR_CHECK_USRP],[
+ PKG_CHECK_MODULES(USRP, usrp >= 0.2,
+ [HAVE_USRP=yes
+ AC_DEFINE(HAVE_USRP,[1],[Define if you have a USRP])],
+ [HAVE_USRP=no])
+
+ AM_CONDITIONAL(HAVE_USRP, test x$HAVE_USRP = xyes)
+])
+
diff --git a/gsm-receiver/config/gr_doxygen.m4 b/gsm-receiver/config/gr_doxygen.m4
new file mode 100644
index 0000000..4670c29
--- /dev/null
+++ b/gsm-receiver/config/gr_doxygen.m4
@@ -0,0 +1,59 @@
+dnl
+dnl Copyright 2003,2005 Free Software Foundation, Inc.
+dnl
+dnl This file is part of GNU Radio
+dnl
+dnl GNU Radio is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 3, or (at your option)
+dnl any later version.
+dnl
+dnl GNU Radio is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with GNU Radio; see the file COPYING. If not, write to
+dnl the Free Software Foundation, Inc., 51 Franklin Street,
+dnl Boston, MA 02110-1301, USA.
+dnl
+
+AC_DEFUN([GR_CHECK_DOXYGEN],[
+ AC_ARG_ENABLE(doxygen, [ --enable-doxygen enable documentation generation with doxygen (no)])
+ AC_ARG_ENABLE(dot, [ --enable-dot use 'dot' to generate graphs in doxygen (auto)])
+ AC_ARG_ENABLE(html-docs, [ --enable-html-docs enable HTML generation with doxygen (yes)], [], [ enable_html_docs=yes])
+ AC_ARG_ENABLE(latex-docs, [ --enable-latex-docs enable LaTeX doc generation with doxygen (no)], [], [ enable_latex_docs=no])
+
+ if test "x$enable_doxygen" = xyes; then
+ AC_PATH_PROG(DOXYGEN, doxygen, , $PATH)
+ if test x$DOXYGEN = x; then
+ if test "x$enable_doxygen" = xyes; then
+ AC_MSG_ERROR([could not find doxygen])
+ fi
+ enable_doc=no
+ generate_docs=
+ else
+ enable_doc=yes
+ generate_docs=docs
+ AC_PATH_PROG(DOT, dot, , $PATH)
+ fi
+ else
+ enable_doc=no
+ fi
+
+ AM_CONDITIONAL(DOC, test x$enable_doc = xyes)
+
+ if test x$DOT = x; then
+ if test "x$enable_dot" = xyes; then
+ AC_MSG_ERROR([could not find dot])
+ fi
+ enable_dot=no
+ else
+ enable_dot=yes
+ fi
+ AC_SUBST(enable_dot)
+ AC_SUBST(enable_html_docs)
+ AC_SUBST(enable_latex_docs)
+ AC_SUBST(generate_docs)
+])
diff --git a/gsm-receiver/config/gr_gprof.m4 b/gsm-receiver/config/gr_gprof.m4
new file mode 100644
index 0000000..20bacf3
--- /dev/null
+++ b/gsm-receiver/config/gr_gprof.m4
@@ -0,0 +1,72 @@
+dnl
+dnl Copyright 2002 Free Software Foundation, Inc.
+dnl
+dnl This file is part of GNU Radio
+dnl
+dnl GNU Radio is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 3, or (at your option)
+dnl any later version.
+dnl
+dnl GNU Radio is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with GNU Radio; see the file COPYING. If not, write to
+dnl the Free Software Foundation, Inc., 51 Franklin Street,
+dnl Boston, MA 02110-1301, USA.
+dnl
+
+dnl FIXME probably need to add linker flag too...
+
+AC_DEFUN([GR_SET_GPROF],[
+ dnl Check for --with-gprof
+ AC_MSG_CHECKING([whether user wants gprof])
+ AC_ARG_WITH(gprof,
+ [ --with-gprof Turn on gprof profiling],
+ [], [ with_gprof=no ])
+ AC_MSG_RESULT($with_gprof)
+
+ dnl gprof profiling flags for the two main compilers
+ cc_profiling_flags="-pg"
+ cxx_profiling_flags="-pg"
+ ld_profiling_flags="-pg"
+ if test $with_gprof = yes
+ then
+ if test -n "${CC}"
+ then
+ LF_CHECK_CC_FLAG($cc_profiling_flags)
+ fi
+ if test -n "${CXX}"
+ then
+ LF_CHECK_CXX_FLAG($cxx_profiling_flags)
+ fi
+ fi
+])
+
+AC_DEFUN([GR_SET_PROF],[
+ dnl Check for --with-prof
+ AC_MSG_CHECKING([whether user wants prof])
+ AC_ARG_WITH(prof,
+ [ --with-prof Turn on prof profiling],
+ [], [ with_prof=no ])
+ AC_MSG_RESULT($with_prof)
+
+ dnl prof profiling flags for the two main compilers
+ cc_profiling_flags="-p"
+ cxx_profiling_flags="-p"
+ ld_profiling_flags="-p"
+ if test $with_prof = yes
+ then
+ if test -n "${CC}"
+ then
+ LF_CHECK_CC_FLAG($cc_profiling_flags)
+ fi
+ if test -n "${CXX}"
+ then
+ LF_CHECK_CXX_FLAG($cxx_profiling_flags)
+ fi
+ fi
+])
diff --git a/gsm-receiver/config/gr_libgnuradio_core_extra_ldflags.m4 b/gsm-receiver/config/gr_libgnuradio_core_extra_ldflags.m4
new file mode 100644
index 0000000..43f872c
--- /dev/null
+++ b/gsm-receiver/config/gr_libgnuradio_core_extra_ldflags.m4
@@ -0,0 +1,40 @@
+# Check for (MinGW)win32 extra ld options. -*- Autoconf -*-
+
+# Copyright 2003,2004,2005 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+dnl
+AC_DEFUN([GR_LIBGNURADIO_CORE_EXTRA_LDFLAGS], [
+AC_REQUIRE([AC_PROG_LD])
+# on Mingw32 extra LDFLAGS are required to ease global variable linking
+LIBGNURADIO_CORE_EXTRA_LDFLAGS=""
+
+AC_MSG_CHECKING([whether $LD accepts --enable-runtime-pseudo-reloc])
+if ${LD} --enable-runtime-pseudo-reloc --version >/dev/null 2>&1
+then
+ # libtool requires the quotes
+ LIBGNURADIO_CORE_EXTRA_LDFLAGS="\"-Wl,--enable-runtime-pseudo-reloc\""
+ AC_MSG_RESULT(yes)
+else
+ AC_MSG_RESULT(no)
+fi
+
+AC_SUBST(LIBGNURADIO_CORE_EXTRA_LDFLAGS)
+
+])
diff --git a/gsm-receiver/config/gr_no_undefined.m4 b/gsm-receiver/config/gr_no_undefined.m4
new file mode 100644
index 0000000..c8d745d
--- /dev/null
+++ b/gsm-receiver/config/gr_no_undefined.m4
@@ -0,0 +1,44 @@
+dnl
+dnl Copyright 2005 Free Software Foundation, Inc.
+dnl
+dnl This file is part of GNU Radio
+dnl
+dnl GNU Radio is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 3, or (at your option)
+dnl any later version.
+dnl
+dnl GNU Radio is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with GNU Radio; see the file COPYING. If not, write to
+dnl the Free Software Foundation, Inc., 51 Franklin Street,
+dnl Boston, MA 02110-1301, USA.
+dnl
+
+# GR_NO_UNDEFINED()
+#
+# Detemine whether we need to use the -no-undefined linker flag
+# when building shared libraries.
+# Sets NO_UNDEFINED to "" or "-no-undefined"
+#
+# As far as I can tell, we need -no-undefined only when building
+# windows DLLs. This occurs when using MinGW and Cygwin.
+#
+# For now, we stub this out.
+
+AC_DEFUN([GR_NO_UNDEFINED],[
+ AC_REQUIRE([AC_CANONICAL_HOST])
+ no_undefined=""
+ case "${host_os}" in
+ *mingw* | *cygwin*)
+
+ # on MinGW/Cygwin extra LDFLAGS are required
+ no_undefined="-no-undefined"
+ ;;
+ esac
+ AC_SUBST(NO_UNDEFINED,[$no_undefined])
+])
diff --git a/gsm-receiver/config/gr_omnithread.m4 b/gsm-receiver/config/gr_omnithread.m4
new file mode 100644
index 0000000..b5e4090
--- /dev/null
+++ b/gsm-receiver/config/gr_omnithread.m4
@@ -0,0 +1,51 @@
+# Check for Omnithread (pthread/NT) thread support. -*- Autoconf -*-
+
+# Copyright 2003 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Boston, MA
+# 02110-1301, USA.
+
+AC_DEFUN([GR_OMNITHREAD],
+[
+ # Check first for POSIX
+ ACX_PTHREAD(
+ [ ot_posix="yes"
+ AC_DEFINE(OMNITHREAD_POSIX,[1],[Define to 1 to enable pthread])
+ ],[
+ # If no POSIX support found, then check for NT threads
+ AC_MSG_CHECKING([for NT threads])
+
+ AC_LINK_IFELSE([
+ #include <windows.h>
+ #include <winbase.h>
+ int main() { InitializeCriticalSection(NULL); return 0; }
+ ],
+ [
+ ot_nt="yes"
+ AC_DEFINE(OMNITHREAD_NT,[1],[Define to 1 to enable NT thread])
+ ],
+ [AC_MSG_FAILURE([GNU Radio requires POSIX threads. pthreads not found.])]
+ )
+ AC_MSG_RESULT(yes)
+ ])
+ AM_CONDITIONAL(OMNITHREAD_POSIX, test "x$ot_posix" = xyes)
+ AM_CONDITIONAL(OMNITHREAD_NT, test "x$ot_nt" = xyes)
+
+ save_LIBS="$LIBS"
+ AC_SEARCH_LIBS([clock_gettime], [rt], [PTHREAD_LIBS="$PTHREAD_LIBS $LIBS"])
+ AC_CHECK_FUNCS([clock_gettime gettimeofday nanosleep])
+ LIBS="$save_LIBS"
+])
+
diff --git a/gsm-receiver/config/gr_pwin32.m4 b/gsm-receiver/config/gr_pwin32.m4
new file mode 100644
index 0000000..7b99cba
--- /dev/null
+++ b/gsm-receiver/config/gr_pwin32.m4
@@ -0,0 +1,146 @@
+# Check for (mingw)win32 POSIX replacements. -*- Autoconf -*-
+
+# Copyright 2003,2004,2005 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+
+
+AC_DEFUN([GR_PWIN32],
+[
+AC_REQUIRE([AC_HEADER_TIME])
+AC_CHECK_HEADERS([sys/types.h fcntl.h io.h])
+AC_CHECK_HEADERS([windows.h])
+AC_CHECK_HEADERS([winioctl.h winbase.h], [], [], [
+ #if HAVE_WINDOWS_H
+ #include <windows.h>
+ #endif
+])
+
+AC_CHECK_FUNCS([getopt usleep gettimeofday nanosleep rand srand random srandom sleep sigaction])
+AC_CHECK_TYPES([struct timezone, struct timespec, ssize_t],[],[],[
+ #if HAVE_SYS_TYPES_H
+ # include <sys/types.h>
+ #endif
+ #if TIME_WITH_SYS_TIME
+ # include <sys/time.h>
+ # include <time.h>
+ #else
+ # if HAVE_SYS_TIME_H
+ # include <sys/time.h>
+ # else
+ # include <time.h>
+ # endif
+ #endif
+])
+
+dnl Checks for replacements
+AC_REPLACE_FUNCS([getopt usleep gettimeofday])
+
+
+AC_MSG_CHECKING(for Sleep)
+AC_TRY_LINK([ #include <windows.h>
+ #include <winbase.h>
+ ], [ Sleep(0); ],
+ [AC_DEFINE(HAVE_SSLEEP,1,[Define to 1 if you have win32 Sleep])
+ AC_MSG_RESULT(yes)],
+ AC_MSG_RESULT(no)
+ )
+
+dnl Under Win32, mkdir prototype in io.h has only one arg
+AC_MSG_CHECKING(whether mkdir accepts only one arg)
+AC_TRY_COMPILE([#include <sys/types.h>
+ #include <sys/stat.h>
+ #include <fcntl.h>], [
+ mkdir("")
+ ], [ AC_MSG_RESULT(yes)
+ AC_DEFINE(MKDIR_TAKES_ONE_ARG,[],[Define if mkdir accepts only one arg]) ],
+ [ AC_MSG_RESULT(no)
+ ])
+
+AH_BOTTOM(
+[
+/* Define missing prototypes, implemented in replacement lib */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef HAVE_GETOPT
+int getopt (int argc, char * const argv[], const char * optstring);
+extern char * optarg;
+extern int optind, opterr, optopt;
+#endif
+
+#ifndef HAVE_USLEEP
+int usleep(unsigned long usec); /* SUSv2 */
+#endif
+
+#ifndef HAVE_NANOSLEEP
+#ifndef HAVE_STRUCT_TIMESPEC
+#if HAVE_SYS_TYPES_H
+# include <sys/types.h> /* need time_t */
+#endif
+struct timespec {
+ time_t tv_sec;
+ long tv_nsec;
+};
+#endif
+static inline int nanosleep(const struct timespec *req, struct timespec *rem) { return usleep(req->tv_sec*1000000+req->tv_nsec/1000); }
+#endif
+
+#if defined(HAVE_SSLEEP) && !defined(HAVE_SLEEP)
+#ifdef HAVE_WINBASE_H
+#include <windows.h>
+#include <winbase.h>
+#endif
+/* TODO: what about SleepEx? */
+static inline unsigned int sleep (unsigned int nb_sec) { Sleep(nb_sec*1000); return 0; }
+#endif
+
+#ifndef HAVE_GETTIMEOFDAY
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#ifndef HAVE_STRUCT_TIMEZONE
+struct timezone {
+ int tz_minuteswest;
+ int tz_dsttime;
+};
+#endif
+int gettimeofday(struct timeval *tv, struct timezone *tz);
+#endif
+
+#if !defined(HAVE_RANDOM) && defined(HAVE_RAND)
+#include <stdlib.h>
+static inline long int random (void) { return rand(); }
+#endif
+
+#if !defined(HAVE_SRANDOM) && defined(HAVE_SRAND)
+static inline void srandom (unsigned int seed) { srand(seed); }
+#endif
+
+#ifndef HAVE_SSIZE_T
+typedef size_t ssize_t;
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+])
+
+
+])
diff --git a/gsm-receiver/config/gr_python.m4 b/gsm-receiver/config/gr_python.m4
new file mode 100644
index 0000000..5816b27
--- /dev/null
+++ b/gsm-receiver/config/gr_python.m4
@@ -0,0 +1,111 @@
+dnl
+dnl Copyright 2003,2004,2005 Free Software Foundation, Inc.
+dnl
+dnl This file is part of GNU Radio
+dnl
+dnl GNU Radio is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 3, or (at your option)
+dnl any later version.
+dnl
+dnl GNU Radio is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with GNU Radio; see the file COPYING. If not, write to
+dnl the Free Software Foundation, Inc., 51 Franklin Street,
+dnl Boston, MA 02110-1301, USA.
+dnl
+
+# PYTHON_DEVEL()
+#
+# Checks for Python and tries to get the include path to 'Python.h'.
+# It provides the $(PYTHON_CPPFLAGS) and $(PYTHON_LDFLAGS) output variables.
+#
+AC_DEFUN([PYTHON_DEVEL],[
+ AC_REQUIRE([AM_PATH_PYTHON])
+ AC_REQUIRE([AC_CANONICAL_HOST])
+
+ # For Fedora Core 5 and 6, see ticket:39 in Trac
+ if test -f '/etc/redhat-release'; then
+ if (echo $pyexecdir | grep -q lib64); then
+ pythondir="$pyexecdir"
+ fi
+ fi
+
+ # Check for Python include path
+ AC_MSG_CHECKING([for Python include path])
+ if test -z "$PYTHON" ; then
+ AC_MSG_ERROR([cannot find Python path])
+ fi
+
+ # ask distutils which include path we should use
+ python_cmd='
+import distutils.sysconfig
+import os
+path = distutils.sysconfig.get_python_inc(plat_specific=False)
+if os.sep == "\\":
+ path = path.replace("\\", "/")
+print path
+'
+ python_path=`$PYTHON -c "$python_cmd"`
+ AC_MSG_RESULT([$python_path])
+ if test -z "$python_path" ; then
+ AC_MSG_ERROR([cannot find Python include path])
+ fi
+
+ AC_SUBST(PYTHON_CPPFLAGS,[-I$python_path])
+
+ # Check for Python headers usability
+ python_save_CPPFLAGS=$CPPFLAGS
+ CPPFLAGS="$CPPFLAGS $PYTHON_CPPFLAGS"
+ AC_CHECK_HEADERS([Python.h], [],
+ [AC_MSG_ERROR([cannot find usable Python headers])])
+ CPPFLAGS="$python_save_CPPFLAGS"
+
+ # Only set this on mingw and cygwin hosts, (only implemented
+ # for mingw host, for crosscompiling you need to trick this)
+
+ PYTHON_LDFLAGS=""
+ case $host_os in
+ *mingw* | *cygwin* )
+ AC_MSG_CHECKING([for Python LDFLAGS])
+
+ python_cmd='
+import distutils.sysconfig
+import os
+path = distutils.sysconfig.get_config_var("LIBPL")
+if path == None:
+ path = distutils.sysconfig.PREFIX + "/libs"
+if os.sep == "\\":
+ path = path.replace("\\", "/")
+print path
+'
+ python_stdlib_path=`$PYTHON -c "$python_cmd"`
+
+ python_version_nodot=`echo $PYTHON_VERSION | sed "s,\.,,"`
+ libpython_name="python$PYTHON_VERSION"
+
+ # Standard install of python for win32 has libpython24.a
+ # instead of libpython2.4.a so we check for the library
+ # without the dot in the version number.
+
+ python_stdlib_filename=`find $python_stdlib_path -type f -name libpython$python_version_nodot.* -print | sed "1q"`
+ if test -n "$python_stdlib_filename" ; then
+ libpython_name="python$python_version_nodot"
+ fi
+
+ PYTHON_LDFLAGS="-L$python_stdlib_path -l$libpython_name"
+ AC_MSG_RESULT($PYTHON_LDFLAGS)
+ # Replace all backslashes in PYTHON Paths with forward slashes
+ pythondir=`echo $pythondir |sed 's,\\\\,/,g'`
+ pkgpythondir=`echo $pkgpythondir |sed 's,\\\\,/,g'`
+ pyexecdir=`echo $pyexecdir |sed 's,\\\\,/,g'`
+ pkgpyexecdir=`echo $pkgpyexecdir |sed 's,\\\\,/,g'`
+ ;;
+ esac
+
+ AC_SUBST([PYTHON_LDFLAGS])
+])
diff --git a/gsm-receiver/config/gr_require_mc4020.m4 b/gsm-receiver/config/gr_require_mc4020.m4
new file mode 100644
index 0000000..90774fd
--- /dev/null
+++ b/gsm-receiver/config/gr_require_mc4020.m4
@@ -0,0 +1,33 @@
+dnl
+dnl Copyright 2003,2004 Free Software Foundation, Inc.
+dnl
+dnl This file is part of GNU Radio
+dnl
+dnl GNU Radio is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 3, or (at your option)
+dnl any later version.
+dnl
+dnl GNU Radio is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with GNU Radio; see the file COPYING. If not, write to
+dnl the Free Software Foundation, Inc., 51 Franklin Street,
+dnl Boston, MA 02110-1301, USA.
+dnl
+
+AC_DEFUN([GR_REQUIRE_MC4020],[
+ AC_MSG_CHECKING([for mc4020 A/D driver include file])
+ AC_COMPILE_IFELSE([
+#include <mc4020.h>
+int main (int argc, char **argv)
+{
+ return 0;
+}
+],[AC_MSG_RESULT([yes])],
+ [AC_MSG_RESULT([no])
+ AC_MSG_ERROR([mc4020.h not found.])])
+])
diff --git a/gsm-receiver/config/gr_scripting.m4 b/gsm-receiver/config/gr_scripting.m4
new file mode 100644
index 0000000..86870e7
--- /dev/null
+++ b/gsm-receiver/config/gr_scripting.m4
@@ -0,0 +1,30 @@
+dnl
+dnl Copyright 2003 Free Software Foundation, Inc.
+dnl
+dnl This file is part of GNU Radio
+dnl
+dnl GNU Radio is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 3, or (at your option)
+dnl any later version.
+dnl
+dnl GNU Radio is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with GNU Radio; see the file COPYING. If not, write to
+dnl the Free Software Foundation, Inc., 51 Franklin Street,
+dnl Boston, MA 02110-1301, USA.
+dnl
+
+AC_DEFUN([GR_SCRIPTING],[
+ AC_REQUIRE([AC_PROG_LN_S])
+ AC_REQUIRE([AC_PROG_CXX])
+ AC_REQUIRE([AC_PROG_LIBTOOL])
+
+ SWIG_PROG(1.3.23)
+ SWIG_ENABLE_CXX
+ SWIG_PYTHON
+])
diff --git a/gsm-receiver/config/gr_set_md_cpu.m4 b/gsm-receiver/config/gr_set_md_cpu.m4
new file mode 100644
index 0000000..ebc1fad
--- /dev/null
+++ b/gsm-receiver/config/gr_set_md_cpu.m4
@@ -0,0 +1,44 @@
+dnl
+dnl Copyright 2003 Free Software Foundation, Inc.
+dnl
+dnl This file is part of GNU Radio
+dnl
+dnl GNU Radio is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 3, or (at your option)
+dnl any later version.
+dnl
+dnl GNU Radio is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with GNU Radio; see the file COPYING. If not, write to
+dnl the Free Software Foundation, Inc., 51 Franklin Street,
+dnl Boston, MA 02110-1301, USA.
+dnl
+
+AC_DEFUN([GR_SET_MD_CPU],[
+ AC_REQUIRE([AC_CANONICAL_HOST])
+ AC_ARG_WITH(md-cpu,
+ [ --with-md-cpu=ARCH set machine dependent speedups (auto)],
+ [cf_with_md_cpu="$withval"],
+ [cf_with_md_cpu="$host_cpu"])
+
+ AC_MSG_CHECKING([for machine dependent speedups])
+ case "$cf_with_md_cpu" in
+ x86 | i[[3-7]]86) MD_CPU=x86 MD_SUBCPU=x86 ;;
+ x86_64) MD_CPU=x86 MD_SUBCPU=x86_64 ;;
+# sparc) MD_CPU=sparc ;;
+ *) MD_CPU=generic ;;
+ esac
+ AC_MSG_RESULT($MD_CPU)
+ AC_SUBST(MD_CPU)
+ AC_SUBST(MD_SUBCPU)
+
+ AM_CONDITIONAL(MD_CPU_x86, test $MD_CPU = x86)
+ AM_CONDITIONAL(MD_SUBCPU_x86_64, test $MD_SUBCPU = x86_64)
+ AM_CONDITIONAL(MD_CPU_generic, test $MD_CPU = generic)
+])
+
diff --git a/gsm-receiver/config/gr_swig.m4 b/gsm-receiver/config/gr_swig.m4
new file mode 100644
index 0000000..cdb2805
--- /dev/null
+++ b/gsm-receiver/config/gr_swig.m4
@@ -0,0 +1,85 @@
+dnl
+dnl Copyright 2003 Free Software Foundation, Inc.
+dnl
+dnl This file is part of GNU Radio
+dnl
+dnl GNU Radio is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 3, or (at your option)
+dnl any later version.
+dnl
+dnl GNU Radio is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with GNU Radio; see the file COPYING. If not, write to
+dnl the Free Software Foundation, Inc., 51 Franklin Street,
+dnl Boston, MA 02110-1301, USA.
+dnl
+
+# SWIG_PROG([required-version])
+#
+# Checks for the SWIG program. If found you can (and should) call SWIG via $(SWIG).
+# You can use the optional first argument to check if the version of the available SWIG
+# is greater or equal to the value of the argument. It should have the format:
+# N[.N[.N]] (N is a number between 0 and 999. Only the first N is mandatory.)
+AC_DEFUN([SWIG_PROG],[
+ AC_REQUIRE([AC_PROG_MAKE_SET])
+ AC_CHECK_PROG(SWIG,swig,[`which swig`])
+ if test -z "$SWIG" ; then
+ AC_MSG_ERROR([Cannot find 'swig' program. SWIG version >= $1 required])
+ SWIG=false
+ elif test -n "$1" ; then
+ AC_MSG_CHECKING([for SWIG version])
+ swig_version=`$SWIG -version 2>&1 | \
+ awk '/^SWIG Version [[0-9]+\.[0-9]+\.[0-9]]+.*$/ { split($[3],a,"[[^.0-9]]"); print a[[1]] }'`
+ AC_MSG_RESULT([$swig_version])
+ if test -n "$swig_version" ; then
+ swig_version=`echo $swig_version | \
+ awk '{ split($[1],a,"\."); print [a[1]*1000000+a[2]*1000+a[3]] }' 2>/dev/null`
+ swig_required_version=`echo $1 | \
+ awk '{ split($[1],a,"\."); print [a[1]*1000000+a[2]*1000+a[3]] }' 2>/dev/null`
+ if test $swig_required_version -gt $swig_version ; then
+ AC_MSG_ERROR([SWIG version >= $1 required])
+ fi
+ else
+ AC_MSG_ERROR([cannot determine SWIG version])
+ fi
+ fi
+])
+
+# SWIG_ENABLE_CXX()
+#
+# Enable swig C++ support. This effects all invocations of $(SWIG).
+AC_DEFUN([SWIG_ENABLE_CXX],[
+ AC_REQUIRE([SWIG_PROG])
+ AC_REQUIRE([AC_PROG_CXX])
+ if test "$SWIG" != "false" ; then
+ SWIG="$SWIG -c++"
+ fi
+])
+
+# SWIG_PYTHON([use-shadow-classes])
+#
+# Checks for Python and provides the $(SWIG_PYTHON_CPPFLAGS),
+# $(SWIG_PYTHON_LIB) and $(SWIG_PYTHON_OPT) output variables.
+# $(SWIG_PYTHON_OPT) contains all necessary swig options to generate
+# code for Python. If you need multi module support use
+# $(SWIG_PYTHON_LIB) (provided by the SWIG_MULTI_MODULE_SUPPORT()
+# macro) to link against the appropriate library. It contains the
+# SWIG Python runtime library that is needed by the type check system
+# for example.
+
+AC_DEFUN([SWIG_PYTHON],[
+ AC_REQUIRE([SWIG_PROG])
+ AC_REQUIRE([PYTHON_DEVEL])
+ if test "$SWIG" != "false" ; then
+ AC_SUBST(SWIG_PYTHON_LIB,[-lswigpy])
+dnl test ! "x$1" = "xno" && swig_shadow=" -shadow" || swig_shadow=""
+dnl AC_SUBST(SWIG_PYTHON_OPT,[-python$swig_shadow])
+ AC_SUBST(SWIG_PYTHON_OPT,[-python])
+ fi
+ AC_SUBST(SWIG_PYTHON_CPPFLAGS,[$PYTHON_CPPFLAGS])
+])
diff --git a/gsm-receiver/config/gr_sysv_shm.m4 b/gsm-receiver/config/gr_sysv_shm.m4
new file mode 100644
index 0000000..db5c835
--- /dev/null
+++ b/gsm-receiver/config/gr_sysv_shm.m4
@@ -0,0 +1,36 @@
+# Check for IPC System V shm support. -*- Autoconf -*-
+
+# Copyright 2003 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Boston, MA
+# 02110-1301, USA.
+
+AC_DEFUN([GR_SYSV_SHM],
+[
+ AC_LANG_SAVE
+ AC_LANG_C
+
+ AC_CHECK_HEADERS([sys/ipc.h sys/shm.h])
+
+ save_LIBS="$LIBS"
+ AC_SEARCH_LIBS(shmat, [cygipc ipc],
+ [ IPC_LIBS="$LIBS" ],
+ [ AC_MSG_WARN([SystemV IPC support not found. ]) ]
+ )
+ LIBS="$save_LIBS"
+
+ AC_LANG_RESTORE
+ AC_SUBST(IPC_LIBS)
+])
diff --git a/gsm-receiver/config/gr_x86_64.m4 b/gsm-receiver/config/gr_x86_64.m4
new file mode 100644
index 0000000..3f56c06
--- /dev/null
+++ b/gsm-receiver/config/gr_x86_64.m4
@@ -0,0 +1,39 @@
+dnl
+dnl Copyright 2005 Free Software Foundation, Inc.
+dnl
+dnl This file is part of GNU Radio
+dnl
+dnl GNU Radio is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 3, or (at your option)
+dnl any later version.
+dnl
+dnl GNU Radio is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with GNU Radio; see the file COPYING. If not, write to
+dnl the Free Software Foundation, Inc., 51 Franklin Street,
+dnl Boston, MA 02110-1301, USA.
+dnl
+
+# GR_X86_64()
+#
+# Checks to see if we're on a x86_64 machine, and if so, ensure
+# that libdir ends in "64"
+#
+AC_DEFUN([GR_X86_64],[
+ AC_REQUIRE([AC_CANONICAL_HOST])
+ if test "$host_cpu" = "x86_64"; then
+ AC_MSG_CHECKING([libdir for lib64 suffix])
+ t=${libdir##*/lib}
+ if test "$t" != 64 && test -d /lib64 && ! test -L /lib64; then
+ libdir=${libdir}64
+ AC_MSG_RESULT([no. Setting libdir to $libdir])
+ else
+ AC_MSG_RESULT([yes])
+ fi
+ fi
+])
diff --git a/gsm-receiver/config/lf_cc.m4 b/gsm-receiver/config/lf_cc.m4
new file mode 100644
index 0000000..b9d1c9c
--- /dev/null
+++ b/gsm-receiver/config/lf_cc.m4
@@ -0,0 +1,42 @@
+dnl Autoconf support for C++
+dnl Copyright (C) 1988 Eleftherios Gkioulekas <lf@amath.washington.edu>
+dnl
+dnl This program is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 3 of the License, or
+dnl (at your option) any later version.
+dnl
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; if not, write to the Free Software
+dnl Foundation, Inc., 51 Franklin Street, Boston, MA 02110-1301, USA.
+dnl
+dnl As a special exception to the GNU General Public License, if you
+dnl distribute this file as part of a program that contains a configuration
+dnl script generated by Autoconf, you may include it under the same
+dnl distribution terms that you use for the rest of that program.
+
+# -------------------------------------------------------------------------
+# Use this macro to configure your C compiler
+# When called the macro does the following things:
+# 1. It finds an appropriate C compiler.
+# If you passed the flag --with-cc=foo then it uses that
+# particular compiler
+# 2. Check whether the compiler works.
+# 3. Checks whether the compiler accepts the -g
+# -------------------------------------------------------------------------
+
+AC_DEFUN([LF_CONFIGURE_CC],[
+ dnl Sing the song
+ AC_REQUIRE([AC_PROG_CC])dnl
+ AC_REQUIRE([AC_PROG_CPP])dnl
+ AC_REQUIRE([AC_AIX])dnl
+ AC_REQUIRE([AC_ISC_POSIX])dnl
+ AC_REQUIRE([AC_MINIX])dnl
+ AC_REQUIRE([AC_HEADER_STDC])dnl
+])
+
diff --git a/gsm-receiver/config/lf_cxx.m4 b/gsm-receiver/config/lf_cxx.m4
new file mode 100644
index 0000000..c581c9b
--- /dev/null
+++ b/gsm-receiver/config/lf_cxx.m4
@@ -0,0 +1,121 @@
+dnl Autoconf support for C++
+dnl Copyright (C) 1988 Eleftherios Gkioulekas <lf@amath.washington.edu>
+dnl
+dnl This program is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 3 of the License, or
+dnl (at your option) any later version.
+dnl
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; if not, write to the Free Software
+dnl Foundation, Inc., 51 Franklin Street, Boston, MA 02110-1301, USA.
+dnl
+dnl As a special exception to the GNU General Public License, if you
+dnl distribute this file as part of a program that contains a configuration
+dnl script generated by Autoconf, you may include it under the same
+dnl distribution terms that you use for the rest of that program.
+
+# -----------------------------------------------------------------
+# This macro should be called to configure your C++ compiler.
+# When called, the macro does the following things:
+# 1. It finds an appropriate C++ compiler
+# If you passed the flag --with-cxx=foo, then it uses that
+# particular compiler
+# 2. Checks whether the compiler accepts the -g
+# ------------------------------------------------------------------
+
+AC_DEFUN([LF_CONFIGURE_CXX],[
+ AC_REQUIRE([AC_PROG_CXX])dnl
+ AC_REQUIRE([AC_PROG_CXXCPP])dnl
+ LF_CXX_PORTABILITY
+])
+
+# -----------------------------------------------------------------------
+# This macro tests the C++ compiler for various portability problem.
+# 1. Defines CXX_HAS_NO_BOOL if the compiler does not support the bool
+# data type
+# 2. Defines CXX_HAS_BUGGY_FOR_LOOPS if the compiler has buggy
+# scoping for the for-loop
+# 3. Defines USE_ASSERT if the user wants to use assertions
+# -----------------------------------------------------------------------
+
+
+AC_DEFUN([LF_CXX_PORTABILITY],[
+
+ dnl
+ dnl Check for common C++ portability problems
+ dnl
+
+ dnl AC_LANG_PUSH
+ dnl AC_LANG_CPLUSPLUS
+ AC_LANG_SAVE
+ AC_LANG_CPLUSPLUS
+
+ dnl Check whether we have bool
+ AC_MSG_CHECKING(whether C++ has bool)
+ AC_TRY_RUN([main() { bool b1=true; bool b2=false; }],
+ [ AC_MSG_RESULT(yes) ],
+ [ AC_MSG_RESULT(no)
+ AC_DEFINE(CXX_HAS_NO_BOOL,[],[Define if C++ is missing bool type]) ],
+ [ AC_MSG_WARN(Don't cross-compile)]
+ )
+
+ dnl Test whether C++ has buggy for-loops
+ AC_MSG_CHECKING(whether C++ has buggy scoping in for-loops)
+ AC_TRY_COMPILE([#include <iostream.h>], [
+ for (int i=0;i<10;i++) { }
+ for (int i=0;i<10;i++) { }
+], [ AC_MSG_RESULT(no) ],
+ [ AC_MSG_RESULT(yes)
+ AC_DEFINE(CXX_HAS_BUGGY_FOR_LOOPS,[],[Define if for loop scoping is broken]) ])
+
+ dnl Test whether the user wants to enable assertions
+ AC_MSG_CHECKING(whether user wants assertions)
+ AC_ARG_ENABLE(assert,
+ [ --disable-assert don't use cpp.h assert],
+ [ AC_DEFINE(NDEBUG,[],[Define to disable asserts (don't doit!)])
+ AC_MSG_RESULT(no) ],
+ [ AC_MSG_RESULT(yes) ],
+ )
+
+ dnl Test whether C++ has std::isnan
+ AC_MSG_CHECKING(whether C++ has std::isnan)
+ AC_TRY_COMPILE([#include <cmath>], [
+ std::isnan(0);
+], [ AC_MSG_RESULT(yes)
+ AC_DEFINE(CXX_HAS_STD_ISNAN,[],[Define if has std::isnan]) ],
+ [ AC_MSG_RESULT(no) ])
+
+ dnl Done with the portability checks
+ dnl AC_LANG_POP([C++])
+ AC_LANG_RESTORE
+])
+
+AH_BOTTOM([// Workaround for compilers with buggy for-loop scoping
+// That's quite a few compilers actually including recent versions of
+// Dec Alpha cxx, HP-UX CC and SGI CC.
+// The trivial "if" statement provides the correct scoping to the
+// for loop
+
+#ifdef CXX_HAS_BUGGY_FOR_LOOPS
+#undef for
+#define for if(1) for
+#endif
+])
+
+AH_BOTTOM([// If the C++ compiler we use doesn't have bool, then
+// the following is a near-perfect work-around.
+// You must make sure your code does not depend on "int" and "bool"
+// being two different types, in overloading for instance.
+
+#ifdef CXX_HAS_NO_BOOL
+#define bool int
+#define true 1
+#define false 0
+#endif
+])
diff --git a/gsm-receiver/config/lf_warnings.m4 b/gsm-receiver/config/lf_warnings.m4
new file mode 100644
index 0000000..4e2ca91
--- /dev/null
+++ b/gsm-receiver/config/lf_warnings.m4
@@ -0,0 +1,128 @@
+dnl Copyright (C) 1988 Eleftherios Gkioulekas <lf@amath.washington.edu>
+dnl
+dnl This program is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 3 of the License, or
+dnl (at your option) any later version.
+dnl
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; if not, write to the Free Software
+dnl Foundation, Inc., 51 Franklin Street, Boston, MA 02110-1301, USA.
+dnl
+dnl As a special exception to the GNU General Public License, if you
+dnl distribute this file as part of a program that contains a configuration
+dnl script generated by Autoconf, you may include it under the same
+dnl distribution terms that you use for the rest of that program.
+
+# --------------------------------------------------------------------------
+# Check whether the C++ compiler accepts a certain flag
+# If it does it adds the flag to CXXFLAGS
+# If it does not then it returns an error to lf_ok
+# Usage:
+# LF_CHECK_CXX_FLAG(-flag1 -flag2 -flag3 ...)
+# -------------------------------------------------------------------------
+
+AC_DEFUN([LF_CHECK_CXX_FLAG],[
+ echo 'void f(){}' > conftest.cc
+ for i in $1
+ do
+ AC_MSG_CHECKING([whether $CXX accepts $i])
+ if test -z "`${CXX} $i -c conftest.cc 2>&1`"
+ then
+ CXXFLAGS="${CXXFLAGS} $i"
+ AC_MSG_RESULT(yes)
+ else
+ AC_MSG_RESULT(no)
+ fi
+ done
+ rm -f conftest.cc conftest.o
+])
+
+# --------------------------------------------------------------------------
+# Check whether the C compiler accepts a certain flag
+# If it does it adds the flag to CFLAGS
+# If it does not then it returns an error to lf_ok
+# Usage:
+# LF_CHECK_CC_FLAG(-flag1 -flag2 -flag3 ...)
+# -------------------------------------------------------------------------
+
+AC_DEFUN([LF_CHECK_CC_FLAG],[
+ echo 'void f(){}' > conftest.c
+ for i in $1
+ do
+ AC_MSG_CHECKING([whether $CC accepts $i])
+ if test -z "`${CC} $i -c conftest.c 2>&1`"
+ then
+ CFLAGS="${CFLAGS} $i"
+ AC_MSG_RESULT(yes)
+ else
+ AC_MSG_RESULT(no)
+ fi
+ done
+ rm -f conftest.c conftest.o
+])
+
+# --------------------------------------------------------------------------
+# Check whether the Fortran compiler accepts a certain flag
+# If it does it adds the flag to FFLAGS
+# If it does not then it returns an error to lf_ok
+# Usage:
+# LF_CHECK_F77_FLAG(-flag1 -flag2 -flag3 ...)
+# -------------------------------------------------------------------------
+
+AC_DEFUN([LF_CHECK_F77_FLAG],[
+ cat << EOF > conftest.f
+c....:++++++++++++++++++++++++
+ PROGRAM MAIN
+ PRINT*,'Hello World!'
+ END
+EOF
+ for i in $1
+ do
+ AC_MSG_CHECKING([whether $F77 accepts $i])
+ if test -z "`${F77} $i -c conftest.f 2>&1`"
+ then
+ FFLAGS="${FFLAGS} $i"
+ AC_MSG_RESULT(yes)
+ else
+ AC_MSG_RESULT(no)
+ fi
+ done
+ rm -f conftest.f conftest.o
+])
+
+# ----------------------------------------------------------------------
+# Provide the configure script with an --with-warnings option that
+# turns on warnings. Call this command AFTER you have configured ALL your
+# compilers.
+# ----------------------------------------------------------------------
+
+AC_DEFUN([LF_SET_WARNINGS],[
+ dnl Check for --with-warnings
+ AC_MSG_CHECKING([whether user wants warnings])
+ AC_ARG_WITH(warnings,
+ [ --with-warnings Turn on warnings],
+ [ lf_warnings=yes ], [ lf_warnings=no ])
+ lf_warnings=yes # hard code for now -eb
+ AC_MSG_RESULT($lf_warnings)
+
+ dnl Warnings for the two main compilers
+ cc_warning_flags="-Wall"
+ cxx_warning_flags="-Wall -Woverloaded-virtual"
+ if test $lf_warnings = yes
+ then
+ if test -n "${CC}"
+ then
+ LF_CHECK_CC_FLAG($cc_warning_flags)
+ fi
+ if test -n "${CXX}"
+ then
+ LF_CHECK_CXX_FLAG($cxx_warning_flags)
+ fi
+ fi
+])
diff --git a/gsm-receiver/config/lf_x11.m4 b/gsm-receiver/config/lf_x11.m4
new file mode 100644
index 0000000..460cd60
--- /dev/null
+++ b/gsm-receiver/config/lf_x11.m4
@@ -0,0 +1,39 @@
+dnl Copyright (C) 1988 Eleftherios Gkioulekas <lf@amath.washington.edu>
+dnl
+dnl This program is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 3 of the License, or
+dnl (at your option) any later version.
+dnl
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with this program; if not, write to the Free Software
+dnl Foundation, Inc., 51 Franklin Street, Boston, MA 02110-1301, USA.
+dnl
+dnl As a special exception to the GNU General Public License, if you
+dnl distribute this file as part of a program that contains a configuration
+dnl script generated by Autoconf, you may include it under the same
+dnl distribution terms that you use for the rest of that program.
+
+
+#-----------------------------------------------------------------------
+# This macro searches for Xlib and when it finds it it adds the
+# appropriate flags to CXXFLAGS and export the link sequence to
+# the variable XLIB.
+# In your configure.in file add:
+# LF_PATH_XLIB
+# In your Makefile.am add
+# program_LDADD = .... $(XLIB)
+#------------------------------------------------------------------------
+
+AC_DEFUN([LF_PATH_XLIB],[
+ AC_PATH_XTRA
+ CXXFLAGS="$CXXFLAGS $X_CFLAGS"
+ XLIB="$X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS"
+ AC_SUBST(XLIB)
+])
+
diff --git a/gsm-receiver/config/mkstemp.m4 b/gsm-receiver/config/mkstemp.m4
new file mode 100644
index 0000000..4af0f0a
--- /dev/null
+++ b/gsm-receiver/config/mkstemp.m4
@@ -0,0 +1,89 @@
+#serial 4
+
+# On some hosts (e.g., HP-UX 10.20, SunOS 4.1.4, Solaris 2.5.1), mkstemp has a
+# silly limit that it can create no more than 26 files from a given template.
+# Other systems lack mkstemp altogether.
+# On OSF1/Tru64 V4.0F, the system-provided mkstemp function can create
+# only 32 files per process.
+# On systems like the above, arrange to use the replacement function.
+AC_DEFUN([UTILS_FUNC_MKSTEMP],
+[dnl
+ AC_REPLACE_FUNCS(mkstemp)
+ if test $ac_cv_func_mkstemp = no; then
+ utils_cv_func_mkstemp_limitations=yes
+ else
+ AC_CACHE_CHECK([for mkstemp limitations],
+ utils_cv_func_mkstemp_limitations,
+ [
+ AC_TRY_RUN([
+# include <stdlib.h>
+ int main ()
+ {
+ int i;
+ for (i = 0; i < 70; i++)
+ {
+ char template[] = "conftestXXXXXX";
+ int fd = mkstemp (template);
+ if (fd == -1)
+ exit (1);
+ close (fd);
+ }
+ exit (0);
+ }
+ ],
+ utils_cv_func_mkstemp_limitations=no,
+ utils_cv_func_mkstemp_limitations=yes,
+ utils_cv_func_mkstemp_limitations=yes
+ )
+ ]
+ )
+ fi
+
+ if test $utils_cv_func_mkstemp_limitations = yes; then
+ AC_LIBOBJ(mkstemp)
+ AC_LIBOBJ(tempname)
+ AC_DEFINE(mkstemp, rpl_mkstemp,
+ [Define to rpl_mkstemp if the replacement function should be used.])
+ gl_PREREQ_MKSTEMP
+ jm_PREREQ_TEMPNAME
+ fi
+])
+
+# Prerequisites of lib/mkstemp.c.
+AC_DEFUN([gl_PREREQ_MKSTEMP],
+[
+ AH_BOTTOM(
+ [
+ #ifndef HAVE_MKSTEMP
+ #ifdef __cplusplus
+ extern "C" {
+ #endif
+ int rpl_mkstemp (char *templ);
+ #ifdef __cplusplus
+ }
+ #endif
+ #endif
+ ])
+])
+
+# Prerequisites of lib/tempname.c.
+AC_DEFUN([jm_PREREQ_TEMPNAME],
+[
+ AC_REQUIRE([AC_HEADER_STAT])
+ AC_CHECK_HEADERS_ONCE(fcntl.h sys/time.h unistd.h)
+ AC_CHECK_HEADERS(stdint.h)
+ AC_CHECK_FUNCS(__secure_getenv gettimeofday lstat)
+ AC_CHECK_DECLS_ONCE(getenv)
+ # AC_REQUIRE([jm_AC_TYPE_UINTMAX_T])
+
+ dnl Under Win32, mkdir prototype in io.h has only one arg
+ AC_MSG_CHECKING(whether mkdir accepts only one arg)
+ AC_TRY_COMPILE([#include <sys/types.h>
+ #include <sys/stat.h>
+ #include <fcntl.h>], [
+ mkdir("")
+ ], [ AC_MSG_RESULT(yes)
+ AC_DEFINE(MKDIR_TAKES_ONE_ARG,[],[Define if mkdir accepts only one arg]) ],
+ [ AC_MSG_RESULT(no)
+ ])
+])
diff --git a/gsm-receiver/config/onceonly.m4 b/gsm-receiver/config/onceonly.m4
new file mode 100644
index 0000000..f6fec37
--- /dev/null
+++ b/gsm-receiver/config/onceonly.m4
@@ -0,0 +1,63 @@
+# onceonly.m4 serial 3
+dnl Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License. As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+
+dnl This file defines some "once only" variants of standard autoconf macros.
+dnl AC_CHECK_HEADERS_ONCE like AC_CHECK_HEADERS
+dnl AC_CHECK_FUNCS_ONCE like AC_CHECK_FUNCS
+dnl AC_CHECK_DECLS_ONCE like AC_CHECK_DECLS
+dnl AC_REQUIRE([AC_HEADER_STDC]) like AC_HEADER_STDC
+dnl The advantage is that the check for each of the headers/functions/decls
+dnl will be put only once into the 'configure' file. It keeps the size of
+dnl the 'configure' file down, and avoids redundant output when 'configure'
+dnl is run.
+dnl The drawback is that the checks cannot be conditionalized. If you write
+dnl if some_condition; then gl_CHECK_HEADERS(stdlib.h); fi
+dnl inside an AC_DEFUNed function, the gl_CHECK_HEADERS macro call expands to
+dnl empty, and the check will be inserted before the body of the AC_DEFUNed
+dnl function.
+
+dnl Autoconf version 2.57 or newer is recommended.
+AC_PREREQ(2.54)
+
+# AC_CHECK_HEADERS_ONCE(HEADER1 HEADER2 ...) is a once-only variant of
+# AC_CHECK_HEADERS(HEADER1 HEADER2 ...).
+AC_DEFUN([AC_CHECK_HEADERS_ONCE], [
+ :
+ AC_FOREACH([gl_HEADER_NAME], [$1], [
+ AC_DEFUN([gl_CHECK_HEADER_]m4_quote(translit(defn([gl_HEADER_NAME]),
+ [-./], [___])), [
+ AC_CHECK_HEADERS(gl_HEADER_NAME)
+ ])
+ AC_REQUIRE([gl_CHECK_HEADER_]m4_quote(translit(gl_HEADER_NAME,
+ [-./], [___])))
+ ])
+])
+
+# AC_CHECK_FUNCS_ONCE(FUNC1 FUNC2 ...) is a once-only variant of
+# AC_CHECK_FUNCS(FUNC1 FUNC2 ...).
+AC_DEFUN([AC_CHECK_FUNCS_ONCE], [
+ :
+ AC_FOREACH([gl_FUNC_NAME], [$1], [
+ AC_DEFUN([gl_CHECK_FUNC_]defn([gl_FUNC_NAME]), [
+ AC_CHECK_FUNCS(defn([gl_FUNC_NAME]))
+ ])
+ AC_REQUIRE([gl_CHECK_FUNC_]defn([gl_FUNC_NAME]))
+ ])
+])
+
+# AC_CHECK_DECLS_ONCE(DECL1 DECL2 ...) is a once-only variant of
+# AC_CHECK_DECLS(DECL1, DECL2, ...).
+AC_DEFUN([AC_CHECK_DECLS_ONCE], [
+ :
+ AC_FOREACH([gl_DECL_NAME], [$1], [
+ AC_DEFUN([gl_CHECK_DECL_]defn([gl_DECL_NAME]), [
+ AC_CHECK_DECLS(defn([gl_DECL_NAME]))
+ ])
+ AC_REQUIRE([gl_CHECK_DECL_]defn([gl_DECL_NAME]))
+ ])
+])
diff --git a/gsm-receiver/config/pkg.m4 b/gsm-receiver/config/pkg.m4
new file mode 100644
index 0000000..770f062
--- /dev/null
+++ b/gsm-receiver/config/pkg.m4
@@ -0,0 +1,68 @@
+dnl PKG_CHECK_MODULES(GSTUFF, gtk+-2.0 >= 1.3 glib = 1.3.4, action-if, action-not)
+dnl defines GSTUFF_LIBS, GSTUFF_CFLAGS, see pkg-config man page
+dnl also defines GSTUFF_PKG_ERRORS on error
+AC_DEFUN([PKG_CHECK_MODULES], [
+ succeeded=no
+
+ if test -z "$PKG_CONFIG"; then
+ AC_PATH_PROG(PKG_CONFIG, pkg-config, no)
+ fi
+
+ if test "$PKG_CONFIG" = "no" ; then
+ echo "*** The pkg-config script could not be found. Make sure it is"
+ echo "*** in your path, or set the PKG_CONFIG environment variable"
+ echo "*** to the full path to pkg-config."
+ echo "*** Or see http://www.freedesktop.org/software/pkgconfig to get pkg-config."
+ else
+ dnl If PKG_CONFIG_PATH is not already set, add /usr/local/lib/pkgconfig.
+ dnl If it's set, assume the user knows what they're doing.
+ dnl This should help avoid failures while looking for fftw3f
+ if test -z "$PKG_CONFIG_PATH"; then
+ export PKG_CONFIG_PATH="/usr/local/lib/pkgconfig"
+ fi
+
+ PKG_CONFIG_MIN_VERSION=0.9.0
+ if $PKG_CONFIG --atleast-pkgconfig-version $PKG_CONFIG_MIN_VERSION; then
+ AC_MSG_CHECKING(for $2)
+
+ if $PKG_CONFIG --exists "$2" ; then
+ AC_MSG_RESULT(yes)
+ succeeded=yes
+
+ AC_MSG_CHECKING($1_CFLAGS)
+ $1_CFLAGS=`$PKG_CONFIG --cflags "$2"`
+ AC_MSG_RESULT($$1_CFLAGS)
+
+ AC_MSG_CHECKING($1_LIBS)
+ $1_LIBS=`$PKG_CONFIG --libs "$2"`
+ AC_MSG_RESULT($$1_LIBS)
+
+ AC_MSG_CHECKING($1_INCLUDEDIR)
+ $1_INCLUDEDIR=`$PKG_CONFIG --variable=includedir "$2"`
+ AC_MSG_RESULT($$1_INCLUDEDIR)
+ else
+ $1_CFLAGS=""
+ $1_LIBS=""
+ ## If we have a custom action on failure, don't print errors, but
+ ## do set a variable so people can do so.
+ $1_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "$2"`
+ ifelse([$4], ,echo $$1_PKG_ERRORS,)
+ fi
+
+ AC_SUBST($1_CFLAGS)
+ AC_SUBST($1_LIBS)
+ AC_SUBST($1_INCLUDEDIR)
+ else
+ echo "*** Your version of pkg-config is too old. You need version $PKG_CONFIG_MIN_VERSION or newer."
+ echo "*** See http://www.freedesktop.org/software/pkgconfig"
+ fi
+ fi
+
+ if test $succeeded = yes; then
+ ifelse([$3], , :, [$3])
+ else
+ ifelse([$4], , AC_MSG_ERROR([Library requirements ($2) not met; consider adjusting the PKG_CONFIG_PATH environment variable if your libraries are in a nonstandard prefix so pkg-config can find them.]), [$4])
+ fi
+])
+
+
diff --git a/gsm-receiver/config/usrp_fusb_tech.m4 b/gsm-receiver/config/usrp_fusb_tech.m4
new file mode 100644
index 0000000..b5a930b
--- /dev/null
+++ b/gsm-receiver/config/usrp_fusb_tech.m4
@@ -0,0 +1,56 @@
+dnl
+dnl Copyright 2003 Free Software Foundation, Inc.
+dnl
+dnl This file is part of GNU Radio
+dnl
+dnl GNU Radio is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 3, or (at your option)
+dnl any later version.
+dnl
+dnl GNU Radio is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with GNU Radio; see the file COPYING. If not, write to
+dnl the Free Software Foundation, Inc., 51 Franklin Street,
+dnl Boston, MA 02110-1301, USA.
+dnl
+
+AC_DEFUN([USRP_SET_FUSB_TECHNIQUE],[
+ AC_REQUIRE([AC_CANONICAL_HOST])
+ AC_ARG_WITH(fusb-tech,
+ [ --with-fusb-tech=OS set fast usb technique (auto)],
+ [cf_with_fusb_tech="$withval"],
+ [cf_with_fusb_tech="$host_os"])
+
+
+ AC_CHECK_HEADER([linux/usbdevice_fs.h],
+ [x_have_usbdevice_fs_h=yes],
+ [x_have_usbdevice_fs_h=no])
+
+ AC_MSG_CHECKING([for fast usb technique to use])
+ case "$cf_with_fusb_tech" in
+ linux*) if test x${x_have_usbdevice_fs_h} = xyes;
+ then
+ FUSB_TECH=linux
+ else
+ FUSB_TECH=generic
+ fi ;;
+
+ darwin*) FUSB_TECH=darwin ;;
+ cygwin*|win*|mingw*) FUSB_TECH=win32 ;;
+ *) FUSB_TECH=generic ;;
+ esac
+
+ AC_MSG_RESULT($FUSB_TECH)
+ AC_SUBST(FUSB_TECH)
+
+ AM_CONDITIONAL(FUSB_TECH_darwin, test $FUSB_TECH = darwin)
+ AM_CONDITIONAL(FUSB_TECH_win32, test $FUSB_TECH = win32)
+ AM_CONDITIONAL(FUSB_TECH_generic, test $FUSB_TECH = generic)
+ AM_CONDITIONAL(FUSB_TECH_linux, test $FUSB_TECH = linux)
+])
+
diff --git a/gsm-receiver/config/usrp_libusb.m4 b/gsm-receiver/config/usrp_libusb.m4
new file mode 100644
index 0000000..9fe4753
--- /dev/null
+++ b/gsm-receiver/config/usrp_libusb.m4
@@ -0,0 +1,43 @@
+# Check for libusb support. -*- Autoconf -*-
+
+# Copyright 2003 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Boston, MA
+# 02110-1301, USA.
+
+AC_DEFUN([USRP_LIBUSB],
+[
+ AC_REQUIRE([AC_CANONICAL_HOST])
+ AC_LANG_PUSH(C)
+
+ AC_CHECK_HEADERS([usb.h],
+ [],
+ [ AC_MSG_ERROR([USRP requires libusb. usb.h not found, stop. See http://libusb.sf.net]) ]
+ )
+
+ save_LIBS="$LIBS"
+ case "$host_os" in
+ darwin*) LIBS="$LIBS -lIOKit" ;;
+ *) ;;
+ esac
+ AC_SEARCH_LIBS(usb_bulk_write, [usb],
+ [ USB_LIBS="$LIBS" ],
+ [ AC_MSG_ERROR([USRP requires libusb. usb_bulk_write not found, stop. See http://libusb.sf.net]) ]
+ )
+ LIBS="$save_LIBS"
+
+ AC_LANG_POP
+ AC_SUBST(USB_LIBS)
+])
diff --git a/gsm-receiver/config/usrp_sdcc.m4 b/gsm-receiver/config/usrp_sdcc.m4
new file mode 100644
index 0000000..37ce7c3
--- /dev/null
+++ b/gsm-receiver/config/usrp_sdcc.m4
@@ -0,0 +1,67 @@
+# Check for sdcc support. -*- Autoconf -*-
+
+# Copyright 2004 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Boston, MA
+# 02110-1301, USA.
+
+AC_DEFUN([USRP_SDCC],
+[
+ AC_CHECK_PROG(XCC, sdcc, sdcc -mmcs51 --no-xinit-opt,no)
+ AC_CHECK_PROG(XAS, asx8051, asx8051 -plosgff,no)
+
+ if test "$XCC" = "no" -o "$XAS" = "no" ; then
+ AC_MSG_ERROR([USRP requires sdcc. sdcc not found, stop. See http://sdcc.sf.net])
+ fi
+
+ sdcc_version_min=$1
+
+ sdcc_version=`sdcc --version 2>&1 | \
+ sed 's/\(SDCC.* \)\([[0-9]]*\.[[0-9]]*\.[[0-9]]*\)\( .*$\)/\2/'`
+
+ AC_MSG_CHECKING([sdcc_version "$sdcc_version"])
+
+ sdcc_major_version=`echo $sdcc_version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
+ sdcc_minor_version=`echo $sdcc_version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
+ sdcc_micro_version=`echo $sdcc_version | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
+
+ sdcc_major_min=`echo $sdcc_version_min | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
+ sdcc_minor_min=`echo $sdcc_version_min | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
+ sdcc_micro_min=`echo $sdcc_version_min | \
+ sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
+
+ sdcc_version_proper=`expr \
+ "$sdcc_major_version" \> "$sdcc_major_min" \| \
+ "$sdcc_major_version" \= "$sdcc_major_min" \& \
+ "$sdcc_minor_version" \> "$sdcc_minor_min" \| \
+ "$sdcc_major_version" \= "$sdcc_major_min" \& \
+ "$sdcc_minor_version" \= "$sdcc_minor_min" \& \
+ "$sdcc_micro_version" \>= "$sdcc_micro_min" `
+
+ if test "$sdcc_version_proper" = "1" ; then
+ AC_MSG_RESULT([$sdcc_major_version.$sdcc_minor_version.$sdcc_micro_version])
+ else
+ AC_MSG_ERROR([USRP requires sdcc >= $sdcc_version_min. sdcc not found, stop. See http://sdcc.sf.net])
+ fi
+
+ AC_SUBST(XCC)
+ AC_SUBST(XAS)
+
+])
diff --git a/gsm-receiver/configure.ac b/gsm-receiver/configure.ac
new file mode 100644
index 0000000..30fe57a
--- /dev/null
+++ b/gsm-receiver/configure.ac
@@ -0,0 +1,120 @@
+dnl
+dnl Copyright 2004,2005,2006,2007,2008 Free Software Foundation, Inc.
+dnl
+dnl This file is part of GNU Radio
+dnl
+dnl GNU Radio is free software; you can redistribute it and/or modify
+dnl it under the terms of the GNU General Public License as published by
+dnl the Free Software Foundation; either version 3, or (at your option)
+dnl any later version.
+dnl
+dnl GNU Radio is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+dnl GNU General Public License for more details.
+dnl
+dnl You should have received a copy of the GNU General Public License
+dnl along with GNU Radio; see the file COPYING. If not, write to
+dnl the Free Software Foundation, Inc., 51 Franklin Street,
+dnl Boston, MA 02110-1301, USA.
+dnl
+
+AC_INIT
+AC_PREREQ(2.61)
+AC_CONFIG_SRCDIR([src/lib/gsm.i])
+AM_CONFIG_HEADER(config.h)
+AC_CANONICAL_TARGET([])
+AC_CONFIG_AUX_DIR([.])
+AM_INIT_AUTOMAKE(gsm-receiver,0.0.1)
+AC_CONFIG_MACRO_DIR([config])
+
+GR_X86_64
+dnl LF_CONFIGURE_CC
+LF_CONFIGURE_CXX
+LF_SET_WARNINGS
+
+dnl add ${prefix}/lib${gr_libdir_suffix}/pkgconfig to the head of the PKG_CONFIG_PATH
+if test x${PKG_CONFIG_PATH} = x; then
+ PKG_CONFIG_PATH=${prefix}/lib${gr_libdir_suffix}/pkgconfig
+else
+ PKG_CONFIG_PATH=${prefix}/lib${gr_libdir_suffix}/pkgconfig:${PKG_CONFIG_PATH}
+fi
+export PKG_CONFIG_PATH
+
+
+GR_SET_GPROF
+GR_SET_PROF
+AM_PROG_AS
+AC_PROG_LN_S
+AC_PROG_MAKE_SET
+AC_PROG_INSTALL
+AC_PATH_PROG([RM_PROG], [rm])
+
+AC_LIBTOOL_WIN32_DLL
+AC_ENABLE_SHARED dnl do build shared libraries
+AC_DISABLE_STATIC dnl don't build static libraries
+m4_ifdef([LT_INIT],[LT_INIT],[AC_PROG_LIBTOOL])
+dnl Locate python, SWIG, etc
+GR_NO_UNDEFINED
+GR_SCRIPTING
+
+dnl Checks for libraries.
+
+dnl check for threads (mandatory)
+GR_OMNITHREAD
+
+CFLAGS="${CFLAGS} $PTHREAD_CFLAGS"
+CXXFLAGS="${CXXFLAGS} $PTHREAD_CFLAGS"
+
+if test "x$CXX_FOR_BUILD" = x
+then
+ CXX_FOR_BUILD=${CXX}
+fi
+AC_SUBST(CXX_FOR_BUILD)
+
+dnl Checks for header files.
+AC_HEADER_STDC
+AC_HEADER_SYS_WAIT
+AC_CHECK_HEADERS(fcntl.h limits.h strings.h sys/ioctl.h sys/time.h unistd.h)
+AC_CHECK_HEADERS(sys/mman.h)
+
+dnl Checks for typedefs, structures, and compiler characteristics.
+AC_C_CONST
+AC_C_INLINE
+AC_TYPE_SIZE_T
+AC_HEADER_TIME
+
+dnl Checks for library functions.
+AC_CHECK_FUNCS([])
+
+dnl Check for Mingw support
+GR_PWIN32
+
+PKG_CHECK_MODULES(GNURADIO_CORE, gnuradio-core >= 3)
+dnl LIBS="$LIBS $GNURADIO_CORE_LIBS"
+
+dnl Define where to find boost includes
+dnl defines BOOST_CFLAGS
+GR_REQUIRE_BOOST_INCLUDES
+
+STD_DEFINES_AND_INCLUDES="$GNURADIO_CORE_CFLAGS $BOOST_CFLAGS"
+AC_SUBST(STD_DEFINES_AND_INCLUDES)
+
+
+AC_CONFIG_FILES([\
+ Makefile \
+ config/Makefile \
+ src/Makefile \
+ src/lib/Makefile \
+ src/lib/decoder/Makefile \
+ src/python/Makefile \
+ src/lib/decoder/openbtsstuff/Makefile \
+ gsm-receiver.pc \
+ ])
+dnl # doc/Makefile \
+dnl # src/python/run_tests \
+
+dnl run_tests is created from run_tests.in. Make it executable.
+#AC_CONFIG_COMMANDS([run_tests], [chmod +x src/python/run_tests])
+
+AC_OUTPUT
diff --git a/gsm-receiver/gsm-receiver.pc.in b/gsm-receiver/gsm-receiver.pc.in
new file mode 100644
index 0000000..0a18d4b
--- /dev/null
+++ b/gsm-receiver/gsm-receiver.pc.in
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: gsm-receiver
+Description: The GSM receiver block which does FCCH burst search, sch decoding and normal burst demodulation
+Requires: gnuradio-core
+Version: @VERSION@
+Libs: -L${libdir} -lgsm-receiver
+Cflags: -I${includedir}
diff --git a/gsm-receiver/py-compile b/gsm-receiver/py-compile
new file mode 100755
index 0000000..d6e900b
--- /dev/null
+++ b/gsm-receiver/py-compile
@@ -0,0 +1,146 @@
+#!/bin/sh
+# py-compile - Compile a Python program
+
+scriptversion=2005-05-14.22
+
+# Copyright (C) 2000, 2001, 2003, 2004, 2005 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+# 02110-1301, USA.
+
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# This file is maintained in Automake, please report
+# bugs to <bug-automake@gnu.org> or send patches to
+# <automake-patches@gnu.org>.
+
+if [ -z "$PYTHON" ]; then
+ PYTHON=python
+fi
+
+basedir=
+destdir=
+files=
+while test $# -ne 0; do
+ case "$1" in
+ --basedir)
+ basedir=$2
+ if test -z "$basedir"; then
+ echo "$0: Missing argument to --basedir." 1>&2
+ exit 1
+ fi
+ shift
+ ;;
+ --destdir)
+ destdir=$2
+ if test -z "$destdir"; then
+ echo "$0: Missing argument to --destdir." 1>&2
+ exit 1
+ fi
+ shift
+ ;;
+ -h|--h*)
+ cat <<\EOF
+Usage: py-compile [--help] [--version] [--basedir DIR] [--destdir DIR] FILES..."
+
+Byte compile some python scripts FILES. Use --destdir to specify any
+leading directory path to the FILES that you don't want to include in the
+byte compiled file. Specify --basedir for any additional path information you
+do want to be shown in the byte compiled file.
+
+Example:
+ py-compile --destdir /tmp/pkg-root --basedir /usr/share/test test.py test2.py
+
+Report bugs to <bug-automake@gnu.org>.
+EOF
+ exit $?
+ ;;
+ -v|--v*)
+ echo "py-compile $scriptversion"
+ exit $?
+ ;;
+ *)
+ files="$files $1"
+ ;;
+ esac
+ shift
+done
+
+if test -z "$files"; then
+ echo "$0: No files given. Try \`$0 --help' for more information." 1>&2
+ exit 1
+fi
+
+# if basedir was given, then it should be prepended to filenames before
+# byte compilation.
+if [ -z "$basedir" ]; then
+ pathtrans="path = file"
+else
+ pathtrans="path = os.path.join('$basedir', file)"
+fi
+
+# if destdir was given, then it needs to be prepended to the filename to
+# byte compile but not go into the compiled file.
+if [ -z "$destdir" ]; then
+ filetrans="filepath = path"
+else
+ filetrans="filepath = os.path.normpath('$destdir' + os.sep + path)"
+fi
+
+$PYTHON -c "
+import sys, os, string, py_compile
+
+files = '''$files'''
+
+print 'Byte-compiling python modules...'
+for file in string.split(files):
+ $pathtrans
+ $filetrans
+ if not os.path.exists(filepath) or not (len(filepath) >= 3
+ and filepath[-3:] == '.py'):
+ continue
+ print file,
+ sys.stdout.flush()
+ py_compile.compile(filepath, filepath + 'c', path)
+print" || exit $?
+
+# this will fail for python < 1.5, but that doesn't matter ...
+$PYTHON -O -c "
+import sys, os, string, py_compile
+
+files = '''$files'''
+print 'Byte-compiling python modules (optimized versions) ...'
+for file in string.split(files):
+ $pathtrans
+ $filetrans
+ if not os.path.exists(filepath) or not (len(filepath) >= 3
+ and filepath[-3:] == '.py'):
+ continue
+ print file,
+ sys.stdout.flush()
+ py_compile.compile(filepath, filepath + 'o', path)
+print" 2>/dev/null || :
+
+# Local Variables:
+# mode: shell-script
+# sh-indentation: 2
+# eval: (add-hook 'write-file-hooks 'time-stamp)
+# time-stamp-start: "scriptversion="
+# time-stamp-format: "%:y-%02m-%02d.%02H"
+# time-stamp-end: "$"
+# End:
diff --git a/gsm-receiver/src/Makefile.am b/gsm-receiver/src/Makefile.am
new file mode 100644
index 0000000..79cfa3e
--- /dev/null
+++ b/gsm-receiver/src/Makefile.am
@@ -0,0 +1,23 @@
+#
+# Copyright 2004 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+SUBDIRS = lib python
+
diff --git a/gsm-receiver/src/lib/Assert.h b/gsm-receiver/src/lib/Assert.h
new file mode 100644
index 0000000..acfb3f7
--- /dev/null
+++ b/gsm-receiver/src/lib/Assert.h
@@ -0,0 +1,67 @@
+/*
+* 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 ASSERT_H
+#define ASSERT_H
+
+#include "stdio.h"
+#include <iostream>
+
+#define NDEBUG
+
+/**@name Macros for standard messages. */
+//@{
+#define COUT(text) { std::cout << text << std::endl; }
+#define CERR(text) { std::cerr << __FILE__ << ":" << __LINE__ << ": " << text; }
+#ifdef NDEBUG
+#define DCOUT(text) {}
+#define OBJDCOUT(text) {}
+#else
+#define DCOUT(text) { COUT(__FILE__ << ":" << __LINE__ << " " << text); }
+#define OBJDCOUT(text) { DCOUT(this << " " << text); }
+#endif
+//@}
+
+
+/** This is thrown by assert() so that gdb can catch it. */
+
+class Assertion
+{
+
+ public:
+
+ Assertion() {
+ fprintf( stderr,"Try setting a breakpoint @ %s:%u.\n",__FILE__,__LINE__ );
+ return;
+ }
+
+};
+
+#ifdef NDEBUG
+#define assert(EXPR) {};
+#else
+/** This replaces the regular assert() with a C++ exception. */
+#include "stdio.h"
+#define assert(E) { if (!(E)) { fprintf(stderr,"%s:%u failed assertion '%s'\n",__FILE__,__LINE__,#E); throw Assertion(); } }
+#endif
+
+#endif
diff --git a/gsm-receiver/src/lib/Makefile.am b/gsm-receiver/src/lib/Makefile.am
new file mode 100644
index 0000000..925eaca
--- /dev/null
+++ b/gsm-receiver/src/lib/Makefile.am
@@ -0,0 +1,109 @@
+#
+# Copyright 2004,2005,2006,2008 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+include $(top_srcdir)/Makefile.common
+
+SUBDIRS = decoder
+# Install this stuff so that it ends up as the gnuradio.howto module
+# This usually ends up at:
+# ${prefix}/lib/python${python_version}/site-packages/gnuradio
+
+ourpythondir = $(grpythondir)
+ourlibdir = $(grpyexecdir)
+
+AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES) $(PYTHON_CPPFLAGS) $(WITH_INCLUDES)
+# -I$(OPEN_BTS_INCLUDES)
+
+SWIGPYTHONARGS = $(SWIGPYTHONFLAGS) $(SWIGGRFLAGS) $(WITH_SWIG_INCLUDES) \
+ $(WITH_INCLUDES)
+
+ALL_IFILES = \
+ $(LOCAL_IFILES) \
+ $(NON_LOCAL_IFILES)
+
+NON_LOCAL_IFILES = \
+ $(GNURADIO_CORE_INCLUDEDIR)/swig/gnuradio.i
+
+
+LOCAL_IFILES = \
+ $(top_srcdir)/src/lib/gsm.i
+
+# These files are built by SWIG. The first is the C++ glue.
+# The second is the python wrapper that loads the _howto shared library
+# and knows how to call our extensions.
+
+BUILT_SOURCES = \
+ gsm.cc \
+ gsm.py
+
+# This gets howto.py installed in the right place
+ourpython_PYTHON = \
+ gsm.py
+
+ourlib_LTLIBRARIES = _gsm.la
+
+lib_LTLIBRARIES = libgsmdemod.la
+
+# These are the source files that go into the shared library
+_gsm_la_SOURCES = \
+ gsm.cc
+
+libgsmdemod_la_SOURCES = \
+ gsm_receiver_cf.cc \
+ gsm_receiver_config.cc \
+ viterbi_detector.cc
+
+# magic flags
+_gsm_la_LDFLAGS = $(NO_UNDEFINED) -module -avoid-version
+
+# link the library against some comon swig runtime code and the
+# c++ standard library
+_gsm_la_LIBADD = \
+ $(PYTHON_LDFLAGS) \
+ libgsmdemod.la \
+ -lstdc++ \
+ $(DECODER_LA)
+
+#libgsmdemod_la_LIBADD =
+
+gsm.cc gsm.py: $(LOCAL_IFILES) $(ALL_IFILES)
+ $(SWIG) $(SWIGPYTHONARGS) -module gsm -o gsm.cc $(LOCAL_IFILES)
+
+# These headers get installed in ${prefix}/include/gnuradio
+grinclude_HEADERS = \
+ gsm_receiver_cf.h \
+ gsm_receiver_config.h
+
+noinst_HEADERS = \
+ gsm_constants.h \
+ viterbi_detector.h
+
+# These swig headers get installed in ${prefix}/include/gnuradio/swig
+swiginclude_HEADERS = \
+ $(LOCAL_IFILES)
+
+
+MOSTLYCLEANFILES = $(BUILT_SOURCES) *.pyc
+
+# Don't distribute output of swig
+dist-hook:
+ @for file in $(BUILT_SOURCES); do echo $(RM) $(distdir)/$$file; done
+ @for file in $(BUILT_SOURCES); do $(RM) $(distdir)/$$file; done
diff --git a/gsm-receiver/src/lib/decoder/AUTHORS b/gsm-receiver/src/lib/decoder/AUTHORS
new file mode 100644
index 0000000..dcc5998
--- /dev/null
+++ b/gsm-receiver/src/lib/decoder/AUTHORS
@@ -0,0 +1 @@
+Harald Welte <laforge@gnumonks.org>
diff --git a/gsm-receiver/src/lib/decoder/Makefile.am b/gsm-receiver/src/lib/decoder/Makefile.am
new file mode 100644
index 0000000..1726d68
--- /dev/null
+++ b/gsm-receiver/src/lib/decoder/Makefile.am
@@ -0,0 +1,56 @@
+#
+# Copyright 2001,2002,2004,2005,2006,2007,2008 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+include $(top_srcdir)/Makefile.common
+
+AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES)
+
+SUBDIRS = openbtsstuff
+
+noinst_LTLIBRARIES = libdecoder.la
+
+libdecoder_la_LIBADD = \
+ openbtsstuff/libopenbtsdecoder.la
+
+libdecoder_la_SOURCES = \
+ sch.c \
+ cch.c \
+ fire_crc.c \
+ gsmstack.c \
+ interleave.c \
+ out_pcap.c \
+ tun.c
+# tch.c \
+# conv.c
+
+noinst_HEADERS = \
+ sch.h \
+ cch.h \
+ fire_crc.h \
+ gsmstack.h \
+ interleave.h \
+ out_pcap.h \
+ tun.h \
+ system.h \
+ gsmtap.h \
+ a5-1-2.h
+# tch.h \
+# conv.h
diff --git a/gsm-receiver/src/lib/decoder/a5-1-2.h b/gsm-receiver/src/lib/decoder/a5-1-2.h
new file mode 100644
index 0000000..de764ee
--- /dev/null
+++ b/gsm-receiver/src/lib/decoder/a5-1-2.h
@@ -0,0 +1,453 @@
+/*
+ * A pedagogical implementation of the GSM A5/1 and A5/2 "voice privacy"
+ * encryption algorithms.
+ *
+ * Copyright (C) 1998-1999: Marc Briceno, Ian Goldberg, and David Wagner
+ *
+ * The source code below is optimized for instructional value and clarity.
+ * Performance will be terrible, but that's not the point.
+ *
+ * This software may be export-controlled by US law.
+ *
+ * This software is free for commercial and non-commercial use as long as
+ * the following conditions are adhered to.
+ * Copyright remains the authors' and as such any Copyright notices in
+ * the code are not to be removed.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * The license and distribution terms for any publicly available version
+ * or derivative of this code cannot be changed. i.e. this code cannot
+ * simply be copied and put under another distribution license
+ * [including the GNU Public License].
+ *
+ * Background: The Global System for Mobile communications is the most
+ * widely deployed digital cellular telephony system in the world. GSM
+ * makes use of four core cryptographic algorithms, none of which has
+ * been published by the GSM MOU. This failure to subject the
+ * algorithms to public review is all the more puzzling given that over
+ * 215 million GSM subscribers are expected to rely on the claimed
+ * security of the system.
+ *
+ * The four core GSM cryptographic algorithms are:
+ * A3 authentication algorithm
+ * A5/1 "stronger" over-the-air voice-privacy algorithm
+ * A5/2 "weaker" over-the-air voice-privacy algorithm
+ * A8 voice-privacy key generation algorithm
+ *
+ * In April of 1998, our group showed that COMP128, the algorithm used by the
+ * overwhelming majority of GSM providers for both A3 and A8 functionality
+ * is fatally flawed and allows for cloning of GSM mobile phones.
+ *
+ * Furthermore, we demonstrated that all A8 implementations we could locate,
+ * including the few that did not use COMP128 for key generation, had been
+ * deliberately weakened by reducing the keyspace from 64 bits to 54 bits.
+ * The remaining 10 bits are simply set to zero!
+ *
+ * See http://www.scard.org/gsm for additional information.
+ *
+ * [May 1999]
+ * One question so far unanswered is if A5/1, the "stronger" of the two
+ * widely deployed voice-privacy algorithm is at least as strong as the
+ * key. Meaning: "Does A5/1 have a work factor of at least 54 bits"?
+ * Absent a publicly available A5/1 reference implementation, this question
+ * could not be answered. We hope that our reference implementation below,
+ * which has been verified against official A5/1 test vectors, will provide
+ * the cryptographic community with the base on which to construct the
+ * answer to this important question.
+ *
+ * Initial indications about the strength of A5/1 are not encouraging.
+ * A variant of A5, while not A5/1 itself, has been estimated to have a
+ * work factor of well below 54 bits. See http://jya.com/crack-a5.htm for
+ * background information and references.
+ *
+ * With COMP128 broken and A5/1 published below, we will now turn our
+ * attention to A5/2.
+ *
+ * [August 1999]
+ * 19th Annual International Cryptology Conference - Crypto'99
+ * Santa Barbara, California
+ *
+ * A5/2 has been added to the previously published A5/1 source. Our
+ * implementation has been verified against official test vectors.
+ *
+ * This means that our group has now reverse engineered the entire set
+ * of cryptographic algorithms used in the overwhelming majority of GSM
+ * installations, including all the over-the-air "voice privacy" algorithms.
+ *
+ * The "voice privacy" algorithm A5/2 proved especially weak. Which perhaps
+ * should come as no surprise, since even GSM MOU members have admitted that
+ * A5/2 was designed with heavy input by intelligence agencies to ensure
+ * breakability. Just how insecure is A5/2? It can be broken in real time
+ * with a work factor of a mere 16 bits. GSM might just as well use no "voice
+ * privacy" algorithm at all.
+ *
+ * We announced the break of A5/2 at the Crypto'99 Rump Session.
+ * Details will be published in a scientific paper following soon.
+ *
+ *
+ * -- Marc Briceno <marc@scard.org>
+ * Voice: +1 (925) 798-4042
+ *
+ */
+
+
+#include <stdio.h>
+
+
+/* Masks for the shift registers */
+#define R1MASK 0x07FFFF /* 19 bits, numbered 0..18 */
+#define R2MASK 0x3FFFFF /* 22 bits, numbered 0..21 */
+#define R3MASK 0x7FFFFF /* 23 bits, numbered 0..22 */
+#ifdef A5_2
+#define R4MASK 0x01FFFF /* 17 bits, numbered 0..16 */
+#endif /* A5_2 */
+
+
+#ifndef A5_2
+/* Middle bit of each of the three shift registers, for clock control */
+#define R1MID 0x000100 /* bit 8 */
+#define R2MID 0x000400 /* bit 10 */
+#define R3MID 0x000400 /* bit 10 */
+#else /* A5_2 */
+/* A bit of R4 that controls each of the shift registers */
+#define R4TAP1 0x000400 /* bit 10 */
+#define R4TAP2 0x000008 /* bit 3 */
+#define R4TAP3 0x000080 /* bit 7 */
+#endif /* A5_2 */
+
+
+/* Feedback taps, for clocking the shift registers.
+ * These correspond to the primitive polynomials
+ * x^19 + x^5 + x^2 + x + 1, x^22 + x + 1,
+ * x^23 + x^15 + x^2 + x + 1, and x^17 + x^5 + 1. */
+
+
+#define R1TAPS 0x072000 /* bits 18,17,16,13 */
+#define R2TAPS 0x300000 /* bits 21,20 */
+#define R3TAPS 0x700080 /* bits 22,21,20,7 */
+#ifdef A5_2
+#define R4TAPS 0x010800 /* bits 16,11 */
+#endif /* A5_2 */
+
+
+typedef unsigned char byte;
+typedef unsigned long word;
+typedef word bit;
+
+
+/* Calculate the parity of a 32-bit word, i.e. the sum of its bits modulo 2
+*/
+bit parity(word x)
+{
+ x ^= x >> 16;
+ x ^= x >> 8;
+ x ^= x >> 4;
+ x ^= x >> 2;
+ x ^= x >> 1;
+ return x&1;
+}
+
+
+/* Clock one shift register. For A5/2, when the last bit of the frame
+ * is loaded in, one particular bit of each register is forced to '1';
+ * that bit is passed in as the last argument. */
+#ifndef A5_2
+word clockone(word reg, word mask, word taps)
+{
+#else /* A5_2 */
+word clockone(word reg, word mask, word taps, word loaded_bit) {
+#endif /* A5_2 */
+ word t = reg & taps;
+ reg = (reg << 1) & mask;
+ reg |= parity(t);
+#ifdef A5_2
+ reg |= loaded_bit;
+#endif /* A5_2 */
+ return reg;
+}
+
+
+/* The three shift registers. They're in global variables to make the code
+ * easier to understand.
+ * A better implementation would not use global variables. */
+word R1, R2, R3;
+#ifdef A5_2
+word R4;
+#endif /* A5_2 */
+
+
+/* Return 1 iff at least two of the parameter words are non-zero. */
+bit majority(word w1, word w2, word w3) {
+ int sum = (w1 != 0) + (w2 != 0) + (w3 != 0);
+ if (sum >= 2)
+ return 1;
+ else
+ return 0;
+}
+
+
+/* Clock two or three of R1,R2,R3, with clock control
+ * according to their middle bits.
+ * Specifically, we clock Ri whenever Ri's middle bit
+ * agrees with the majority value of the three middle bits. For A5/2,
+ * use particular bits of R4 instead of the middle bits. Also, for A5/2,
+ * always clock R4.
+ * If allP == 1, clock all three of R1,R2,R3, ignoring their middle bits.
+ * This is only used for key setup. If loaded == 1, then this is the last
+ * bit of the frame number, and if we're doing A5/2, we have to set a
+ * particular bit in each of the four registers. */
+void clock(int allP, int loaded) {
+#ifndef A5_2
+ bit maj = majority(R1 & R1MID, R2 & R2MID, R3 & R3MID);
+ if (allP || (((R1&R1MID) != 0) == maj))
+ R1 = clockone(R1, R1MASK, R1TAPS);
+ if (allP || (((R2&R2MID) != 0) == maj))
+ R2 = clockone(R2, R2MASK, R2TAPS);
+ if (allP || (((R3&R3MID) != 0) == maj))
+ R3 = clockone(R3, R3MASK, R3TAPS);
+#else /* A5_2 */
+ bit maj = majority(R4 & R4TAP1, R4 & R4TAP2, R4 & R4TAP3);
+ if (allP || (((R4&R4TAP1) != 0) == maj))
+ R1 = clockone(R1, R1MASK, R1TAPS, loaded << 15);
+ if (allP || (((R4&R4TAP2) != 0) == maj))
+ R2 = clockone(R2, R2MASK, R2TAPS, loaded << 16);
+ if (allP || (((R4&R4TAP3) != 0) == maj))
+ R3 = clockone(R3, R3MASK, R3TAPS, loaded << 18);
+ R4 = clockone(R4, R4MASK, R4TAPS, loaded << 10);
+#endif /* A5_2 */
+}
+
+
+/* Generate an output bit from the current state.
+ * You grab a bit from each register via the output generation taps;
+ * then you XOR the resulting three bits. For A5/2, in addition to
+ * the top bit of each of R1,R2,R3, also XOR in a majority function
+ * of three particular bits of the register (one of them complemented)
+ * to make it non-linear. Also, for A5/2, delay the output by one
+ * clock cycle for some reason. */
+bit getbit() {
+ bit topbits = (((R1 >> 18) ^ (R2 >> 21) ^ (R3 >> 22)) & 0x01);
+#ifndef A5_2
+ return topbits;
+#else /* A5_2 */
+ static bit delaybit = 0;
+ bit nowbit = delaybit;
+ delaybit = (
+ topbits
+ ^ majority(R1 & 0x8000, (~R1) & 0x4000, R1 & 0x1000)
+ ^ majority((~R2) & 0x10000, R2 & 0x2000, R2 & 0x200)
+ ^ majority(R3 & 0x40000, R3 & 0x10000, (~R3) & 0x2000)
+ );
+ return nowbit;
+#endif /* A5_2 */
+}
+
+
+/* Do the A5 key setup. This routine accepts a 64-bit key and
+ * a 22-bit frame number. */
+void keysetup(byte key_reversed[8], word frame) {
+ int i;
+ bit keybit, framebit;
+
+ byte key[8];
+ for(i=0; i<8; i++){
+ key[i] = key_reversed[7-i];
+ }
+ /* Zero out the shift registers. */
+ R1 = R2 = R3 = 0;
+#ifdef A5_2
+ R4 = 0;
+#endif /* A5_2 */
+
+
+ /* Load the key into the shift registers,
+ * LSB of first byte of key array first,
+ * clocking each register once for every
+ * key bit loaded. (The usual clock
+ * control rule is temporarily disabled.) */
+ for (i = 0; i < 64; i++) {
+ clock(1, 0); /* always clock */
+ keybit = (key[i/8] >> (i & 7)) & 1; /* The i-th bit of the key */
+ R1 ^= keybit;
+ R2 ^= keybit;
+ R3 ^= keybit;
+#ifdef A5_2
+ R4 ^= keybit;
+#endif /* A5_2 */
+ }
+
+
+ /* Load the frame number into the shift registers, LSB first,
+ * clocking each register once for every key bit loaded.
+ * (The usual clock control rule is still disabled.)
+ * For A5/2, signal when the last bit is being clocked in. */
+ for (i = 0; i < 22; i++) {
+ clock(1, i == 21); /* always clock */
+ framebit = (frame >> i) & 1; /* The i-th bit of the frame # */
+ R1 ^= framebit;
+ R2 ^= framebit;
+ R3 ^= framebit;
+#ifdef A5_2
+ R4 ^= framebit;
+#endif /* A5_2 */
+ }
+
+
+ /* Run the shift registers for 100 clocks
+ * to mix the keying material and frame number
+ * together with output generation disabled,
+ * so that there is sufficient avalanche.
+ * We re-enable the majority-based clock control
+ * rule from now on. */
+ for (i = 0; i < 100; i++) {
+ clock(0, 0);
+ }
+ /* For A5/2, we have to load the delayed output bit. This does _not_
+ * change the state of the registers. For A5/1, this is a no-op. */
+ getbit();
+
+
+ /* Now the key is properly set up. */
+}
+
+
+/* Generate output. We generate 228 bits of
+ * keystream output. The first 114 bits is for
+ * the A->B frame; the next 114 bits is for the
+ * B->A frame. You allocate a 15-byte buffer
+ * for each direction, and this function fills
+ * it in. */
+void run(byte AtoBkeystream[], byte BtoAkeystream[]) {
+ int i;
+
+
+ /* Zero out the output buffers. */
+ for (i = 0; i <= 113 / 8; i++)
+ AtoBkeystream[i] = BtoAkeystream[i] = 0;
+
+
+ /* Generate 114 bits of keystream for the
+ * A->B direction. Store it, MSB first. */
+ for (i = 0; i < 114; i++) {
+ clock(0, 0);
+ AtoBkeystream[i/8] |= getbit() << (7 - (i & 7));
+ }
+
+
+ /* Generate 114 bits of keystream for the
+ * B->A direction. Store it, MSB first. */
+ for (i = 0; i < 114; i++) {
+ clock(0, 0);
+ BtoAkeystream[i/8] |= getbit() << (7 - (i & 7));
+ }
+}
+
+void runA51(unsigned char AtoBkeystream[]) {
+ int i;
+
+ /* Zero out the output buffers. */
+ for (i = 0; i < 114; i++)
+ AtoBkeystream[i] = 0;
+
+
+ /* Generate 114 bits of keystream for the
+ * A->B direction. Store it, MSB first. */
+ for (i = 0; i < 114; i++) {
+ clock(0, 0);
+ AtoBkeystream[i] = getbit();
+ }
+}
+
+
+/* Test the code by comparing it against
+ * a known-good test vector. */
+void test() {
+#ifndef A5_2
+ byte key[8] = {0x12, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF};
+ word frame = 0x134;
+ byte goodAtoB[15] = { 0x53, 0x4E, 0xAA, 0x58, 0x2F, 0xE8, 0x15,
+ 0x1A, 0xB6, 0xE1, 0x85, 0x5A, 0x72, 0x8C, 0x00
+ };
+ byte goodBtoA[15] = { 0x24, 0xFD, 0x35, 0xA3, 0x5D, 0x5F, 0xB6,
+ 0x52, 0x6D, 0x32, 0xF9, 0x06, 0xDF, 0x1A, 0xC0
+ };
+#else /* A5_2 */
+ byte key[8] = {0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+ word frame = 0x21;
+ byte goodAtoB[15] = { 0xf4, 0x51, 0x2c, 0xac, 0x13, 0x59, 0x37,
+ 0x64, 0x46, 0x0b, 0x72, 0x2d, 0xad, 0xd5, 0x00
+ };
+ byte goodBtoA[15] = { 0x48, 0x00, 0xd4, 0x32, 0x8e, 0x16, 0xa1,
+ 0x4d, 0xcd, 0x7b, 0x97, 0x22, 0x26, 0x51, 0x00
+ };
+#endif /* A5_2 */
+ byte AtoB[15], BtoA[15];
+ int i, failed = 0;
+
+
+ keysetup(key, frame);
+ run(AtoB, BtoA);
+
+
+ /* Compare against the test vector. */
+ for (i = 0; i < 15; i++)
+ if (AtoB[i] != goodAtoB[i])
+ failed = 1;
+ for (i = 0; i < 15; i++)
+ if (BtoA[i] != goodBtoA[i])
+ failed = 1;
+
+
+ /* Print some debugging output. */
+ printf("key: 0x");
+ for (i = 0; i < 8; i++)
+ printf("%02X", key[i]);
+ printf("\n");
+ printf("frame number: 0x%06X\n", (unsigned int)frame);
+ printf("known good output:\n");
+ printf(" A->B: 0x");
+ for (i = 0; i < 15; i++)
+ printf("%02X", goodAtoB[i]);
+ printf(" B->A: 0x");
+ for (i = 0; i < 15; i++)
+ printf("%02X", goodBtoA[i]);
+ printf("\n");
+ printf("observed output:\n");
+ printf(" A->B: 0x");
+ for (i = 0; i < 15; i++)
+ printf("%02X", AtoB[i]);
+ printf(" B->A: 0x");
+ for (i = 0; i < 15; i++)
+ printf("%02X", BtoA[i]);
+ printf("\n");
+
+
+ if (!failed) {
+ printf("Self-check succeeded: everything looks ok.\n");
+// exit(0);
+ } else {
+ /* Problems! The test vectors didn't compare*/
+ printf("\nI don't know why this broke; contact the authors.\n");
+ }
+}
+
diff --git a/gsm-receiver/src/lib/decoder/burst_types.h b/gsm-receiver/src/lib/decoder/burst_types.h
new file mode 100644
index 0000000..ee51f9a
--- /dev/null
+++ b/gsm-receiver/src/lib/decoder/burst_types.h
@@ -0,0 +1,214 @@
+// $Id: burst_types.h,v 1.5 2007/03/14 05:44:53 jl Exp $
+
+#pragma once
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <gsm_constants.h>
+
+static const int TB_LEN = 3;
+static const int TB_OS1 = 0;
+static const int TB_OS2 = 145;
+static const unsigned char tail_bits[] = {0, 0, 0};
+
+/*
+ * The normal burst is used to carry information on traffic and control
+ * channels.
+ */
+
+static const int N_TSC_NUM = 8; // number of training sequence codes
+static const int N_TSC_CODE_LEN = 26; // length of tsc
+static const int N_TSC_OS = 61; // tsc offset
+static const int N_EDATA_LEN_1 = 58; // length of first data section
+static const int N_EDATA_OS_1 = 3; // offset of first data section
+static const int N_EDATA_LEN_2 = 58; // length of second data section
+static const int N_EDATA_OS_2 = 87; // offset of second data section
+#if 0
+static const unsigned char n_tsc[][N_TSC_CODE_LEN] = {
+/* 0 */ {
+ 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0,
+ 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1
+ },
+/* 1 */ {
+ 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1,
+ 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1
+ },
+/* 2 */ {
+ 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1,
+ 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0
+ },
+/* 3 */ {
+ 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0,
+ 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0
+ },
+/* 4 */ {
+ 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0,
+ 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1
+ },
+/* 5 */ {
+ 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0
+ },
+/* 6 */ {
+ 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1,
+ 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1
+ },
+/* 7 */ {
+ 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0,
+ 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0
+ }
+};
+
+#endif
+
+/*
+ * The frequency correction burst is used for frequency synchronization
+ * of the mobile. This is broadcast in TS0 together with the SCH and
+ * BCCH.
+ *
+ * Modulating the bits below causes a spike at 62.5kHz above (below for
+ * COMPACT) the center frequency. One can use this spike with a narrow
+ * band filter to accurately determine the center of the channel.
+ */
+static const int FC_CODE_LEN = 142;
+static const int FC_OS = 3;
+static const unsigned char fc_fb[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static const unsigned char fc_compact_fb[] = {
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0
+};
+
+
+/*
+ * The synchronization burst is used for time synchronization of the
+ * mobile. The bits given below were chosen for their correlation
+ * properties. The synchronization channel (SCH) contains a long
+ * training sequence (given below) and carries the TDMA frame number and
+ * base station identity code. It is broadcast in TS0 in the frame
+ * following the frequency correction burst.
+ */
+static const int SB_CODE_LEN = 64;
+static const int SB_ETS_OS = 42;
+static const int SB_EDATA_LEN_1 = 39;
+static const int SB_EDATA_OS_1 = 3;
+static const int SB_EDATA_LEN_2 = 39;
+static const int SB_EDATA_OS_2 = 106;
+static const unsigned char sb_etsc[] = {
+ 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
+ 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1,
+ 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1
+};
+
+static const unsigned char sb_cts_etsc[] = {
+ 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1,
+ 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0,
+ 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0,
+ 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1
+};
+
+static const unsigned char sb_compact_etsc[] = {
+ 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1,
+ 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0,
+ 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0
+};
+
+
+/*
+ * A base tranceiver station must transmit a burst in every timeslot of
+ * every TDMA frame in channel C0. The dummy burst will be transmitted
+ * on all timeslots of all TDMA frames for which no other channel
+ * requires a burst to be transmitted.
+ */
+static const int D_CODE_LEN = 142;
+static const int D_MB_OS = 3;
+static const unsigned char d_mb[] = {
+ 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0,
+ 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0,
+ 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0,
+ 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0,
+ 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0,
+ 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0,
+ 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1,
+ 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1,
+ 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0
+};
+
+
+/*
+ * The access burst is used for random access from a mobile.
+ */
+static const int AB_ETB_CODE_LEN = 8;
+static const int AB_ETB_OS = 0;
+static const unsigned char ab_etb[] = {
+ 0, 0, 1, 1, 1, 0, 1, 0
+};
+
+static const int AB_SSB_CODE_LEN = 41;
+static const int AB_SSB_OS = 8;
+static const unsigned char ab_ssb[] = {
+ 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1,
+ 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0,
+ 0, 0, 1, 1, 1, 1, 0, 0, 0
+};
+
+static const unsigned char ab_ts1_ssb[] = {
+ 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0,
+ 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1,
+ 0, 0, 1, 0, 0, 1, 1, 0, 1
+};
+
+static const unsigned char ab_ts2_ssb[] = {
+ 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1,
+ 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1,
+ 1, 0, 1, 1, 1, 0, 1, 1, 1
+};
+
+
+typedef enum {
+ burst_n_0,
+ burst_n_1,
+ burst_n_2,
+ burst_n_3,
+ burst_n_4,
+ burst_n_5,
+ burst_n_6,
+ burst_n_7,
+ burst_fc,
+ burst_fc_c,
+ burst_s,
+ burst_s_cts,
+ burst_s_c,
+ burst_d,
+ burst_a,
+ burst_a_ts1,
+ burst_a_ts2,
+ burst_not_a_burst
+} burst_t;
+
+static const int N_BURST_TYPES = ((int)(burst_not_a_burst) + 1);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gsm-receiver/src/lib/decoder/cch.c b/gsm-receiver/src/lib/decoder/cch.c
new file mode 100644
index 0000000..f1da56d
--- /dev/null
+++ b/gsm-receiver/src/lib/decoder/cch.c
@@ -0,0 +1,482 @@
+//TODO: this file shouldn't be part of the GSM Receiver
+#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];
+}
+ */
+
+
+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 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;
+ }
+}
+ */
+
+
+static 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)];
+ 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);
+ if (errors)
+ return NULL;
+
+ // 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)
+ {
+ errors = -1;
+ DEBUGF("error: sacch: parity error (%d)\n", errors);
+ return NULL;
+ } else {
+ DEBUGF("Successfully corrected parity bits!\n");
+ memcpy(decoded_data, crc_result, sizeof crc_result);
+ errors = 0;
+ }
+ }
+
+ 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
diff --git a/gsm-receiver/src/lib/decoder/cch.h b/gsm-receiver/src/lib/decoder/cch.h
new file mode 100644
index 0000000..a642721
--- /dev/null
+++ b/gsm-receiver/src/lib/decoder/cch.h
@@ -0,0 +1,56 @@
+//TODO: this file shouldn't be part of the GSM Receiver
+#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)
+
+unsigned char *decode_cch(GS_CTX *ctx, unsigned char *burst, unsigned int *len);
+//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/gsm-receiver/src/lib/decoder/fire_crc.c b/gsm-receiver/src/lib/decoder/fire_crc.c
new file mode 100644
index 0000000..7cdfc0b
--- /dev/null
+++ b/gsm-receiver/src/lib/decoder/fire_crc.c
@@ -0,0 +1,179 @@
+//TODO: this file shouldn't be part of the GSM Receiver
+/* -*- c++ -*- */
+/*
+ * Copyright 2005 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "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");
+}
+
+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/gsm-receiver/src/lib/decoder/fire_crc.h b/gsm-receiver/src/lib/decoder/fire_crc.h
new file mode 100644
index 0000000..aa6319c
--- /dev/null
+++ b/gsm-receiver/src/lib/decoder/fire_crc.h
@@ -0,0 +1,47 @@
+//TODO: this file shouldn't be part of the GSM Receiver
+/* -*- c++ -*- */
+/*
+ * Copyright 2005 Free Software Foundation, Inc.
+ *
+ * This file is part of GNU Radio
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+
+#ifndef INCLUDED_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/gsm-receiver/src/lib/decoder/gsmstack.c b/gsm-receiver/src/lib/decoder/gsmstack.c
new file mode 100644
index 0000000..c3f1921
--- /dev/null
+++ b/gsm-receiver/src/lib/decoder/gsmstack.c
@@ -0,0 +1,206 @@
+/*
+ * Invoke gsmstack() with any kind of burst. Automaticly decode and retrieve
+ * information.
+ */
+#include "system.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include "gsmstack.h"
+//#include "gsm_constants.h"
+#include "interleave.h"
+//#include "sch.h"
+#include "cch.h"
+
+static const int USEFUL_BITS = 142;
+
+//#include "out_pcap.h"
+enum BURST_TYPE {
+ UNKNOWN,
+ FCCH,
+ PARTIAL_SCH, //successful correlation, but missing data ^
+ SCH,
+ CTS_SCH,
+ COMPACT_SCH,
+ NORMAL,
+ DUMMY,
+ ACCESS
+};
+static void out_gsmdecode(char type, int arfcn, int ts, int fn, char *data, int len);
+
+/* encode a decoded burst (1 bit per byte) into 8-bit-per-byte */
+static void burst_octify(unsigned char *dest,
+ const unsigned char *data, int length)
+{
+ int bitpos = 0;
+
+ while (bitpos < USEFUL_BITS) {
+ unsigned char tbyte;
+ int i;
+
+ tbyte = 0;
+ for (i = 0; (i < 8) && (bitpos < length); i++) {
+ tbyte <<= 1;
+ tbyte |= data[bitpos++];
+ }
+ if (i < 8)
+ tbyte <<= 8 - i;
+ *dest++ = tbyte;
+ }
+}
+
+
+#if 0
+static void
+diff_decode(char *dst, char *src, int len)
+{
+ const char *end = src + len;
+ unsigned char last;
+
+ src += 3;
+ last = 0;
+ memset(dst, 0, 3);
+ dst += 3;
+
+ while (src < end)
+ {
+ *dst = !*src ^ last;
+ last = *dst;
+ src++;
+ dst++;
+ }
+}
+#endif
+
+/*
+ * Initialize a new GSMSTACK context.
+ */
+int
+GS_new(GS_CTX *ctx)
+{
+ memset(ctx, 0, sizeof *ctx);
+ interleave_init(&ctx->interleave_ctx, 456, 114);
+ ctx->fn = -1;
+ ctx->bsic = -1;
+
+ ctx->tun_fd = mktun("gsm", ctx->ether_addr);
+ if (ctx->tun_fd < 0)
+ fprintf(stderr, "cannot open 'gsm' tun device, did you create it?\n");
+
+ ctx->pcap_fd = open_pcap_file("gsm-receiver.pcap");
+ if (ctx->pcap_fd < 0)
+ fprintf(stderr, "cannot open PCAP file: %s\n", strerror(errno));
+
+ ctx->burst_pcap_fd = open_pcap_file("gsm-receiver-burst.pcap");
+ if (ctx->burst_pcap_fd < 0)
+ fprintf(stderr, "cannot open burst PCAP file: %s\n", strerror(errno));
+
+ return 0;
+}
+
+#define BURST_BYTES ((USEFUL_BITS/8)+1)
+/*
+ * 142 bit
+ */
+int
+GS_process(GS_CTX *ctx, int ts, int type, const unsigned char *src, int fn)
+{
+// int fn;
+ int bsic;
+ int ret;
+ unsigned char *data;
+ int len;
+ struct gs_ts_ctx *ts_ctx = &ctx->ts_ctx[ts];
+ unsigned char octified[BURST_BYTES];
+
+ memset(ctx->msg, 0, sizeof(ctx->msg));
+
+ /* write burst to burst PCAP file */
+ burst_octify(octified, src, USEFUL_BITS);
+ write_pcap_packet(ctx->burst_pcap_fd, 0 /* arfcn */, ts, ctx->fn,
+ 1, type, octified, BURST_BYTES);
+
+#if 0
+ if (ts != 0) {
+ /* non-0 timeslots should end up in PCAP */
+ data = decode_cch(ctx, ctx->burst, &len);
+ if (data == NULL)
+ return -1;
+// write_pcap_packet(ctx->pcap_fd, 0 /* arfcn */, ts, ctx->fn, data, len);
+ return;
+ }
+#endif
+
+/* if (ts == 0) {
+ if (type == SCH) {
+// ret = decode_sch(src, &fn, &bsic);
+ if (ret != 0)
+ return 0;
+ if ((ctx->bsic > 0) && (bsic != ctx->bsic))
+ fprintf(stderr, "WARN: BSIC changed.\n");
+ //DEBUGF("FN %d, BSIC %d\n", fn, bsic);
+ ctx->fn = fn;
+ ctx->bsic = bsic;
+ /* Reset message concatenator */
+// ts_ctx->burst_count = 0;
+// return 0;
+// }
+
+ /* If we did not get Frame Number yet then return */
+// if (ctx->fn < 0)
+// return 0;
+
+// ctx->fn++;
+// }
+ ctx->fn = fn;
+ if (type == NORMAL) {
+ /* Interested in these frame numbers (cch)
+ * 2-5, 12-15, 22-25, 23-35, 42-45
+ * 6-9, 16-19, 26-29, 36-39, 46-49
+ */
+ /* Copy content data into new array */
+ //DEBUGF("burst count %d\n", ctx->burst_count);
+ memcpy(ts_ctx->burst + (116 * ts_ctx->burst_count), src, 58);
+ memcpy(ts_ctx->burst + (116 * ts_ctx->burst_count) + 58, src + 58 + 26, 58);
+ ts_ctx->burst_count++;
+ /* Return if not enough bursts for a full gsm message */
+ if (ts_ctx->burst_count < 4)
+ return 0;
+
+ ts_ctx->burst_count = 0;
+ data = decode_cch(ctx, ts_ctx->burst, &len);
+ if (data == NULL) {
+ DEBUGF("cannot decode fnr=0x%08x ts=%d\n", ctx->fn, ts);
+ return -1;
+ }
+ //DEBUGF("OK TS %d, len %d\n", ts, len);
+
+ out_gsmdecode(0, 0, ts, ctx->fn - 4, data, len);
+ write_interface(ctx->tun_fd, data+1, len-1, ctx->ether_addr);
+ write_pcap_packet(ctx->pcap_fd, 0 /* arfcn */, ts, ctx->fn,
+ 0, NORMAL, data, len);
+#if 0
+ if (ctx->fn % 51 != 0) && ( (((ctx->fn % 51 + 5) % 10 == 0) || (((ctx->fn % 51) + 1) % 10 ==0) ) )
+ ready = 1;
+#endif
+
+ return 0;
+ }
+}
+
+
+/*
+ * Output data so that it can be parsed from gsmdeocde.
+ */
+static void
+out_gsmdecode(char type, int arfcn, int ts, int fn, char *data, int len)
+{
+ char *end = data + len;
+
+ /* FIXME: speed this up by first printing into an array */
+ while (data < end)
+ printf(" %02.2x", (unsigned char)*data++);
+ printf("\n");
+ fflush(stdout);
+}
diff --git a/gsm-receiver/src/lib/decoder/gsmstack.h b/gsm-receiver/src/lib/decoder/gsmstack.h
new file mode 100644
index 0000000..9355785
--- /dev/null
+++ b/gsm-receiver/src/lib/decoder/gsmstack.h
@@ -0,0 +1,43 @@
+//TODO: this file shouldn't be part of the GSM Receiver
+#ifndef __GSMSTACK_H__
+#define __GSMSTACK_H__ 1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <linux/if_ether.h>
+#include "interleave.h"
+
+struct gs_ts_ctx {
+ /* FIXME: later do this per each ts per each arfcn */
+ unsigned char burst[4 * 58 * 2];
+ int burst_count;
+};
+
+typedef struct
+{
+ int flags;
+ int fn;
+ int bsic;
+ char msg[23]; /* last decoded message */
+
+ INTERLEAVE_CTX interleave_ctx;
+
+ struct gs_ts_ctx ts_ctx[8];
+
+ int tun_fd;
+ unsigned char ether_addr[ETH_ALEN];
+
+ int pcap_fd;
+ int burst_pcap_fd;
+} GS_CTX;
+
+int GS_new(GS_CTX *ctx);
+int GS_process(GS_CTX *ctx, int ts, int type, const unsigned char *src, int fn);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/gsm-receiver/src/lib/decoder/gsmtap.h b/gsm-receiver/src/lib/decoder/gsmtap.h
new file mode 100644
index 0000000..1022194
--- /dev/null
+++ b/gsm-receiver/src/lib/decoder/gsmtap.h
@@ -0,0 +1,41 @@
+#ifndef _GSMTAP_H
+#define _GSMTAP_H
+
+/* gsmtap header, pseudo-header in front of the actua GSM payload*/
+
+#include <sys/types.h>
+
+#define GSMTAP_VERSION 0x01
+
+#define GSMTAP_TYPE_UM 0x01
+#define GSMTAP_TYPE_ABIS 0x02
+#define GSMTAP_TYPE_UM_BURST 0x03 /* raw burst bits */
+
+#define GSMTAP_BURST_UNKNOWN 0x00
+#define GSMTAP_BURST_FCCH 0x01
+#define GSMTAP_BURST_PARTIAL_SCH 0x02
+#define GSMTAP_BURST_SCH 0x03
+#define GSMTAP_BURST_CTS_SCH 0x04
+#define GSMTAP_BURST_COMPACT_SCH 0x05
+#define GSMTAP_BURST_NORMAL 0x06
+#define GSMTAP_BURST_DUMMY 0x07
+#define GSMTAP_BURST_ACCESS 0x08
+
+struct gsmtap_hdr {
+ u_int8_t version; /* version, set to 0x01 currently */
+ u_int8_t hdr_len; /* length in number of 32bit words */
+ u_int8_t type; /* see GSMTAP_TYPE_* */
+ u_int8_t timeslot; /* timeslot (0..7 on Um) */
+
+ u_int16_t arfcn; /* ARFCN (frequency) */
+ u_int8_t noise_db; /* noise figure in dB */
+ u_int8_t signal_db; /* signal level in dB */
+
+ u_int32_t frame_number; /* GSM Frame Number (FN) */
+
+ u_int8_t burst_type; /* Type of burst, see above */
+ u_int8_t antenna_nr; /* Antenna Number */
+ u_int16_t res; /* reserved for future use (RFU) */
+
+} __attribute__((packed));
+#endif /* _GSMTAP_H */
diff --git a/gsm-receiver/src/lib/decoder/interleave.c b/gsm-receiver/src/lib/decoder/interleave.c
new file mode 100644
index 0000000..7b45927
--- /dev/null
+++ b/gsm-receiver/src/lib/decoder/interleave.c
@@ -0,0 +1,47 @@
+//TODO: this file shouldn't be part of the GSM Receiver
+#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 */
+// 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)
+{
+
+ int k;
+ for (k = 0; k < ictx->trans_size; k++)
+ dst[k] = src[ictx->trans[k]];
+}
+
diff --git a/gsm-receiver/src/lib/decoder/interleave.h b/gsm-receiver/src/lib/decoder/interleave.h
new file mode 100644
index 0000000..fa1912f
--- /dev/null
+++ b/gsm-receiver/src/lib/decoder/interleave.h
@@ -0,0 +1,19 @@
+//TODO: this file shouldn't be part of the GSM Receiver
+/*
+ * $Id:$
+ */
+
+#ifndef __GSMSP_INTERLEAVE_H__
+#define __GSMSP_INTERLEAVE_H__ 1
+
+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_deinit(INTERLEAVE_CTX *ictx);
+void interleave_decode(INTERLEAVE_CTX *ictx, unsigned char *dst, unsigned char *src);
+
+#endif
diff --git a/gsm-receiver/src/lib/decoder/openbtsstuff/AUTHORS b/gsm-receiver/src/lib/decoder/openbtsstuff/AUTHORS
new file mode 100644
index 0000000..8075492
--- /dev/null
+++ b/gsm-receiver/src/lib/decoder/openbtsstuff/AUTHORS
@@ -0,0 +1,173 @@
+#
+# Copyright 2008 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+
+David A. Burgess, dburgess@kestrelsp.com:
+ CommonLibs/Assert.h
+ CommonLibs/BitVector.cpp
+ CommonLibs/BitVectorTest.cpp
+ CommonLibs/Interthread.h
+ CommonLibs/InterthreadTest.cpp
+ CommonLibs/LinkedLists.cpp
+ CommonLibs/LinkedLists.h
+ CommonLibs/Sockets.cpp
+ CommonLibs/Sockets.h
+ CommonLibs/SocketsTest.cpp
+ CommonLibs/Threads.cpp
+ CommonLibs/Threads.h
+ CommonLibs/Timeval.cpp
+ CommonLibs/Timeval.h
+ CommonLibs/TimevalTest.cpp
+ CommonLibs/Vector.h
+ CommonLibs/VectorTest.cpp
+ Control/CallControl.cpp
+ Control/ControlCommon.cpp
+ Control/ControlCommon.h
+ Control/FACCHDispatch.cpp
+ Control/MobilityManagement.cpp
+ Control/PagerTest.cpp
+ Control/RadioResource.cpp
+ Control/SDCCHDispatch.cpp
+ GSM/GSM610Tables.cpp
+ GSM/GSM610Tables.h
+ GSM/GSMCommon.cpp
+ GSM/GSMCommon.h
+ GSM/GSMConfig.h
+ GSM/GSML1FEC.cpp
+ GSM/GSML1FEC.h
+ GSM/GSML2LAPDm.cpp
+ GSM/GSML2LAPDm.h
+ GSM/GSML3CCElements.cpp
+ GSM/GSML3CCElements.h
+ GSM/GSML3CCMessages.cpp
+ GSM/GSML3CCMessages.h
+ GSM/GSML3CommonElements.cpp
+ GSM/GSML3CommonElements.h
+ GSM/GSML3MMElements.cpp
+ GSM/GSML3MMElements.h
+ GSM/GSML3MMMessages.cpp
+ GSM/GSML3MMMessages.h
+ GSM/GSML3Message.cpp
+ GSM/GSML3Message.h
+ GSM/GSML3RRElements.cpp
+ GSM/GSML3RRElements.h
+ GSM/GSML3RRMessages.cpp
+ GSM/GSML3RRMessages.h
+ GSM/GSMLogicalChannel.h
+ GSM/GSMTDMA.cpp
+ GSM/GSMTDMA.h
+ GSM/GSMTransfer.cpp
+ GSM/GSMTransfer.h
+ LICENSEBLOCK
+ SIP/SIPEngine.h
+ SIP/SIPInterface.h
+ TRXManager/TRXManager.cpp
+ Transceiver/Complex.h
+ apps/OpenBTS900.cpp
+ tests/AGCHTest.cpp
+ tests/BeaconTest.cpp
+ tests/CallTest.cpp
+ tests/CallTest2.cpp
+ tests/LAPDmTest.cpp
+ tests/LoopbackTest.cpp
+ tests/RegistrationTest.cpp
+ tests/TRXSimulator.cpp
+
+Harvind S. Samra, hssamra@kestrelsp.com:
+ Control/PagerTest.cpp
+ Control/RadioResource.cpp
+ GSM/GSMConfig.h
+ GSM/GSMTransfer.h
+ LICENSEBLOCK
+ Transceiver/ComplexTest.cpp
+ Transceiver/Transceiver.cpp
+ Transceiver/Transceiver.h
+ Transceiver/USRPDevice.cpp
+ Transceiver/USRPDevice.h
+ Transceiver/USRPping.cpp
+ Transceiver/radioInterface.cpp
+ Transceiver/radioInterface.h
+ Transceiver/rcvLPF_651.h
+ Transceiver/runTransceiver.cpp
+ Transceiver/sendLPF_961.h
+ Transceiver/sigProcLib.cpp
+ Transceiver/sigProcLib.h
+ Transceiver/sigProcLibTest.cpp
+ Transceiver/sweepGenerator.cpp
+ Transceiver/testRadio.cpp
+
+Raffi Sevlian, raffisev@gmail.com:
+ Control/CallControl.cpp
+ Control/ControlCommon.cpp
+ Control/ControlCommon.h
+ Control/FACCHDispatch.cpp
+ Control/MobilityManagement.cpp
+ Control/PagerTest.cpp
+ Control/RadioResource.cpp
+ GSM/GSMCommon.h
+ GSM/GSMConfig.h
+ GSM/GSML1FEC.h
+ GSM/GSML3CCElements.cpp
+ GSM/GSML3CCElements.h
+ GSM/GSML3CCMessages.cpp
+ GSM/GSML3CCMessages.h
+ GSM/GSML3CommonElements.cpp
+ GSM/GSML3CommonElements.h
+ GSM/GSML3MMElements.cpp
+ GSM/GSML3MMElements.h
+ GSM/GSML3MMMessages.cpp
+ GSM/GSML3MMMessages.h
+ GSM/GSML3Message.cpp
+ GSM/GSML3Message.h
+ GSM/GSML3RRElements.cpp
+ GSM/GSML3RRElements.h
+ GSM/GSML3RRMessages.cpp
+ GSM/GSML3RRMessages.h
+ GSM/GSMLogicalChannel.h
+ GSM/GSMSAPMux.cpp
+ GSM/GSMSAPMux.h
+ GSM/GSMTransfer.h
+ LICENSEBLOCK
+ SIP/SIPEngine.cpp
+ SIP/SIPInterface.cpp
+ SIP/SIPInterface.h
+ SIP/SIPMessage.cpp
+ SIP/SIPMessage.h
+ SIP/SIPUtility.cpp
+ SIP/SIPUtility.h
+ SMS/CMMessage.cpp
+ SMS/CMMessage.h
+ SMS/CMProcessor.cpp
+ SMS/CMProcessor.h
+ SMS/CMTest.cpp
+ SMS/RLMessage.cpp
+ SMS/RLMessage.h
+ SMS/RLProcessor.cpp
+ SMS/RLProcessor.h
+ SMS/SMSMessages.cpp
+ SMS/SMSMessages.h
+ SMS/SMSProcessors.cpp
+ SMS/SMSProcessors.h
+ SMS/SMSTransfer.cpp
+ SMS/SMSTransfer.h
+ SMS/TLMessage.cpp
+ SMS/TLMessage.h
+ SMS/TLProcessor.cpp
+ SMS/TLProcessor.h
+ TRXManager/TRXManager.h
diff --git a/gsm-receiver/src/lib/decoder/openbtsstuff/Assert.h b/gsm-receiver/src/lib/decoder/openbtsstuff/Assert.h
new file mode 100644
index 0000000..00ad07d
--- /dev/null
+++ b/gsm-receiver/src/lib/decoder/openbtsstuff/Assert.h
@@ -0,0 +1,49 @@
+/*
+* 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 ASSERT_H
+#define ASSERT_H
+
+#include "stdio.h"
+
+/** This is thrown by assert() so that gdb can catch it. */
+class Assertion {
+
+ public:
+
+ Assertion()
+ {
+ fprintf(stderr,"Try setting a breakpoint @ %s:%u.\n",__FILE__,__LINE__);
+ return;
+ }
+
+};
+
+#ifdef NDEBUG
+#define assert(EXPR) {};
+#else
+/** This replaces the regular assert() with a C++ exception. */
+#include "stdio.h"
+#define assert(E) { if (!(E)) { fprintf(stderr,"%s:%u failed assertion '%s'\n",__FILE__,__LINE__,#E); throw Assertion(); } }
+#endif
+
+#endif
diff --git a/gsm-receiver/src/lib/decoder/openbtsstuff/BitVector.cpp b/gsm-receiver/src/lib/decoder/openbtsstuff/BitVector.cpp
new file mode 100644
index 0000000..89d8d19
--- /dev/null
+++ b/gsm-receiver/src/lib/decoder/openbtsstuff/BitVector.cpp
@@ -0,0 +1,513 @@
+/*
+* 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/>.
+
+*/
+
+
+
+
+#include "BitVector.h"
+#include <iostream>
+
+using namespace std;
+
+
+/**
+ Apply a Galois polymonial to a binary seqeunce.
+ @param val The input sequence.
+ @param poly The polynomial.
+ @param order The order of the polynomial.
+ @return Single-bit result.
+*/
+unsigned applyPoly(uint64_t val, uint64_t poly, unsigned order)
+{
+ uint64_t prod = val & poly;
+ unsigned sum = prod;
+ for (unsigned i=1; i<order; i++) sum ^= prod>>i;
+ return sum & 0x01;
+}
+
+
+
+
+
+
+BitVector::BitVector(const char *valString)
+ :Vector<char>(strlen(valString))
+{
+ uint32_t accum = 0;
+ for (size_t i=0; i<size(); i++) {
+ accum <<= 1;
+ if (valString[i]=='1') accum |= 0x01;
+ mStart[i] = accum;
+ }
+}
+
+
+
+
+
+uint64_t BitVector::peekField(size_t readIndex, unsigned length) const
+{
+ uint64_t accum = 0;
+ char *dp = mStart + readIndex;
+ assert(dp+length <= mEnd);
+ for (unsigned i=0; i<length; i++) {
+ accum = (accum<<1) | ((*dp++) & 0x01);
+ }
+ return accum;
+}
+
+
+uint64_t BitVector::readField(size_t& readIndex, unsigned length) const
+{
+ const uint64_t retVal = peekField(readIndex,length);
+ readIndex += length;
+ return retVal;
+}
+
+
+void BitVector::fillField(size_t writeIndex, uint64_t value, unsigned length)
+{
+ char *dpBase = mStart + writeIndex;
+ char *dp = dpBase + length - 1;
+ assert(dp < mEnd);
+ while (dp>=dpBase) {
+ *dp-- = value & 0x01;
+ value >>= 1;
+ }
+}
+
+void BitVector::writeField(size_t& writeIndex, uint64_t value, unsigned length)
+{
+ fillField(writeIndex,value,length);
+ writeIndex += length;
+}
+
+
+void BitVector::invert()
+{
+ for (size_t i=0; i<size(); i++) {
+ mStart[i] = ~mStart[i];
+ }
+}
+
+
+
+
+void BitVector::reverse8()
+{
+ assert(size()>=8);
+
+ char tmp0 = mStart[0];
+ mStart[0] = mStart[7];
+ mStart[7] = tmp0;
+
+ char tmp1 = mStart[1];
+ mStart[1] = mStart[6];
+ mStart[6] = tmp1;
+
+ char tmp2 = mStart[2];
+ mStart[2] = mStart[5];
+ mStart[5] = tmp2;
+
+ char tmp3 = mStart[3];
+ mStart[3] = mStart[4];
+ mStart[4] = tmp3;
+}
+
+
+
+void BitVector::LSB8MSB()
+{
+ size_t size8 = 8*(size()/8);
+ size_t iTop = size8 - 8;
+ for (size_t i=0; i<=iTop; i+=8) segment(i,8).reverse8();
+}
+
+
+
+uint64_t BitVector::syndrome(Generator& gen) const
+{
+ gen.clear();
+ const char *dp = mStart;
+ while (dp<mEnd) gen.syndromeShift(*dp++);
+ return gen.state();
+}
+
+
+uint64_t BitVector::parity(Generator& gen) const
+{
+ gen.clear();
+ const char *dp = mStart;
+ while (dp<mEnd) gen.encoderShift(*dp++);
+ return gen.state();
+}
+
+
+void BitVector::encode(const ViterbiR2O4& coder, BitVector& target)
+{
+ size_t sz = size();
+ assert(sz*coder.iRate() == target.size());
+
+ // Build a "history" array where each element contains the full history.
+ uint32_t history[sz];
+ uint32_t accum = 0;
+ for (size_t i=0; i<sz; i++) {
+ accum = (accum<<1) | bit(i);
+ history[i] = accum;
+ }
+
+ // Look up histories in the pre-generated state table.
+ char *op = target.begin();
+ for (size_t i=0; i<sz; i++) {
+ unsigned index = coder.cMask() & history[i];
+ for (unsigned g=0; g<coder.iRate(); g++) {
+ *op++ = coder.stateTable(g,index);
+ }
+ }
+}
+
+
+
+unsigned BitVector::sum() const
+{
+ unsigned sum = 0;
+ for (size_t i=0; i<size(); i++) sum += mStart[i] & 0x01;
+ return sum;
+}
+
+
+
+
+void BitVector::map(const unsigned *map, size_t mapSize, BitVector& dest) const
+{
+ for (unsigned i=0; i<mapSize; i++) {
+ dest.mStart[i] = mStart[map[i]];
+ }
+}
+
+
+
+
+void BitVector::unmap(const unsigned *map, size_t mapSize, BitVector& dest) const
+{
+ for (unsigned i=0; i<mapSize; i++) {
+ dest.mStart[map[i]] = mStart[i];
+ }
+}
+
+
+
+
+
+
+
+
+
+
+ostream& operator<<(ostream& os, const BitVector& hv)
+{
+ for (size_t i=0; i<hv.size(); i++) {
+ if (hv.bit(i)) os << '1';
+ else os << '0';
+ }
+ return os;
+}
+
+
+
+
+ViterbiR2O4::ViterbiR2O4()
+{
+ assert(mDeferral < 32);
+ mCoeffs[0] = 0x019;
+ mCoeffs[1] = 0x01b;
+ computeStateTables(0);
+ computeStateTables(1);
+ computeGeneratorTable();
+}
+
+
+
+
+void ViterbiR2O4::initializeStates()
+{
+ for (unsigned i=0; i<mIStates; i++) clear(mSurvivors[i]);
+ for (unsigned i=0; i<mNumCands; i++) clear(mCandidates[i]);
+}
+
+
+
+void ViterbiR2O4::computeStateTables(unsigned g)
+{
+ assert(g<mIRate);
+ for (unsigned state=0; state<mIStates; state++) {
+ // 0 input
+ uint32_t inputVal = state<<1;
+ mStateTable[g][inputVal] = applyPoly(inputVal, mCoeffs[g], mOrder+1);
+ // 1 input
+ inputVal |= 1;
+ mStateTable[g][inputVal] = applyPoly(inputVal, mCoeffs[g], mOrder+1);
+ }
+}
+
+void ViterbiR2O4::computeGeneratorTable()
+{
+ for (unsigned index=0; index<mIStates*2; index++) {
+ mGeneratorTable[index] = (mStateTable[0][index]<<1) | mStateTable[1][index];
+ }
+}
+
+
+
+
+
+
+void ViterbiR2O4::branchCandidates()
+{
+ // Branch to generate new input states.
+ const vCand *sp = mSurvivors;
+ for (unsigned i=0; i<mNumCands; i+=2) {
+ // extend and suffix
+ const uint32_t iState0 = (sp->iState) << 1; // input state for 0
+ const uint32_t iState1 = iState0 | 0x01; // input state for 1
+ const uint32_t oStateShifted = (sp->oState) << mIRate; // shifted output
+ const float cost = sp->cost;
+ sp++;
+ // 0 input extension
+ mCandidates[i].cost = cost;
+ mCandidates[i].oState = oStateShifted | mGeneratorTable[iState0 & mCMask];
+ mCandidates[i].iState = iState0;
+ // 1 input extension
+ mCandidates[i+1].cost = cost;
+ mCandidates[i+1].oState = oStateShifted | mGeneratorTable[iState1 & mCMask];
+ mCandidates[i+1].iState = iState1;
+ }
+}
+
+
+void ViterbiR2O4::getSoftCostMetrics(const uint32_t inSample, const float *matchCost, const float *mismatchCost)
+{
+ const float *cTab[2] = {matchCost,mismatchCost};
+ for (unsigned i=0; i<mNumCands; i++) {
+ vCand& thisCand = mCandidates[i];
+ // We examine input bits 2 at a time for a rate 1/2 coder.
+ const unsigned mismatched = inSample ^ (thisCand.oState);
+ thisCand.cost += cTab[mismatched&0x01][1] + cTab[(mismatched>>1)&0x01][0];
+ }
+}
+
+
+void ViterbiR2O4::pruneCandidates()
+{
+ const vCand* c1 = mCandidates; // 0-prefix
+ const vCand* c2 = mCandidates + mIStates; // 1-prefix
+ for (unsigned i=0; i<mIStates; i++) {
+ if (c1[i].cost < c2[i].cost) mSurvivors[i] = c1[i];
+ else mSurvivors[i] = c2[i];
+ }
+}
+
+
+const ViterbiR2O4::vCand& ViterbiR2O4::minCost() const
+{
+ int minIndex = 0;
+ float minCost = mSurvivors[0].cost;
+ for (unsigned i=1; i<mIStates; i++) {
+ const float thisCost = mSurvivors[i].cost;
+ if (thisCost>=minCost) continue;
+ minCost = thisCost;
+ minIndex=i;
+ }
+ return mSurvivors[minIndex];
+}
+
+
+const ViterbiR2O4::vCand& ViterbiR2O4::step(uint32_t inSample, const float *probs, const float *iprobs)
+{
+ branchCandidates();
+ getSoftCostMetrics(inSample,probs,iprobs);
+ pruneCandidates();
+ return minCost();
+}
+
+
+uint64_t Parity::syndrome(const BitVector& receivedCodeword)
+{
+ return receivedCodeword.syndrome(*this);
+}
+
+
+void Parity::writeParityWord(const BitVector& data, BitVector& parityTarget, bool invert)
+{
+ uint64_t pWord = data.parity(*this);
+ if (invert) pWord = ~pWord;
+ parityTarget.fillField(0,pWord,size());
+}
+
+
+
+
+
+
+
+
+
+SoftVector::SoftVector(const BitVector& source)
+{
+ resize(source.size());
+ for (size_t i=0; i<size(); i++) {
+ if (source.bit(i)) mStart[i]=1.0F;
+ else mStart[i]=0.0F;
+ }
+}
+
+
+BitVector SoftVector::sliced() const
+{
+ size_t sz = size();
+ BitVector newSig(sz);
+ for (size_t i=0; i<sz; i++) {
+ if (mStart[i]>0.5F) newSig[i]=1;
+ else newSig[i] = 0;
+ }
+ return newSig;
+}
+
+
+
+void SoftVector::decode(ViterbiR2O4 &decoder, BitVector& target) const
+{
+ const size_t sz = size();
+ const unsigned deferral = decoder.deferral();
+ const size_t ctsz = sz + deferral;
+ assert(sz <= decoder.iRate()*target.size());
+
+ // Build a "history" array where each element contains the full history.
+ uint32_t history[ctsz];
+ {
+ BitVector bits = sliced();
+ uint32_t accum = 0;
+ for (size_t i=0; i<sz; i++) {
+ accum = (accum<<1) | bits.bit(i);
+ history[i] = accum;
+ }
+ // Repeat last bit at the end.
+ for (size_t i=sz; i<ctsz; i++) {
+ accum = (accum<<1) | (accum & 0x01);
+ history[i] = accum;
+ }
+ }
+
+ // Precompute metric tables.
+ float matchCostTable[ctsz];
+ float mismatchCostTable[ctsz];
+ {
+ const float *dp = mStart;
+ for (size_t i=0; i<sz; i++) {
+ // pVal is the probability that a bit is correct.
+ // ipVal is the probability that a bit is correct.
+ float pVal = dp[i];
+ if (pVal>0.5F) pVal = 1.0F-pVal;
+ float ipVal = 1.0F-pVal;
+ // This is a cheap approximation to an ideal cost function.
+ if (pVal<0.01F) pVal = 0.01;
+ if (ipVal<0.01F) ipVal = 0.01;
+ matchCostTable[i] = 0.25F/ipVal;
+ mismatchCostTable[i] = 0.25F/pVal;
+ }
+
+ // pad end of table with unknowns
+ for (size_t i=sz; i<ctsz; i++) {
+ matchCostTable[i] = 0.5F;
+ mismatchCostTable[i] = 0.5F;
+ }
+ }
+
+ {
+ decoder.initializeStates();
+ // Each sample of history[] carries its history.
+ // So we only have to process every iRate-th sample.
+ const unsigned step = decoder.iRate();
+ // input pointer
+ const uint32_t *ip = history + step - 1;
+ // output pointers
+ char *op = target.begin();
+ const char *const opt = target.end();
+ // table pointers
+ const float* match = matchCostTable;
+ const float* mismatch = mismatchCostTable;
+ size_t oCount = 0;
+ while (op<opt) {
+ // Viterbi algorithm
+ const ViterbiR2O4::vCand &minCost = decoder.step(*ip, match, mismatch);
+ ip += step;
+ match += step;
+ mismatch += step;
+ // output
+ if (oCount>=deferral) *op++ = (minCost.iState >> deferral);
+ oCount++;
+ }
+ }
+}
+
+
+
+
+ostream& operator<<(ostream& os, const SoftVector& sv)
+{
+ for (size_t i=0; i<sv.size(); i++) {
+ if (sv[i]<0.25) os << "0";
+ else if (sv[i]>0.75) os << "1";
+ else os << "-";
+ }
+ return os;
+}
+
+
+
+void BitVector::pack(unsigned char* targ) const
+{
+ // Assumes MSB-first packing.
+ unsigned bytes = size()/8;
+ for (unsigned i=0; i<bytes; i++) {
+ targ[i] = peekField(i*8,8);
+ }
+ unsigned whole = bytes*8;
+ unsigned rem = size() - whole;
+ if (rem==0) return;
+ targ[bytes] = peekField(whole,rem) << (8-rem);
+}
+
+
+void BitVector::unpack(const unsigned char* src)
+{
+ // Assumes MSB-first packing.
+ unsigned bytes = size()/8;
+ for (unsigned i=0; i<bytes; i++) {
+ fillField(i*8,src[i],8);
+ }
+ unsigned whole = bytes*8;
+ unsigned rem = size() - whole;
+ if (rem==0) return;
+ fillField(whole,src[bytes],rem);
+}
+
+// vim: ts=4 sw=4
diff --git a/gsm-receiver/src/lib/decoder/openbtsstuff/BitVector.h b/gsm-receiver/src/lib/decoder/openbtsstuff/BitVector.h
new file mode 100644
index 0000000..3019c2c
--- /dev/null
+++ b/gsm-receiver/src/lib/decoder/openbtsstuff/BitVector.h
@@ -0,0 +1,427 @@
+/*
+* 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 FECVECTORS_H
+#define FECVECTORS_H
+
+#include "Vector.h"
+#include <stdint.h>
+
+
+class BitVector;
+class SoftVector;
+
+
+
+/** Shift-register (LFSR) generator. */
+class Generator {
+
+ private:
+
+ uint64_t mCoeff; ///< polynomial coefficients. LSB is zero exponent.
+ uint64_t mState; ///< shift register state. LSB is most recent.
+ uint64_t mMask; ///< mask for reading state
+ unsigned mLen; ///< number of bits used in shift register
+ unsigned mLen_1; ///< mLen - 1
+
+ public:
+
+ Generator(uint64_t wCoeff, unsigned wLen)
+ :mCoeff(wCoeff),mState(0),
+ mMask((1ULL<<wLen)-1),
+ mLen(wLen),mLen_1(wLen-1)
+ { assert(wLen<64); }
+
+ void clear() { mState=0; }
+
+ /**@name Accessors */
+ //@{
+ uint64_t state() const { return mState & mMask; }
+ unsigned size() const { return mLen; }
+ //@}
+
+ /**
+ Calculate one bit of a syndrome.
+ This is in the .h for inlining.
+ */
+ void syndromeShift(unsigned inBit)
+ {
+ const unsigned fb = (mState>>(mLen_1)) & 0x01;
+ mState = (mState<<1) ^ (inBit & 0x01);
+ if (fb) mState ^= mCoeff;
+ }
+
+ /**
+ Update the generator state by one cycle.
+ This is in the .h for inlining.
+ */
+ void encoderShift(unsigned inBit)
+ {
+ const unsigned fb = ((mState>>(mLen_1)) ^ inBit) & 0x01;
+ mState <<= 1;
+ if (fb) mState ^= mCoeff;
+ }
+
+
+};
+
+
+
+
+/** Parity (CRC-type) generator and checker based on a Generator. */
+class Parity : public Generator {
+
+ protected:
+
+ unsigned mCodewordSize;
+
+ public:
+
+ Parity(uint64_t wCoefficients, unsigned wParitySize, unsigned wCodewordSize)
+ :Generator(wCoefficients, wParitySize),
+ mCodewordSize(wCodewordSize)
+ { }
+
+ /** Compute the parity word and write it into the target segment. */
+ void writeParityWord(const BitVector& data, BitVector& parityWordTarget, bool invert=true);
+
+ /** Compute the syndrome of a received sequence. */
+ uint64_t syndrome(const BitVector& receivedCodeword);
+};
+
+
+
+
+/**
+ Class to represent convolutional coders/decoders of rate 1/2, memory length 4.
+ This is the "workhorse" coder for most GSM channels.
+*/
+class ViterbiR2O4 {
+
+ private:
+ /**name Lots of precomputed elements so the compiler can optimize like hell. */
+ //@{
+ /**@name Core values. */
+ //@{
+ static const unsigned mIRate = 2; ///< reciprocal of rate
+ static const unsigned mOrder = 4; ///< memory length of generators
+ //@}
+ /**@name Derived values. */
+ //@{
+ static const unsigned mIStates = 0x01 << mOrder; ///< number of states, number of survivors
+ static const uint32_t mSMask = mIStates-1; ///< survivor mask
+ static const uint32_t mCMask = (mSMask<<1) | 0x01; ///< candidate mask
+ static const uint32_t mOMask = (0x01<<mIRate)-1; ///< ouput mask, all iRate low bits set
+ static const unsigned mNumCands = mIStates*2; ///< number of candidates to generate during branching
+ static const unsigned mDeferral = 6*mOrder; ///< deferral to be used
+ //@}
+ //@}
+
+ /** Precomputed tables. */
+ //@{
+ uint32_t mCoeffs[mIRate]; ///< polynomial for each generator
+ uint32_t mStateTable[mIRate][2*mIStates]; ///< precomputed generator output tables
+ uint32_t mGeneratorTable[2*mIStates]; ///< precomputed coder output table
+ //@}
+
+ public:
+
+ /**
+ A candidate sequence in a Viterbi decoder.
+ The 32-bit state register can support a deferral of 6 with a 4th-order coder.
+ */
+ typedef struct candStruct {
+ uint32_t iState; ///< encoder input associated with this candidate
+ uint32_t oState; ///< encoder output associated with this candidate
+ float cost; ///< cost (metric value), float to support soft inputs
+ } vCand;
+
+ /** Clear a structure. */
+ void clear(vCand& v)
+ {
+ v.iState=0;
+ v.oState=0;
+ v.cost=0;
+ }
+
+
+ private:
+
+ /**@name Survivors and candidates. */
+ //@{
+ vCand mSurvivors[mIStates]; ///< current survivor pool
+ vCand mCandidates[2*mIStates]; ///< current candidate pool
+ //@}
+
+ public:
+
+ unsigned iRate() const { return mIRate; }
+ uint32_t cMask() const { return mCMask; }
+ uint32_t stateTable(unsigned g, unsigned i) const { return mStateTable[g][i]; }
+ unsigned deferral() const { return mDeferral; }
+
+
+ ViterbiR2O4();
+
+ /** Set all cost metrics to zero. */
+ void initializeStates();
+
+ /**
+ Full cycle of the Viterbi algorithm: branch, metrics, prune, select.
+ @return reference to minimum-cost candidate.
+ */
+ const vCand& step(uint32_t inSample, const float *probs, const float *iprobs);
+
+ private:
+
+ /** Branch survivors into new candidates. */
+ void branchCandidates();
+
+ /** Compute cost metrics for soft-inputs. */
+ void getSoftCostMetrics(uint32_t inSample, const float *probs, const float *iprobs);
+
+ /** Select survivors from the candidate set. */
+ void pruneCandidates();
+
+ /** Find the minimum cost survivor. */
+ const vCand& minCost() const;
+
+ /**
+ Precompute the state tables.
+ @param g Generator index 0..((1/rate)-1)
+ */
+ void computeStateTables(unsigned g);
+
+ /**
+ Precompute the generator outputs.
+ mCoeffs must be defined first.
+ */
+ void computeGeneratorTable();
+
+};
+
+
+
+
+class BitVector : public Vector<char> {
+
+
+ public:
+
+ /**@name Constructors. */
+ //@{
+
+ /**@name Casts of Vector constructors. */
+ //@{
+ BitVector(char* wData, char* wStart, char* wEnd)
+ :Vector<char>(wData,wStart,wEnd)
+ { }
+ BitVector(size_t len=0):Vector<char>(len) {}
+ BitVector(const Vector<char>& source):Vector<char>(source) {}
+ BitVector(Vector<char>& source):Vector<char>(source) {}
+ BitVector(const Vector<char>& source1, const Vector<char> source2):Vector<char>(source1,source2) {}
+ //@}
+
+ /** Construct from a string of "0" and "1". */
+ BitVector(const char* valString);
+ //@}
+
+ /** Index a single bit. */
+ bool bit(size_t index) const
+ {
+ // We put this code in .h for fast inlining.
+ const char *dp = mStart+index;
+ assert(dp<mEnd);
+ return (*dp) & 0x01;
+ }
+
+ /**@name Casts and overrides of Vector operators. */
+ //@{
+ BitVector segment(size_t start, size_t span)
+ {
+ char* wStart = mStart + start;
+ char* wEnd = wStart + span;
+ assert(wEnd<=mEnd);
+ return BitVector(NULL,wStart,wEnd);
+ }
+
+ BitVector alias()
+ { return segment(0,size()); }
+
+ const BitVector segment(size_t start, size_t span) const
+ { return (BitVector)(Vector<char>::segment(start,span)); }
+
+ BitVector head(size_t span) { return segment(0,span); }
+ const BitVector head(size_t span) const { return segment(0,span); }
+ BitVector tail(size_t start) { return segment(start,size()-start); }
+ const BitVector tail(size_t start) const { return segment(start,size()-start); }
+ //@}
+
+
+ void zero() { fill(0); }
+
+ /**@name FEC operations. */
+ //@{
+ /** Calculate the syndrome of the vector with the given Generator. */
+ uint64_t syndrome(Generator& gen) const;
+ /** Calculate the parity word for the vector with the given Generator. */
+ uint64_t parity(Generator& gen) const;
+ /** Encode the signal with the GSM rate 1/2 convolutional encoder. */
+ void encode(const ViterbiR2O4& encoder, BitVector& target);
+ //@}
+
+
+ /** Invert 0<->1. */
+ void invert();
+
+ /**@name Byte-wise operations. */
+ //@{
+ /** Reverse an 8-bit vector. */
+ void reverse8();
+ /** Reverse groups of 8 within the vector (byte reversal). */
+ void LSB8MSB();
+ //@}
+
+ /**@name Serialization and deserialization. */
+ //@{
+ uint64_t peekField(size_t readIndex, unsigned length) const;
+ uint64_t readField(size_t& readIndex, unsigned length) const;
+ void fillField(size_t writeIndex, uint64_t value, unsigned length);
+ void writeField(size_t& writeIndex, uint64_t value, unsigned length);
+ //@}
+
+ /** Sum of bits. */
+ unsigned sum() const;
+
+ /** Reorder bits, dest[i] = this[map[i]]. */
+ void map(const unsigned *map, size_t mapSize, BitVector& dest) const;
+
+ /** Reorder bits, dest[map[i]] = this[i]. */
+ void unmap(const unsigned *map, size_t mapSize, BitVector& dest) const;
+
+ /** Pack into a char array. */
+ void pack(unsigned char*) const;
+
+ /** Unopack from a char array. */
+ void unpack(const unsigned char*);
+
+};
+
+
+
+std::ostream& operator<<(std::ostream&, const BitVector&);
+
+
+
+
+
+
+/**
+ The SoftVector class is used to represent a soft-decision signal.
+ Values 0..1 represent probabilities that a bit is "true".
+ */
+class SoftVector: public Vector<float> {
+
+ public:
+
+ /** Build a SoftVector of a given length. */
+ SoftVector(size_t wSize=0):Vector<float>(wSize) {}
+
+ /** Construct a SoftVector from a C string of "0", "1", and "X". */
+ SoftVector(const char* valString);
+
+ /** Construct a SoftVector from a BitVector. */
+ SoftVector(const BitVector& source);
+
+ /**
+ Wrap a SoftVector around a block of floats.
+ The block will be delete[]ed upon desctuction.
+ */
+ SoftVector(float *wData, unsigned length)
+ :Vector<float>(wData,length)
+ {}
+
+ SoftVector(float* wData, float* wStart, float* wEnd)
+ :Vector<float>(wData,wStart,wEnd)
+ { }
+
+ /**
+ Casting from a Vector<float>.
+ Note that this is NOT pass-by-reference.
+ */
+ SoftVector(Vector<float> source)
+ :Vector<float>(source)
+ {}
+
+
+ /**@name Casts and overrides of Vector operators. */
+ //@{
+ SoftVector segment(size_t start, size_t span)
+ {
+ float* wStart = mStart + start;
+ float* wEnd = wStart + span;
+ assert(wEnd<=mEnd);
+ return SoftVector(NULL,wStart,wEnd);
+ }
+
+ SoftVector alias()
+ { return segment(0,size()); }
+
+ const SoftVector segment(size_t start, size_t span) const
+ { return (SoftVector)(Vector<float>::segment(start,span)); }
+
+ SoftVector head(size_t span) { return segment(0,span); }
+ const SoftVector head(size_t span) const { return segment(0,span); }
+ SoftVector tail(size_t start) { return segment(start,size()-start); }
+ const SoftVector tail(size_t start) const { return segment(start,size()-start); }
+ //@}
+
+ /** Decode soft symbols with the GSM rate-1/2 Viterbi decoder. */
+ void decode(ViterbiR2O4 &decoder, BitVector& target) const;
+
+ /** Fill with "unknown" values. */
+ void unknown() { fill(0.5F); }
+
+ /** Return a hard bit value from a given index by slicing. */
+ bool bit(size_t index) const
+ {
+ const float *dp = mStart+index;
+ assert(dp<mEnd);
+ return (*dp)>0.5F;
+ }
+
+ /** Slice the whole signal into bits. */
+ BitVector sliced() const;
+
+};
+
+
+
+std::ostream& operator<<(std::ostream&, const SoftVector&);
+
+
+
+
+
+
+#endif
+// vim: ts=4 sw=4
diff --git a/gsm-receiver/src/lib/decoder/openbtsstuff/GSM610Tables.cpp b/gsm-receiver/src/lib/decoder/openbtsstuff/GSM610Tables.cpp
new file mode 100644
index 0000000..38f643f
--- /dev/null
+++ b/gsm-receiver/src/lib/decoder/openbtsstuff/GSM610Tables.cpp
@@ -0,0 +1,492 @@
+/*
+* 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/>.
+
+*/
+
+
+
+#include "GSM610Tables.h"
+
+
+/*
+RFC 3551 RTP A/V Profile July 2003
+
+
+ Octet Bit 0 Bit 1 Bit 2 Bit 3 Bit 4 Bit 5 Bit 6 Bit 7
+ _____________________________________________________________________
+ 0 1 1 0 1 LARc0.0 LARc0.1 LARc0.2 LARc0.3
+ 1 LARc0.4 LARc0.5 LARc1.0 LARc1.1 LARc1.2 LARc1.3 LARc1.4 LARc1.5
+ 2 LARc2.0 LARc2.1 LARc2.2 LARc2.3 LARc2.4 LARc3.0 LARc3.1 LARc3.2
+ 3 LARc3.3 LARc3.4 LARc4.0 LARc4.1 LARc4.2 LARc4.3 LARc5.0 LARc5.1
+ 4 LARc5.2 LARc5.3 LARc6.0 LARc6.1 LARc6.2 LARc7.0 LARc7.1 LARc7.2
+ 5 Nc0.0 Nc0.1 Nc0.2 Nc0.3 Nc0.4 Nc0.5 Nc0.6 bc0.0
+ 6 bc0.1 Mc0.0 Mc0.1 xmaxc00 xmaxc01 xmaxc02 xmaxc03 xmaxc04
+ 7 xmaxc05 xmc0.0 xmc0.1 xmc0.2 xmc1.0 xmc1.1 xmc1.2 xmc2.0
+ 8 xmc2.1 xmc2.2 xmc3.0 xmc3.1 xmc3.2 xmc4.0 xmc4.1 xmc4.2
+ 9 xmc5.0 xmc5.1 xmc5.2 xmc6.0 xmc6.1 xmc6.2 xmc7.0 xmc7.1
+ 10 xmc7.2 xmc8.0 xmc8.1 xmc8.2 xmc9.0 xmc9.1 xmc9.2 xmc10.0
+ 11 xmc10.1 xmc10.2 xmc11.0 xmc11.1 xmc11.2 xmc12.0 xmc12.1 xcm12.2
+ 12 Nc1.0 Nc1.1 Nc1.2 Nc1.3 Nc1.4 Nc1.5 Nc1.6 bc1.0
+ 13 bc1.1 Mc1.0 Mc1.1 xmaxc10 xmaxc11 xmaxc12 xmaxc13 xmaxc14
+ 14 xmax15 xmc13.0 xmc13.1 xmc13.2 xmc14.0 xmc14.1 xmc14.2 xmc15.0
+ 15 xmc15.1 xmc15.2 xmc16.0 xmc16.1 xmc16.2 xmc17.0 xmc17.1 xmc17.2
+ 16 xmc18.0 xmc18.1 xmc18.2 xmc19.0 xmc19.1 xmc19.2 xmc20.0 xmc20.1
+ 17 xmc20.2 xmc21.0 xmc21.1 xmc21.2 xmc22.0 xmc22.1 xmc22.2 xmc23.0
+ 18 xmc23.1 xmc23.2 xmc24.0 xmc24.1 xmc24.2 xmc25.0 xmc25.1 xmc25.2
+ 19 Nc2.0 Nc2.1 Nc2.2 Nc2.3 Nc2.4 Nc2.5 Nc2.6 bc2.0
+ 20 bc2.1 Mc2.0 Mc2.1 xmaxc20 xmaxc21 xmaxc22 xmaxc23 xmaxc24
+ 21 xmaxc25 xmc26.0 xmc26.1 xmc26.2 xmc27.0 xmc27.1 xmc27.2 xmc28.0
+ 22 xmc28.1 xmc28.2 xmc29.0 xmc29.1 xmc29.2 xmc30.0 xmc30.1 xmc30.2
+ 23 xmc31.0 xmc31.1 xmc31.2 xmc32.0 xmc32.1 xmc32.2 xmc33.0 xmc33.1
+ 24 xmc33.2 xmc34.0 xmc34.1 xmc34.2 xmc35.0 xmc35.1 xmc35.2 xmc36.0
+ 25 Xmc36.1 xmc36.2 xmc37.0 xmc37.1 xmc37.2 xmc38.0 xmc38.1 xmc38.2
+ 26 Nc3.0 Nc3.1 Nc3.2 Nc3.3 Nc3.4 Nc3.5 Nc3.6 bc3.0
+ 27 bc3.1 Mc3.0 Mc3.1 xmaxc30 xmaxc31 xmaxc32 xmaxc33 xmaxc34
+ 28 xmaxc35 xmc39.0 xmc39.1 xmc39.2 xmc40.0 xmc40.1 xmc40.2 xmc41.0
+ 29 xmc41.1 xmc41.2 xmc42.0 xmc42.1 xmc42.2 xmc43.0 xmc43.1 xmc43.2
+ 30 xmc44.0 xmc44.1 xmc44.2 xmc45.0 xmc45.1 xmc45.2 xmc46.0 xmc46.1
+ 31 xmc46.2 xmc47.0 xmc47.1 xmc47.2 xmc48.0 xmc48.1 xmc48.2 xmc49.0
+ 32 xmc49.1 xmc49.2 xmc50.0 xmc50.1 xmc50.2 xmc51.0 xmc51.1 xmc51.2
+
+ Table 3: GSM payload format
+*/
+
+
+/*
+ This file encodes a mapping between
+ GSM 05.03 Table 2 and RFC-3551 Table 3.
+*/
+
+/*
+ Naming convention:
+ xxx_p position (bit index)
+ xxx_l length (bit field length)
+ LAR log area ratio
+ N LTP lag
+ b LTP gain
+ M grid
+ Xmax block amplitude
+ x RPE pulses
+*/
+
+
+/**@name Lengths of GSM 06.10 fields */
+//@{
+const unsigned int LAR1_l=6; ///< log area ratio
+const unsigned int LAR2_l=6; ///< log area ratio
+const unsigned int LAR3_l=5; ///< log area ratio
+const unsigned int LAR4_l=5; ///< log area ratio
+const unsigned int LAR5_l=4; ///< log area ratio
+const unsigned int LAR6_l=4; ///< log area ratio
+const unsigned int LAR7_l=3; ///< log area ratio
+const unsigned int LAR8_l=3; ///< log area ratio
+const unsigned int N_l=7; ///< LTP lag
+const unsigned int b_l=2; ///< LTP gain
+const unsigned int M_l=2; ///< grid position
+const unsigned int Xmax_l=6; ///< block amplitude
+const unsigned int x_l=3; ///< RPE pulses
+//@}
+
+
+
+/*@name Indecies of GSM 06.10 fields as they appear in RFC-3551 Table 3. */
+//@{
+
+/**@name Log area ratios, apply to whole frame. */
+//@{
+const unsigned int LAR1_p = 0;
+const unsigned int LAR2_p = LAR1_p + LAR1_l;
+const unsigned int LAR3_p = LAR2_p + LAR2_l;
+const unsigned int LAR4_p = LAR3_p + LAR3_l;
+const unsigned int LAR5_p = LAR4_p + LAR4_l;
+const unsigned int LAR6_p = LAR5_p + LAR5_l;
+const unsigned int LAR7_p = LAR6_p + LAR6_l;
+const unsigned int LAR8_p = LAR7_p + LAR7_l;
+//@}
+/**@name Subframe 1 */
+//@{
+const unsigned int N1_p = LAR8_p + LAR8_l;
+const unsigned int b1_p = N1_p + N_l;
+const unsigned int M1_p = b1_p + b_l;
+const unsigned int Xmax1_p = M1_p + M_l;
+const unsigned int x1_0_p = Xmax1_p + Xmax_l;
+const unsigned int x1_1_p = x1_0_p + x_l;
+const unsigned int x1_2_p = x1_1_p + x_l;
+const unsigned int x1_3_p = x1_2_p + x_l;
+const unsigned int x1_4_p = x1_3_p + x_l;
+const unsigned int x1_5_p = x1_4_p + x_l;
+const unsigned int x1_6_p = x1_5_p + x_l;
+const unsigned int x1_7_p = x1_6_p + x_l;
+const unsigned int x1_8_p = x1_7_p + x_l;
+const unsigned int x1_9_p = x1_8_p + x_l;
+const unsigned int x1_10_p = x1_9_p + x_l;
+const unsigned int x1_11_p = x1_10_p + x_l;
+const unsigned int x1_12_p = x1_11_p + x_l;
+//@}
+/**@name Subframe 2 */
+//@{
+const unsigned int N2_p = x1_12_p + x_l;
+const unsigned int b2_p = N2_p + N_l;
+const unsigned int M2_p = b2_p + b_l;
+const unsigned int Xmax2_p = M2_p + M_l;
+const unsigned int x2_0_p = Xmax2_p + Xmax_l;
+const unsigned int x2_1_p = x2_0_p + x_l;
+const unsigned int x2_2_p = x2_1_p + x_l;
+const unsigned int x2_3_p = x2_2_p + x_l;
+const unsigned int x2_4_p = x2_3_p + x_l;
+const unsigned int x2_5_p = x2_4_p + x_l;
+const unsigned int x2_6_p = x2_5_p + x_l;
+const unsigned int x2_7_p = x2_6_p + x_l;
+const unsigned int x2_8_p = x2_7_p + x_l;
+const unsigned int x2_9_p = x2_8_p + x_l;
+const unsigned int x2_10_p = x2_9_p + x_l;
+const unsigned int x2_11_p = x2_10_p + x_l;
+const unsigned int x2_12_p = x2_11_p + x_l;
+//@}
+/**@mame Subframe 3 */
+//@{
+const unsigned int N3_p = x2_12_p + x_l;
+const unsigned int b3_p = N3_p + N_l;
+const unsigned int M3_p = b3_p + b_l;
+const unsigned int Xmax3_p = M3_p + M_l;
+const unsigned int x3_0_p = Xmax3_p + Xmax_l;
+const unsigned int x3_1_p = x3_0_p + x_l;
+const unsigned int x3_2_p = x3_1_p + x_l;
+const unsigned int x3_3_p = x3_2_p + x_l;
+const unsigned int x3_4_p = x3_3_p + x_l;
+const unsigned int x3_5_p = x3_4_p + x_l;
+const unsigned int x3_6_p = x3_5_p + x_l;
+const unsigned int x3_7_p = x3_6_p + x_l;
+const unsigned int x3_8_p = x3_7_p + x_l;
+const unsigned int x3_9_p = x3_8_p + x_l;
+const unsigned int x3_10_p = x3_9_p + x_l;
+const unsigned int x3_11_p = x3_10_p + x_l;
+const unsigned int x3_12_p = x3_11_p + x_l;
+//@}
+/**@name Subframe 4 */
+//@{
+const unsigned int N4_p = x3_12_p + x_l;
+const unsigned int b4_p = N4_p + N_l;
+const unsigned int M4_p = b4_p + b_l;
+const unsigned int Xmax4_p = M4_p + M_l;
+const unsigned int x4_0_p = Xmax4_p + Xmax_l;
+const unsigned int x4_1_p = x4_0_p + x_l;
+const unsigned int x4_2_p = x4_1_p + x_l;
+const unsigned int x4_3_p = x4_2_p + x_l;
+const unsigned int x4_4_p = x4_3_p + x_l;
+const unsigned int x4_5_p = x4_4_p + x_l;
+const unsigned int x4_6_p = x4_5_p + x_l;
+const unsigned int x4_7_p = x4_6_p + x_l;
+const unsigned int x4_8_p = x4_7_p + x_l;
+const unsigned int x4_9_p = x4_8_p + x_l;
+const unsigned int x4_10_p = x4_9_p + x_l;
+const unsigned int x4_11_p = x4_10_p + x_l;
+const unsigned int x4_12_p = x4_11_p + x_l;
+//@}
+//@}
+
+
+/*
+ This array encodes GSM 05.03 Table 2.
+ It's also GSM 06.10 Table A2.1a.
+ This is the order of bits as they appear in
+ the d[] bits of the GSM TCH/F.
+ RTP[4+g610BitOrder[i]] <=> GSM[i]
+*/
+unsigned int GSM::g610BitOrder[260] = {
+/**@name importance class 1 */
+//@{
+/** LAR1:5 */ LAR1_p+LAR1_l-1-5, /* bit 0 */
+/** Xmax1:5 */ Xmax1_p+Xmax_l-1-5,
+/** Xmax2:5 */ Xmax2_p+Xmax_l-1-5,
+/** Xmax3:5 */ Xmax3_p+Xmax_l-1-5,
+/** Xmax4:5 */ Xmax4_p+Xmax_l-1-5,
+//@}
+/**@name importance class 2 */
+//@{
+/** LAR1:4 */ LAR1_p+LAR1_l-1-4,
+/** LAR2:5 */ LAR2_p+LAR2_l-1-5,
+/** LAR3:4 */ LAR3_p+LAR3_l-1-4,
+//@}
+/**@name importance class 3 */
+//@{
+/** LAR1:3 */ LAR1_p+LAR1_l-1-3,
+/** LAR2:4 */ LAR2_p+LAR2_l-1-4,
+/** LAR3:3 */ LAR3_p+LAR3_l-1-3, /* bit 10 */
+/** LAR4:4 */ LAR4_p+LAR4_l-1-4,
+/** N1:6 */ N1_p+N_l-1-6,
+/** N2:6 */ N2_p+N_l-1-6,
+/** N3:6 */ N3_p+N_l-1-6,
+/** N4:6 */ N4_p+N_l-1-6,
+/** Xmax1:4 */ Xmax1_p+Xmax_l-1-4,
+/** Xmax2:4 */ Xmax2_p+Xmax_l-1-4,
+/** Xmax3:4 */ Xmax3_p+Xmax_l-1-4,
+/** Xmax4:4 */ Xmax4_p+Xmax_l-1-4,
+/** LAR2:3 */ LAR2_p+LAR2_l-1-3, /* bit 20 */
+/** LAR5:3 */ LAR5_p+LAR5_l-1-3,
+/** LAR6:3 */ LAR6_p+LAR6_l-1-3,
+/** N1:5 */ N1_p+N_l-1-5,
+/** N2:5 */ N2_p+N_l-1-5,
+/** N3:5 */ N3_p+N_l-1-5,
+/** N4:5 */ N4_p+N_l-1-5,
+/** N1:4 */ N1_p+N_l-1-4,
+/** N2:4 */ N2_p+N_l-1-4,
+/** N3:4 */ N3_p+N_l-1-4,
+/** N4:4 */ N4_p+N_l-1-4, /* bit 30 */
+/** N1:3 */ N1_p+N_l-1-3,
+/** N2:3 */ N2_p+N_l-1-3,
+/** N3:3 */ N3_p+N_l-1-3,
+/** N4:3 */ N4_p+N_l-1-3,
+/** N1:2 */ N1_p+N_l-1-2,
+/** N2:2 */ N2_p+N_l-1-2,
+/** N3:2 */ N3_p+N_l-1-2,
+/** N4:2 */ N4_p+N_l-1-2,
+//@}
+/**@name importance class 4 */
+//@{
+/** Xmax1:3 */ Xmax1_p+Xmax_l-1-3,
+/** Xmax2:3 */ Xmax2_p+Xmax_l-1-3, /* bit 40 */
+/** Xmax3:3 */ Xmax3_p+Xmax_l-1-3,
+/** Xmax4:3 */ Xmax4_p+Xmax_l-1-3,
+/** LAR1:2 */ LAR1_p+LAR1_l-1-2,
+/** LAR4:3 */ LAR4_p+LAR4_l-1-3,
+/** LAR7:2 */ LAR7_p+LAR7_l-1-2,
+/** N1:1 */ N1_p+N_l-1-1,
+/** N2:1 */ N2_p+N_l-1-1,
+/** N3:1 */ N3_p+N_l-1-1,
+/** N4:1 */ N4_p+N_l-1-1,
+/** LAR5:2 */ LAR5_p+LAR5_l-1-2, /* bit 50 */
+/** LAR6:2 */ LAR6_p+LAR6_l-1-2,
+/** b1:1 */ b1_p+b_l-1-1,
+/** b2:1 */ b2_p+b_l-1-1,
+/** b3:1 */ b3_p+b_l-1-1,
+/** b4:1 */ b4_p+b_l-1-1,
+/** N1:0 */ N1_p+N_l-1-0,
+/** N2:0 */ N2_p+N_l-1-0,
+/** N3:0 */ N3_p+N_l-1-0,
+/** N4:0 */ N4_p+N_l-1-0,
+/** M1:1 */ M1_p+M_l-1-1, /* bit 60 */
+/** M2:1 */ M2_p+M_l-1-1,
+/** M3:1 */ M3_p+M_l-1-1,
+/** M4:1 */ M4_p+M_l-1-1,
+//@}
+/**@name importance class 5 */
+//@{
+/** LAR1:1 */ LAR1_p+LAR1_l-1-1,
+/** LAR2:2 */ LAR2_p+LAR2_l-1-2,
+/** LAR3:2 */ LAR3_p+LAR3_l-1-2,
+/** LAR8:2 */ LAR8_p+LAR8_l-1-2,
+/** LAR4:2 */ LAR4_p+LAR4_l-1-2,
+/** LAR5:1 */ LAR5_p+LAR5_l-1-1,
+/** LAR7:1 */ LAR7_p+LAR7_l-1-1, /* bit 70 */
+/** b1:0 */ b1_p+b_l-1-0,
+/** b2:0 */ b2_p+b_l-1-0,
+/** b3:0 */ b3_p+b_l-1-0,
+/** b4:0 */ b4_p+b_l-1-0,
+/** Xmax1:2 */ Xmax1_p+Xmax_l-1-2,
+/** Xmax2:2 */ Xmax2_p+Xmax_l-1-2,
+/** Xmax3:2 */ Xmax3_p+Xmax_l-1-2,
+/** Xmax4:2 */ Xmax4_p+Xmax_l-1-2,
+/** x1_0:2 */ x1_0_p+x_l-1-2,
+/** x1_1:2 */ x1_1_p+x_l-1-2, /* bit 80 */
+/** x1_2:2 */ x1_2_p+x_l-1-2,
+/** x1_3:2 */ x1_3_p+x_l-1-2,
+/** x1_4:2 */ x1_4_p+x_l-1-2,
+/** x1_5:2 */ x1_5_p+x_l-1-2,
+/** x1_6:2 */ x1_6_p+x_l-1-2,
+/** x1_7:2 */ x1_7_p+x_l-1-2,
+/** x1_8:2 */ x1_8_p+x_l-1-2,
+/** x1_9:2 */ x1_9_p+x_l-1-2,
+/** x1_10:2 */ x1_10_p+x_l-1-2,
+/** x1_11:2 */ x1_11_p+x_l-1-2, /* bit 90 */
+/** x1_12:2 */ x1_12_p+x_l-1-2,
+/** x2_0:2 */ x2_0_p+x_l-1-2,
+/** x2_1:2 */ x2_1_p+x_l-1-2,
+/** x2_2:2 */ x2_2_p+x_l-1-2,
+/** x2_3:2 */ x2_3_p+x_l-1-2,
+/** x2_4:2 */ x2_4_p+x_l-1-2,
+/** x2_5:2 */ x2_5_p+x_l-1-2,
+/** x2_6:2 */ x2_6_p+x_l-1-2,
+/** x2_7:2 */ x2_7_p+x_l-1-2,
+/** x2_8:2 */ x2_8_p+x_l-1-2, /* bit 100 */
+/** x2_9:2 */ x2_9_p+x_l-1-2,
+/** x2_10:2 */ x2_10_p+x_l-1-2,
+/** x2_11:2 */ x2_11_p+x_l-1-2,
+/** x2_12:2 */ x2_12_p+x_l-1-2,
+/** x3_0:2 */ x3_0_p+x_l-1-2,
+/** x3_1:2 */ x3_1_p+x_l-1-2,
+/** x3_2:2 */ x3_2_p+x_l-1-2,
+/** x3_3:2 */ x3_3_p+x_l-1-2,
+/** x3_4:2 */ x3_4_p+x_l-1-2,
+/** x3_5:2 */ x3_5_p+x_l-1-2, /* bit 110 */
+/** x3_6:2 */ x3_6_p+x_l-1-2,
+/** x3_7:2 */ x3_7_p+x_l-1-2,
+/** x3_8:2 */ x3_8_p+x_l-1-2,
+/** x3_9:2 */ x3_9_p+x_l-1-2,
+/** x3_10:2 */ x3_10_p+x_l-1-2,
+/** x3_11:2 */ x3_11_p+x_l-1-2,
+/** x3_12:2 */ x3_12_p+x_l-1-2,
+/** x4_0:2 */ x4_0_p+x_l-1-2,
+/** x4_1:2 */ x4_1_p+x_l-1-2,
+/** x4_2:2 */ x4_2_p+x_l-1-2, /* bit 120 */
+/** x4_3:2 */ x4_3_p+x_l-1-2,
+/** x4_4:2 */ x4_4_p+x_l-1-2,
+/** x4_5:2 */ x4_5_p+x_l-1-2,
+/** x4_6:2 */ x4_6_p+x_l-1-2,
+/** x4_7:2 */ x4_7_p+x_l-1-2,
+/** x4_8:2 */ x4_8_p+x_l-1-2,
+/** x4_9:2 */ x4_9_p+x_l-1-2,
+/** x4_10:2 */ x4_10_p+x_l-1-2,
+/** x4_11:2 */ x4_11_p+x_l-1-2,
+/** x4_12:2 */ x4_12_p+x_l-1-2, /* bit 130 */
+/** M1:0 */ M1_p+M_l-1-0,
+/** M2:0 */ M2_p+M_l-1-0,
+/** M3:0 */ M3_p+M_l-1-0,
+/** M4:0 */ M4_p+M_l-1-0,
+/** Xmax1:1 */ Xmax1_p+Xmax_l-1-1,
+/** Xmax2:1 */ Xmax2_p+Xmax_l-1-1,
+/** Xmax3:1 */ Xmax3_p+Xmax_l-1-1,
+/** Xmax4:1 */ Xmax4_p+Xmax_l-1-1,
+/** x1_0:1 */ x1_0_p+x_l-1-1,
+/** x1_1:1 */ x1_1_p+x_l-1-1, /* bit 140 */
+/** x1_2:1 */ x1_2_p+x_l-1-1,
+/** x1_3:1 */ x1_3_p+x_l-1-1,
+/** x1_4:1 */ x1_4_p+x_l-1-1,
+/** x1_5:1 */ x1_5_p+x_l-1-1,
+/** x1_6:1 */ x1_6_p+x_l-1-1,
+/** x1_7:1 */ x1_7_p+x_l-1-1,
+/** x1_8:1 */ x1_8_p+x_l-1-1,
+/** x1_9:1 */ x1_9_p+x_l-1-1,
+/** x1_10:1 */ x1_10_p+x_l-1-1,
+/** x1_11:1 */ x1_11_p+x_l-1-1, /* bit 150 */
+/** x1_12:1 */ x1_12_p+x_l-1-1,
+/** x2_0:1 */ x2_0_p+x_l-1-1,
+/** x2_1:1 */ x2_1_p+x_l-1-1,
+/** x2_2:1 */ x2_2_p+x_l-1-1,
+/** x2_3:1 */ x2_3_p+x_l-1-1,
+/** x2_4:1 */ x2_4_p+x_l-1-1,
+/** x2_5:1 */ x2_5_p+x_l-1-1,
+/** x2_6:1 */ x2_6_p+x_l-1-1,
+/** x2_7:1 */ x2_7_p+x_l-1-1,
+/** x2_8:1 */ x2_8_p+x_l-1-1, /* bit 160 */
+/** x2_9:1 */ x2_9_p+x_l-1-1,
+/** x2_10:1 */ x2_10_p+x_l-1-1,
+/** x2_11:1 */ x2_11_p+x_l-1-1,
+/** x2_12:1 */ x2_12_p+x_l-1-1,
+/** x3_0:1 */ x3_0_p+x_l-1-1,
+/** x3_1:1 */ x3_1_p+x_l-1-1,
+/** x3_2:1 */ x3_2_p+x_l-1-1,
+/** x3_3:1 */ x3_3_p+x_l-1-1,
+/** x3_4:1 */ x3_4_p+x_l-1-1,
+/** x3_5:1 */ x3_5_p+x_l-1-1, /* bit 170 */
+/** x3_6:1 */ x3_6_p+x_l-1-1,
+/** x3_7:1 */ x3_7_p+x_l-1-1,
+/** x3_8:1 */ x3_8_p+x_l-1-1,
+/** x3_9:1 */ x3_9_p+x_l-1-1,
+/** x3_10:1 */ x3_10_p+x_l-1-1,
+/** x3_11:1 */ x3_11_p+x_l-1-1,
+/** x3_12:1 */ x3_12_p+x_l-1-1,
+/** x4_0:1 */ x4_0_p+x_l-1-1,
+/** x4_1:1 */ x4_1_p+x_l-1-1,
+/** x4_2:1 */ x4_2_p+x_l-1-1, /* bit 180 */
+/** x4_3:1 */ x4_3_p+x_l-1-1,
+//@}
+/**@name importance class 6 */
+//@{
+/** x4_4:1 */ x4_4_p+x_l-1-1,
+/** x4_5:1 */ x4_5_p+x_l-1-1,
+/** x4_6:1 */ x4_6_p+x_l-1-1,
+/** x4_7:1 */ x4_7_p+x_l-1-1,
+/** x4_8:1 */ x4_8_p+x_l-1-1,
+/** x4_9:1 */ x4_9_p+x_l-1-1,
+/** x4_10:1 */ x4_10_p+x_l-1-1,
+/** x4_11:1 */ x4_11_p+x_l-1-1,
+/** x4_12:1 */ x4_12_p+x_l-1-1, /* bit 190 */
+/** LAR1:0 */ LAR1_p+LAR1_l-1-0,
+/** LAR2:1 */ LAR2_p+LAR2_l-1-1,
+/** LAR3:1 */ LAR3_p+LAR3_l-1-1,
+/** LAR6:1 */ LAR6_p+LAR6_l-1-1,
+/** LAR7:0 */ LAR7_p+LAR7_l-1-0,
+/** LAR8:1 */ LAR8_p+LAR8_l-1-1,
+/** LAR8:0 */ LAR8_p+LAR8_l-1-0,
+/** LAR3:0 */ LAR3_p+LAR3_l-1-0,
+/** LAR4:1 */ LAR4_p+LAR4_l-1-1,
+/** LAR4:0 */ LAR4_p+LAR4_l-1-0,
+/** LAR5:0 */ LAR5_p+LAR5_l-1-0,
+/** Xmax1:0 */ Xmax1_p+Xmax_l-1-0,
+/** Xmax2:0 */ Xmax2_p+Xmax_l-1-0,
+/** Xmax3:0 */ Xmax3_p+Xmax_l-1-0,
+/** Xmax4:0 */ Xmax4_p+Xmax_l-1-0,
+/** x1_0:0 */ x1_0_p+x_l-1-0,
+/** x1_1:0 */ x1_1_p+x_l-1-0,
+/** x1_2:0 */ x1_2_p+x_l-1-0,
+/** x1_3:0 */ x1_3_p+x_l-1-0,
+/** x1_4:0 */ x1_4_p+x_l-1-0,
+/** x1_5:0 */ x1_5_p+x_l-1-0,
+/** x1_6:0 */ x1_6_p+x_l-1-0,
+/** x1_7:0 */ x1_7_p+x_l-1-0,
+/** x1_8:0 */ x1_8_p+x_l-1-0,
+/** x1_9:0 */ x1_9_p+x_l-1-0,
+/** x1_10:0 */ x1_10_p+x_l-1-0,
+/** x1_11:0 */ x1_11_p+x_l-1-0,
+/** x1_12:0 */ x1_12_p+x_l-1-0,
+/** x2_0:0 */ x2_0_p+x_l-1-0,
+/** x2_1:0 */ x2_1_p+x_l-1-0,
+/** x2_2:0 */ x2_2_p+x_l-1-0,
+/** x2_3:0 */ x2_3_p+x_l-1-0,
+/** x2_4:0 */ x2_4_p+x_l-1-0,
+/** x2_5:0 */ x2_5_p+x_l-1-0,
+/** x2_6:0 */ x2_6_p+x_l-1-0,
+/** x2_7:0 */ x2_7_p+x_l-1-0,
+/** x2_8:0 */ x2_8_p+x_l-1-0,
+/** x2_9:0 */ x2_9_p+x_l-1-0,
+/** x2_10:0 */ x2_10_p+x_l-1-0,
+/** x2_11:0 */ x2_11_p+x_l-1-0,
+/** x2_12:0 */ x2_12_p+x_l-1-0,
+/** x3_0:0 */ x3_0_p+x_l-1-0,
+/** x3_1:0 */ x3_1_p+x_l-1-0,
+/** x3_2:0 */ x3_2_p+x_l-1-0,
+/** x3_3:0 */ x3_3_p+x_l-1-0,
+/** x3_4:0 */ x3_4_p+x_l-1-0,
+/** x3_5:0 */ x3_5_p+x_l-1-0,
+/** x3_6:0 */ x3_6_p+x_l-1-0,
+/** x3_7:0 */ x3_7_p+x_l-1-0,
+/** x3_8:0 */ x3_8_p+x_l-1-0,
+/** x3_9:0 */ x3_9_p+x_l-1-0,
+/** x3_10:0 */ x3_10_p+x_l-1-0,
+/** x3_11:0 */ x3_11_p+x_l-1-0,
+/** x3_12:0 */ x3_12_p+x_l-1-0,
+/** x4_0:0 */ x4_0_p+x_l-1-0,
+/** x4_1:0 */ x4_1_p+x_l-1-0,
+/** x4_2:0 */ x4_2_p+x_l-1-0,
+/** x4_3:0 */ x4_3_p+x_l-1-0,
+/** x4_4:0 */ x4_4_p+x_l-1-0,
+/** x4_5:0 */ x4_5_p+x_l-1-0,
+/** x4_6:0 */ x4_6_p+x_l-1-0,
+/** x4_7:0 */ x4_7_p+x_l-1-0,
+/** x4_8:0 */ x4_8_p+x_l-1-0,
+/** x4_9:0 */ x4_9_p+x_l-1-0,
+/** x4_10:0 */ x4_10_p+x_l-1-0,
+/** x4_11:0 */ x4_11_p+x_l-1-0,
+/** x4_12:0 */ x4_12_p+x_l-1-0,
+/** LAR2:0 */ LAR2_p+LAR2_l-1-0,
+/** LAR6:0 */ LAR6_p+LAR6_l-1-0
+//@}
+};
+
diff --git a/gsm-receiver/src/lib/decoder/openbtsstuff/GSM610Tables.h b/gsm-receiver/src/lib/decoder/openbtsstuff/GSM610Tables.h
new file mode 100644
index 0000000..53a8e1c
--- /dev/null
+++ b/gsm-receiver/src/lib/decoder/openbtsstuff/GSM610Tables.h
@@ -0,0 +1,37 @@
+/*
+* 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/gsm-receiver/src/lib/decoder/openbtsstuff/GSMCommon.cpp b/gsm-receiver/src/lib/decoder/openbtsstuff/GSMCommon.cpp
new file mode 100644
index 0000000..0bec812
--- /dev/null
+++ b/gsm-receiver/src/lib/decoder/openbtsstuff/GSMCommon.cpp
@@ -0,0 +1,315 @@
+/*
+* 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/>.
+
+*/
+
+
+#include "GSMCommon.h"
+
+using namespace GSM;
+using namespace std;
+
+
+ostream& GSM::operator<<(ostream& os, L3PD val)
+{
+ switch (val) {
+ case L3CallControlPD: os << "Call Control"; break;
+ case L3MobilityManagementPD: os << "Mobility Management"; break;
+ case L3RadioResourcePD: os << "Radio Resource"; break;
+ default: os << hex << "0x" << (int)val << dec;
+ }
+ return os;
+}
+
+
+const BitVector GSM::gTrainingSequence[] = {
+ BitVector("00100101110000100010010111"),
+ BitVector("00101101110111100010110111"),
+ BitVector("01000011101110100100001110"),
+ BitVector("01000111101101000100011110"),
+ BitVector("00011010111001000001101011"),
+ BitVector("01001110101100000100111010"),
+ BitVector("10100111110110001010011111"),
+ BitVector("11101111000100101110111100"),
+};
+
+const BitVector GSM::gDummyBurst("0001111101101110110000010100100111000001001000100000001111100011100010111000101110001010111010010100011001100111001111010011111000100101111101010000");
+
+const BitVector GSM::gRACHSynchSequence("01001011011111111001100110101010001111000");
+
+
+
+char encodeGSMChar(char ascii)
+{
+ // Given an ASCII char, return the corresponding GSM char.
+ static char reverseTable[256]={0};
+ static bool init = false;
+ if (!init) {
+ for (size_t i=0; i<sizeof(gGSMAlphabet); i++) {
+ reverseTable[(unsigned)gGSMAlphabet[i]]=i;
+ }
+ init=true;
+ }
+ return reverseTable[(unsigned)ascii];
+}
+
+
+char encodeBCDChar(char ascii)
+{
+ // Given an ASCII char, return the corresponding BCD.
+ if ((ascii>='0') && (ascii<='9')) return ascii-'0';
+ switch (ascii) {
+ case '.': return 11;
+ case '*': return 11;
+ case '#': return 12;
+ case 'a': return 13;
+ case 'b': return 14;
+ case 'c': return 15;
+ default: return 15;
+ }
+}
+
+
+
+
+unsigned GSM::uplinkFreqKHz(GSMBand band, unsigned ARFCN)
+{
+ switch (band) {
+ case GSM850:
+ assert((ARFCN<252)&&(ARFCN>129));
+ return 824200+200*(ARFCN-128);
+ case EGSM900:
+ if (ARFCN<=124) return 890000+200*ARFCN;
+ assert((ARFCN>974)&&(ARFCN<1024));
+ return 890000+200*(ARFCN-1024);
+ case DCS1800:
+ assert((ARFCN>511)&&(ARFCN<886));
+ return 1710200+200*(ARFCN-512);
+ case PCS1900:
+ assert((ARFCN>511)&&(ARFCN<811));
+ return 1850200+200*(ARFCN-512);
+ default:
+ abort();
+ }
+}
+
+
+unsigned GSM::downlinkFreqKHz(GSMBand band, unsigned ARFCN)
+{
+ static unsigned uplinkOffset[] = {
+ 45000, // 850
+ 45000, // 900
+ 95000, // 1800
+ 80000 // 1900
+ };
+ return uplinkFreqKHz(band,ARFCN) + uplinkOffset[band];
+}
+
+
+
+
+int32_t GSM::FNDelta(int32_t v1, int32_t v2)
+{
+ static const int64_t halfModulus = gHyperframe/2;
+ int32_t delta = v1-v2;
+ if (delta>halfModulus) delta -= gHyperframe;
+ else if (delta<-halfModulus) delta += gHyperframe;
+ return (int32_t) delta;
+}
+
+int GSM::FNCompare(int32_t v1, int32_t v2)
+{
+ int32_t delta = FNDelta(v1,v2);
+ if (delta==0) return 0;
+ else if (delta>0) return 1;
+ else return -1;
+}
+
+
+
+
+ostream& GSM::operator<<(ostream& os, const Time& t)
+{
+ os << t.TN() << ":" << t.FN();
+ return os;
+}
+
+
+
+
+void Clock::set(const Time& when)
+{
+ mLock.lock();
+ mBaseTime = Timeval(0);
+ mBaseFN = when.FN();
+ mLock.unlock();
+}
+
+
+int32_t Clock::FN() const
+{
+ mLock.lock();
+ Timeval now;
+ int deltaSec = now.sec() - mBaseTime.sec();
+ int deltaUSec = now.usec() - mBaseTime.usec();
+ int elapsedUSec = 1000000*deltaSec + deltaUSec;
+ int elapsedFrames = elapsedUSec / gFrameMicroseconds;
+ int32_t currentFN = (mBaseFN + elapsedFrames) % gHyperframe;
+ mLock.unlock();
+ return currentFN;
+}
+
+
+void Clock::wait(const Time& when) const
+{
+ int32_t now = FN();
+ int32_t target = when.FN();
+ int32_t delta = FNDelta(target,now);
+ if (delta<1) return;
+ const int32_t maxSleep = 51*26;
+ if (delta>maxSleep) delta=maxSleep;
+ sleepFrames(delta);
+}
+
+
+
+
+
+
+
+ostream& GSM::operator<<(ostream& os, TypeOfNumber type)
+{
+ switch (type) {
+ case UnknownTypeOfNumber: os << "unknown"; break;
+ case InternationalNumber: os << "international"; break;
+ case NationalNumber: os << "national"; break;
+ case NetworkSpecificNumber: os << "network-specific"; break;
+ case ShortCodeNumber: os << "short code"; break;
+ default: os << "?" << type << "?";
+ }
+ return os;
+}
+
+
+ostream& GSM::operator<<(ostream& os, NumberingPlan plan)
+{
+ switch (plan) {
+ case UnknownPlan: os << "unknown"; break;
+ case E164Plan: os << "E.164/ISDN"; break;
+ case X121Plan: os << "X.121/data"; break;
+ case F69Plan: os << "F.69/Telex"; break;
+ case NationalPlan: os << "national"; break;
+ case PrivatePlan: os << "private"; break;
+ default: os << "?" << (int)plan << "?";
+ }
+ return os;
+}
+
+ostream& GSM::operator<<(ostream& os, MobileIDType wID)
+{
+ switch (wID) {
+ case NoIDType: os << "None"; break;
+ case IMSIType: os << "IMSI"; break;
+ case IMEIType: os << "IMEI"; break;
+ case TMSIType: os << "TMSI"; break;
+ case IMEISVType: os << "IMEISV"; break;
+ default: os << "?" << (int)wID << "?";
+ }
+ return os;
+}
+
+
+ostream& GSM::operator<<(ostream& os, TypeAndOffset tao)
+{
+ switch (tao) {
+ case TDMA_MISC: os << "(misc)"; break;
+ case TCHF_0: os << "TCH/F"; break;
+ case TCHH_0: os << "TCH/H-0"; break;
+ case TCHH_1: os << "TCH/H-1"; break;
+ case SDCCH_4_0: os << "SDCCH/4-0"; break;
+ case SDCCH_4_1: os << "SDCCH/4-1"; break;
+ case SDCCH_4_2: os << "SDCCH/4-2"; break;
+ case SDCCH_4_3: os << "SDCCH/4-3"; break;
+ case SDCCH_8_0: os << "SDCCH/8-0"; break;
+ case SDCCH_8_1: os << "SDCCH/8-1"; break;
+ case SDCCH_8_2: os << "SDCCH/8-2"; break;
+ case SDCCH_8_3: os << "SDCCH/8-3"; break;
+ case SDCCH_8_4: os << "SDCCH/8-4"; break;
+ case SDCCH_8_5: os << "SDCCH/8-5"; break;
+ case SDCCH_8_6: os << "SDCCH/8-6"; break;
+ case SDCCH_8_7: os << "SDCCH/8-7"; break;
+ case TDMA_BEACON: os << "(beacon)"; break;
+ default: os << "?" << (int)tao << "?";
+ }
+ return os;
+}
+
+ostream& GSM::operator<<(ostream& os, ChannelType val)
+{
+ switch (val) {
+ case UndefinedCHType: os << "undefined"; return os;
+ case SCHType: os << "SCH"; break;
+ case FCCHType: os << "FCCH"; break;
+ case BCCHType: os << "BCCH"; break;
+ case RACHType: os << "RACH"; break;
+ case SDCCHType: os << "SDCCH"; break;
+ case FACCHType: os << "FACCH"; break;
+ case CCCHType: os << "CCCH"; break;
+ case SACCHType: os << "SACCH"; break;
+ case TCHFType: os << "TCH/F"; break;
+ case TCHHType: os << "TCH/H"; break;
+ case AnyTCHType: os << "any TCH"; break;
+ case LoopbackFullType: os << "Loopback Full"; break;
+ case LoopbackHalfType: os << "Loopback Half"; break;
+ case AnyDCCHType: os << "any DCCH"; break;
+ default: os << "?" << (int)val << "?";
+ }
+ return os;
+}
+
+
+
+
+bool Z100Timer::expired() const
+{
+ // A non-active timer does not expire.
+ if (!mActive) return false;
+ return mEndTime.passed();
+}
+
+void Z100Timer::set()
+{
+ mEndTime = Timeval(mLimitTime);
+ mActive=true;
+}
+
+long Z100Timer::remaining() const
+{
+ if (!mActive) return 0;
+ long rem = mEndTime.remaining();
+ if (rem<0) rem=0;
+ return rem;
+}
+
+void Z100Timer::wait() const
+{
+ while (!expired()) msleep(remaining());
+}
+
+// vim: ts=4 sw=4
diff --git a/gsm-receiver/src/lib/decoder/openbtsstuff/GSMCommon.h b/gsm-receiver/src/lib/decoder/openbtsstuff/GSMCommon.h
new file mode 100644
index 0000000..9dc1c95
--- /dev/null
+++ b/gsm-receiver/src/lib/decoder/openbtsstuff/GSMCommon.h
@@ -0,0 +1,537 @@
+/**@file Common-use GSM declarations, most from the GSM 04.xx and 05.xx series. */
+/*
+* 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 GSMCOMMON_H
+#define GSMCOMMON_H
+
+#include <stdlib.h>
+#include <sys/time.h>
+#include <ostream>
+#include <vector>
+
+#include <Threads.h>
+#include <Timeval.h>
+#include <BitVector.h>
+
+
+
+
+namespace GSM {
+
+/**@namespace GSM This namespace covers L1 FEC, L2 and L3 message translation. */
+
+
+/* forward references */
+class L1FEC;
+class L2LAPDm;
+class L3Processor;
+class LogicalChannel;
+class L2Header;
+
+
+/** A base class for GSM exceptions. */
+class GSMError {};
+
+/** Duration ofa GSM frame, in microseconds. */
+const unsigned gFrameMicroseconds = 4615;
+
+
+/** Sleep for a given number of GSM frame periods. */
+inline void sleepFrames(unsigned frames)
+ { usleep(frames*gFrameMicroseconds); }
+
+/** Sleep for 1 GSM frame period. */
+inline void sleepFrame()
+ { usleep(gFrameMicroseconds); }
+
+
+
+/** GSM Training sequences from GSM 05.02 5.2.3. */
+extern const BitVector gTrainingSequence[];
+
+/** C0T0 filler burst, GSM 05.02, 5.2.6 */
+extern const BitVector gDummyBurst;
+
+/** Random access burst synch. sequence */
+extern const BitVector gRACHSynchSequence;
+
+
+/**@name Support for GSM 7-bit alphabet, GSM 03.38 6.2.1. */
+//@{
+/** Indexed by GSM 7-bit, returns ASCII. */
+static const char gGSMAlphabet[] = "@\243$\245\350\351\371\354\362\347\n\330\370\r\305\345D_FGLOPCSTZ \306\346\337\311 !\"#\244%&\'()*+,-./0123456789:;<=>?\241ABCDEFGHIJKLMNOPQRSTUVWXYZ\304\326\321\334\247\277abcdefghijklmnopqrstuvwxyz\344\366\361\374\341";
+char encodeGSMChar(char ascii);
+inline char decodeGSMChar(char sms) { return gGSMAlphabet[(unsigned)sms]; }
+//@}
+
+
+/**@name BCD-ASCII mapping, GMS 04.08 Table 10.5.118. */
+//@{
+/** Indexed by BCD, returns ASCII. */
+static const char gBCDAlphabet[] = "0123456789.#abc";
+char encodeBCDChar(char ascii);
+inline char decodeBCDChar(char bcd) { return gBCDAlphabet[(unsigned)bcd]; }
+//@}
+
+
+/**@name Globally-fixed GSM timeout values (all in ms). */
+//@{
+/**@name GSM LAPDm timeouts, GSM 04.06 5.8, ITU-T Q.921 5.9 */
+//@{
+const unsigned T200ms = 900; ///< LAPDm ACK timeout, set for typical turnaround time
+//@}
+/**@name GSM timeouts for radio resource management, GSM 04.08 11.1. */
+//@{
+const unsigned T3101ms = 4000; ///< L1 timeout for SDCCH assignment
+const unsigned T3107ms = 3000; ///< L1 timeout for TCH/FACCH assignment
+const unsigned T3109ms = 10000; ///< L1 timeout for an existing channel
+const unsigned T3111ms = 2*T200ms; ///< L1 timeout for reassignment of a channel
+const unsigned T3113ms = 10000; ///< timeout for paging response
+const unsigned T3122ms = 2000; ///< RR access holdoff time (GSM 04.08 3.3.1.1.3.2)
+//@}
+/**@name GSM timeouts for mobility management, GSM 04.08 11.2. */
+//@{
+const unsigned T3212ms = 8*360000; ///< location updating period (in 6-min increments, 0-255)
+//const unsigned T3212ms = 0; ///< location updating period (in 6-min increments, 0-255), 0 disables
+//@}
+//@}
+
+
+
+
+/** GSM 04.08 Table 10.5.118 */
+enum TypeOfNumber {
+ UnknownTypeOfNumber = 0,
+ InternationalNumber = 1,
+ NationalNumber = 2,
+ NetworkSpecificNumber = 3,
+ ShortCodeNumber = 4
+};
+
+std::ostream& operator<<(std::ostream&, TypeOfNumber);
+
+
+/** GSM 04.08 Table 10.5.118 */
+enum NumberingPlan {
+ UnknownPlan = 0,
+ E164Plan = 1,
+ X121Plan = 3,
+ F69Plan = 4,
+ NationalPlan = 8,
+ PrivatePlan = 9
+};
+
+std::ostream& operator<<(std::ostream&, NumberingPlan);
+
+
+
+/** Codes for GSM band types, GSM 05.05 2. */
+enum GSMBand {
+ GSM850=0, ///< US cellular
+ EGSM900, ///< extended GSM
+ DCS1800, ///< worldwide DCS band
+ PCS1900 ///< US PCS band
+};
+
+
+/**@name Actual radio carrier frequencies, in kHz, GSM 05.05 2 */
+//@{
+unsigned uplinkFreqKHz(GSMBand wBand, unsigned wARFCN);
+unsigned downlinkFreqKHz(GSMBand wBand, unsigned wARFCN);
+//@}
+
+
+
+/**@name GSM Logical channel (LCH) types. */
+//@{
+/** Codes for logical channel types. */
+enum ChannelType {
+ ///@name Non-dedicated control channels.
+ //@{
+ SCHType, ///< sync
+ FCCHType, ///< frequency correction
+ BCCHType, ///< broadcast control
+ CCCHType, ///< common control, a combination of several sub-types
+ RACHType, ///< random access
+ SACCHType, ///< slow associated control (acutally dedicated, but...)
+ //@}
+ ///@name Dedicated control channels (DCCHs).
+ //@{
+ SDCCHType, ///< standalone dedicated control
+ FACCHType, ///< fast associated control
+ //@}
+ ///@name Traffic channels
+ //@{
+ TCHFType, ///< full-rate traffic
+ TCHHType, ///< half-rate traffic
+ AnyTCHType, ///< any TCH type
+ //@}
+ ///@name Special internal channel types.
+ //@{
+ LoopbackFullType, ///< loopback testing
+ LoopbackHalfType, ///< loopback testing
+ AnyDCCHType, ///< any dedicated control channel
+ UndefinedCHType, ///< undefined
+ //@}
+};
+
+
+/** Print channel type name to a stream. */
+std::ostream& operator<<(std::ostream& os, ChannelType val);
+
+
+//@}
+
+
+
+/** Mobile identity types, GSM 04.08 10.5.1.4 */
+enum MobileIDType {
+ NoIDType = 0,
+ IMSIType = 1,
+ IMEIType = 2,
+ IMEISVType = 3,
+ TMSIType = 4
+};
+
+std::ostream& operator<<(std::ostream& os, MobileIDType);
+
+
+/** Type and TDMA offset of a logical channel, from GSM 04.08 10.5.2.5 */
+enum TypeAndOffset {
+ TDMA_MISC=0,
+ TCHF_0=1,
+ TCHH_0=2, TCHH_1=3,
+ SDCCH_4_0=4, SDCCH_4_1=5, SDCCH_4_2=6, SDCCH_4_3=7,
+ SDCCH_8_0=8, SDCCH_8_1=9, SDCCH_8_2=10, SDCCH_8_3=11,
+ SDCCH_8_4=12, SDCCH_8_5=13, SDCCH_8_6=14, SDCCH_8_7=15,
+ /// An extra one for our internal use.
+ TDMA_BEACON=255
+};
+
+std::ostream& operator<<(std::ostream& os, TypeAndOffset);
+
+
+
+
+
+
+
+
+/**
+ L3 Protocol Discriminator, GSM 04.08 10.2, GSM 04.07 11.2.3.1.1.
+*/
+enum L3PD {
+ L3GroupCallControlPD=0x00,
+ L3BroadcastCallControlPD=0x01,
+ L3PDSS1PD=0x02,
+ L3CallControlPD=0x03,
+ L3PDSS2PD=0x04,
+ L3MobilityManagementPD=0x05,
+ L3RadioResourcePD=0x06,
+ L3MobilityManagementGPRSPD=0x08,
+ L3SMSPD=0x09,
+ L3GPRSSessionManagementPD=0x0a,
+ L3NonCallSSPD=0x0b,
+ L3LocationPD=0x0c,
+ L3ExtendedPD=0x0e,
+ L3TestProcedurePD=0x0f,
+ L3UndefinedPD=-1
+};
+
+
+
+std::ostream& operator<<(std::ostream& os, L3PD val);
+
+
+
+
+/**@name Modulus operations for frame numbers. */
+//@{
+/** The GSM hyperframe is largest time period in the GSM system, GSM 05.02 4.3.3. */
+const int32_t gHyperframe = 2048UL * 26UL * 51UL;
+
+/** Get a clock difference, within the modulus. */
+int32_t FNDelta(int32_t v1, int32_t v2);
+
+/**
+ Compare two frame clock values.
+ @return 1 if v1>v2, -1 if v1<v2, 0 if v1==v2
+*/
+int FNCompare(int32_t v1, int32_t v2);
+
+
+//@}
+
+
+
+
+/**
+ GSM frame clock value.
+ No internal thread sync.
+*/
+class Time {
+
+ private:
+
+ int mFN; ///< frame number in the hyperframe
+ unsigned mTN; ///< timeslot number
+
+ public:
+
+ Time(int wFN=0, unsigned wTN=0)
+ :mFN(wFN),mTN(wTN)
+ { }
+
+
+ /** Move the time forward to a given position in a given modulus. */
+ void rollForward(unsigned wFN, unsigned modulus)
+ { while ((mFN % modulus) != wFN) mFN++; }
+
+ /**@name Accessors. */
+ //@{
+ int FN() const { return mFN; }
+ void FN(unsigned wFN) { mFN = wFN; }
+ unsigned TN() const { return mTN; }
+ void TN(unsigned wTN) { mTN=wTN; }
+ //@}
+
+ /**@name Arithmetic. */
+ //@{
+
+ Time& operator++()
+ {
+ mFN = (mFN+1) % gHyperframe;
+ return *this;
+ }
+
+ Time& decTN(int step=1)
+ {
+ if ((int)mTN<step) mFN = *this - Time(1,0);
+ if (mTN-step < 0) mTN = (mTN-step+8) % 8;
+ else mTN = (mTN-step) % 8;
+ return *this;
+ }
+
+ Time& incTN(int step=1)
+ {
+ mFN = mFN + (mTN + step)/8;
+ mTN = (mTN+step) % 8;
+ return *this;
+ }
+
+ Time& operator+=(int step)
+ {
+ mFN = (mFN+step) % gHyperframe;
+ return *this;
+ }
+
+ Time operator+(int step) const
+ {
+ Time newVal = *this;
+ newVal += step;
+ return newVal;
+ }
+
+ Time operator-(int step) const
+ {
+ return operator+(-step);
+ }
+
+ Time operator+(const Time& other) const
+ {
+ unsigned newTN = (mTN + other.mTN) % 8;
+ uint64_t newFN = (mFN+other.mFN + (mTN + other.mTN)/8) % gHyperframe;
+ return Time(newFN,newTN);
+ }
+
+ int operator-(const Time& other) const
+ {
+ return FNDelta(mFN,other.mFN);
+ }
+
+ //@}
+
+
+ /**@name Comparisons. */
+ //@{
+
+ bool operator<(const Time& other) const
+ {
+ if (mFN==other.mFN) return (mTN<other.mTN);
+ return FNCompare(mFN,other.mFN)<0;
+ }
+
+ bool operator>(const Time& other) const
+ {
+ if (mFN==other.mFN) return (mTN>other.mTN);
+ return FNCompare(mFN,other.mFN)>0;
+ }
+
+ bool operator<=(const Time& other) const
+ {
+ if (mFN==other.mFN) return (mTN<=other.mTN);
+ return FNCompare(mFN,other.mFN)<=0;
+ }
+
+ bool operator>=(const Time& other) const
+ {
+ if (mFN==other.mFN) return (mTN>=other.mTN);
+ return FNCompare(mFN,other.mFN)>=0;
+ }
+
+ bool operator==(const Time& other) const
+ {
+ return (mFN == other.mFN) && (mTN==other.mTN);
+ }
+
+ //@}
+
+
+
+ /**@name Standard derivations. */
+ //@{
+
+ unsigned SFN() const { return mFN / (26*51); }
+
+ unsigned T1() const { return SFN() % 2048; }
+
+ unsigned T2() const { return mFN % 26; }
+
+ unsigned T3() const { return mFN % 51; }
+
+ /** GSM 05.02 3.3.2.2.1. */
+ unsigned T3p() const { return (T3()-1)/10; }
+
+ /** GSM 05.02 6.3.1.3. */
+ unsigned TC() const { return (FN()/51) % 8; }
+
+ /** GSM 04.08 10.5.2.30. */
+ unsigned T1p() const { return SFN() % 32; }
+
+ /** GSM 05.02 6.2.3 */
+ unsigned T1R() const { return T1() % 64; }
+
+ //@}
+};
+
+
+std::ostream& operator<<(std::ostream& os, const Time& ts);
+
+
+
+
+
+
+/**
+ A class for calculating the current GSM frame number.
+*/
+class Clock {
+
+ private:
+
+ mutable Mutex mLock;
+ int32_t mBaseFN;
+ Timeval mBaseTime;
+
+ public:
+
+ Clock(const Time& when = Time(0))
+ :mBaseFN(when.FN())
+ {}
+
+ /** Set the clock to a value. */
+ void set(const Time&);
+
+ /** Read the clock. */
+ int32_t FN() const;
+
+ /** Read the clock. */
+ Time get() const { return Time(FN()); }
+
+ /** Block until the clock passes a given time. */
+ void wait(const Time&) const;
+};
+
+
+
+
+
+
+
+
+/**
+ CCITT Z.100 activity timer, as described in GSM 04.06 5.1.
+ All times are in milliseconds.
+*/
+class Z100Timer {
+
+ private:
+
+ Timeval mEndTime; ///< the time at which this timer will expire
+ long mLimitTime; ///< timeout in milliseconds
+ bool mActive; ///< true if timer is active
+
+ public:
+
+ /** Create a timer with a given timeout in milliseconds. */
+ Z100Timer(long wLimitTime)
+ :mLimitTime(wLimitTime),
+ mActive(false)
+ {}
+
+ /** True if the timer is active and expired. */
+ bool expired() const;
+
+ /** Start or restart the timer. */
+ void set();
+
+ /** Stop the timer. */
+ void reset() { mActive = false; }
+
+ /** Returns true if the timer is active. */
+ bool active() const { return mActive; }
+
+ /**
+ Remaining time until expiration, in milliseconds.
+ Returns zero if the timer has expired.
+ */
+ long remaining() const;
+
+ /**
+ Block until the timer expires.
+ Returns immediately if the timer is not running.
+ */
+ void wait() const;
+};
+
+
+
+
+
+}; // namespace GSM
+
+
+#endif
+
+// vim: ts=4 sw=4
diff --git a/gsm-receiver/src/lib/decoder/openbtsstuff/GSML1FEC.cpp b/gsm-receiver/src/lib/decoder/openbtsstuff/GSML1FEC.cpp
new file mode 100644
index 0000000..1c99a0f
--- /dev/null
+++ b/gsm-receiver/src/lib/decoder/openbtsstuff/GSML1FEC.cpp
@@ -0,0 +1,256 @@
+/*
+* 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/>.
+
+*/
+
+
+#define NDEBUG
+
+
+#include "GSML1FEC.h"
+#include "GSMCommon.h"
+#include "RxBurst.h"
+//#include "GSMSAPMux.h"
+//#include "GSMConfig.h"
+#include "GSMTDMA.h"
+#include "GSM610Tables.h"
+#include "Assert.h"
+
+
+using namespace std;
+using namespace GSM;
+
+/*
+ Compilation flags:
+ NOCONTROL Compile without referencing control layer functions.
+*/
+
+
+/*
+
+ Notes on reading the GSM specifications.
+
+ Every FEC section in GSM 05.03 uses standard names for the bits at
+ different stages of the encoding/decoding process.
+
+ This is all described formally in GSM 05.03 2.2.
+
+ "d" -- data bits. The actual payloads from L2 and the vocoders.
+ "p" -- parity bits. These are calculated from d.
+ "u" -- uncoded bits. A concatenation of d, p and inner tail bits.
+ "c" -- coded bits. These are the convolutionally encoded from u.
+ "i" -- interleaved bits. These are the output of the interleaver.
+ "e" -- "encrypted" bits. These are the channel bits in the radio bursts.
+
+ The "e" bits are call "encrypted" even when encryption is not used.
+
+ The encoding process is:
+
+ L2 -> d -> -> calc p -> u -> c -> i -> e -> radio bursts
+
+ The decoding process is:
+
+ radio bursts -> e -> i -> c -> u -> check p -> d -> L2
+
+ Bit ordering in d is LSB-first in each octet.
+ Bit ordering everywhere else in the OpenBTS code is MSB-first
+ in every field to give contiguous fields across byte boundaries.
+ We use the BitVector::LSB8MSB() method to translate.
+
+*/
+
+TCHFACCHL1Decoder::TCHFACCHL1Decoder(const TDMAMapping& wMapping)
+ : mTCHU(189), mTCHD(260), mC(456),
+ mClass1_c(mC.head(378)), mClass1A_d(mTCHD.head(50)), mClass2_c(mC.segment(378, 78)),
+ mTCHParity(0x0b, 3, 50), mMapping(wMapping)
+{
+ for (int i = 0; i < 8; i++) {
+ mI[i] = SoftVector(114);
+ }
+}
+
+
+void TCHFACCHL1Decoder::writeLowSide(const RxBurst& inBurst)
+{
+ OBJDCOUT("TCHFACCHL1Decoder::writeLowSide " << inBurst);
+ // If the channel is closed, ignore the burst.
+// if (!active()) {
+// OBJDCOUT("TCHFACCHL1Decoder::writeLowSide not active, ignoring input");
+// return;
+// }
+ processBurst(inBurst);
+}
+
+bool TCHFACCHL1Decoder::processBurst( const RxBurst& inBurst)
+{
+ // Accept the burst into the deinterleaving buffer.
+ // Return true if we are ready to interleave.
+
+ // TODO -- One quick test of burst validity is to look at the tail bits.
+ // We could do that as a double-check against putting garbage into
+ // the interleaver or accepting bad parameters.
+
+ // Get the physical parameters of the burst.
+ // RSSI is dB wrt full scale.
+// mRSSI = inBurst.RSSI();
+ // Timing error is a float in symbol intervals.
+// mTimingError = inBurst.timingError();
+ // This flag is used as a half-ass semaphore.
+ // It is cleared when the new value is read.
+// mPhyNew = true;
+
+ // The reverse index runs 0..3 as the bursts arrive.
+ // It is the "B" index of GSM 05.03 3.1.3 and 3.1.4.
+ int B = mMapping.reverseMapping(inBurst.time().FN()) % 8;
+ // A negative value means that the demux is misconfigured.
+ assert(B >= 0);
+ OBJDCOUT("TCHFACCHL1Decoder::processBurst B=" << B << " " << inBurst);
+
+ // Pull the data fields (e-bits) out of the burst and put them into i[B][].
+ // GSM 05.03 3.1.4
+ inBurst.data1().copyToSegment(mI[B], 0);
+ inBurst.data2().copyToSegment(mI[B], 57);
+
+ // Every 4th frame is the start of a new block.
+ // So if this isn't a "4th" frame, return now.
+ if (B % 4 != 3) return false;
+
+ // Deinterleave according to the diagonal "phase" of B.
+ // See GSM 05.03 3.1.3.
+ // Deinterleaves i[] to c[]
+ if (B == 3) deinterleave(4);
+ else deinterleave(0);
+
+ // See if this was the end of a stolen frame, GSM 05.03 4.2.5.
+ bool stolen = inBurst.Hl();
+ OBJDCOUT("TCHFACCHL!Decoder::processBurst Hl=" << inBurst.Hl() << " Hu=" << inBurst.Hu());
+ /* if (stolen) {
+ if (decode()) {
+ OBJDCOUT("TCHFACCHL1Decoder::processBurst good FACCH frame");
+ countGoodFrame();
+ handleGoodFrame();
+ } else {
+ OBJDCOUT("TCHFACCHL1Decoder::processBurst bad FACCH frame");
+ countBadFrame();
+ }
+ }*/
+
+ // Always feed the traffic channel, even on a stolen frame.
+ // decodeTCH will handle the GSM 06.11 bad frmae processing.
+ bool traffic = decodeTCH(stolen);
+// if (traffic) {
+ OBJDCOUT("TCHFACCHL1Decoder::processBurst good TCH frame");
+// countGoodFrame();
+ // Don't let the channel timeout.
+ // mLock.lock();
+ // mT3109.set();
+ // mLock.unlock();
+// }
+// else countBadFrame();
+
+ return traffic;
+}
+
+void TCHFACCHL1Decoder::deinterleave(int blockOffset )
+{
+ OBJDCOUT("TCHFACCHL1Decoder::deinterleave blockOffset=" << blockOffset);
+ for (int k = 0; k < 456; k++) {
+ int B = ( k + blockOffset ) % 8;
+ int j = 2 * ((49 * k) % 57) + ((k % 8) / 4);
+ mC[k] = mI[B][j];
+ mI[B][j] = 0.5F;
+ //OBJDCOUT("deinterleave k="<<k<<" B="<<B<<" j="<<j);
+ }
+}
+
+bool TCHFACCHL1Decoder::decodeTCH(bool stolen)
+{
+ // GSM 05.02 3.1.2, but backwards
+
+ // If the frame wasn't stolen, we'll update this with parity later.
+ bool good = !stolen;
+
+ // Good or bad, we will be sending *something* to the speech channel.
+ // Allocate it in this scope.
+ unsigned char * newFrame = new unsigned char[33];
+
+ if (!stolen) {
+
+ // 3.1.2.2
+ // decode from c[] to u[]
+ mClass1_c.decode(mVCoder, mTCHU);
+ //mC.head(378).decode(mVCoder,mTCHU);
+
+ // 3.1.2.2
+ // copy class 2 bits c[] to d[]
+ mClass2_c.sliced().copyToSegment(mTCHD, 182);
+ //mC.segment(378,78).sliced().copyToSegment(mTCHD,182);
+
+ // 3.1.2.1
+ // copy class 1 bits u[] to d[]
+ for (unsigned k = 0; k <= 90; k++) {
+ mTCHD[2*k] = mTCHU[k];
+ mTCHD[2*k+1] = mTCHU[184-k];
+ }
+
+ // 3.1.2.1
+ // check parity of class 1A
+ unsigned sentParity = (~mTCHU.peekField(91, 3)) & 0x07;
+ //unsigned calcParity = mTCHD.head(50).parity(mTCHParity) & 0x07;
+ unsigned calcParity = mClass1A_d.parity(mTCHParity) & 0x07;
+
+ // 3.1.2.2
+ // Check the tail bits, too.
+ unsigned tail = mTCHU.peekField(185, 4);
+
+ OBJDCOUT("TCHFACCHL1Decoder::decodeTCH c[]=" << mC);
+ //OBJDCOUT("TCHFACCHL1Decoder::decodeTCH u[]=" << mTCHU);
+ OBJDCOUT("TCHFACCHL1Decoder::decodeTCH d[]=" << mTCHD);
+ OBJDCOUT("TCHFACCHL1Decoder::decodeTCH sentParity=" << sentParity
+ << " calcParity=" << calcParity << " tail=" << tail);
+ good = (sentParity == calcParity) && (tail == 0);
+ if (good) {
+ // Undo Um's importance-sorted bit ordering.
+ // See GSM 05.03 3.1 and Tablee 2.
+ BitVector payload = mVFrame.payload();
+ mTCHD.unmap(g610BitOrder, 260, payload);
+ mVFrame.pack(newFrame);
+ // Save a copy for bad frame processing.
+ memcpy(mPrevGoodFrame, newFrame, 33);
+ return true;
+ }
+ }
+
+ if (!good) {
+ // TODO -- Bad frame processing, GSM 06.11.
+ // For now, just repeat the last good frame.
+ // TODO -- Need to apply attenuation and randomization of grid positions.
+ memcpy(newFrame, mPrevGoodFrame, 33);
+ //d_gsm_file.write((char *)newFrame, 33);
+ }
+
+
+ // Good or bad, we must feed the speech channel.
+// mSpeechQ.write(newFrame);
+
+
+ return false;
+}
+
+// vim: ts=4 sw=4
diff --git a/gsm-receiver/src/lib/decoder/openbtsstuff/GSML1FEC.h b/gsm-receiver/src/lib/decoder/openbtsstuff/GSML1FEC.h
new file mode 100644
index 0000000..c367681
--- /dev/null
+++ b/gsm-receiver/src/lib/decoder/openbtsstuff/GSML1FEC.h
@@ -0,0 +1,146 @@
+/*
+* 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 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/>.
+*
+* This software is distributed under the terms of the GNU Public License.
+* See the COPYING file in the main directory for details.
+*/
+
+
+
+#ifndef GSML1FEC_H
+#define GSML1FEC_H
+
+//#include "Threads.h"
+#include "Assert.h"
+#include "BitVector.h"
+
+#include "GSMCommon.h"
+//#include "GSMTransfer.h"
+#include "GSMTDMA.h"
+#include "VocoderFrame.h"
+#include "RxBurst.h"
+//#include "GSM610Tables.h"
+#include <stdio.h>
+
+
+
+namespace GSM
+{
+
+
+//class SAPMux;
+ class L1FEC;
+ class L1Decoder;
+
+
+
+ /*
+ Naming convention for bit vectors follows GSM 05.03 Section 2.2.
+ d[k] data
+ u[k] data bits after first encoding step
+ c[k] data bits after second encoding step
+ i[B][k] interleaved data bits
+ e[B][k] bits in a burst
+ */
+
+
+
+
+ /** L1 decoder used for full rate TCH and FACCH -- mostly from GSM 05.03 3.1 and 4.2 */
+//: public XCCHL1Decoder
+ class TCHFACCHL1Decoder
+ {
+
+ protected:
+ SoftVector mI[8]; ///< deinterleaving history, 8 blocks instead of 4
+ SoftVector mC; ///< c[], as per GSM 05.03 2.2
+ BitVector mTCHU; ///< u[] (uncoded) in the spec
+ BitVector mTCHD; ///< d[] (data) in the spec
+ SoftVector mClass1_c; ///< the class 1 part of c[]
+ BitVector mClass1A_d; ///< the class 1A part of d[]
+ SoftVector mClass2_c; ///< the class 2 part of c[]
+ ViterbiR2O4 mVCoder;
+
+ VocoderFrame mVFrame; ///< unpacking buffer for vocoder frame
+ unsigned char mPrevGoodFrame[33]; ///< previous good frame.
+
+ Parity mTCHParity;
+ const TDMAMapping& mMapping; ///< multiplexing description
+
+// InterthreadQueue<unsigned char> mSpeechQ; ///< output queue for speech frames
+
+ static const unsigned mMaxQSize = 3;
+
+
+ public:
+
+ TCHFACCHL1Decoder( const TDMAMapping& wMapping );
+
+ ChannelType channelType() const {
+ return FACCHType;
+ }
+
+
+ /** TCH/FACCH has a special-case writeLowSide. */
+ void writeLowSide(const RxBurst& inBurst);
+
+ /**
+ Unlike other DCCHs, TCH/FACCH process burst calls
+ deinterleave, decode, handleGoodFrame.
+ */
+ bool processBurst( const RxBurst& );
+
+ /** Deinterleave i[] to c[]. */
+ void deinterleave(int blockOffset );
+
+ void replaceFACCH( int blockOffset );
+
+ /**
+ Decode a traffic frame from TCHI[] and enqueue it.
+ Return true if there's a good frame.
+ */
+ bool decodeTCH(bool stolen);
+
+ unsigned char * get_voice_frame(){
+ return mPrevGoodFrame;
+ }
+ /**
+ Receive a traffic frame.
+ Non-blocking. Returns NULL if queue is dry.
+ Caller is responsible for deleting the returned array.
+ */
+// unsigned char *recvTCH() { return mSpeechQ.read(0); }
+
+ /** Return count of internally-queued traffic frames. */
+// unsigned queueSize() const { return mSpeechQ.size(); }
+
+ };
+
+
+
+
+
+
+}; // namespace GSM
+
+
+
+
+
+#endif
+
+// vim: ts=4 sw=4
diff --git a/gsm-receiver/src/lib/decoder/openbtsstuff/GSMTDMA.cpp b/gsm-receiver/src/lib/decoder/openbtsstuff/GSMTDMA.cpp
new file mode 100644
index 0000000..27ebe0e
--- /dev/null
+++ b/gsm-receiver/src/lib/decoder/openbtsstuff/GSMTDMA.cpp
@@ -0,0 +1,337 @@
+/*
+* 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/>.
+
+*/
+
+
+#include "GSMTDMA.h"
+
+
+using namespace GSM;
+
+
+
+
+TDMAMapping::TDMAMapping(TypeAndOffset
+ wTypeAndOffset, bool wDownlink, bool wUplink, char wAllowedSlots, bool wC0Only,
+ unsigned wRepeatLength, unsigned wNumFrames, const unsigned *wFrameMapping)
+ :mTypeAndOffset(wTypeAndOffset),
+ mDownlink(wDownlink),mUplink(wUplink),mAllowedSlots(wAllowedSlots),mC0Only(wC0Only),
+ mRepeatLength(wRepeatLength),mNumFrames(wNumFrames),mFrameMapping(wFrameMapping)
+{
+ // Sanity check.
+ assert(mRepeatLength<=mMaxRepeatLength);
+
+ // Default, -1, means a non-occupied position.
+ for (unsigned i=0; i<mMaxRepeatLength; i++) mReverseMapping[i]=-1;
+
+ // Fill in the reverse map, precomputed for speed.
+ for (unsigned i=0; i<mNumFrames; i++) {
+ unsigned mapping = mFrameMapping[i];
+ assert(mapping<mRepeatLength);
+ mReverseMapping[mapping] = i;
+ }
+}
+
+
+
+
+
+/** A macro to save some typing when we set up TDMA maps. */
+#define MAKE_TDMA_MAPPING(NAME,TYPEANDOFFSET,DOWNLINK,UPLINK,ALLOWEDSLOTS,C0ONLY,REPEAT) \
+ const TDMAMapping GSM::g##NAME##Mapping(TYPEANDOFFSET,DOWNLINK,UPLINK,ALLOWEDSLOTS,C0ONLY, \
+ REPEAT,sizeof(NAME##Frames)/sizeof(unsigned),NAME##Frames)
+
+const unsigned LoopbackTestFullFrames[] = {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};
+MAKE_TDMA_MAPPING(LoopbackTestFull,TDMA_MISC,true,true,0xff,false,51);
+
+const unsigned FCCHFrames[] = {0,10,20,30,40};
+MAKE_TDMA_MAPPING(FCCH,TDMA_BEACON,true,false,0x01,true,51);
+
+const unsigned SCHFrames[] = {1,11,21,31,41};
+MAKE_TDMA_MAPPING(SCH,TDMA_BEACON,true,false,0x01,true,51);
+
+const unsigned BCCHFrames[] = {2,3,4,5};
+MAKE_TDMA_MAPPING(BCCH,TDMA_BEACON,true,false,0x55,true,51);
+
+// Note that we removed frames for the SDCCH components of the Combination-V C0T0.
+const unsigned RACHC5Frames[] = {4,5,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,45,46};
+MAKE_TDMA_MAPPING(RACHC5,TDMA_BEACON,false,true,0x55,true,51);
+
+// CCCH 0-2 are used in C-IV and C-V. The others are used in C-IV only.
+
+const unsigned CCCH_0Frames[] = {6,7,8,9};
+MAKE_TDMA_MAPPING(CCCH_0,TDMA_BEACON,true,false,0x55,true,51);
+
+const unsigned CCCH_1Frames[] = {12,13,14,15};
+MAKE_TDMA_MAPPING(CCCH_1,TDMA_BEACON,true,false,0x55,true,51);
+
+const unsigned CCCH_2Frames[] = {16,17,18,19};
+MAKE_TDMA_MAPPING(CCCH_2,TDMA_BEACON,true,false,0x55,true,51);
+
+const unsigned CCCH_3Frames[] = {22,23,24,25};
+MAKE_TDMA_MAPPING(CCCH_3,TDMA_BEACON,true,false,0x55,true,51);
+
+// TODO -- Other CCCH subchannels 4-8 for support of C-IV.
+
+const unsigned SDCCH_4_0DFrames[] = {22,23,24,25};
+MAKE_TDMA_MAPPING(SDCCH_4_0D,SDCCH_4_0,true,false,0x01,true,51);
+
+const unsigned SDCCH_4_0UFrames[] = {37,38,39,40};
+MAKE_TDMA_MAPPING(SDCCH_4_0U,SDCCH_4_0,false,true,0x01,true,51);
+
+const unsigned SDCCH_4_1DFrames[] = {26,27,28,29};
+MAKE_TDMA_MAPPING(SDCCH_4_1D,SDCCH_4_1,true,false,0x01,true,51);
+
+const unsigned SDCCH_4_1UFrames[] = {41,42,43,44};
+MAKE_TDMA_MAPPING(SDCCH_4_1U,SDCCH_4_1,false,true,0x01,true,51);
+
+const unsigned SDCCH_4_2DFrames[] = {32,33,34,35};
+MAKE_TDMA_MAPPING(SDCCH_4_2D,SDCCH_4_2,true,false,0x01,true,51);
+
+const unsigned SDCCH_4_2UFrames[] = {47,48,49,50};
+MAKE_TDMA_MAPPING(SDCCH_4_2U,SDCCH_4_2,false,true,0x01,true,51);
+
+const unsigned SDCCH_4_3DFrames[] = {36,37,38,39};
+MAKE_TDMA_MAPPING(SDCCH_4_3D,SDCCH_4_3,true,false,0x01,true,51);
+
+const unsigned SDCCH_4_3UFrames[] = {0,1,2,3};
+MAKE_TDMA_MAPPING(SDCCH_4_3U,SDCCH_4_3,false,true,0x01,true,51);
+
+
+const unsigned SACCH_C4_0DFrames[] = {42,43,44,45};
+MAKE_TDMA_MAPPING(SACCH_C4_0D,SDCCH_4_0,true,false,0x01,true,102);
+
+const unsigned SACCH_C4_0UFrames[] = {57,58,59,60};
+MAKE_TDMA_MAPPING(SACCH_C4_0U,SDCCH_4_0,false,true,0x01,true,102);
+
+const unsigned SACCH_C4_1DFrames[] = {46,47,48,49};
+MAKE_TDMA_MAPPING(SACCH_C4_1D,SDCCH_4_1,true,false,0x01,true,102);
+
+const unsigned SACCH_C4_1UFrames[] = {61,62,63,64};
+MAKE_TDMA_MAPPING(SACCH_C4_1U,SDCCH_4_1,false,true,0x01,true,102);
+
+const unsigned SACCH_C4_2DFrames[] = {93,94,95,96};
+MAKE_TDMA_MAPPING(SACCH_C4_2D,SDCCH_4_2,true,false,0x01,true,102);
+
+const unsigned SACCH_C4_2UFrames[] = {6,7,8,9};
+MAKE_TDMA_MAPPING(SACCH_C4_2U,SDCCH_4_2,false,true,0x01,true,102);
+
+const unsigned SACCH_C4_3DFrames[] = {97,98,99,100};
+MAKE_TDMA_MAPPING(SACCH_C4_3D,SDCCH_4_3,true,false,0x01,true,102);
+
+const unsigned SACCH_C4_3UFrames[] = {10,11,12,13};
+MAKE_TDMA_MAPPING(SACCH_C4_3U,SDCCH_4_3,false,true,0x01,true,102);
+
+
+const unsigned SDCCH_8_0DFrames[] = {0,1,2,3};
+MAKE_TDMA_MAPPING(SDCCH_8_0D,SDCCH_8_0,true,false,0xFF,true,51);
+
+const unsigned SDCCH_8_0UFrames[] = {15,16,17,18};
+MAKE_TDMA_MAPPING(SDCCH_8_0U,SDCCH_8_0,false,true,0xFF,true,51);
+
+const unsigned SDCCH_8_1DFrames[] = {4,5,6,7};
+MAKE_TDMA_MAPPING(SDCCH_8_1D,SDCCH_8_1,true,false,0xFF,true,51);
+
+const unsigned SDCCH_8_1UFrames[] = {19,20,21,22};
+MAKE_TDMA_MAPPING(SDCCH_8_1U,SDCCH_8_1,false,true,0xFF,true,51);
+
+const unsigned SDCCH_8_2DFrames[] = {8,9,10,11};
+MAKE_TDMA_MAPPING(SDCCH_8_2D,SDCCH_8_2,true,false,0xFF,true,51);
+
+const unsigned SDCCH_8_2UFrames[] = {23,24,25,26};
+MAKE_TDMA_MAPPING(SDCCH_8_2U,SDCCH_8_2,false,true,0xFF,true,51);
+
+const unsigned SDCCH_8_3DFrames[] = {12,13,14,15};
+MAKE_TDMA_MAPPING(SDCCH_8_3D,SDCCH_8_3,true,false,0xFF,true,51);
+
+const unsigned SDCCH_8_3UFrames[] = {27,28,29,30};
+MAKE_TDMA_MAPPING(SDCCH_8_3U,SDCCH_8_3,false,true,0xFF,true,51);
+
+const unsigned SDCCH_8_4DFrames[] = {16,17,18,19};
+MAKE_TDMA_MAPPING(SDCCH_8_4D,SDCCH_8_4,true,false,0xFF,true,51);
+
+const unsigned SDCCH_8_4UFrames[] = {31,32,33,34};
+MAKE_TDMA_MAPPING(SDCCH_8_4U,SDCCH_8_4,false,true,0xFF,true,51);
+
+const unsigned SDCCH_8_5DFrames[] = {20,21,22,23};
+MAKE_TDMA_MAPPING(SDCCH_8_5D,SDCCH_8_5,true,false,0xFF,true,51);
+
+const unsigned SDCCH_8_5UFrames[] = {35,36,37,38};
+MAKE_TDMA_MAPPING(SDCCH_8_5U,SDCCH_8_5,false,true,0xFF,true,51);
+
+const unsigned SDCCH_8_6DFrames[] = {24,25,26,27};
+MAKE_TDMA_MAPPING(SDCCH_8_6D,SDCCH_8_6,true,false,0xFF,true,51);
+
+const unsigned SDCCH_8_6UFrames[] = {39,40,41,42};
+MAKE_TDMA_MAPPING(SDCCH_8_6U,SDCCH_8_6,false,true,0xFF,true,51);
+
+const unsigned SDCCH_8_7DFrames[] = {28,29,30,31};
+MAKE_TDMA_MAPPING(SDCCH_8_7D,SDCCH_8_7,true,false,0xFF,true,51);
+
+const unsigned SDCCH_8_7UFrames[] = {43,44,45,46};
+MAKE_TDMA_MAPPING(SDCCH_8_7U,SDCCH_8_7,false,true,0xFF,true,51);
+
+
+const unsigned SACCH_C8_0DFrames[] = {32,33,34,35};
+MAKE_TDMA_MAPPING(SACCH_C8_0D,SDCCH_8_0,true,false,0xFF,true,102);
+
+const unsigned SACCH_C8_0UFrames[] = {47,48,49,50};
+MAKE_TDMA_MAPPING(SACCH_C8_0U,SDCCH_8_0,false,true,0xFF,true,102);
+
+const unsigned SACCH_C8_1DFrames[] = {36,37,38,39};
+MAKE_TDMA_MAPPING(SACCH_C8_1D,SDCCH_8_1,true,false,0xFF,true,102);
+
+const unsigned SACCH_C8_1UFrames[] = {51,52,53,54};
+MAKE_TDMA_MAPPING(SACCH_C8_1U,SDCCH_8_1,false,true,0xFF,true,102);
+
+const unsigned SACCH_C8_2DFrames[] = {40,41,42,43};
+MAKE_TDMA_MAPPING(SACCH_C8_2D,SDCCH_8_2,true,false,0xFF,true,102);
+
+const unsigned SACCH_C8_2UFrames[] = {55,56,57,58};
+MAKE_TDMA_MAPPING(SACCH_C8_2U,SDCCH_8_2,false,true,0xFF,true,102);
+
+const unsigned SACCH_C8_3DFrames[] = {44,45,46,47};
+MAKE_TDMA_MAPPING(SACCH_C8_3D,SDCCH_8_3,true,false,0xFF,true,102);
+
+const unsigned SACCH_C8_3UFrames[] = {59,60,61,62};
+MAKE_TDMA_MAPPING(SACCH_C8_3U,SDCCH_8_3,false,true,0xFF,true,102);
+
+const unsigned SACCH_C8_4DFrames[] = {82,84,85,86};
+MAKE_TDMA_MAPPING(SACCH_C8_4D,SDCCH_8_4,true,false,0xFF,true,102);
+
+const unsigned SACCH_C8_4UFrames[] = {98,99,100,101};
+MAKE_TDMA_MAPPING(SACCH_C8_4U,SDCCH_8_4,false,true,0xFF,true,102);
+
+const unsigned SACCH_C8_5DFrames[] = {87,88,89,90};
+MAKE_TDMA_MAPPING(SACCH_C8_5D,SDCCH_8_5,true,false,0xFF,true,102);
+
+const unsigned SACCH_C8_5UFrames[] = {0,1,2,3};
+MAKE_TDMA_MAPPING(SACCH_C8_5U,SDCCH_8_5,false,true,0xFF,true,102);
+
+const unsigned SACCH_C8_6DFrames[] = {91,92,93,94};
+MAKE_TDMA_MAPPING(SACCH_C8_6D,SDCCH_8_6,true,false,0xFF,true,102);
+
+const unsigned SACCH_C8_6UFrames[] = {4,5,6,7};
+MAKE_TDMA_MAPPING(SACCH_C8_6U,SDCCH_8_6,false,true,0xFF,true,102);
+
+const unsigned SACCH_C8_7DFrames[] = {95,96,97,98};
+MAKE_TDMA_MAPPING(SACCH_C8_7D,SDCCH_8_7,true,false,0xFF,true,102);
+
+const unsigned SACCH_C8_7UFrames[] = {8,9,10,11};
+MAKE_TDMA_MAPPING(SACCH_C8_7U,SDCCH_8_7,false,true,0xFF,true,102);
+
+
+
+const unsigned SACCH_TF_T0Frames[] = {12,38,64,90};
+MAKE_TDMA_MAPPING(SACCH_TF_T0,TCHF_0,true,true,0x01,true,104);
+
+const unsigned SACCH_TF_T1Frames[] = {25,51,77,103};
+MAKE_TDMA_MAPPING(SACCH_TF_T1,TCHF_0,true,true,0x02,true,104);
+
+const unsigned SACCH_TF_T2Frames[] = {38,64,90,12};
+MAKE_TDMA_MAPPING(SACCH_TF_T2,TCHF_0,true,true,0x04,true,104);
+
+const unsigned SACCH_TF_T3Frames[] = {51,77,103,25};
+MAKE_TDMA_MAPPING(SACCH_TF_T3,TCHF_0,true,true,0x08,true,104);
+
+const unsigned SACCH_TF_T4Frames[] = {64,90,12,38};
+MAKE_TDMA_MAPPING(SACCH_TF_T4,TCHF_0,true,true,0x10,true,104);
+
+const unsigned SACCH_TF_T5Frames[] = {77,103,25,51};
+MAKE_TDMA_MAPPING(SACCH_TF_T5,TCHF_0,true,true,0x20,true,104);
+
+const unsigned SACCH_TF_T6Frames[] = {90,12,38,64};
+MAKE_TDMA_MAPPING(SACCH_TF_T6,TCHF_0,true,true,0x40,true,104);
+
+const unsigned SACCH_TF_T7Frames[] = {103,25,51,77};
+MAKE_TDMA_MAPPING(SACCH_TF_T7,TCHF_0,true,true,0x80,true,104);
+
+const unsigned FACCH_TCHFFrames[] = {0,1,2,3,4,5,6,7,8,9,10,11,13,14,15,16,17,18,19,20,21,22,23,24};
+MAKE_TDMA_MAPPING(FACCH_TCHF,TCHF_0,true,true,0xff,true,26);
+
+
+
+
+
+
+
+const MappingPair GSM::gSDCCH_4_0Pair(gSDCCH_4_0DMapping,gSDCCH_4_0UMapping);
+const MappingPair GSM::gSDCCH_4_1Pair(gSDCCH_4_1DMapping,gSDCCH_4_1UMapping);
+const MappingPair GSM::gSDCCH_4_2Pair(gSDCCH_4_2DMapping,gSDCCH_4_2UMapping);
+const MappingPair GSM::gSDCCH_4_3Pair(gSDCCH_4_3DMapping,gSDCCH_4_3UMapping);
+const MappingPair GSM::gSDCCH_8_0Pair(gSDCCH_8_0DMapping,gSDCCH_8_0UMapping);
+const MappingPair GSM::gSDCCH_8_1Pair(gSDCCH_8_1DMapping,gSDCCH_8_1UMapping);
+const MappingPair GSM::gSDCCH_8_2Pair(gSDCCH_8_2DMapping,gSDCCH_8_2UMapping);
+const MappingPair GSM::gSDCCH_8_3Pair(gSDCCH_8_3DMapping,gSDCCH_8_3UMapping);
+const MappingPair GSM::gSDCCH_8_4Pair(gSDCCH_8_4DMapping,gSDCCH_8_4UMapping);
+const MappingPair GSM::gSDCCH_8_5Pair(gSDCCH_8_5DMapping,gSDCCH_8_5UMapping);
+const MappingPair GSM::gSDCCH_8_6Pair(gSDCCH_8_6DMapping,gSDCCH_8_6UMapping);
+const MappingPair GSM::gSDCCH_8_7Pair(gSDCCH_8_7DMapping,gSDCCH_8_7UMapping);
+
+const MappingPair GSM::gSACCH_C4_0Pair(gSACCH_C4_0DMapping,gSACCH_C4_0UMapping);
+const MappingPair GSM::gSACCH_C4_1Pair(gSACCH_C4_1DMapping,gSACCH_C4_1UMapping);
+const MappingPair GSM::gSACCH_C4_2Pair(gSACCH_C4_2DMapping,gSACCH_C4_2UMapping);
+const MappingPair GSM::gSACCH_C4_3Pair(gSACCH_C4_3DMapping,gSACCH_C4_3UMapping);
+const MappingPair GSM::gSACCH_C8_0Pair(gSACCH_C8_0DMapping,gSACCH_C8_0UMapping);
+const MappingPair GSM::gSACCH_C8_1Pair(gSACCH_C8_1DMapping,gSACCH_C8_1UMapping);
+const MappingPair GSM::gSACCH_C8_2Pair(gSACCH_C8_2DMapping,gSACCH_C8_2UMapping);
+const MappingPair GSM::gSACCH_C8_3Pair(gSACCH_C8_3DMapping,gSACCH_C8_3UMapping);
+const MappingPair GSM::gSACCH_C8_4Pair(gSACCH_C8_4DMapping,gSACCH_C8_4UMapping);
+const MappingPair GSM::gSACCH_C8_5Pair(gSACCH_C8_5DMapping,gSACCH_C8_5UMapping);
+const MappingPair GSM::gSACCH_C8_6Pair(gSACCH_C8_6DMapping,gSACCH_C8_6UMapping);
+const MappingPair GSM::gSACCH_C8_7Pair(gSACCH_C8_7DMapping,gSACCH_C8_7UMapping);
+
+const MappingPair GSM::gFACCH_TCHFPair(gFACCH_TCHFMapping,gFACCH_TCHFMapping);
+
+const MappingPair GSM::gSACCH_FT_T0Pair(gSACCH_TF_T0Mapping, gSACCH_TF_T0Mapping);
+const MappingPair GSM::gSACCH_FT_T1Pair(gSACCH_TF_T1Mapping, gSACCH_TF_T1Mapping);
+const MappingPair GSM::gSACCH_FT_T2Pair(gSACCH_TF_T2Mapping, gSACCH_TF_T2Mapping);
+const MappingPair GSM::gSACCH_FT_T3Pair(gSACCH_TF_T3Mapping, gSACCH_TF_T3Mapping);
+const MappingPair GSM::gSACCH_FT_T4Pair(gSACCH_TF_T4Mapping, gSACCH_TF_T4Mapping);
+const MappingPair GSM::gSACCH_FT_T5Pair(gSACCH_TF_T5Mapping, gSACCH_TF_T5Mapping);
+const MappingPair GSM::gSACCH_FT_T6Pair(gSACCH_TF_T6Mapping, gSACCH_TF_T6Mapping);
+const MappingPair GSM::gSACCH_FT_T7Pair(gSACCH_TF_T7Mapping, gSACCH_TF_T7Mapping);
+
+
+
+const CompleteMapping GSM::gSDCCH_4_0(gSDCCH_4_0Pair,gSACCH_C4_0Pair);
+const CompleteMapping GSM::gSDCCH_4_1(gSDCCH_4_1Pair,gSACCH_C4_1Pair);
+const CompleteMapping GSM::gSDCCH_4_2(gSDCCH_4_2Pair,gSACCH_C4_2Pair);
+const CompleteMapping GSM::gSDCCH_4_3(gSDCCH_4_3Pair,gSACCH_C4_3Pair);
+const CompleteMapping GSM::gSDCCH_8_0(gSDCCH_8_0Pair,gSACCH_C8_0Pair);
+const CompleteMapping GSM::gSDCCH_8_1(gSDCCH_8_1Pair,gSACCH_C8_1Pair);
+const CompleteMapping GSM::gSDCCH_8_2(gSDCCH_8_2Pair,gSACCH_C8_2Pair);
+const CompleteMapping GSM::gSDCCH_8_3(gSDCCH_8_3Pair,gSACCH_C8_3Pair);
+const CompleteMapping GSM::gSDCCH_8_4(gSDCCH_8_4Pair,gSACCH_C8_4Pair);
+const CompleteMapping GSM::gSDCCH_8_5(gSDCCH_8_5Pair,gSACCH_C8_5Pair);
+const CompleteMapping GSM::gSDCCH_8_6(gSDCCH_8_6Pair,gSACCH_C8_6Pair);
+const CompleteMapping GSM::gSDCCH_8_7(gSDCCH_8_7Pair,gSACCH_C8_7Pair);
+
+const CompleteMapping GSM::gTCHF_T0(gFACCH_TCHFPair,gSACCH_FT_T0Pair);
+const CompleteMapping GSM::gTCHF_T1(gFACCH_TCHFPair,gSACCH_FT_T1Pair);
+const CompleteMapping GSM::gTCHF_T2(gFACCH_TCHFPair,gSACCH_FT_T2Pair);
+const CompleteMapping GSM::gTCHF_T3(gFACCH_TCHFPair,gSACCH_FT_T3Pair);
+const CompleteMapping GSM::gTCHF_T4(gFACCH_TCHFPair,gSACCH_FT_T4Pair);
+const CompleteMapping GSM::gTCHF_T5(gFACCH_TCHFPair,gSACCH_FT_T5Pair);
+const CompleteMapping GSM::gTCHF_T6(gFACCH_TCHFPair,gSACCH_FT_T6Pair);
+const CompleteMapping GSM::gTCHF_T7(gFACCH_TCHFPair,gSACCH_FT_T7Pair);
+
+
+
diff --git a/gsm-receiver/src/lib/decoder/openbtsstuff/GSMTDMA.h b/gsm-receiver/src/lib/decoder/openbtsstuff/GSMTDMA.h
new file mode 100644
index 0000000..3b55b94
--- /dev/null
+++ b/gsm-receiver/src/lib/decoder/openbtsstuff/GSMTDMA.h
@@ -0,0 +1,358 @@
+/**@file Common-use GSM declarations, most from the GSM 04.xx and 05.xx series. */
+/*
+* 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 GSMTDMA_H
+#define GSMTDMA_H
+
+
+#include "GSMCommon.h"
+
+
+namespace GSM {
+
+
+/**
+ A description of a channel's multiplexing pattern.
+ From GSM 05.02 Clause 7.
+ This object encodes a line from tables 1-4 in the spec.
+ The columns of interest in this encoding are:
+ - 1, Channel Designation
+ - 2, Subchannel
+ - 3, Direction
+ - 4, Allowable Time Slot Assignments
+ - 5, Allowable RF Channel Assignments
+ - 7, Repeat Length in TDMA Frames
+ - 8, Interleaved Block TDMA Frame Mapping
+
+ Col 6, Burst Type, is implied by 1 & 2 and encoded into the transcevier source code.
+*/
+class TDMAMapping {
+
+ public:
+
+ /// The longest "repeat length" of any channel we support is 104 for the SACCH/TF.
+ static const unsigned mMaxRepeatLength = 104;
+
+ private:
+
+ TypeAndOffset mTypeAndOffset; ///< col 1, 2, encoded as per GSM 04.08 10.5.2.5
+ bool mDownlink; ///< col 3, true for downlink channels
+ bool mUplink; ///< col 3, true for uplink channels
+ char mAllowedSlots; ///< col 4, an 8-bit mask
+ bool mC0Only; ///< col 5, true if channel is limited to C0
+ unsigned mRepeatLength; ///< col 7
+ unsigned mNumFrames; ///< number of occupied frames in col 8
+ const unsigned *mFrameMapping; ///< col 8
+ unsigned mReverseMapping[mMaxRepeatLength]; ///< index reversal of mapping, -1 means unused
+
+
+ public:
+
+
+ /**
+ Construct a TDMAMapping, encoding one line of GSM 05.02 Clause 7 Tables 1-4.
+ @param wTypeAndOffset Encoding of "Channel designnation". See GSM 04.08 10.5.2.5.
+ @param wDownlink True for downlink and bidirectional hannels
+ @param wUplink True for uplink and bidirectional channels
+ @param wRepeatLength "Repeat Length in TDMA Frames"
+ @param wNumFrames Number of occupied TDMA frames in frame mapping.
+ @param wFrameMapping "Interleaved Block TDMA Frame Mapping" -- MUST PERSIST!!
+ */
+ TDMAMapping(TypeAndOffset wTypeAndOffset,
+ bool wDownlink, bool wUplink, char wAllowedSlots, bool wC0Only,
+ unsigned wRepeatLength, unsigned wNumFrames, const unsigned *wFrameMapping);
+
+ /** Given a count of frames sent, return the corresponding frame number. */
+ unsigned frameMapping(unsigned count) const
+ { return mFrameMapping[count % mNumFrames]; }
+
+ /** Given a frame number, return the corresponding count, modulo patten length. */
+ int reverseMapping(unsigned FN) const
+ { return mReverseMapping[FN % mRepeatLength]; }
+
+ /**@name Simple accessors. */
+ //@{
+ unsigned numFrames() const { return mNumFrames; }
+
+ unsigned repeatLength() const { return mRepeatLength; }
+
+ TypeAndOffset typeAndOffset() const { return mTypeAndOffset; }
+
+ bool uplink() const { return mUplink; }
+
+ bool downlink() const { return mDownlink; }
+
+ bool C0Only() const { return mC0Only; }
+ //@}
+
+ ///< Return true if this channel is allowed on this slot.
+ bool allowedSlot(unsigned slot) const
+ { return mAllowedSlots & (1<<slot); }
+};
+
+
+
+/**@name Mux parameters for standard channels, from GSM 05.03 Clause 7 Tables 1-4. */
+//@{
+/**@name Beacon channels */
+//@{
+extern const TDMAMapping gFCCHMapping; ///< GSM 05.02 Clause 7 Table 3 Line 1 B0-B4
+extern const TDMAMapping gSCHMapping; ///< GSM 05.02 Clause 7 Table 3 Line 2 B0-B4
+extern const TDMAMapping gBCCHMapping; ///< GSM 05.02 Clause 7 Table 3 Line 3
+/// GSM 05.02 Clause 7 Table 3 Line 7 B0-B50, excluding C-V SDCCH parts (SDCCH/4 and SCCH/C4)
+extern const TDMAMapping gRACHC5Mapping;
+extern const TDMAMapping gCCCH_0Mapping; ///< GSM 05.02 Clause 7 Table 3 Line 5 B0
+extern const TDMAMapping gCCCH_1Mapping; ///< GSM 05.02 Clause 7 Table 3 Line 5 B1
+extern const TDMAMapping gCCCH_2Mapping; ///< GSM 05.02 Clause 7 Table 3 Line 5 B2
+extern const TDMAMapping gCCCH_3Mapping; ///< GSM 05.02 Clause 7 Table 3 Line 5 B3
+extern const TDMAMapping gCCCH_4Mapping; ///< GSM 05.02 Clause 7 Table 3 Line 5 B4
+extern const TDMAMapping gCCCH_5Mapping; ///< GSM 05.02 Clause 7 Table 3 Line 5 B5
+extern const TDMAMapping gCCCH_6Mapping; ///< GSM 05.02 Clause 7 Table 3 Line 5 B6
+extern const TDMAMapping gCCCH_7Mapping; ///< GSM 05.02 Clause 7 Table 3 Line 5 B7
+extern const TDMAMapping gCCCH_8Mapping; ///< GSM 05.02 Clause 7 Table 3 Line 5 B8
+//@}
+/**@name SDCCH */
+//@{
+///@name For Combination V
+//@{
+extern const TDMAMapping gSDCCH_4_0DMapping; ///< GSM 05.02 Clause 7 Table 3 Line 10/0D
+extern const TDMAMapping gSDCCH_4_0UMapping; ///< GSM 05.02 Clause 7 Table 3 Line 10/0U
+extern const TDMAMapping gSDCCH_4_1DMapping;
+extern const TDMAMapping gSDCCH_4_1UMapping;
+extern const TDMAMapping gSDCCH_4_2DMapping;
+extern const TDMAMapping gSDCCH_4_2UMapping;
+extern const TDMAMapping gSDCCH_4_3DMapping;
+extern const TDMAMapping gSDCCH_4_3UMapping;
+//@}
+///@name For Combination VII
+//@{
+extern const TDMAMapping gSDCCH_8_0DMapping;
+extern const TDMAMapping gSDCCH_8_0UMapping;
+extern const TDMAMapping gSDCCH_8_1DMapping;
+extern const TDMAMapping gSDCCH_8_1UMapping;
+extern const TDMAMapping gSDCCH_8_2DMapping;
+extern const TDMAMapping gSDCCH_8_2UMapping;
+extern const TDMAMapping gSDCCH_8_3DMapping;
+extern const TDMAMapping gSDCCH_8_3UMapping;
+extern const TDMAMapping gSDCCH_8_4DMapping;
+extern const TDMAMapping gSDCCH_8_4UMapping;
+extern const TDMAMapping gSDCCH_8_5DMapping;
+extern const TDMAMapping gSDCCH_8_5UMapping;
+extern const TDMAMapping gSDCCH_8_6DMapping;
+extern const TDMAMapping gSDCCH_8_6UMapping;
+extern const TDMAMapping gSDCCH_8_7DMapping;
+extern const TDMAMapping gSDCCH_8_7UMapping;
+//@}
+//@}
+/**@name SACCH */
+//@{
+/**name SACCH for SDCCH */
+//@{
+///@name For Combination V
+//@{
+extern const TDMAMapping gSACCH_C4_0DMapping;
+extern const TDMAMapping gSACCH_C4_0UMapping;
+extern const TDMAMapping gSACCH_C4_1DMapping;
+extern const TDMAMapping gSACCH_C4_1UMapping;
+extern const TDMAMapping gSACCH_C4_2DMapping;
+extern const TDMAMapping gSACCH_C4_2UMapping;
+extern const TDMAMapping gSACCH_C4_3DMapping;
+extern const TDMAMapping gSACCH_C4_3UMapping;
+//@}
+///@name For Combination VII
+//@{
+extern const TDMAMapping gSACCH_C8_0DMapping;
+extern const TDMAMapping gSACCH_C8_0UMapping;
+extern const TDMAMapping gSACCH_C8_1DMapping;
+extern const TDMAMapping gSACCH_C8_1UMapping;
+extern const TDMAMapping gSACCH_C8_2DMapping;
+extern const TDMAMapping gSACCH_C8_2UMapping;
+extern const TDMAMapping gSACCH_C8_3DMapping;
+extern const TDMAMapping gSACCH_C8_3UMapping;
+extern const TDMAMapping gSACCH_C8_4DMapping;
+extern const TDMAMapping gSACCH_C8_4UMapping;
+extern const TDMAMapping gSACCH_C8_5DMapping;
+extern const TDMAMapping gSACCH_C8_5UMapping;
+extern const TDMAMapping gSACCH_C8_6DMapping;
+extern const TDMAMapping gSACCH_C8_6UMapping;
+extern const TDMAMapping gSACCH_C8_7DMapping;
+extern const TDMAMapping gSACCH_C8_7UMapping;
+//@}
+//@}
+/**@name SACCH for TCH/F on different timeslots. */
+//@{
+extern const TDMAMapping gSACCH_TF_T0Mapping;
+extern const TDMAMapping gSACCH_TF_T1Mapping;
+extern const TDMAMapping gSACCH_TF_T2Mapping;
+extern const TDMAMapping gSACCH_TF_T3Mapping;
+extern const TDMAMapping gSACCH_TF_T4Mapping;
+extern const TDMAMapping gSACCH_TF_T5Mapping;
+extern const TDMAMapping gSACCH_TF_T6Mapping;
+extern const TDMAMapping gSACCH_TF_T7Mapping;
+//@}
+//@}
+/**name FACCH+TCH/F placement */
+//@{
+extern const TDMAMapping gFACCH_TCHFMapping;
+//@}
+/**@name Test fixtures. */
+extern const TDMAMapping gLoopbackTestFullMapping;
+extern const TDMAMapping gLoopbackTestHalfUMapping;
+extern const TDMAMapping gLoopbackTestHalfDMapping;
+//@}
+
+
+/** Combined uplink/downlink information. */
+class MappingPair {
+
+ private:
+
+ const TDMAMapping& mDownlink;
+ const TDMAMapping& mUplink;
+
+ public:
+
+ MappingPair(const TDMAMapping& wDownlink, const TDMAMapping& wUplink)
+ :mDownlink(wDownlink), mUplink(wUplink)
+ {}
+
+ MappingPair(const TDMAMapping& wMapping)
+ :mDownlink(wMapping), mUplink(wMapping)
+ {}
+
+ const TDMAMapping& downlink() const { return mDownlink; }
+ const TDMAMapping& uplink() const { return mUplink; }
+
+};
+
+
+/**@name Common placement pairs. */
+//@{
+/**@ SDCCH placement pairs. */
+//@{
+extern const MappingPair gSDCCH_4_0Pair;
+extern const MappingPair gSDCCH_4_1Pair;
+extern const MappingPair gSDCCH_4_2Pair;
+extern const MappingPair gSDCCH_4_3Pair;
+extern const MappingPair gSDCCH_8_0Pair;
+extern const MappingPair gSDCCH_8_1Pair;
+extern const MappingPair gSDCCH_8_2Pair;
+extern const MappingPair gSDCCH_8_3Pair;
+extern const MappingPair gSDCCH_8_4Pair;
+extern const MappingPair gSDCCH_8_5Pair;
+extern const MappingPair gSDCCH_8_6Pair;
+extern const MappingPair gSDCCH_8_7Pair;
+//@}
+/**@ SACCH-for-SDCCH placement pairs. */
+//@{
+extern const MappingPair gSACCH_C4_0Pair;
+extern const MappingPair gSACCH_C4_1Pair;
+extern const MappingPair gSACCH_C4_2Pair;
+extern const MappingPair gSACCH_C4_3Pair;
+extern const MappingPair gSACCH_C8_0Pair;
+extern const MappingPair gSACCH_C8_1Pair;
+extern const MappingPair gSACCH_C8_2Pair;
+extern const MappingPair gSACCH_C8_3Pair;
+extern const MappingPair gSACCH_C8_4Pair;
+extern const MappingPair gSACCH_C8_5Pair;
+extern const MappingPair gSACCH_C8_6Pair;
+extern const MappingPair gSACCH_C8_7Pair;
+//@}
+/**@name Traffic channels. */
+//@{
+extern const MappingPair gFACCH_TCHFPair;
+extern const MappingPair gSACCH_FT_T0Pair;
+extern const MappingPair gSACCH_FT_T1Pair;
+extern const MappingPair gSACCH_FT_T2Pair;
+extern const MappingPair gSACCH_FT_T3Pair;
+extern const MappingPair gSACCH_FT_T4Pair;
+extern const MappingPair gSACCH_FT_T5Pair;
+extern const MappingPair gSACCH_FT_T6Pair;
+extern const MappingPair gSACCH_FT_T7Pair;
+//@}
+//@}
+
+
+
+/** A CompleteMapping includes uplink, downlink and the SACCH. */
+class CompleteMapping {
+
+ private:
+
+ const MappingPair& mLCH;
+ const MappingPair& mSACCH;
+
+ public:
+
+ CompleteMapping(const MappingPair& wLCH, const MappingPair& wSACCH)
+ :mLCH(wLCH), mSACCH(wSACCH)
+ {}
+
+ const MappingPair& LCH() const { return mLCH; }
+ const MappingPair& SACCH() const { return mSACCH; }
+
+};
+
+
+
+/**@name Complete placements for common channel types. */
+//@{
+/**@name SDCCH/4 */
+//@{
+extern const CompleteMapping gSDCCH_4_0;
+extern const CompleteMapping gSDCCH_4_1;
+extern const CompleteMapping gSDCCH_4_2;
+extern const CompleteMapping gSDCCH_4_3;
+//@}
+/**@name SDCCH/8 */
+//@{
+extern const CompleteMapping gSDCCH_8_0;
+extern const CompleteMapping gSDCCH_8_1;
+extern const CompleteMapping gSDCCH_8_2;
+extern const CompleteMapping gSDCCH_8_3;
+extern const CompleteMapping gSDCCH_8_4;
+extern const CompleteMapping gSDCCH_8_5;
+extern const CompleteMapping gSDCCH_8_6;
+extern const CompleteMapping gSDCCH_8_7;
+//@}
+/**@name TCH/F on different slots. */
+//@{
+extern const CompleteMapping gTCHF_T0;
+extern const CompleteMapping gTCHF_T1;
+extern const CompleteMapping gTCHF_T2;
+extern const CompleteMapping gTCHF_T3;
+extern const CompleteMapping gTCHF_T4;
+extern const CompleteMapping gTCHF_T5;
+extern const CompleteMapping gTCHF_T6;
+extern const CompleteMapping gTCHF_T7;
+//@}
+//@}
+
+
+}; // namespace GSM
+
+
+#endif
+
+// vim: ts=4 sw=4
diff --git a/gsm-receiver/src/lib/decoder/openbtsstuff/Makefile.am b/gsm-receiver/src/lib/decoder/openbtsstuff/Makefile.am
new file mode 100644
index 0000000..5a14202
--- /dev/null
+++ b/gsm-receiver/src/lib/decoder/openbtsstuff/Makefile.am
@@ -0,0 +1,49 @@
+#
+# Copyright 2001,2002,2004,2005,2006,2007,2008 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+include $(top_srcdir)/Makefile.common
+
+AM_CPPFLAGS = $(STD_DEFINES_AND_INCLUDES)
+
+noinst_LTLIBRARIES = libopenbtsdecoder.la
+
+libopenbtsdecoder_la_SOURCES = \
+BitVector.cpp \
+GSM610Tables.cpp \
+GSMCommon.cpp \
+GSML1FEC.cpp \
+GSMTDMA.cpp \
+Threads.cpp \
+Timeval.cpp
+
+
+noinst_HEADERS = \
+Assert.h \
+BitVector.h \
+GSM610Tables.h \
+GSMCommon.h \
+GSML1FEC.h \
+GSMTDMA.h \
+RxBurst.h \
+Threads.h \
+Timeval.h \
+Vector.h \
+VocoderFrame.h
diff --git a/gsm-receiver/src/lib/decoder/openbtsstuff/RxBurst.h b/gsm-receiver/src/lib/decoder/openbtsstuff/RxBurst.h
new file mode 100644
index 0000000..4348fb8
--- /dev/null
+++ b/gsm-receiver/src/lib/decoder/openbtsstuff/RxBurst.h
@@ -0,0 +1,69 @@
+#ifndef _RXBURST_H
+#define _RXBURST_H
+
+#include "GSMCommon.h"
+#include "BitVector.h"
+
+namespace GSM {
+
+/**@name Positions of stealing bits within a normal burst, GSM 05.03 3.1.4. */
+//@{
+static const unsigned gHlIndex = 60; ///< index of first stealing bit, GSM 05.03 3.1.4
+static const unsigned gHuIndex = 87; ///< index of second stealing bit, GSM 05.03 3.1.4
+//@}
+
+static const unsigned gSlotLen = 148; ///< number of symbols per slot, not counting guard periods
+
+
+/**
+ Class to represent one timeslot of channel bits with soft encoding.
+*/
+class RxBurst : public SoftVector {
+
+ private:
+
+ Time mTime; ///< timeslot and frame on which this was received
+// float mTimingError; ///< Timing error in symbol steps, <0 means early.
+// float mRSSI; ///< RSSI estimate associated with the slot, dB wrt full scale.
+
+ public:
+
+ /** Wrap an RxBurst around an existing float array. */
+ RxBurst(float* wData, const Time &wTime)
+ :SoftVector(wData,gSlotLen),mTime(wTime)
+// mTimingError(wTimingError),mRSSI(wRSSI)
+ { }
+
+
+ Time time() const { return mTime; }
+
+ void time(const Time& wTime) { mTime = wTime; }
+
+// float RSSI() const { return mRSSI; }
+
+// float timingError() const { return mTimingError; }
+
+ /** Return a SoftVector alias to the first data field. */
+ const SoftVector data1() const { return segment(3, 57); }
+
+ /** Return a SoftVector alias to the second data field. */
+ const SoftVector data2() const { return segment(88, 57); }
+
+ /** Return upper stealing bit. */
+ bool Hu() const { return bit(gHuIndex); }
+
+ /** Return lower stealing bit. */
+ bool Hl() const { return bit(gHlIndex); }
+
+// friend std::ostream& operator<<(std::ostream& os, const RxBurst& ts);
+};
+
+// std::ostream& operator<<(std::ostream& os, const RxBurst& ts){
+// os << "time=" << ts.time();
+// os << " data=(" << (const SoftVector&)ts << ")" ;
+// return os;
+// }
+
+
+}
+#endif
diff --git a/gsm-receiver/src/lib/decoder/openbtsstuff/Threads.cpp b/gsm-receiver/src/lib/decoder/openbtsstuff/Threads.cpp
new file mode 100644
index 0000000..b97f3fe
--- /dev/null
+++ b/gsm-receiver/src/lib/decoder/openbtsstuff/Threads.cpp
@@ -0,0 +1,106 @@
+/*
+* 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/>.
+
+*/
+
+
+
+
+#include "Threads.h"
+#include "Timeval.h"
+
+
+using namespace std;
+
+
+
+
+Mutex gStreamLock; ///< Global lock to control access to cout and cerr.
+
+void lockCout()
+{
+ gStreamLock.lock();
+ Timeval entryTime;
+ cout << entryTime << " " << pthread_self() << ": ";
+}
+
+
+void unlockCout()
+{
+ cout << dec << endl << flush;
+ gStreamLock.unlock();
+}
+
+
+void lockCerr()
+{
+ gStreamLock.lock();
+ Timeval entryTime;
+ cerr << entryTime << " " << pthread_self() << ": ";
+}
+
+void unlockCerr()
+{
+ cerr << dec << endl << flush;
+ gStreamLock.unlock();
+}
+
+
+
+
+
+
+
+Mutex::Mutex()
+{
+ assert(!pthread_mutexattr_init(&mAttribs));
+ assert(!pthread_mutexattr_settype(&mAttribs,PTHREAD_MUTEX_RECURSIVE));
+ assert(!pthread_mutex_init(&mMutex,&mAttribs));
+}
+
+
+Mutex::~Mutex()
+{
+ pthread_mutex_destroy(&mMutex);
+ assert(!pthread_mutexattr_destroy(&mAttribs));
+}
+
+
+
+
+/** Block for the signal up to the cancellation timeout. */
+void Signal::wait(Mutex& wMutex, unsigned timeout) const
+{
+ struct timespec waitTime = Timeval(timeout).timespec();
+ // FIXME -- With -O3 optimzation in OS X this doesn't block. See bug #320.
+ pthread_cond_timedwait(&mSignal,&wMutex.mMutex,&waitTime);
+}
+
+
+void Thread::start(void *(*task)(void*), void *arg)
+{
+ assert(mThread==((pthread_t)0));
+ assert(!pthread_attr_init(&mAttrib));
+ assert(!pthread_attr_setstacksize(&mAttrib, mStackSize));
+ assert(!pthread_create(&mThread, &mAttrib, task, arg));
+}
+
+
+
+// vim: ts=4 sw=4
diff --git a/gsm-receiver/src/lib/decoder/openbtsstuff/Threads.h b/gsm-receiver/src/lib/decoder/openbtsstuff/Threads.h
new file mode 100644
index 0000000..14cff04
--- /dev/null
+++ b/gsm-receiver/src/lib/decoder/openbtsstuff/Threads.h
@@ -0,0 +1,150 @@
+/*
+* 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 THREADS_H
+#define THREADS_H
+
+
+#include <pthread.h>
+#include <iostream>
+#include "Assert.h"
+
+class Mutex;
+
+
+/**@name Multithreaded access for standard streams. */
+//@{
+
+/**@name Functions for gStreamLock. */
+//@{
+extern Mutex gStreamLock; ///< global lock for cout and cerr
+void lockCerr(); ///< call prior to writing cerr
+void unlockCerr(); ///< call after writing cerr
+void lockCout(); ///< call prior to writing cout
+void unlockCout(); ///< call after writing cout
+//@}
+
+/**@name Macros for standard messages. */
+//@{
+#define COUT(text) { lockCout(); std::cout << text; unlockCout(); }
+#define CERR(text) { lockCerr(); std::cerr << __FILE__ << ":" << __LINE__ << ": " << text; unlockCerr(); }
+#ifdef NDEBUG
+#define DCOUT(text) {}
+#define OBJDCOUT(text) {}
+#else
+#define DCOUT(text) { COUT(__FILE__ << ":" << __LINE__ << " " << text); }
+#define OBJDCOUT(text) { DCOUT(this << " " << text); }
+#endif
+//@}
+//@}
+
+
+
+/**@defgroup C++ wrappers for pthread mechanisms. */
+//@{
+
+/** A class for recursive mutexes based on pthread_mutex. */
+class Mutex {
+
+ private:
+
+ pthread_mutex_t mMutex;
+ pthread_mutexattr_t mAttribs;
+
+ public:
+
+ Mutex();
+
+ ~Mutex();
+
+ void lock() { pthread_mutex_lock(&mMutex); }
+
+ void unlock() { pthread_mutex_unlock(&mMutex); }
+
+ friend class Signal;
+
+};
+
+
+
+/** A C++ interthread signal based on pthread condition variables. */
+class Signal {
+
+ private:
+
+ mutable pthread_cond_t mSignal;
+
+ public:
+
+ Signal() { assert(!pthread_cond_init(&mSignal,NULL)); }
+
+ ~Signal() { pthread_cond_destroy(&mSignal); }
+
+ /** Block for the signal up to the cancellation timeout. */
+ void wait(Mutex& wMutex, unsigned timeout=1000000000) const;
+
+ void signal() { pthread_cond_signal(&mSignal); }
+
+ void broadcast() { pthread_cond_broadcast(&mSignal); }
+
+};
+
+
+
+#define START_THREAD(thread,function,argument) \
+ thread.start((void *(*)(void*))function, (void*)argument);
+
+/** A C++ wrapper for pthread threads. */
+class Thread {
+
+ private:
+
+ pthread_t mThread;
+ pthread_attr_t mAttrib;
+ const static size_t mStackSize=4*65536;
+
+
+ public:
+
+ /** Create a thread in a non-running state. */
+ Thread():mThread((pthread_t)0) { }
+
+ /**
+ Destroy the Thread.
+ It should be stopped and joined.
+ */
+ ~Thread() { assert(!pthread_attr_destroy(&mAttrib)); }
+
+
+ /** Start the thread on a task. */
+ void start(void *(*task)(void*), void *arg);
+
+ /** Join a thread that will stop on its own. */
+ void join() { assert(!pthread_join(mThread,NULL)); }
+
+};
+
+
+
+
+#endif
+// vim: ts=4 sw=4
diff --git a/gsm-receiver/src/lib/decoder/openbtsstuff/Timeval.cpp b/gsm-receiver/src/lib/decoder/openbtsstuff/Timeval.cpp
new file mode 100644
index 0000000..e7590cb
--- /dev/null
+++ b/gsm-receiver/src/lib/decoder/openbtsstuff/Timeval.cpp
@@ -0,0 +1,93 @@
+/*
+* 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/>.
+
+*/
+
+
+
+#include "Timeval.h"
+
+using namespace std;
+
+void Timeval::future(unsigned offset)
+{
+ now();
+ unsigned sec = offset/1000;
+ unsigned msec = offset%1000;
+ mTimeval.tv_usec += msec*1000;
+ mTimeval.tv_sec += sec;
+ if (mTimeval.tv_usec>1000000) {
+ mTimeval.tv_usec -= 1000000;
+ mTimeval.tv_sec += 1;
+ }
+}
+
+
+struct timespec Timeval::timespec() const
+{
+ struct timespec retVal;
+ retVal.tv_sec = mTimeval.tv_sec;
+ retVal.tv_nsec = 1000 * (long)mTimeval.tv_usec;
+ return retVal;
+}
+
+
+bool Timeval::passed() const
+{
+ Timeval nowTime;
+ if (nowTime.mTimeval.tv_sec < mTimeval.tv_sec) return false;
+ if (nowTime.mTimeval.tv_sec > mTimeval.tv_sec) return true;
+ if (nowTime.mTimeval.tv_usec > mTimeval.tv_usec) return true;
+ return false;
+}
+
+double Timeval::seconds() const
+{
+ return ((double)mTimeval.tv_sec) + 1e-6*((double)mTimeval.tv_usec);
+}
+
+
+
+long Timeval::delta(const Timeval& other) const
+{
+ long deltaS = other.sec() - sec();
+ long deltaUs = other.usec() - usec();
+ return 1000*deltaS + deltaUs/1000;
+}
+
+
+
+
+ostream& operator<<(ostream& os, const Timeval& tv)
+{
+ os.setf( ios::fixed, ios::floatfield );
+ os << tv.seconds();
+ return os;
+}
+
+
+ostream& operator<<(ostream& os, const struct timespec& ts)
+{
+ os << ts.tv_sec << "," << ts.tv_nsec;
+ return os;
+}
+
+
+
+// vim: ts=4 sw=4
diff --git a/gsm-receiver/src/lib/decoder/openbtsstuff/Timeval.h b/gsm-receiver/src/lib/decoder/openbtsstuff/Timeval.h
new file mode 100644
index 0000000..44618bc
--- /dev/null
+++ b/gsm-receiver/src/lib/decoder/openbtsstuff/Timeval.h
@@ -0,0 +1,96 @@
+/*
+* 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 TIMEVAL_H
+#define TIMEVAL_H
+
+#include "sys/time.h"
+#include <iostream>
+
+
+
+inline void msleep(long v) { usleep((v+500)/1000); }
+
+
+/** A C++ wrapper for struct timeval. */
+class Timeval {
+
+ private:
+
+ struct timeval mTimeval;
+
+ public:
+
+ /** Set the value to gettimeofday. */
+ void now() { gettimeofday(&mTimeval,NULL); }
+
+ /** Set the value to gettimeofday plus an offset. */
+ void future(unsigned offset);
+
+ //@{
+ Timeval(unsigned sec, unsigned usec)
+ {
+ mTimeval.tv_sec = sec;
+ mTimeval.tv_usec = usec;
+ }
+
+ Timeval(const struct timeval& wTimeval)
+ :mTimeval(wTimeval)
+ {}
+
+ /**
+ Create a Timeval offset into the future.
+ @param offset milliseconds
+ */
+ Timeval(unsigned offset=0) { future(offset); }
+ //@}
+
+ /** Convert to a struct timespec. */
+ struct timespec timespec() const;
+
+ /** Return total seconds. */
+ double seconds() const;
+
+ uint32_t sec() const { return mTimeval.tv_sec; }
+ uint32_t usec() const { return mTimeval.tv_usec; }
+
+ /** Return differnce from other (other-self), in ms. */
+ long delta(const Timeval& other) const;
+
+ /** Elapsed time in ms. */
+ long elapsed() const { return delta(Timeval()); }
+
+ /** Remaining time in ms. */
+ long remaining() const { return -elapsed(); }
+
+ /** Return true if the time has passed, as per gettimeofday. */
+ bool passed() const;
+
+};
+
+std::ostream& operator<<(std::ostream& os, const Timeval&);
+
+std::ostream& operator<<(std::ostream& os, const struct timespec&);
+
+
+#endif
+// vim: ts=4 sw=4
diff --git a/gsm-receiver/src/lib/decoder/openbtsstuff/Vector.h b/gsm-receiver/src/lib/decoder/openbtsstuff/Vector.h
new file mode 100644
index 0000000..cec278a
--- /dev/null
+++ b/gsm-receiver/src/lib/decoder/openbtsstuff/Vector.h
@@ -0,0 +1,257 @@
+/**@file Simplified Vector template with aliases. */
+/*
+* 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 VECTOR_H
+#define VECTOR_H
+
+#include <string.h>
+#include <iostream>
+#include "Assert.h"
+
+
+/**
+ A simplified Vector template with aliases.
+ Unlike std::vector, this class does not support dynamic resizing.
+ Unlike std::vector, this class does support "aliases" and subvectors.
+*/
+template <class T> class Vector {
+
+ // TODO -- Replace memcpy calls with for-loops.
+
+ public:
+
+ /**@name Iterator types. */
+ //@{
+ typedef T* iterator;
+ typedef const T* const_iterator;
+ //@}
+
+ protected:
+
+ T* mData; ///< allocated data block, if any
+ T* mStart; ///< start of useful data
+ T* mEnd; ///< end of useful data + 1
+
+ public:
+
+ /** Return the size of the Vector. */
+ size_t size() const
+ {
+ assert(mStart>=mData);
+ assert(mEnd>=mStart);
+ return mEnd - mStart;
+ }
+
+ /** Return size in bytes. */
+ size_t bytes() const { return size()*sizeof(T); }
+
+ /** Change the size of the Vector, discarding content. */
+ void resize(size_t newSize)
+ {
+ if (mData!=NULL) delete[] mData;
+ if (newSize==0) mData=NULL;
+ else mData = new T[newSize];
+ mStart = mData;
+ mEnd = mStart + newSize;
+ }
+
+ /** Release memory and clear pointers. */
+ void clear() { resize(0); }
+
+
+ /** Copy data from another vector. */
+ void clone(const Vector<T>& other)
+ {
+ resize(other.size());
+ memcpy(mData,other.mStart,other.bytes());
+ }
+
+
+
+
+ //@{
+
+ /** Build an empty Vector of a given size. */
+ Vector(size_t wSize=0):mData(NULL) { resize(wSize); }
+
+ /** Build a Vector by shifting the data block. */
+ Vector(Vector<T>& other)
+ :mData(other.mData),mStart(other.mStart),mEnd(other.mEnd)
+ { other.mData=NULL; }
+
+ /** Build a Vector by copying another. */
+ Vector(const Vector<T>& other):mData(NULL) { clone(other); }
+
+ /** Build a Vector with explicit values. */
+ Vector(T* wData, T* wStart, T* wEnd)
+ :mData(wData),mStart(wStart),mEnd(wEnd)
+ { }
+
+ /** Build a vector from an existing block, NOT to be deleted upon destruction. */
+ Vector(T* wStart, size_t span)
+ :mData(NULL),mStart(wStart),mEnd(wStart+span)
+ { }
+
+ /** Build a Vector by concatenation. */
+ Vector(const Vector<T>& other1, const Vector<T>& other2)
+ :mData(NULL)
+ {
+ resize(other1.size()+other2.size());
+ memcpy(mStart, other1.mStart, other1.bytes());
+ memcpy(mStart+other1.size(), other2.mStart, other2.bytes());
+ }
+
+ //@}
+
+ /** Destroy a Vector, deleting held memory. */
+ ~Vector() { clear(); }
+
+
+
+
+ //@{
+
+ /** Assign from another Vector, shifting ownership. */
+ void operator=(Vector<T>& other)
+ {
+ clear();
+ mData=other.mData;
+ mStart=other.mStart;
+ mEnd=other.mEnd;
+ other.mData=NULL;
+ }
+
+ /** Assign from another Vector, copying. */
+ void operator=(const Vector<T>& other) { clone(other); }
+
+ //@}
+
+
+ //@{
+
+ /** Return an alias to a segment of this Vector. */
+ Vector<T> segment(size_t start, size_t span)
+ {
+ T* wStart = mStart + start;
+ T* wEnd = wStart + span;
+ assert(wEnd<=mEnd);
+ return Vector<T>(NULL,wStart,wEnd);
+ }
+
+ /** Return an alias to a segment of this Vector. */
+ const Vector<T> segment(size_t start, size_t span) const
+ {
+ T* wStart = mStart + start;
+ T* wEnd = wStart + span;
+ assert(wEnd<=mEnd);
+ return Vector<T>(NULL,wStart,wEnd);
+ }
+
+ Vector<T> head(size_t span) { return segment(0,span); }
+ const Vector<T> head(size_t span) const { return segment(0,span); }
+ Vector<T> tail(size_t start) { return segment(start,size()-start); }
+ const Vector<T> tail(size_t start) const { return segment(start,size()-start); }
+
+ /**
+ Copy part of this Vector to a segment of another Vector.
+ @param other The other vector.
+ @param start The start point in the other vector.
+ @param span The number of elements to copy.
+ */
+ void copyToSegment(Vector<T>& other, size_t start, size_t span) const
+ {
+ T* base = other.mStart + start;
+ assert(base+span<=other.mEnd);
+ assert(mStart+span<=mEnd);
+ memcpy(base,mStart,span*sizeof(T));
+ }
+
+ /** Copy all of this Vector to a segment of another Vector. */
+ void copyToSegment(Vector<T>& other, size_t start=0) const { copyToSegment(other,start,size()); }
+
+ void copyTo(Vector<T>& other) const { copyToSegment(other,0,size()); }
+
+ /**
+ Copy a segment of this vector into another.
+ @param other The other vector (to copt into starting at 0.)
+ @param start The start point in this vector.
+ @param span The number of elements to copy.
+ */
+ void segmentCopyTo(Vector<T>& other, size_t start, size_t span)
+ {
+ T* base = mStart + start;
+ assert(base+span<=mEnd);
+ assert(other.mStart+span<=other.mEnd);
+ memcpy(other.mStart,base,span*sizeof(T));
+ }
+
+ void fill(const T& val)
+ {
+ T* dp=mStart;
+ while (dp<mEnd) *dp++=val;
+ }
+
+
+ //@}
+
+
+ //@{
+
+ T& operator[](size_t index)
+ {
+ assert(mStart+index<mEnd);
+ return mStart[index];
+ }
+
+ const T& operator[](size_t index) const
+ {
+ assert(mStart+index<mEnd);
+ return mStart[index];
+ }
+
+ const T* begin() const { return mStart; }
+ T* begin() { return mStart; }
+ const T* end() const { return mEnd; }
+ T* end() { return mEnd; }
+ //@}
+
+
+};
+
+
+
+
+/** Basic print operator for Vector objects. */
+template <class T>
+std::ostream& operator<<(std::ostream& os, const Vector<T>& v)
+{
+ for (unsigned i=0; i<v.size(); i++) os << v[i] << " ";
+ return os;
+}
+
+
+
+#endif
+// vim: ts=4 sw=4
diff --git a/gsm-receiver/src/lib/decoder/openbtsstuff/VocoderFrame.h b/gsm-receiver/src/lib/decoder/openbtsstuff/VocoderFrame.h
new file mode 100644
index 0000000..c0e51c0
--- /dev/null
+++ b/gsm-receiver/src/lib/decoder/openbtsstuff/VocoderFrame.h
@@ -0,0 +1,25 @@
+#ifndef _VOCODERFRAME_H
+#define _VOCODERFRAME_H
+
+#include "BitVector.h"
+//#include "GSMCommon.h"
+
+class VocoderFrame : public BitVector {
+
+ public:
+
+ VocoderFrame()
+ :BitVector(264)
+ { fillField(0,0x0d,4); }
+
+ /** Construct by unpacking a char[33]. */
+ VocoderFrame(const unsigned char *src)
+ :BitVector(264)
+ { unpack(src); }
+
+ BitVector payload() { return tail(4); }
+ const BitVector payload() const { return tail(4); }
+
+};
+
+#endif
diff --git a/gsm-receiver/src/lib/decoder/out_pcap.c b/gsm-receiver/src/lib/decoder/out_pcap.c
new file mode 100644
index 0000000..4da5fd6
--- /dev/null
+++ b/gsm-receiver/src/lib/decoder/out_pcap.c
@@ -0,0 +1,111 @@
+/* PCAP support for gsm-tvoid
+ * (C) 2008 by Harald Welte <laforge@gnumonks.org>
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <pcap.h>
+#include <errno.h>
+#include <time.h>
+
+#include "out_pcap.h"
+#include "gsmtap.h"
+
+#ifndef LINKTYPE_GSMTAP
+#define LINKTYPE_GSMTAP 2342
+#endif
+
+#define TCPDUMP_MAGIC 0xa1b2c3d4
+
+struct pcap_timeval {
+ int32_t tv_sec;
+ int32_t tv_usec;
+};
+
+struct pcap_sf_pkthdr {
+ struct pcap_timeval ts; /* time stamp */
+ u_int32_t caplen; /* lenght of portion present */
+ u_int32_t len; /* length of this packet */
+};
+
+static int write_pcap_file_header(int fd)
+{
+ struct pcap_file_header pfh;
+
+ pfh.magic = TCPDUMP_MAGIC;
+ pfh.version_major = PCAP_VERSION_MAJOR;
+ pfh.version_minor = PCAP_VERSION_MINOR;
+ pfh.thiszone = timezone;
+ pfh.sigfigs = 0;
+ pfh.snaplen = 1024; /* FIXME */
+ pfh.linktype = LINKTYPE_GSMTAP;
+
+ if (write(fd, &pfh, sizeof(pfh)) < sizeof(pfh))
+ return -1;
+
+ return 0;
+}
+
+/* open pcap file and write header */
+int open_pcap_file(char *fname)
+{
+ int fd;
+ int rc;
+
+ fd = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0660);
+ if (fd < 0)
+ return fd;
+
+ rc = write_pcap_file_header(fd);
+ if (rc < 0) {
+ close(fd);
+ fd = -EIO;
+ }
+
+ return fd;
+}
+
+int write_pcap_packet(int fd, int arfcn, int ts, int fn,
+ int burst, int burst_type,
+ const unsigned char *data, unsigned int len)
+{
+ unsigned char buf[8192];
+ struct pcap_sf_pkthdr *ph;
+ struct gsmtap_hdr *gh;
+ struct timeval tv;
+ int rc;
+
+ if (fd < 0)
+ return -EINVAL;
+
+ ph = (struct pcap_sf_pkthdr *) &buf[0];
+ gh = (struct gsmtap_hdr *) &buf[sizeof(struct pcap_sf_pkthdr)];
+
+ gettimeofday(&tv, NULL);
+
+ ph->ts.tv_sec = tv.tv_sec;
+ ph->ts.tv_usec = tv.tv_usec;
+ ph->caplen = ph->len = len + sizeof(struct gsmtap_hdr);
+
+ gh->version = GSMTAP_VERSION;
+ gh->hdr_len = sizeof(struct gsmtap_hdr)>>2;
+ if (burst)
+ gh->type = GSMTAP_TYPE_UM_BURST;
+ else
+ gh->type = GSMTAP_TYPE_UM;
+ gh->timeslot = ts;
+ gh->arfcn = htons(arfcn);
+ /* we don't support signal/noise yet */
+ gh->noise_db = gh->signal_db = 0;
+ gh->frame_number = htonl(fn);
+ gh->burst_type = burst_type & 0xff;
+
+ memcpy(buf + sizeof(*ph) + sizeof(*gh), data, len);
+
+ rc = write(fd, buf, sizeof(*ph) + sizeof(*gh) + len);
+
+ //fsync(fd);
+
+ return rc;
+}
diff --git a/gsm-receiver/src/lib/decoder/out_pcap.h b/gsm-receiver/src/lib/decoder/out_pcap.h
new file mode 100644
index 0000000..5ae5e3c
--- /dev/null
+++ b/gsm-receiver/src/lib/decoder/out_pcap.h
@@ -0,0 +1,9 @@
+#ifndef _PCAP_IF_H
+#define _PCAP_IF_H
+
+extern int open_pcap_file(char *fname);
+
+int write_pcap_packet(int fd, int arfcn, int ts, int fn,
+ int burst, int burst_type,
+ const unsigned char *data, unsigned int len);
+#endif
diff --git a/gsm-receiver/src/lib/decoder/sch.c b/gsm-receiver/src/lib/decoder/sch.c
new file mode 100644
index 0000000..6f141dd
--- /dev/null
+++ b/gsm-receiver/src/lib/decoder/sch.c
@@ -0,0 +1,333 @@
+#include "system.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include "gsm_constants.h"
+
+/*
+ * 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/gsm-receiver/src/lib/decoder/sch.h b/gsm-receiver/src/lib/decoder/sch.h
new file mode 100644
index 0000000..4d47eb5
--- /dev/null
+++ b/gsm-receiver/src/lib/decoder/sch.h
@@ -0,0 +1,17 @@
+
+#ifndef __SCH_H__
+#define __SCH_H__ 1
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ int decode_sch(const unsigned char *buf, int * t1_o, int * t2_o, int * t3_o, int * ncc, int * bcc);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/gsm-receiver/src/lib/decoder/system.h b/gsm-receiver/src/lib/decoder/system.h
new file mode 100644
index 0000000..414730a
--- /dev/null
+++ b/gsm-receiver/src/lib/decoder/system.h
@@ -0,0 +1,11 @@
+
+#ifndef __GSMTVOID_SYSTEM_H__
+#define __GSMTVOID_SYSTEM_H__ 1
+
+#define DEBUGF(a...) { \
+ fprintf(stderr, "%s:%d ", __FILE__, __LINE__); \
+ fprintf(stderr, a); \
+} while (0)
+
+#endif
+
diff --git a/gsm-receiver/src/lib/decoder/tun.c b/gsm-receiver/src/lib/decoder/tun.c
new file mode 100644
index 0000000..2abda90
--- /dev/null
+++ b/gsm-receiver/src/lib/decoder/tun.c
@@ -0,0 +1,125 @@
+// $Id: tun.cc,v 1.2 2007-07-07 16:31:42 jl Exp $
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <libgen.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <linux/if_tun.h>
+#include <linux/if.h>
+#include <linux/if_ether.h>
+#include <arpa/inet.h>
+
+int mktun(const char *chan_name, unsigned char *ether_addr) {
+
+ struct ifreq ifr;
+ // struct ifreq ifw;
+ char if_name[IFNAMSIZ];
+ int fd, one = 1;
+ // int sd;
+
+ // construct TUN interface
+ if((fd = open("/dev/net/tun", O_RDWR)) == -1) {
+ perror("open");
+ return -1;
+ }
+ memset(&ifr, 0, sizeof(ifr));
+ ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
+ snprintf(ifr.ifr_name, IFNAMSIZ, "%s", chan_name);
+ if(ioctl(fd, TUNSETIFF, (void *)&ifr) == -1) {
+ perror("TUNSETIFF");
+ close(fd);
+ return -1;
+ }
+
+ // save actual name
+ memcpy(if_name, ifr.ifr_name, IFNAMSIZ);
+
+ // get ether addr
+ memset(&ifr, 0, sizeof(ifr));
+ memcpy(ifr.ifr_name, if_name, IFNAMSIZ);
+ if(ioctl(fd, SIOCGIFHWADDR, (void *)&ifr) == -1) {
+ perror("SIOCGIFHWADDR");
+ close(fd);
+ return -1;
+ }
+ memcpy(ether_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN);
+
+ // set persistent
+ if(ioctl(fd, TUNSETPERSIST, (void *)&one) == -1) {
+ perror("TUNSETPERSIST");
+ close(fd);
+ return -1;
+ }
+
+ // set interface up
+ /* XXX must be root
+ if((sd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
+ perror("socket");
+ close(fd);
+ return -1;
+ }
+
+ // get current flags
+ memset(&ifr, 0, sizeof(ifr));
+ strncpy(ifr.ifr_name, if_name, IFNAMSIZ - 1);
+ if(ioctl(sd, SIOCGIFFLAGS, &ifr) == -1) {
+ perror("SIOCGIFFLAGS");
+ close(sd);
+ close(fd);
+ return -1;
+ }
+
+ // set up
+ memset(&ifw, 0, sizeof(ifw));
+ strncpy(ifw.ifr_name, if_name, IFNAMSIZ - 1);
+ ifw.ifr_flags = ifr.ifr_flags | IFF_UP | IFF_RUNNING;
+ if(ioctl(sd, SIOCSIFFLAGS, &ifw) == -1) {
+ perror("SIOCSIFFLAGS");
+ close(sd);
+ close(fd);
+ return -1;
+ }
+ close(sd);
+ */
+
+ return fd;
+}
+
+
+static inline int min(int a, int b) {
+
+ return (a < b)? a : b;
+}
+
+
+static const unsigned int DEFAULT_MTU = 1500;
+static const unsigned short ether_type = 0xfed5; // current dtap ethertype
+
+int write_interface(int fd, unsigned char *data, unsigned int data_len,
+ unsigned char *ether_addr) {
+
+ unsigned char frame[DEFAULT_MTU]; // XXX buffer overflow?
+ struct ethhdr eh;
+
+ if(fd < 0)
+ return data_len;
+
+ memcpy(eh.h_dest, ether_addr, ETH_ALEN);
+ memcpy(eh.h_source, ether_addr, ETH_ALEN);
+ eh.h_proto = htons(ether_type);
+
+ memcpy(frame, &eh, sizeof(eh));
+ memcpy(frame + sizeof(eh), data,
+ min(data_len, sizeof(frame) - sizeof(eh)));
+
+ if(write(fd, frame, sizeof(eh) + data_len) == -1) {
+ perror("write");
+ return -1;
+ }
+
+ return data_len;
+}
diff --git a/gsm-receiver/src/lib/decoder/tun.h b/gsm-receiver/src/lib/decoder/tun.h
new file mode 100644
index 0000000..a7868c4
--- /dev/null
+++ b/gsm-receiver/src/lib/decoder/tun.h
@@ -0,0 +1,4 @@
+// $Id: tun.h,v 1.1.1.1 2007-06-01 04:26:57 jl Exp $
+
+int mktun(const char *, unsigned char *);
+int write_interface(int, unsigned char *, unsigned int, unsigned char *);
diff --git a/gsm-receiver/src/lib/gsm.i b/gsm-receiver/src/lib/gsm.i
new file mode 100644
index 0000000..3a5c561
--- /dev/null
+++ b/gsm-receiver/src/lib/gsm.i
@@ -0,0 +1,49 @@
+/* -*- c++ -*- */
+/*
+ * @file
+ * @author Piotr Krysik <pkrysik@stud.elka.pw.edu.pl>
+ * @section LICENSE
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+%feature("autodoc", "1"); // generate python docstrings
+
+%include "exception.i"
+%import "gnuradio.i" // the common stuff
+
+/* %include "gsm_constants.h" */
+
+%{
+#include "gnuradio_swig_bug_workaround.h" // mandatory bug fix
+#include "gsm_receiver_cf.h"
+#include <stdexcept>
+/* #include "gsm_constants.h" */
+%}
+
+// ----------------------------------------------------------------
+
+GR_SWIG_BLOCK_MAGIC(gsm,receiver_cf);
+
+gsm_receiver_cf_sptr gsm_make_receiver_cf ( gr_feval_dd *tuner, gr_feval_dd *synchronizer, int osr, std::string key);
+
+class gsm_receiver_cf : public gr_block
+{
+private:
+ gsm_receiver_cf ( gr_feval_dd *tuner, gr_feval_dd *synchronizer, int osr);
+};
+
+// ----------------------------------------------------------------
diff --git a/gsm-receiver/src/lib/gsm_constants.h b/gsm-receiver/src/lib/gsm_constants.h
new file mode 100644
index 0000000..939099d
--- /dev/null
+++ b/gsm-receiver/src/lib/gsm_constants.h
@@ -0,0 +1,150 @@
+#ifndef INCLUDED_GSM_CONSTANTS_H
+#define INCLUDED_GSM_CONSTANTS_H
+
+#define GSM_SYMBOL_RATE (1625000.0/6.0) //symbols per second
+#define GSM_SYMBOL_PERIOD (1.0/GSM_SYMBOL_RATE) //seconds per symbol
+
+//Burst timing
+#define TAIL_BITS 3
+#define GUARD_BITS 8
+#define GUARD_FRACTIONAL 0.25 //fractional part of guard period
+#define GUARD_PERIOD GUARD_BITS + GUARD_FRACTIONAL
+#define DATA_BITS 57 //size of 1 data block in normal burst
+#define STEALING_BIT 1
+#define N_TRAIN_BITS 26
+#define N_SYNC_BITS 64
+#define USEFUL_BITS 142 //(2*(DATA_BITS+STEALING_BIT) + N_TRAIN_BITS )
+#define FCCH_BITS USEFUL_BITS
+#define BURST_SIZE (USEFUL_BITS+2*TAIL_BITS)
+
+#define SCH_DATA_LEN 39
+#define TS_BITS (TAIL_BITS+USEFUL_BITS+TAIL_BITS+GUARD_BITS) //a full TS (156 bits)
+#define TS_PER_FRAME 8
+#define FRAME_BITS (TS_PER_FRAME * TS_BITS + 2) // 156.25 * 8
+#define FCCH_POS TAIL_BITS
+#define SYNC_POS 39
+#define TRAIN_POS ( TAIL_BITS + (DATA_BITS+STEALING_BIT) + 5) //first 5 bits of a training sequence
+ //aren't used for channel impulse response estimation
+#define TRAIN_BEGINNING 5
+#define SAFETY_MARGIN 6 //
+
+#define FCCH_HITS_NEEDED (USEFUL_BITS - 4)
+#define FCCH_MAX_MISSES 1
+#define FCCH_MAX_FREQ_OFFSET 100
+
+#define CHAN_IMP_RESP_LENGTH 5
+
+#define MAX_SCH_ERRORS 5 //maximum number of subsequent sch errors after which gsm receiver goes to find_next_fcch state
+
+typedef enum {empty, fcch_burst, sch_burst, normal_burst, rach_burst, dummy, dummy_or_normal} burst_type;
+typedef enum {unknown, multiframe_26, multiframe_51} multiframe_type;
+
+static const unsigned char SYNC_BITS[] = {
+ 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1,
+ 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1,
+ 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1
+};
+
+const unsigned FCCH_FRAMES[] = {0, 10, 20, 30, 40};
+const unsigned SCH_FRAMES[] = {1, 11, 21, 31, 41};
+
+const unsigned BCCH_FRAMES[] = {2, 3, 4, 5}; //!!the receiver shouldn't care about logical
+ //!!channels so this will be removed from this header
+const unsigned TEST_CCH_FRAMES[] = {2, 3, 4, 5, 6, 7, 8, 9, 12, 13, 14, 15, 16, 17, 18, 19, 22, 23, 24, 25, 26, 27, 28, 29, 32, 33, 34, 35, 36, 37, 38, 39, 42, 43, 44, 45, 46, 47, 48, 49};
+const unsigned TRAFFIC_CHANNEL_F[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24};
+const unsigned TEST51[] = {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};
+
+
+#define TSC0 0
+#define TSC1 1
+#define TSC2 2
+#define TSC3 3
+#define TSC4 4
+#define TSC5 5
+#define TSC6 6
+#define TSC7 7
+#define TS_DUMMY 8
+
+#define TRAIN_SEQ_NUM 9
+
+#define TIMESLOT0 0
+#define TIMESLOT1 1
+#define TIMESLOT2 2
+#define TIMESLOT3 3
+#define TIMESLOT4 4
+#define TIMESLOT5 5
+#define TIMESLOT6 6
+#define TIMESLOT7 7
+
+
+static const unsigned char train_seq[TRAIN_SEQ_NUM][N_TRAIN_BITS] = {
+ {0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1},
+ {0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1},
+ {0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0},
+ {0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0},
+ {0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1},
+ {0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0},
+ {1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1},
+ {1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0},
+ {0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1} // DUMMY
+};
+
+
+//Dummy burst 0xFB 76 0A 4E 09 10 1F 1C 5C 5C 57 4A 33 39 E9 F1 2F A8
+static const unsigned char dummy_burst[] = {
+ 1, 1, 1, 1, 1, 0, 1, 1, 0, 1,
+ 1, 1, 0, 1, 1, 0, 0, 0, 0, 0,
+ 1, 0, 1, 0, 0, 1, 0, 0, 1, 1,
+ 1, 0, 0, 0, 0, 0, 1, 0, 0, 1,
+ 0, 0, 0, 1, 0, 0, 0, 0, 0, 0,
+ 0, 1, 1, 1, 1, 1, 0, 0,
+
+ 0, 1, 1, 1, 0, 0, 0, 1, 0, 1,
+ 1, 1, 0, 0, 0, 1, 0, 1, 1, 1,
+ 0, 0, 0, 1, 0, 1,
+
+ 0, 1, 1, 1, 0, 1, 0, 0, 1, 0,
+ 1, 0, 0, 0, 1, 1, 0, 0, 1, 1,
+ 0, 0, 1, 1, 1, 0, 0, 1, 1, 1,
+ 1, 0, 1, 0, 0, 1, 1, 1, 1, 1,
+ 0, 0, 0, 1, 0, 0, 1, 0, 1, 1,
+ 1, 1, 1, 0, 1, 0, 1, 0
+};
+
+
+/*
+ * The frequency correction burst is used for frequency synchronization
+ * of the mobile. This is broadcast in TS0 together with the SCH and
+ * BCCH.
+ *
+ * Modulating the bits below causes a spike at 62.5kHz above (below for
+ * COMPACT) the center frequency. One can use this spike with a narrow
+ * band filter to accurately determine the center of the channel.
+ */
+static const unsigned char fc_fb[] = { //I don't use this tables,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //I copied this here from burst_types.h because
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, //the description is very informative - p.krysik
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static const unsigned char fc_compact_fb[] = {
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
+ 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0
+};
+
+
+#endif /* INCLUDED_GSM_CONSTANTS_H */
diff --git a/gsm-receiver/src/lib/gsm_receiver_cf.cc b/gsm-receiver/src/lib/gsm_receiver_cf.cc
new file mode 100644
index 0000000..4742b33
--- /dev/null
+++ b/gsm-receiver/src/lib/gsm_receiver_cf.cc
@@ -0,0 +1,853 @@
+/* -*- c++ -*- */
+/*
+ * @file
+ * @author Piotr Krysik <pkrysik@stud.elka.pw.edu.pl>
+ * @section LICENSE
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gr_io_signature.h>
+#include <gr_math.h>
+#include <math.h>
+#include <Assert.h>
+#include <boost/circular_buffer.hpp>
+#include <algorithm>
+#include <numeric>
+#include <gsm_receiver_cf.h>
+#include <viterbi_detector.h>
+#include <string.h>
+#include <sch.h>
+
+
+#include "RxBurst.h"
+#include "GSMCommon.h"
+
+#define SYNC_SEARCH_RANGE 30
+// #define TRAIN_SEARCH_RANGE 40
+//FIXME: decide to use this define or not
+
+//TODO: this shouldn't be here - remove it when gsm receiver's interface will be ready
+void decrypt(const unsigned char * burst_binary, byte * KC, float * decrypted_data, unsigned FN)
+{
+ byte AtoB[2*DATA_BITS];
+
+ keysetup(KC, FN);
+ runA51(AtoB);
+
+ for (int i = 0; i < 148; i++) {
+ decrypted_data[i] = burst_binary[i];
+ }
+
+ for (int i = 0; i < 57; i++) {
+ decrypted_data[i+3] = AtoB[i] ^ burst_binary[i+3];
+ }
+
+ for (int i = 0; i < 57; i++) {
+ decrypted_data[i+88] = AtoB[i+57] ^ burst_binary[i+88];
+ }
+}
+
+void gsm_receiver_cf::read_key(std::string key)
+{
+ int i;
+ int b;
+ for (i = 0;i < 8;i++) {
+ b = d_hex_to_int[(char)key[(i)*2]]*16 + d_hex_to_int[(char)key[i*2+1]];
+ d_KC[i] = (byte)b;
+ }
+}
+
+void gsm_receiver_cf::process_normal_burst(burst_counter burst_nr, const unsigned char * burst_binary)
+{
+// static byte KC[] = { 0xAD, 0x6A, 0x3E, 0xC2, 0xB4, 0x42, 0xE4, 0x00 };
+// static byte KC[] = { 0x2B, 0x08, 0x74, 0x9F, 0xDD, 0x0D, 0x9C, 0x00 };
+// printf("%x", KC[0]);
+ float decrypted_data[148];
+ unsigned char * voice_frame;
+
+// if (burst_nr.get_timeslot_nr() == 7) {
+ if (burst_nr.get_timeslot_nr() >= 1 && burst_nr.get_timeslot_nr() <= 7) {
+ decrypt(burst_binary, d_KC, decrypted_data, burst_nr.get_frame_nr_mod());
+
+ GSM::Time time(burst_nr.get_frame_nr(), burst_nr.get_timeslot_nr());
+ GSM::RxBurst rxbrst(decrypted_data, time);
+ switch (burst_nr.get_timeslot_nr()) {
+ case 1:
+ if ( d_tch_decoder1.processBurst( rxbrst ) == true) {
+ fwrite(d_tch_decoder1.get_voice_frame(), 1 , 33, d_gsm_file);
+ }
+ break;
+ case 2:
+ if ( d_tch_decoder2.processBurst( rxbrst ) == true) {
+ fwrite(d_tch_decoder2.get_voice_frame(), 1 , 33, d_gsm_file);
+ }
+ break;
+ case 3:
+ if ( d_tch_decoder3.processBurst( rxbrst ) == true) {
+ fwrite(d_tch_decoder3.get_voice_frame(), 1 , 33, d_gsm_file);
+ }
+ break;
+ case 4:
+ if ( d_tch_decoder4.processBurst( rxbrst ) == true) {
+ fwrite(d_tch_decoder4.get_voice_frame(), 1 , 33, d_gsm_file);
+ }
+ break;
+ case 5:
+ if ( d_tch_decoder5.processBurst( rxbrst ) == true) {
+ fwrite(d_tch_decoder5.get_voice_frame(), 1 , 33, d_gsm_file);
+ }
+ break;
+ case 6:
+ if ( d_tch_decoder6.processBurst( rxbrst ) == true) {
+ fwrite(d_tch_decoder6.get_voice_frame(), 1 , 33, d_gsm_file);
+ }
+ break;
+ case 7:
+ if ( d_tch_decoder7.processBurst( rxbrst ) == true) {
+ fwrite(d_tch_decoder7.get_voice_frame(), 1 , 33, d_gsm_file);
+ }
+ break;
+ }
+ }
+
+ if (burst_nr.get_timeslot_nr() == 0) {
+ GS_process(&d_gs_ctx, TIMESLOT0, 6, &burst_binary[3], burst_nr.get_frame_nr());
+ }
+}
+//TODO: this shouldn't be here also - the same reason
+void gsm_receiver_cf::configure_receiver()
+{
+ d_channel_conf.set_multiframe_type(TSC0, multiframe_51);
+
+ d_channel_conf.set_burst_types(TSC0, TEST_CCH_FRAMES, sizeof(TEST_CCH_FRAMES) / sizeof(unsigned), normal_burst);
+ d_channel_conf.set_burst_types(TSC0, FCCH_FRAMES, sizeof(FCCH_FRAMES) / sizeof(unsigned), fcch_burst);
+
+ d_channel_conf.set_multiframe_type(TIMESLOT1, multiframe_26);
+ d_channel_conf.set_burst_types(TIMESLOT1, TRAFFIC_CHANNEL_F, sizeof(TRAFFIC_CHANNEL_F) / sizeof(unsigned), dummy_or_normal);
+ d_channel_conf.set_multiframe_type(TIMESLOT2, multiframe_26);
+ d_channel_conf.set_burst_types(TIMESLOT2, TRAFFIC_CHANNEL_F, sizeof(TRAFFIC_CHANNEL_F) / sizeof(unsigned), dummy_or_normal);
+
+ d_channel_conf.set_multiframe_type(TIMESLOT3, multiframe_26);
+ d_channel_conf.set_burst_types(TIMESLOT3, TRAFFIC_CHANNEL_F, sizeof(TRAFFIC_CHANNEL_F) / sizeof(unsigned), dummy_or_normal);
+ d_channel_conf.set_multiframe_type(TIMESLOT4, multiframe_26);
+ d_channel_conf.set_burst_types(TIMESLOT4, TRAFFIC_CHANNEL_F, sizeof(TRAFFIC_CHANNEL_F) / sizeof(unsigned), dummy_or_normal);
+
+ d_channel_conf.set_multiframe_type(TIMESLOT5, multiframe_26);
+ d_channel_conf.set_burst_types(TIMESLOT5, TRAFFIC_CHANNEL_F, sizeof(TRAFFIC_CHANNEL_F) / sizeof(unsigned), dummy_or_normal);
+ d_channel_conf.set_multiframe_type(TIMESLOT6, multiframe_26);
+ d_channel_conf.set_burst_types(TIMESLOT6, TRAFFIC_CHANNEL_F, sizeof(TRAFFIC_CHANNEL_F) / sizeof(unsigned), dummy_or_normal);
+
+ d_channel_conf.set_multiframe_type(TIMESLOT7, multiframe_26);
+ d_channel_conf.set_burst_types(TIMESLOT7, TRAFFIC_CHANNEL_F, sizeof(TRAFFIC_CHANNEL_F) / sizeof(unsigned), dummy_or_normal);
+
+}
+
+
+typedef std::list<float> list_float;
+typedef std::vector<float> vector_float;
+
+typedef boost::circular_buffer<float> circular_buffer_float;
+
+gsm_receiver_cf_sptr
+gsm_make_receiver_cf(gr_feval_dd *tuner, gr_feval_dd *synchronizer, int osr, std::string key)
+{
+ return gsm_receiver_cf_sptr(new gsm_receiver_cf(tuner, synchronizer, osr, key));
+}
+
+static const int MIN_IN = 1; // mininum number of input streams
+static const int MAX_IN = 1; // maximum number of input streams
+static const int MIN_OUT = 0; // minimum number of output streams
+static const int MAX_OUT = 1; // maximum number of output streams
+
+/*
+ * The private constructor
+ */
+gsm_receiver_cf::gsm_receiver_cf(gr_feval_dd *tuner, gr_feval_dd *synchronizer, int osr, std::string key)
+ : gr_block("gsm_receiver",
+ gr_make_io_signature(MIN_IN, MAX_IN, sizeof(gr_complex)),
+ gr_make_io_signature(MIN_OUT, MAX_OUT, 142 * sizeof(float))),
+ d_OSR(osr),
+ d_chan_imp_length(CHAN_IMP_RESP_LENGTH),
+ d_tuner(tuner),
+ d_counter(0),
+ d_fcch_start_pos(0),
+ d_freq_offset(0),
+ d_state(first_fcch_search),
+ d_burst_nr(osr),
+ d_failed_sch(0),
+ d_tch_decoder1( GSM::gFACCH_TCHFMapping ),
+ d_tch_decoder2( GSM::gFACCH_TCHFMapping ),
+ d_tch_decoder3( GSM::gFACCH_TCHFMapping ),
+ d_tch_decoder4( GSM::gFACCH_TCHFMapping ),
+ d_tch_decoder5( GSM::gFACCH_TCHFMapping ),
+ d_tch_decoder6( GSM::gFACCH_TCHFMapping ),
+ d_tch_decoder7( GSM::gFACCH_TCHFMapping )
+{
+ int i;
+ 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++) {
+ gr_complex startpoint;
+ if (i == 6) { //this is nasty hack
+ startpoint = gr_complex(-1.0, 0.0); //if I don't change it here all bits of normal bursts for BTSes with bcc=6 will have reversed values
+ } else {
+ startpoint = gr_complex(1.0, 0.0); //I've checked this hack for bcc==0,1,2,3,4,6
+ } //I don't know what about bcc==5 and 7 yet
+ //TODO:find source of this situation - this is purely mathematical problem I guess
+
+ gmsk_mapper(train_seq[i], N_TRAIN_BITS, d_norm_training_seq[i], startpoint);
+ }
+ d_gsm_file = fopen( "speech.gsm", "wb" );
+
+ d_hex_to_int['0'] = 0;
+ d_hex_to_int['4'] = 4;
+ d_hex_to_int['8'] = 8;
+ d_hex_to_int['c'] = 0xc;
+ d_hex_to_int['1'] = 1;
+ d_hex_to_int['5'] = 5;
+ d_hex_to_int['9'] = 9;
+ d_hex_to_int['d'] = 0xd;
+ d_hex_to_int['2'] = 2;
+ d_hex_to_int['6'] = 6;
+ d_hex_to_int['a'] = 0xa;
+ d_hex_to_int['e'] = 0xe;
+ d_hex_to_int['3'] = 3;
+ d_hex_to_int['7'] = 7;
+ d_hex_to_int['b'] = 0xb;
+ d_hex_to_int['f'] = 0xf;
+ read_key(key);
+ /* Initialize GSM Stack */
+ GS_new(&d_gs_ctx); //TODO: remove it! it's not a right place for a decoder
+}
+
+/*
+ * Virtual destructor.
+ */
+gsm_receiver_cf::~gsm_receiver_cf()
+{
+}
+
+void gsm_receiver_cf::forecast(int noutput_items, gr_vector_int &nitems_items_required)
+{
+ nitems_items_required[0] = noutput_items * floor((TS_BITS + 2 * GUARD_PERIOD) * d_OSR);
+}
+
+int
+gsm_receiver_cf::general_work(int noutput_items,
+ gr_vector_int &nitems_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items)
+{
+ const gr_complex *input = (const gr_complex *) input_items[0];
+ //float *out = (float *) output_items[0];
+ int produced_out = 0; //how many output elements were produced - this isn't used yet
+ //probably the gsm receiver will be changed into sink so this variable won't be necessary
+
+ switch (d_state) {
+ //bootstrapping
+ case first_fcch_search:
+ if (find_fcch_burst(input, nitems_items[0])) { //find frequency correction burst in the input buffer
+ set_frequency(d_freq_offset); //if fcch search is successful set frequency offset
+ //produced_out = 0;
+ d_state = next_fcch_search;
+ } else {
+ //produced_out = 0;
+ d_state = first_fcch_search;
+ }
+ break;
+
+ case next_fcch_search: { //this state is used because it takes some time (a bunch of buffered samples)
+ float prev_freq_offset = d_freq_offset; //before previous set_frequqency cause change
+ if (find_fcch_burst(input, nitems_items[0])) {
+ if (abs(prev_freq_offset - d_freq_offset) > FCCH_MAX_FREQ_OFFSET) {
+ set_frequency(d_freq_offset); //call set_frequncy only frequency offset change is greater than some value
+ }
+ //produced_out = 0;
+ d_state = sch_search;
+ } else {
+ //produced_out = 0;
+ d_state = next_fcch_search;
+ }
+ break;
+ }
+
+ case sch_search: {
+ vector_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(nitems_items[0])) { //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
+ DCOUT("sch burst_start: " << burst_start);
+ DCOUT("bcc: " << d_bcc << " ncc: " << d_ncc << " t1: " << t1 << " t2: " << t2 << " t3: " << t3);
+ d_burst_nr.set(t1, t2, t3, 0); //set counter of bursts value
+
+ //configure the receiver - tell him where to find which burst type
+ d_channel_conf.set_multiframe_type(TIMESLOT0, multiframe_51); //in the timeslot nr.0 bursts changes according to t3 counter
+ configure_receiver();//TODO: this shouldn't be here - remove it when gsm receiver's interface will be ready
+ d_channel_conf.set_burst_types(TIMESLOT0, FCCH_FRAMES, sizeof(FCCH_FRAMES) / sizeof(unsigned), fcch_burst); //tell where to find fcch bursts
+ d_channel_conf.set_burst_types(TIMESLOT0, SCH_FRAMES, sizeof(SCH_FRAMES) / sizeof(unsigned), sch_burst); //sch bursts
+ d_channel_conf.set_burst_types(TIMESLOT0, BCCH_FRAMES, sizeof(BCCH_FRAMES) / sizeof(unsigned), normal_burst);//!and maybe normal bursts of the BCCH logical channel
+ d_burst_nr++;
+
+ consume_each(burst_start + BURST_SIZE * d_OSR); //consume samples up to next guard period
+ d_state = synchronized;
+ } else {
+ d_state = next_fcch_search; //if there is error in the sch burst go back to fcch search phase
+ }
+ } else {
+ d_state = sch_search;
+ }
+ break;
+ }
+ //in this state receiver is synchronized and it processes bursts according to burst type for given burst number
+ case synchronized: {
+ vector_complex channel_imp_resp(CHAN_IMP_RESP_LENGTH*d_OSR);
+ int burst_start;
+ int offset = 0;
+ int to_consume = 0;
+ unsigned char output_binary[BURST_SIZE];
+
+ burst_type b_type = d_channel_conf.get_burst_type(d_burst_nr); //get burst type for given burst number
+
+ switch (b_type) {
+ case fcch_burst: { //if it's FCCH burst
+ 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 = compute_freq_offset(input, first_sample, last_sample); //extract frequency offset from it
+
+ d_freq_offset_vals.push_front(freq_offset);
+
+ if (d_freq_offset_vals.size() >= 10) {
+ double sum = std::accumulate(d_freq_offset_vals.begin(), d_freq_offset_vals.end(), 0);
+ double mean_offset = sum / d_freq_offset_vals.size(); //compute mean
+ d_freq_offset_vals.clear();
+ if (abs(mean_offset) > FCCH_MAX_FREQ_OFFSET) {
+ d_freq_offset -= mean_offset; //and adjust frequency if it have changed beyond
+ set_frequency(d_freq_offset); //some limit
+ DCOUT("mean_offset: " << mean_offset);
+ DCOUT("Adjusting frequency, new frequency offset: " << d_freq_offset << "\n");
+ }
+ }
+ }
+ break;
+ case sch_burst: { //if it's SCH burst
+ int t1, t2, t3, d_ncc, d_bcc;
+ burst_start = get_sch_chan_imp_resp(input, &channel_imp_resp[0]); //get channel impulse response
+ detect_burst(input, &channel_imp_resp[0], burst_start, output_binary); //MLSE detection of bits
+ 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;
+ DCOUT("bcc: " << d_bcc << " ncc: " << d_ncc << " t1: " << t1 << " t2: " << t2 << " t3: " << t3);
+ offset = burst_start - floor((GUARD_PERIOD) * d_OSR); //compute offset from burst_start - burst should start after a guard period
+ DCOUT(offset);
+ 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 = next_fcch_search; //TODO: this isn't good, the receiver is going wild when it goes back to next_fcch_search from here
+// d_freq_offset_vals.clear();
+ DCOUT("many sch decoding errors");
+ }
+ }
+ }
+ break;
+
+ case normal_burst: //if it's normal burst
+ burst_start = get_norm_chan_imp_resp(input, &channel_imp_resp[0], d_bcc); //get channel impulse response for given training sequence number - d_bcc
+ detect_burst(input, &channel_imp_resp[0], burst_start, output_binary); //MLSE detection of bits
+ process_normal_burst(d_burst_nr, output_binary); //TODO: this shouldn't be here - remove it when gsm receiver's interface will be ready
+ break;
+
+ case dummy_or_normal: {
+ burst_start = get_norm_chan_imp_resp(input, &channel_imp_resp[0], TS_DUMMY);
+ detect_burst(input, &channel_imp_resp[0], burst_start, output_binary);
+
+ std::vector<unsigned char> v(20);
+ std::vector<unsigned char>::iterator it;
+ it = std::set_difference(output_binary + TRAIN_POS, output_binary + TRAIN_POS + 16, &train_seq[TS_DUMMY][5], &train_seq[TS_DUMMY][21], v.begin());
+ int different_bits = (it - v.begin());
+
+ if (different_bits > 2) {
+ burst_start = get_norm_chan_imp_resp(input, &channel_imp_resp[0], d_bcc);
+ detect_burst(input, &channel_imp_resp[0], burst_start, output_binary);
+ if (!output_binary[0] && !output_binary[1] && !output_binary[2]) {
+ process_normal_burst(d_burst_nr, output_binary); //TODO: this shouldn't be here - remove it when gsm receiver's interface will be ready
+ }
+ }
+ }
+ case rach_burst:
+ //implementation of this channel isn't possible in current gsm_receiver
+ //it would take some realtime processing, counter of samples from USRP to
+ //stay synchronized with this device and possibility to switch frequency from uplink
+ //to C0 (where sch is) back and forth
+
+ break;
+ case dummy: //if it's dummy
+ burst_start = get_norm_chan_imp_resp(input, &channel_imp_resp[0], TS_DUMMY); //read dummy
+ detect_burst(input, &channel_imp_resp[0], burst_start, output_binary); // but as far as I know it's pointless
+ break;
+ case empty: //if it's empty burst
+ break; //do nothing
+ }
+
+ 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
+ //and add offset which is introduced by
+ //0.25 fractional part of a guard period
+ //burst_number computes this offset
+ //but choice of this class to do this was random
+ consume_each(to_consume);
+ }
+ break;
+ }
+
+ return produced_out;
+}
+
+bool gsm_receiver_cf::find_fcch_burst(const gr_complex *input, const int nitems)
+{
+ 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;
+ circular_buffer_float::iterator buffer_iter;
+
+ /**@name 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;
+ //@}
+
+ fcch_search_state = init;
+
+ while (!end) {
+ switch (fcch_search_state) {
+
+ 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;
+
+ break;
+
+ case search: // search for positive samples
+ sample_number++;
+
+ 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]);
+
+ 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;
+ }
+ }
+
+ 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
+ }
+
+ 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;
+
+ case fcch_found: {
+ DCOUT("fcch found on position: " << d_counter + start_pos);
+ to_consume = start_pos + FCCH_HITS_NEEDED * d_OSR + 1; //consume one FCCH burst
+
+ d_fcch_start_pos = d_counter + start_pos;
+
+ //compute frequency offset
+ double phase_offset = best_sum / FCCH_HITS_NEEDED;
+ double freq_offset = phase_offset * 1625000.0 / (12.0 * M_PI);
+ d_freq_offset -= freq_offset;
+ DCOUT("freq_offset: " << d_freq_offset);
+
+ end = true;
+ result = true;
+ break;
+ }
+
+ case search_fail:
+ end = true;
+ result = false;
+ break;
+ }
+ }
+
+ d_counter += to_consume;
+ consume_each(to_consume);
+
+ return result;
+}
+
+double gsm_receiver_cf::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 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;
+}
+
+void gsm_receiver_cf::set_frequency(double freq_offset)
+{
+ d_tuner->calleval(freq_offset);
+}
+
+inline float gsm_receiver_cf::compute_phase_diff(gr_complex val1, gr_complex val2)
+{
+ gr_complex conjprod = val1 * conj(val2);
+ return gr_fast_atan2f(imag(conjprod), real(conjprod));
+}
+
+bool gsm_receiver_cf::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) {
+ if (d_counter + nitems >= sample_nr_near_sch_start) {
+ to_consume = sample_nr_near_sch_start - d_counter;
+ } else {
+ to_consume = nitems;
+ }
+ result = false;
+ } else {
+ to_consume = 0;
+ result = true;
+ }
+
+ d_counter += to_consume;
+ consume_each(to_consume);
+ return result;
+}
+
+int gsm_receiver_cf::get_sch_chan_imp_resp(const gr_complex *input, gr_complex * chan_imp_resp)
+{
+ vector_complex correlation_buffer;
+ vector_float power_buffer;
+ 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++) {
+ 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(pow(abs(correlation), 2));
+ }
+
+ //compute window energies
+ vector_float::iterator iter = power_buffer.begin();
+ bool loop_end = false;
+ while (iter != power_buffer.end()) {
+ 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) {
+ break;
+ }
+ iter++;
+ window_energy_buffer.push_back(energy);
+ }
+
+ strongest_window_nr = max_element(window_energy_buffer.begin(), window_energy_buffer.end()) - window_energy_buffer.begin();
+// d_channel_imp_resp.clear();
+
+ 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);
+ 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;
+}
+
+void gsm_receiver_cf::detect_burst(const gr_complex * input, gr_complex * chan_imp_resp, int burst_start, unsigned char * output_binary)
+{
+ float output[BURST_SIZE];
+ 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, 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);
+ }
+}
+
+//TODO consider placing this funtion in a separate class for signal processing
+void gsm_receiver_cf::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 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
+ current_symbol = 2 * input[i] - 1;
+ //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];
+ previous_symbol = current_symbol;
+ }
+}
+
+//TODO consider use of some generalized function for correlation and placing it in a separate class for signal processing
+gr_complex gsm_receiver_cf::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
+//TODO consider placing this funtion in a separate class for signal processing
+inline void gsm_receiver_cf::autocorrelation(const gr_complex * input, gr_complex * out, int nitems)
+{
+ int i, k;
+ for (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]);
+ }
+ }
+}
+
+//TODO consider use of some generalized function for filtering and placing it in a separate class for signal processing
+inline void gsm_receiver_cf::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++) {
+ 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++;
+ }
+ }
+}
+
+//TODO: get_norm_chan_imp_resp is similar to get_sch_chan_imp_resp - consider joining this two functions
+//TODO: this is place where most errors are introduced and can be corrected by improvements to this fuction
+//especially computations of strongest_window_nr
+int gsm_receiver_cf::get_norm_chan_imp_resp(const gr_complex *input, gr_complex * chan_imp_resp, int bcc)
+{
+ vector_complex correlation_buffer;
+ vector_float power_buffer;
+ 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;
+// int search_start_pos = search_center - d_chan_imp_length * d_OSR;
+ int search_stop_pos = search_center + d_chan_imp_length * d_OSR + 2 * 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(pow(abs(correlation), 2));
+ }
+
+ //compute window energies
+ vector_float::iterator iter = power_buffer.begin();
+ bool loop_end = false;
+ while (iter != power_buffer.end()) {
+ vector_float::iterator iter_ii = iter;
+ energy = 0;
+
+ for (int ii = 0; ii < (d_chan_imp_length - 2)*d_OSR; ii++, iter_ii++) {
+// 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) {
+ break;
+ }
+ iter++;
+
+ window_energy_buffer.push_back(energy);
+ }
+ //!why doesn't this work
+ strongest_window_nr = max_element(window_energy_buffer.begin(), window_energy_buffer.end()) - window_energy_buffer.begin();
+ strongest_window_nr = 3; //! so I have to override it here
+
+ 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);
+ chan_imp_resp[ii] = correlation;
+ }
+ // We want to use the first sample of the impulseresponse, and the
+ // corresponding samples of the received signal.
+ // the variable sync_w should contain the beginning of the used part of
+ // training sequence, which is 3+57+1+6=67 bits into the burst. That is
+ // we have that sync_t16 equals first sample in bit number 67.
+
+ burst_start = search_start_pos + chan_imp_resp_center + strongest_window_nr - TRAIN_POS * d_OSR;
+
+ // GMSK modulator introduces ISI - each bit is expanded for 3*Tb
+ // and it's maximum value is in the last bit period, so burst starts
+ // 2*Tb earlier
+ burst_start -= 2 * d_OSR;
+ burst_start += 2;
+ //std::cout << " burst_start: " << burst_start << " center: " << ((float)(search_start_pos + strongest_window_nr + chan_imp_resp_center)) / d_OSR << " stronegest window nr: " << strongest_window_nr << "\n";
+
+ return burst_start;
+}
+
diff --git a/gsm-receiver/src/lib/gsm_receiver_cf.h b/gsm-receiver/src/lib/gsm_receiver_cf.h
new file mode 100644
index 0000000..21cb1ff
--- /dev/null
+++ b/gsm-receiver/src/lib/gsm_receiver_cf.h
@@ -0,0 +1,254 @@
+/* -*- c++ -*- */
+/*
+ * @file
+ * @author Piotr Krysik <pkrysik@stud.elka.pw.edu.pl>
+ * @section LICENSE
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+#ifndef INCLUDED_GSM_RECEIVER_CF_H
+#define INCLUDED_GSM_RECEIVER_CF_H
+
+#include <vector>
+#include <list>
+#include <gr_block.h>
+#include <gr_complex.h>
+#include <gr_feval.h>
+#include <gsm_constants.h>
+#include <gsm_receiver_config.h>
+
+#include <gsmstack.h> //TODO: remember to remove this line in the future!
+#include "GSML1FEC.h" //!!
+#include <a5-1-2.h>//!!
+#include <string>//!!
+#include <map>//!!
+
+class gsm_receiver_cf;
+
+typedef boost::shared_ptr<gsm_receiver_cf> gsm_receiver_cf_sptr;
+typedef std::vector<gr_complex> vector_complex;
+
+gsm_receiver_cf_sptr gsm_make_receiver_cf(gr_feval_dd *tuner, gr_feval_dd *synchronizer, int osr, std::string key);
+
+/** GSM Receiver GNU Radio block
+ *
+ * GSM Receiver class supports frequency correction, synchronisation and
+ * MLSE (Maximum Likelihood Sequence Estimation) estimation of synchronisation
+ * bursts and normal bursts.
+ * \ingroup block
+ */
+
+class gsm_receiver_cf : public gr_block
+{
+ private:
+ std::map<char,int> d_hex_to_int;
+ FILE * d_gsm_file; //!!
+ byte d_KC[8]; //!!
+ GSM::TCHFACCHL1Decoder d_tch_decoder1; //!!
+ GSM::TCHFACCHL1Decoder d_tch_decoder2; //!!
+ GSM::TCHFACCHL1Decoder d_tch_decoder3; //!!
+ GSM::TCHFACCHL1Decoder d_tch_decoder4; //!!
+ GSM::TCHFACCHL1Decoder d_tch_decoder5; //!!
+ GSM::TCHFACCHL1Decoder d_tch_decoder6; //!!
+ GSM::TCHFACCHL1Decoder d_tch_decoder7; //!!
+ /**@name Configuration of the receiver */
+ //@{
+ const int d_OSR; ///< oversampling ratio
+ const int d_chan_imp_length; ///< channel impulse length
+ //@}
+
+ gr_complex d_sch_training_seq[N_SYNC_BITS]; ///<encoded training sequence of a SCH burst
+ gr_complex d_norm_training_seq[TRAIN_SEQ_NUM][N_TRAIN_BITS]; ///<encoded training sequences of a normal bursts and dummy bursts
+
+ gr_feval_dd *d_tuner; ///<callback to a python object which is used for frequency tunning
+ gr_feval_dd *d_synchronizer; ///<callback to a python object which is used to correct offset of USRP's internal clock
+
+ /** Countes samples consumed by the receiver
+ *
+ * It is used in beetween find_fcch_burst and reach_sch_burst calls.
+ * My intention was to synchronize this counter with some internal sample
+ * counter of the USRP. Simple access to such USRP's counter isn't possible
+ * so this variable isn't used in the "synchronized" state of the receiver yet.
+ */
+ unsigned d_counter;
+
+ /**@name Variables used to store result of the find_fcch_burst fuction */
+ //@{
+ unsigned d_fcch_start_pos; ///< position of the first sample of the fcch burst
+ float d_freq_offset; ///< frequency offset of the received signal
+ //@}
+ std::list<double> d_freq_offset_vals;
+
+ /**@name Identifiers of the BTS extracted from the SCH burst */
+ //@{
+ int d_ncc; ///< network color code
+ int d_bcc; ///< base station color code
+ //@}
+
+ /**@name Internal state of the gsm receiver */
+ //@{
+ enum states {
+ first_fcch_search, next_fcch_search, sch_search, // synchronization search part
+ synchronized // receiver is synchronized in this state
+ } d_state;
+ //@}
+
+ /**@name Variables which make internal state in the "synchronized" state */
+ //@{
+ burst_counter d_burst_nr; ///< frame number and timeslot number
+ channel_configuration d_channel_conf; ///< mapping of burst_counter to burst_type
+ //@}
+
+ unsigned d_failed_sch; ///< number of subsequent erroneous SCH bursts
+
+ // GSM Stack
+ GS_CTX d_gs_ctx;//TODO: remove it! it'a not right place for a decoder
+
+ friend gsm_receiver_cf_sptr gsm_make_receiver_cf(gr_feval_dd *tuner, gr_feval_dd *synchronizer, int osr, std::string key);
+ gsm_receiver_cf(gr_feval_dd *tuner, gr_feval_dd *synchronizer, int osr, std::string key);
+
+ /** Function whis is used to search a FCCH burst and to compute frequency offset before
+ * "synchronized" state of the receiver
+ *
+ * TODO: Describe the FCCH search algorithm in the documentation
+ * @param input vector with input signal
+ * @param nitems number of samples in the input vector
+ * @return
+ */
+ bool find_fcch_burst(const gr_complex *input, const int nitems);
+
+ /** Computes frequency offset from FCCH burst samples
+ *
+ * @param input vector with input samples
+ * @param first_sample number of the first sample of the FCCH busrt
+ * @param last_sample number of the last sample of the FCCH busrt
+ * @return frequency offset
+ */
+ double compute_freq_offset(const gr_complex * input, unsigned first_sample, unsigned last_sample);
+
+ /** Calls d_tuner's method to set frequency offset from Python level
+ *
+ * @param freq_offset absolute frequency offset of the received signal
+ */
+ void set_frequency(double freq_offset);
+
+ /** Computes angle between two complex numbers
+ *
+ * @param val1 first complex number
+ * @param val2 second complex number
+ * @return
+ */
+ inline float compute_phase_diff(gr_complex val1, gr_complex val2);
+
+ /** Function whis is used to get near to SCH burst
+ *
+ * @param nitems number of samples in the gsm_receiver's buffer
+ * @return true if SCH burst is near, false otherwise
+ */
+ bool reach_sch_burst(const int nitems);
+
+ /** Extracts channel impulse response from a SCH burst and computes first sample number of this burst
+ *
+ * @param input vector with input samples
+ * @param chan_imp_resp complex vector where channel impulse response will be stored
+ * @return number of first sample of the burst
+ */
+ int get_sch_chan_imp_resp(const gr_complex *input, gr_complex * chan_imp_resp);
+
+ /** MLSE detection of a burst bits
+ *
+ * Detects bits of burst using viterbi algorithm.
+ * @param input vector with input samples
+ * @param chan_imp_resp vector with the channel impulse response
+ * @param burst_start number of the first sample of the burst
+ * @param output_binary vector with output bits
+ */
+ void detect_burst(const gr_complex * input, gr_complex * chan_imp_resp, int burst_start, unsigned char * output_binary);
+
+ /** Encodes differentially input bits and maps them into MSK states
+ *
+ * @param input vector with input bits
+ * @param nitems number of samples in the "input" vector
+ * @param gmsk_output bits mapped into MSK states
+ * @param start_point first state
+ */
+ void gmsk_mapper(const unsigned char * input, int nitems, gr_complex * gmsk_output, gr_complex start_point);
+
+ /** Correlates MSK mapped sequence with input signal
+ *
+ * @param sequence MKS mapped sequence
+ * @param length length of the sequence
+ * @param input_signal vector with input samples
+ * @return correlation value
+ */
+ gr_complex correlate_sequence(const gr_complex * sequence, int length, const gr_complex * input);
+
+ /** Computes autocorrelation of input vector for positive arguments
+ *
+ * @param input vector with input samples
+ * @param out output vector
+ * @param nitems length of the input vector
+ */
+ inline void autocorrelation(const gr_complex * input, gr_complex * out, int nitems);
+
+ /** Filters input signal through channel impulse response
+ *
+ * @param input vector with input samples
+ * @param nitems number of samples to pass through filter
+ * @param filter filter taps - channel impulse response
+ * @param filter_length nember of filter taps
+ * @param output vector with filtered samples
+ */
+ inline void mafi(const gr_complex * input, int nitems, gr_complex * filter, int filter_length, gr_complex * output);
+
+ /** Extracts channel impulse response from a normal burst and computes first sample number of this burst
+ *
+ * @param input vector with input samples
+ * @param chan_imp_resp complex vector where channel impulse response will be stored
+ * @param search_range possible absolute offset of a channel impulse response start
+ * @param bcc base station color code - number of a training sequence
+ * @return first sample number of normal burst
+ */
+ int get_norm_chan_imp_resp(const gr_complex * input, gr_complex * chan_imp_resp, int bcc);
+
+
+ /**
+ *
+ */
+ void read_key(std::string key);
+
+ /**
+ *
+ */
+ void process_normal_burst(burst_counter burst_nr, const unsigned char * burst_binary);
+
+ /**
+ *
+ */
+ void configure_receiver();
+
+
+
+ public:
+ ~gsm_receiver_cf();
+ void forecast(int noutput_items, gr_vector_int &ninput_items_required);
+ int general_work(int noutput_items,
+ gr_vector_int &ninput_items,
+ gr_vector_const_void_star &input_items,
+ gr_vector_void_star &output_items);
+};
+
+#endif /* INCLUDED_GSM_RECEIVER_CF_H */
diff --git a/gsm-receiver/src/lib/gsm_receiver_config.cc b/gsm-receiver/src/lib/gsm_receiver_config.cc
new file mode 100644
index 0000000..44344f7
--- /dev/null
+++ b/gsm-receiver/src/lib/gsm_receiver_config.cc
@@ -0,0 +1,84 @@
+/* -*- c++ -*- */
+/*
+ * @file
+ * @author Piotr Krysik <pkrysik@stud.elka.pw.edu.pl>
+ * @section LICENSE
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ *
+ * @section DESCRIPTION
+ * This file contains classes which define gsm_receiver configuration
+ * and the burst_counter which is used to store internal state of the receiver
+ * when it's synchronized
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gsm_receiver_config.h>
+
+burst_counter & burst_counter::operator++(int)
+{
+ d_timeslot_nr++;
+ if (d_timeslot_nr == TS_PER_FRAME) {
+ d_timeslot_nr = 0;
+
+ if ((d_t2 == 25) && (d_t3 == 50)) {
+ d_t1 = (d_t1 + 1) % (1 << 11);
+ }
+
+ d_t2 = (d_t2 + 1) % 26;
+ d_t3 = (d_t3 + 1) % 51;
+ }
+
+ //update offset - this is integer for d_OSR which is multiple of four
+ d_offset_fractional += GUARD_FRACTIONAL * d_OSR;
+ d_offset_integer = floor(d_offset_fractional);
+ d_offset_fractional = d_offset_fractional - d_offset_integer;
+ return (*this);
+}
+
+void burst_counter::set(uint32_t t1, uint32_t t2, uint32_t t3, uint32_t timeslot_nr)
+{
+ d_t1 = t1;
+ d_t2 = t2;
+ d_t3 = t3;
+ d_timeslot_nr = timeslot_nr;
+ double first_sample_position = (get_frame_nr() * 8 + timeslot_nr) * TS_BITS;
+ d_offset_fractional = first_sample_position - floor(first_sample_position);
+ d_offset_integer = 0;
+}
+
+burst_type channel_configuration::get_burst_type(burst_counter burst_nr)
+{
+ uint32_t timeslot_nr = burst_nr.get_timeslot_nr();
+ multiframe_type m_type = d_timeslots_descriptions[timeslot_nr].get_type();
+ uint32_t nr;
+
+ switch (m_type) {
+ case multiframe_26:
+ nr = burst_nr.get_t2();
+ break;
+ case multiframe_51:
+ nr = burst_nr.get_t3();
+ break;
+ default:
+ nr = 0;
+ break;
+ }
+
+ return d_timeslots_descriptions[timeslot_nr].get_burst_type(nr);
+}
diff --git a/gsm-receiver/src/lib/gsm_receiver_config.h b/gsm-receiver/src/lib/gsm_receiver_config.h
new file mode 100644
index 0000000..b7ba43a
--- /dev/null
+++ b/gsm-receiver/src/lib/gsm_receiver_config.h
@@ -0,0 +1,164 @@
+/* -*- c++ -*- */
+/*
+ * @file
+ * @author Piotr Krysik <pkrysik@stud.elka.pw.edu.pl>
+ * @section LICENSE
+ *
+ * GNU Radio is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * GNU Radio is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Radio; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ *
+ * @section DESCRIPTION
+ * This file contains classes which define gsm_receiver configuration
+ * and the burst_counter which is used to store internal state of the receiver
+ * when it's synchronized
+ */
+#ifndef INCLUDED_GSM_RECEIVER_CONFIG_H
+#define INCLUDED_GSM_RECEIVER_CONFIG_H
+
+#include <vector>
+#include <algorithm>
+#include <math.h>
+#include <stdint.h>
+#include <gsm_constants.h>
+
+class multiframe_configuration
+{
+ private:
+ multiframe_type d_type;
+ std::vector<burst_type> d_burst_types;
+ public:
+ multiframe_configuration() {
+ d_type = unknown;
+ fill(d_burst_types.begin(), d_burst_types.end(), empty);
+ }
+
+ ~multiframe_configuration() {}
+
+ void set_type(multiframe_type type) {
+ if (type == multiframe_26) {
+ d_burst_types.resize(26);
+ } else {
+ d_burst_types.resize(51);
+ }
+
+ d_type = type;
+ }
+
+ void set_burst_type(int nr, burst_type type) {
+ d_burst_types[nr] = type;
+ }
+
+ multiframe_type get_type() {
+ return d_type;
+ }
+
+ burst_type get_burst_type(int nr) {
+ return d_burst_types[nr];
+ }
+};
+
+class burst_counter
+{
+ private:
+ const int d_OSR;
+ uint32_t d_t1, d_t2, d_t3, d_timeslot_nr;
+ double d_offset_fractional;
+ double d_offset_integer;
+ public:
+ burst_counter(int osr):
+ d_OSR(osr),
+ d_t1(0),
+ d_t2(0),
+ d_t3(0),
+ d_timeslot_nr(0),
+ d_offset_fractional(0.0),
+ d_offset_integer(0.0) {
+ }
+
+ burst_counter(int osr, uint32_t t1, uint32_t t2, uint32_t t3, uint32_t timeslot_nr):
+ d_OSR(osr),
+ d_t1(t1),
+ d_t2(t2),
+ d_t3(t3),
+ d_timeslot_nr(timeslot_nr),
+ d_offset_fractional(0.0),
+ d_offset_integer(0.0) {
+ double first_sample_position = (get_frame_nr() * 8 + timeslot_nr) * TS_BITS;
+ d_offset_integer = floor(first_sample_position);
+ d_offset_fractional = first_sample_position - floor(first_sample_position);
+ }
+
+ burst_counter & operator++(int);
+ void set(uint32_t t1, uint32_t t2, uint32_t t3, uint32_t timeslot_nr);
+
+ uint32_t get_t1() {
+ return d_t1;
+ }
+
+ uint32_t get_t2() {
+ return d_t2;
+ }
+
+ uint32_t get_t3() {
+ return d_t3;
+ }
+
+ uint32_t get_timeslot_nr() {
+ return d_timeslot_nr;
+ }
+
+ uint32_t get_frame_nr() {
+ return (51 * 26 * d_t1) + (51 * (((d_t3 + 26) - d_t2) % 26)) + d_t3;
+ }
+
+ uint32_t get_frame_nr_mod() {
+ return (d_t1 << 11) + (d_t3 << 5) + d_t2;
+ }
+
+ unsigned get_offset() {
+ return (unsigned)d_offset_integer;
+ }
+};
+
+class channel_configuration
+{
+ private:
+ multiframe_configuration d_timeslots_descriptions[TS_PER_FRAME];
+ public:
+ channel_configuration() {
+ for (int i = 0; i < TS_PER_FRAME; i++) {
+ d_timeslots_descriptions[i].set_type(unknown);
+ }
+ }
+
+ void set_multiframe_type(int timeslot_nr, multiframe_type type) {
+ d_timeslots_descriptions[timeslot_nr].set_type(type);
+ }
+
+ void set_burst_types(int timeslot_nr, const unsigned mapping[], unsigned mapping_size, burst_type b_type) {
+ unsigned i;
+ for (i = 0; i < mapping_size; i++) {
+ d_timeslots_descriptions[timeslot_nr].set_burst_type(mapping[i], b_type);
+ }
+ }
+
+ void set_single_burst_type(int timeslot_nr, int burst_nr, burst_type b_type) {
+ d_timeslots_descriptions[timeslot_nr].set_burst_type(burst_nr, b_type);
+ }
+
+ burst_type get_burst_type(burst_counter burst_nr);
+};
+
+#endif /* INCLUDED_GSM_RECEIVER_CONFIG_H */
diff --git a/gsm-receiver/src/lib/viterbi_detector.cc b/gsm-receiver/src/lib/viterbi_detector.cc
new file mode 100644
index 0000000..f3445cf
--- /dev/null
+++ b/gsm-receiver/src/lib/viterbi_detector.cc
@@ -0,0 +1,554 @@
+/* -*- c++ -*- */
+/*
+ * @file
+ * @author Piotr Krysik <pkrysik@stud.elka.pw.edu.pl>
+ * @section LICENSE
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/*
+ * viterbi_detector:
+ * This part does the detection of received sequnece.
+ * Employed algorithm is viterbi Maximum Likehood Sequence Estimation.
+ * At this moment it gives hard decisions on the output, but
+ * it was designed with soft decisions in mind.
+ *
+ * SYNTAX: void viterbi_detector(
+ * const gr_complex * input,
+ * unsigned int samples_num,
+ * gr_complex * rhh,
+ * unsigned int start_state,
+ * const unsigned int * stop_states,
+ * unsigned int stops_num,
+ * float * output)
+ *
+ * INPUT: input: Complex received signal afted matched filtering.
+ * samples_num: Number of samples in the input table.
+ * rhh: The autocorrelation of the estimated channel
+ * impulse response.
+ * start_state: Number of the start point. In GSM each burst
+ * starts with sequence of three bits (0,0,0) which
+ * indicates start point of the algorithm.
+ * stop_states: Table with numbers of possible stop states.
+ * stops_num: Number of possible stop states
+ *
+ *
+ * OUTPUT: output: Differentially decoded hard output of the algorithm:
+ * -1 for logical "0" and 1 for logical "1"
+ *
+ * SUB_FUNC: none
+ *
+ * TEST(S): Tested with real world normal burst.
+ */
+
+#include <gnuradio/gr_complex.h>
+#include <gsm_constants.h>
+#define PATHS_NUM (1 << (CHAN_IMP_RESP_LENGTH-1))
+
+void viterbi_detector(const gr_complex * input, unsigned int samples_num, gr_complex * rhh, unsigned int start_state, const unsigned int * stop_states, unsigned int stops_num, float * output)
+{
+ float increment[8];
+ float path_metrics1[16];
+ float path_metrics2[16];
+ float * new_path_metrics;
+ float * old_path_metrics;
+ float * tmp;
+ float trans_table[BURST_SIZE][16];
+ float pm_candidate1, pm_candidate2;
+ bool real_imag;
+ float input_symbol_real, input_symbol_imag;
+ unsigned int i, sample_nr;
+
+/*
+* Setup first path metrics, so only state pointed by start_state is possible.
+* Start_state metric is equal to zero, the rest is written with some very low value,
+* which makes them practically impossible to occur.
+*/
+ for(i=0; i<PATHS_NUM; i++){
+ path_metrics1[i]=(-10e30);
+ }
+ path_metrics1[start_state]=0;
+
+/*
+* Compute Increment - a table of values which does not change for subsequent input samples.
+* Increment is table of reference levels for computation of branch metrics:
+* branch metric = (+/-)received_sample (+/-) reference_level
+*/
+ increment[0] = -rhh[1].imag() -rhh[2].real() -rhh[3].imag() +rhh[4].real();
+ increment[1] = rhh[1].imag() -rhh[2].real() -rhh[3].imag() +rhh[4].real();
+ increment[2] = -rhh[1].imag() +rhh[2].real() -rhh[3].imag() +rhh[4].real();
+ increment[3] = rhh[1].imag() +rhh[2].real() -rhh[3].imag() +rhh[4].real();
+ increment[4] = -rhh[1].imag() -rhh[2].real() +rhh[3].imag() +rhh[4].real();
+ increment[5] = rhh[1].imag() -rhh[2].real() +rhh[3].imag() +rhh[4].real();
+ increment[6] = -rhh[1].imag() +rhh[2].real() +rhh[3].imag() +rhh[4].real();
+ increment[7] = rhh[1].imag() +rhh[2].real() +rhh[3].imag() +rhh[4].real();
+
+
+/*
+* Computation of path metrics and decisions (Add-Compare-Select).
+* It's composed of two parts: one for odd input samples (imaginary numbers)
+* and one for even samples (real numbers).
+* Each part is composed of independent (parallelisable) statements like
+* this one:
+* pm_candidate1 = old_path_metrics[0] - input_symbol_real - increment[7];
+* pm_candidate2 = old_path_metrics[8] - input_symbol_real + increment[0];
+* if(pm_candidate1 > pm_candidate2){
+* new_path_metrics[0] = pm_candidate1;
+* trans_table[sample_nr][0] = -1.0;
+* }
+* else{
+* new_path_metrics[0] = pm_candidate2;
+* trans_table[sample_nr][0] = 1.0;
+* }
+* This is very good point for optimisations (SIMD or OpenMP) as it's most time
+* consuming part of this function.
+*/
+ sample_nr=0;
+ old_path_metrics=path_metrics1;
+ new_path_metrics=path_metrics2;
+ while(sample_nr<samples_num){
+ //Processing imag states
+ real_imag=1;
+ input_symbol_imag = input[sample_nr].imag();
+
+ pm_candidate1 = old_path_metrics[0] + input_symbol_imag - increment[2];
+ pm_candidate2 = old_path_metrics[8] + input_symbol_imag + increment[5];
+ if(pm_candidate1 > pm_candidate2){
+ new_path_metrics[0] = pm_candidate1;
+ trans_table[sample_nr][0] = -1.0;
+ }
+ else{
+ new_path_metrics[0] = pm_candidate2;
+ trans_table[sample_nr][0] = 1.0;
+ }
+
+ pm_candidate1 = old_path_metrics[0] - input_symbol_imag + increment[2];
+ pm_candidate2 = old_path_metrics[8] - input_symbol_imag - increment[5];
+ if(pm_candidate1 > pm_candidate2){
+ new_path_metrics[1] = pm_candidate1;
+ trans_table[sample_nr][1] = -1.0;
+ }
+ else{
+ new_path_metrics[1] = pm_candidate2;
+ trans_table[sample_nr][1] = 1.0;
+ }
+
+ pm_candidate1 = old_path_metrics[1] + input_symbol_imag - increment[3];
+ pm_candidate2 = old_path_metrics[9] + input_symbol_imag + increment[4];
+ if(pm_candidate1 > pm_candidate2){
+ new_path_metrics[2] = pm_candidate1;
+ trans_table[sample_nr][2] = -1.0;
+ }
+ else{
+ new_path_metrics[2] = pm_candidate2;
+ trans_table[sample_nr][2] = 1.0;
+ }
+
+ pm_candidate1 = old_path_metrics[1] - input_symbol_imag + increment[3];
+ pm_candidate2 = old_path_metrics[9] - input_symbol_imag - increment[4];
+ if(pm_candidate1 > pm_candidate2){
+ new_path_metrics[3] = pm_candidate1;
+ trans_table[sample_nr][3] = -1.0;
+ }
+ else{
+ new_path_metrics[3] = pm_candidate2;
+ trans_table[sample_nr][3] = 1.0;
+ }
+
+ pm_candidate1 = old_path_metrics[2] + input_symbol_imag - increment[0];
+ pm_candidate2 = old_path_metrics[10] + input_symbol_imag + increment[7];
+ if(pm_candidate1 > pm_candidate2){
+ new_path_metrics[4] = pm_candidate1;
+ trans_table[sample_nr][4] = -1.0;
+ }
+ else{
+ new_path_metrics[4] = pm_candidate2;
+ trans_table[sample_nr][4] = 1.0;
+ }
+
+ pm_candidate1 = old_path_metrics[2] - input_symbol_imag + increment[0];
+ pm_candidate2 = old_path_metrics[10] - input_symbol_imag - increment[7];
+ if(pm_candidate1 > pm_candidate2){
+ new_path_metrics[5] = pm_candidate1;
+ trans_table[sample_nr][5] = -1.0;
+ }
+ else{
+ new_path_metrics[5] = pm_candidate2;
+ trans_table[sample_nr][5] = 1.0;
+ }
+
+ pm_candidate1 = old_path_metrics[3] + input_symbol_imag - increment[1];
+ pm_candidate2 = old_path_metrics[11] + input_symbol_imag + increment[6];
+ if(pm_candidate1 > pm_candidate2){
+ new_path_metrics[6] = pm_candidate1;
+ trans_table[sample_nr][6] = -1.0;
+ }
+ else{
+ new_path_metrics[6] = pm_candidate2;
+ trans_table[sample_nr][6] = 1.0;
+ }
+
+ pm_candidate1 = old_path_metrics[3] - input_symbol_imag + increment[1];
+ pm_candidate2 = old_path_metrics[11] - input_symbol_imag - increment[6];
+ if(pm_candidate1 > pm_candidate2){
+ new_path_metrics[7] = pm_candidate1;
+ trans_table[sample_nr][7] = -1.0;
+ }
+ else{
+ new_path_metrics[7] = pm_candidate2;
+ trans_table[sample_nr][7] = 1.0;
+ }
+
+ pm_candidate1 = old_path_metrics[4] + input_symbol_imag - increment[6];
+ pm_candidate2 = old_path_metrics[12] + input_symbol_imag + increment[1];
+ if(pm_candidate1 > pm_candidate2){
+ new_path_metrics[8] = pm_candidate1;
+ trans_table[sample_nr][8] = -1.0;
+ }
+ else{
+ new_path_metrics[8] = pm_candidate2;
+ trans_table[sample_nr][8] = 1.0;
+ }
+
+ pm_candidate1 = old_path_metrics[4] - input_symbol_imag + increment[6];
+ pm_candidate2 = old_path_metrics[12] - input_symbol_imag - increment[1];
+ if(pm_candidate1 > pm_candidate2){
+ new_path_metrics[9] = pm_candidate1;
+ trans_table[sample_nr][9] = -1.0;
+ }
+ else{
+ new_path_metrics[9] = pm_candidate2;
+ trans_table[sample_nr][9] = 1.0;
+ }
+
+ pm_candidate1 = old_path_metrics[5] + input_symbol_imag - increment[7];
+ pm_candidate2 = old_path_metrics[13] + input_symbol_imag + increment[0];
+ if(pm_candidate1 > pm_candidate2){
+ new_path_metrics[10] = pm_candidate1;
+ trans_table[sample_nr][10] = -1.0;
+ }
+ else{
+ new_path_metrics[10] = pm_candidate2;
+ trans_table[sample_nr][10] = 1.0;
+ }
+
+ pm_candidate1 = old_path_metrics[5] - input_symbol_imag + increment[7];
+ pm_candidate2 = old_path_metrics[13] - input_symbol_imag - increment[0];
+ if(pm_candidate1 > pm_candidate2){
+ new_path_metrics[11] = pm_candidate1;
+ trans_table[sample_nr][11] = -1.0;
+ }
+ else{
+ new_path_metrics[11] = pm_candidate2;
+ trans_table[sample_nr][11] = 1.0;
+ }
+
+ pm_candidate1 = old_path_metrics[6] + input_symbol_imag - increment[4];
+ pm_candidate2 = old_path_metrics[14] + input_symbol_imag + increment[3];
+ if(pm_candidate1 > pm_candidate2){
+ new_path_metrics[12] = pm_candidate1;
+ trans_table[sample_nr][12] = -1.0;
+ }
+ else{
+ new_path_metrics[12] = pm_candidate2;
+ trans_table[sample_nr][12] = 1.0;
+ }
+
+ pm_candidate1 = old_path_metrics[6] - input_symbol_imag + increment[4];
+ pm_candidate2 = old_path_metrics[14] - input_symbol_imag - increment[3];
+ if(pm_candidate1 > pm_candidate2){
+ new_path_metrics[13] = pm_candidate1;
+ trans_table[sample_nr][13] = -1.0;
+ }
+ else{
+ new_path_metrics[13] = pm_candidate2;
+ trans_table[sample_nr][13] = 1.0;
+ }
+
+ pm_candidate1 = old_path_metrics[7] + input_symbol_imag - increment[5];
+ pm_candidate2 = old_path_metrics[15] + input_symbol_imag + increment[2];
+ if(pm_candidate1 > pm_candidate2){
+ new_path_metrics[14] = pm_candidate1;
+ trans_table[sample_nr][14] = -1.0;
+ }
+ else{
+ new_path_metrics[14] = pm_candidate2;
+ trans_table[sample_nr][14] = 1.0;
+ }
+
+ pm_candidate1 = old_path_metrics[7] - input_symbol_imag + increment[5];
+ pm_candidate2 = old_path_metrics[15] - input_symbol_imag - increment[2];
+ if(pm_candidate1 > pm_candidate2){
+ new_path_metrics[15] = pm_candidate1;
+ trans_table[sample_nr][15] = -1.0;
+ }
+ else{
+ new_path_metrics[15] = pm_candidate2;
+ trans_table[sample_nr][15] = 1.0;
+ }
+ tmp=old_path_metrics;
+ old_path_metrics=new_path_metrics;
+ new_path_metrics=tmp;
+
+ sample_nr++;
+ if(sample_nr==samples_num)
+ break;
+
+ //Processing real states
+ real_imag=0;
+ input_symbol_real = input[sample_nr].real();
+
+ pm_candidate1 = old_path_metrics[0] - input_symbol_real - increment[7];
+ pm_candidate2 = old_path_metrics[8] - input_symbol_real + increment[0];
+ if(pm_candidate1 > pm_candidate2){
+ new_path_metrics[0] = pm_candidate1;
+ trans_table[sample_nr][0] = -1.0;
+ }
+ else{
+ new_path_metrics[0] = pm_candidate2;
+ trans_table[sample_nr][0] = 1.0;
+ }
+
+ pm_candidate1 = old_path_metrics[0] + input_symbol_real + increment[7];
+ pm_candidate2 = old_path_metrics[8] + input_symbol_real - increment[0];
+ if(pm_candidate1 > pm_candidate2){
+ new_path_metrics[1] = pm_candidate1;
+ trans_table[sample_nr][1] = -1.0;
+ }
+ else{
+ new_path_metrics[1] = pm_candidate2;
+ trans_table[sample_nr][1] = 1.0;
+ }
+
+ pm_candidate1 = old_path_metrics[1] - input_symbol_real - increment[6];
+ pm_candidate2 = old_path_metrics[9] - input_symbol_real + increment[1];
+ if(pm_candidate1 > pm_candidate2){
+ new_path_metrics[2] = pm_candidate1;
+ trans_table[sample_nr][2] = -1.0;
+ }
+ else{
+ new_path_metrics[2] = pm_candidate2;
+ trans_table[sample_nr][2] = 1.0;
+ }
+
+ pm_candidate1 = old_path_metrics[1] + input_symbol_real + increment[6];
+ pm_candidate2 = old_path_metrics[9] + input_symbol_real - increment[1];
+ if(pm_candidate1 > pm_candidate2){
+ new_path_metrics[3] = pm_candidate1;
+ trans_table[sample_nr][3] = -1.0;
+ }
+ else{
+ new_path_metrics[3] = pm_candidate2;
+ trans_table[sample_nr][3] = 1.0;
+ }
+
+ pm_candidate1 = old_path_metrics[2] - input_symbol_real - increment[5];
+ pm_candidate2 = old_path_metrics[10] - input_symbol_real + increment[2];
+ if(pm_candidate1 > pm_candidate2){
+ new_path_metrics[4] = pm_candidate1;
+ trans_table[sample_nr][4] = -1.0;
+ }
+ else{
+ new_path_metrics[4] = pm_candidate2;
+ trans_table[sample_nr][4] = 1.0;
+ }
+
+ pm_candidate1 = old_path_metrics[2] + input_symbol_real + increment[5];
+ pm_candidate2 = old_path_metrics[10] + input_symbol_real - increment[2];
+ if(pm_candidate1 > pm_candidate2){
+ new_path_metrics[5] = pm_candidate1;
+ trans_table[sample_nr][5] = -1.0;
+ }
+ else{
+ new_path_metrics[5] = pm_candidate2;
+ trans_table[sample_nr][5] = 1.0;
+ }
+
+ pm_candidate1 = old_path_metrics[3] - input_symbol_real - increment[4];
+ pm_candidate2 = old_path_metrics[11] - input_symbol_real + increment[3];
+ if(pm_candidate1 > pm_candidate2){
+ new_path_metrics[6] = pm_candidate1;
+ trans_table[sample_nr][6] = -1.0;
+ }
+ else{
+ new_path_metrics[6] = pm_candidate2;
+ trans_table[sample_nr][6] = 1.0;
+ }
+
+ pm_candidate1 = old_path_metrics[3] + input_symbol_real + increment[4];
+ pm_candidate2 = old_path_metrics[11] + input_symbol_real - increment[3];
+ if(pm_candidate1 > pm_candidate2){
+ new_path_metrics[7] = pm_candidate1;
+ trans_table[sample_nr][7] = -1.0;
+ }
+ else{
+ new_path_metrics[7] = pm_candidate2;
+ trans_table[sample_nr][7] = 1.0;
+ }
+
+ pm_candidate1 = old_path_metrics[4] - input_symbol_real - increment[3];
+ pm_candidate2 = old_path_metrics[12] - input_symbol_real + increment[4];
+ if(pm_candidate1 > pm_candidate2){
+ new_path_metrics[8] = pm_candidate1;
+ trans_table[sample_nr][8] = -1.0;
+ }
+ else{
+ new_path_metrics[8] = pm_candidate2;
+ trans_table[sample_nr][8] = 1.0;
+ }
+
+ pm_candidate1 = old_path_metrics[4] + input_symbol_real + increment[3];
+ pm_candidate2 = old_path_metrics[12] + input_symbol_real - increment[4];
+ if(pm_candidate1 > pm_candidate2){
+ new_path_metrics[9] = pm_candidate1;
+ trans_table[sample_nr][9] = -1.0;
+ }
+ else{
+ new_path_metrics[9] = pm_candidate2;
+ trans_table[sample_nr][9] = 1.0;
+ }
+
+ pm_candidate1 = old_path_metrics[5] - input_symbol_real - increment[2];
+ pm_candidate2 = old_path_metrics[13] - input_symbol_real + increment[5];
+ if(pm_candidate1 > pm_candidate2){
+ new_path_metrics[10] = pm_candidate1;
+ trans_table[sample_nr][10] = -1.0;
+ }
+ else{
+ new_path_metrics[10] = pm_candidate2;
+ trans_table[sample_nr][10] = 1.0;
+ }
+
+ pm_candidate1 = old_path_metrics[5] + input_symbol_real + increment[2];
+ pm_candidate2 = old_path_metrics[13] + input_symbol_real - increment[5];
+ if(pm_candidate1 > pm_candidate2){
+ new_path_metrics[11] = pm_candidate1;
+ trans_table[sample_nr][11] = -1.0;
+ }
+ else{
+ new_path_metrics[11] = pm_candidate2;
+ trans_table[sample_nr][11] = 1.0;
+ }
+
+ pm_candidate1 = old_path_metrics[6] - input_symbol_real - increment[1];
+ pm_candidate2 = old_path_metrics[14] - input_symbol_real + increment[6];
+ if(pm_candidate1 > pm_candidate2){
+ new_path_metrics[12] = pm_candidate1;
+ trans_table[sample_nr][12] = -1.0;
+ }
+ else{
+ new_path_metrics[12] = pm_candidate2;
+ trans_table[sample_nr][12] = 1.0;
+ }
+
+ pm_candidate1 = old_path_metrics[6] + input_symbol_real + increment[1];
+ pm_candidate2 = old_path_metrics[14] + input_symbol_real - increment[6];
+ if(pm_candidate1 > pm_candidate2){
+ new_path_metrics[13] = pm_candidate1;
+ trans_table[sample_nr][13] = -1.0;
+ }
+ else{
+ new_path_metrics[13] = pm_candidate2;
+ trans_table[sample_nr][13] = 1.0;
+ }
+
+ pm_candidate1 = old_path_metrics[7] - input_symbol_real - increment[0];
+ pm_candidate2 = old_path_metrics[15] - input_symbol_real + increment[7];
+ if(pm_candidate1 > pm_candidate2){
+ new_path_metrics[14] = pm_candidate1;
+ trans_table[sample_nr][14] = -1.0;
+ }
+ else{
+ new_path_metrics[14] = pm_candidate2;
+ trans_table[sample_nr][14] = 1.0;
+ }
+
+ pm_candidate1 = old_path_metrics[7] + input_symbol_real + increment[0];
+ pm_candidate2 = old_path_metrics[15] + input_symbol_real - increment[7];
+ if(pm_candidate1 > pm_candidate2){
+ new_path_metrics[15] = pm_candidate1;
+ trans_table[sample_nr][15] = -1.0;
+ }
+ else{
+ new_path_metrics[15] = pm_candidate2;
+ trans_table[sample_nr][15] = 1.0;
+ }
+ tmp=old_path_metrics;
+ old_path_metrics=new_path_metrics;
+ new_path_metrics=tmp;
+
+ sample_nr++;
+ }
+
+/*
+* Find the best from the stop states by comparing their path metrics.
+* Not every stop state is always possible, so we are searching in
+* a subset of them.
+*/
+ unsigned int best_stop_state;
+ float stop_state_metric, max_stop_state_metric;
+ best_stop_state = stop_states[0];
+ max_stop_state_metric = old_path_metrics[best_stop_state];
+ for(i=1; i< stops_num; i++){
+ stop_state_metric = old_path_metrics[stop_states[i]];
+ if(stop_state_metric > max_stop_state_metric){
+ max_stop_state_metric = stop_state_metric;
+ best_stop_state = stop_states[i];
+ }
+ }
+
+/*
+* This table was generated with hope that it gives a litle speedup during
+* traceback stage.
+* Received bit is related to the number of state in the trellis.
+* I've numbered states so their parity (number of ones) is related
+* to a received bit.
+*/
+ static const unsigned int parity_table[PATHS_NUM] = { 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, };
+
+/*
+* Table of previous states in the trellis diagram.
+* For GMSK modulation every state has two previous states.
+* Example:
+* previous_state_nr1 = prev_table[current_state_nr][0]
+* previous_state_nr2 = prev_table[current_state_nr][1]
+*/
+ static const unsigned int prev_table[PATHS_NUM][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}, };
+
+/*
+* Traceback and differential decoding of received sequence.
+* Decisions stored in trans_table are used to restore best path in the trellis.
+*/
+ sample_nr=samples_num;
+ unsigned int state_nr=best_stop_state;
+ unsigned int decision;
+ bool out_bit=0;
+
+ while(sample_nr>0){
+ sample_nr--;
+ decision = (trans_table[sample_nr][state_nr]>0);
+
+ if(decision != out_bit)
+ output[sample_nr]=-trans_table[sample_nr][state_nr];
+ else
+ output[sample_nr]=trans_table[sample_nr][state_nr];
+
+ out_bit = out_bit ^ real_imag ^ parity_table[state_nr];
+ state_nr = prev_table[state_nr][decision];
+ real_imag = !real_imag;
+ }
+}
diff --git a/gsm-receiver/src/lib/viterbi_detector.h b/gsm-receiver/src/lib/viterbi_detector.h
new file mode 100644
index 0000000..0360f83
--- /dev/null
+++ b/gsm-receiver/src/lib/viterbi_detector.h
@@ -0,0 +1,63 @@
+/* -*- c++ -*- */
+/*
+ * @file
+ * @author Piotr Krysik <pkrysik@stud.elka.pw.edu.pl>
+ * @section LICENSE
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; see the file COPYING. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/*
+ * viterbi_detector:
+ * This part does the detection of received sequnece.
+ * Employed algorithm is viterbi Maximum Likehood Sequence Estimation.
+ * At this moment it gives hard decisions on the output, but
+ * it was designed with soft decisions in mind.
+ *
+ * SYNTAX: void viterbi_detector(
+ * const gr_complex * input,
+ * unsigned int samples_num,
+ * gr_complex * rhh,
+ * unsigned int start_state,
+ * const unsigned int * stop_states,
+ * unsigned int stops_num,
+ * float * output)
+ *
+ * INPUT: input: Complex received signal afted matched filtering.
+ * samples_num: Number of samples in the input table.
+ * rhh: The autocorrelation of the estimated channel
+ * impulse response.
+ * start_state: Number of the start point. In GSM each burst
+ * starts with sequence of three bits (0,0,0) which
+ * indicates start point of the algorithm.
+ * stop_states: Table with numbers of possible stop states.
+ * stops_num: Number of possible stop states
+ *
+ *
+ * OUTPUT: output: Differentially decoded hard output of the algorithm:
+ * -1 for logical "0" and 1 for logical "1"
+ *
+ * SUB_FUNC: none
+ *
+ * TEST(S): Tested with real world normal burst.
+ */
+
+#ifndef INCLUDED_VITERBI_DETECTOR_H
+#define INCLUDED_VITERBI_DETECTOR_H
+
+void viterbi_detector(const gr_complex * input, unsigned int samples_num, gr_complex * rhh, unsigned int start_state, const unsigned int * stop_states, unsigned int stops_num, float * output);
+
+#endif /* INCLUDED_VITERBI_DETECTOR_H */
diff --git a/gsm-receiver/src/python/Makefile.am b/gsm-receiver/src/python/Makefile.am
new file mode 100644
index 0000000..9a4befd
--- /dev/null
+++ b/gsm-receiver/src/python/Makefile.am
@@ -0,0 +1,24 @@
+#
+# Copyright 2004 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+#
+
+include $(top_srcdir)/Makefile.common
+
+EXTRA_DIST = gsm_findfcch.py gsm_findfcch_usrp.py
diff --git a/gsm-receiver/src/python/capture.sh b/gsm-receiver/src/python/capture.sh
new file mode 100755
index 0000000..ef205d8
--- /dev/null
+++ b/gsm-receiver/src/python/capture.sh
@@ -0,0 +1,45 @@
+#! /bin/sh
+
+if [ $1"x" = x ]; then
+ echo "./capture.sh <freq> [duration==10] [decim==112] [gain==52]"
+ echo "Example: ./capture.sh 940.4M"
+ exit 1
+fi
+FREQ=$1
+
+DURATION=$2
+if [ $2"x" = x ]; then
+ DURATION=10
+fi
+DECIM=$3
+if [ $3"x" = x ]; then
+ DECIM=112
+fi
+
+GAIN=$4
+if [ $4"x" = x ]; then
+ GAIN=52
+fi
+
+
+USRP_PROG=usrp_rx_cfile.py
+while :; do
+ which "$USRP_PROG"
+ if [ $? -eq 0 ]; then
+ break
+ fi
+ USRP_PROG=/usr/share/gnuradio/usrp/usrp_rx_cfile.py
+ which "$USRP_PROG"
+ if [ $? -eq 0 ]; then
+ break
+ fi
+
+ echo "ERROR: usrp_rx_cfile.py not found. Make sure it's in your PATH!"
+ exit 1
+done
+
+FILE="capture_${FREQ}_${DECIM}.cfile"
+samples=`expr 64000000 / $DECIM '*' $DURATION`
+echo "Capturing for $DURATION seconds to $FILE ($samples samples)"
+$USRP_PROG -g $GAIN -d "$DECIM" -f "$FREQ" -N $samples $FILE
+
diff --git a/gsm-receiver/src/python/cfile b/gsm-receiver/src/python/cfile
new file mode 100644
index 0000000..943e35f
--- /dev/null
+++ b/gsm-receiver/src/python/cfile
Binary files differ
diff --git a/gsm-receiver/src/python/go.sh b/gsm-receiver/src/python/go.sh
new file mode 100755
index 0000000..e0d1290
--- /dev/null
+++ b/gsm-receiver/src/python/go.sh
@@ -0,0 +1,12 @@
+#! /bin/sh
+
+#echo "go.sh <file.cfile> [decim==112]"
+
+DECIM=$2
+FILE=$1
+
+if [ $DECIM"x" = x ]; then
+ DECIM=112
+fi
+
+./gsm_receive.py -d "$DECIM" -I "$FILE" | ../../../gsmdecode/src/gsmdecode -i
diff --git a/gsm-receiver/src/python/gsm_receive.py b/gsm-receiver/src/python/gsm_receive.py
new file mode 100755
index 0000000..4cfb876
--- /dev/null
+++ b/gsm-receiver/src/python/gsm_receive.py
@@ -0,0 +1,117 @@
+#!/usr/bin/env python
+
+from gnuradio import gr, gru, blks2
+#, gsm
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+from os import sys
+
+for extdir in ['../../debug/src/lib','../../debug/src/lib/.libs','../lib','../lib/.libs','../..debug/src/lib/decoder/openbts/SIP']:
+ if extdir not in sys.path:
+ sys.path.append(extdir)
+import gsm
+
+class tuner(gr.feval_dd):
+ def __init__(self, top_block):
+ gr.feval_dd.__init__(self)
+ self.top_block = top_block
+ def eval(self, freq_offet):
+ self.top_block.set_center_frequency(freq_offet)
+ return freq_offet
+
+class synchronizer(gr.feval_dd):
+ def __init__(self, top_block):
+ gr.feval_dd.__init__(self)
+ self.top_block = top_block
+
+ def eval(self, timing_offset):
+ self.top_block.set_timing(timing_offset)
+ return freq_offet
+
+class gsm_receiver_first_blood(gr.top_block):
+ def __init__(self):
+ gr.top_block.__init__(self)
+ (options, args) = self._process_options()
+ self.tuner_callback = tuner(self)
+ self.synchronizer_callback = synchronizer(self)
+ self.options = options
+ self.args = args
+ self._set_rates()
+ self.source = self._set_source()
+ self.filtr = self._set_filter()
+ self.interpolator = self._set_interpolator()
+ self.receiver = self._set_receiver()
+ self.converter = self._set_converter()
+ self.sink = self._set_sink()
+
+ self.connect(self.source, self.filtr, self.interpolator, self.receiver, self.converter, self.sink)
+
+ def _set_sink(self):
+ nazwa_pliku_wy = self.options.outputfile
+ ujscie = gr.file_sink(gr.sizeof_float, nazwa_pliku_wy)
+ return ujscie
+
+ def _set_source(self):
+ nazwa_pliku = self.options.inputfile
+ zrodlo = gr.file_source(gr.sizeof_gr_complex, nazwa_pliku, False)
+ return zrodlo
+
+ def _set_rates(self):
+ options = self.options
+ clock_rate = 64e6
+ self.clock_rate = clock_rate
+ self.input_rate = clock_rate / options.decim
+ self.gsm_symb_rate = 1625000.0 / 6.0
+ self.sps = self.input_rate / self.gsm_symb_rate / self.options.osr
+
+ def _set_filter(self):
+ filter_cutoff = 145e3
+ filter_t_width = 10e3
+ offset = 0
+# print "input_rate:", self.input_rate, "sample rate:", self.sps, " filter_cutoff:", filter_cutoff, " filter_t_width:", filter_t_width
+ filter_taps = gr.firdes.low_pass(1.0, self.input_rate, filter_cutoff, filter_t_width, gr.firdes.WIN_HAMMING)
+ filtr = gr.freq_xlating_fir_filter_ccf(1, filter_taps, offset, self.input_rate)
+ return filtr
+
+ def _set_converter(self):
+ v2s = gr.vector_to_stream(gr.sizeof_float, 142)
+ return v2s
+
+ def _set_interpolator(self):
+ interpolator = gr.fractional_interpolator_cc(0, self.sps)
+ return interpolator
+
+ def _set_receiver(self):
+ receiver = gsm.receiver_cf(self.tuner_callback, self.synchronizer_callback, self.options.osr, self.options.key.replace(' ', '').lower())
+ return receiver
+
+ def _process_options(self):
+ parser = OptionParser(option_class=eng_option)
+ parser.add_option("-d", "--decim", type="int", default=128,
+ help="Set USRP decimation rate to DECIM [default=%default]")
+ parser.add_option("-r", "--osr", type="int", default=4,
+ help="Oversampling ratio [default=%default]")
+ parser.add_option("-I", "--inputfile", type="string", default="cfile",
+ help="Input filename")
+ parser.add_option("-O", "--outputfile", type="string", default="cfile2.out",
+ help="Output filename")
+ parser.add_option("-k", "--key", type="string", default="2B 08 74 9F DD 0D 9C 00",
+ help="KC session key")
+
+ (options, args) = parser.parse_args ()
+ return (options, args)
+
+ def set_center_frequency(self, center_freq):
+ self.filtr.set_center_freq(center_freq)
+
+ def set_timing(self, timing_offset):
+ pass
+
+def main():
+ try:
+ gsm_receiver_first_blood().run()
+ except KeyboardInterrupt:
+ pass
+
+if __name__ == '__main__':
+ main()
diff --git a/gsm-receiver/src/python/gsm_receive_usrp.py b/gsm-receiver/src/python/gsm_receive_usrp.py
new file mode 100755
index 0000000..a4e9720
--- /dev/null
+++ b/gsm-receiver/src/python/gsm_receive_usrp.py
@@ -0,0 +1,141 @@
+#!/usr/bin/env python
+#this file isn't ready to use now - gsm-receiver lacks realtime processing capability
+#there are many underruns of buffer for samples from usrp's, many blocks of samples get lost and
+#receiver isn't prepared for this situation too well
+
+from gnuradio import gr, gru, blks2
+#, gsm
+from gnuradio import usrp
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+from os import sys
+
+for extdir in ['../../debug/src/lib','../../debug/src/lib/.libs']:
+ if extdir not in sys.path:
+ sys.path.append(extdir)
+import gsm
+
+def pick_subdevice(u):
+ if u.db[0][0].dbid() >= 0:
+ return (0, 0)
+ if u.db[1][0].dbid() >= 0:
+ return (1, 0)
+ return (0, 0)
+
+class tune(gr.feval_dd):
+ def __init__(self, top_block):
+ gr.feval_dd.__init__(self)
+ self.top_block = top_block
+ # self.center_freq = 0
+ def eval(self, freq_offet):
+ # self.center_freq = self.center_freq - freq_offet
+ self.top_block.set_frequency(freq_offet)
+ return freq_offet
+
+class gsm_receiver_first_blood(gr.top_block):
+ def __init__(self):
+ gr.top_block.__init__(self)
+ (options, args) = self._process_options()
+ self.tune_callback = tune(self)
+ self.options = options
+ self.args = args
+ self._set_rates()
+ self.source = self._set_source()
+ self.filtr = self._set_filter()
+ self.interpolator = self._set_interpolator()
+ self.receiver = self._set_receiver()
+ self.converter = self._set_converter()
+ self.sink = self._set_sink()
+
+ self.connect(self.source, self.filtr, self.interpolator, self.receiver, self.converter, self.sink)
+
+ def _set_sink(self):
+ nazwa_pliku_wy = self.options.outputfile
+ ujscie = gr.file_sink(gr.sizeof_float, nazwa_pliku_wy)
+ return ujscie
+
+ def _set_source(self):
+ options = self.options
+ fusb_block_size = gr.prefs().get_long('fusb', 'block_size', 4096)
+ fusb_nblocks = gr.prefs().get_long('fusb', 'nblocks', 16)
+ self.usrp = usrp.source_c(decim_rate=options.decim, fusb_block_size=fusb_block_size, fusb_nblocks=fusb_nblocks)
+
+ if options.rx_subdev_spec is None:
+ options.rx_subdev_spec = pick_subdevice(self.usrp)
+
+ self.usrp.set_mux(usrp.determine_rx_mux_value(self.usrp, options.rx_subdev_spec))
+ # determine the daughterboard subdevice
+ self.subdev = usrp.selected_subdev(self.usrp, options.rx_subdev_spec)
+ input_rate = self.usrp.adc_freq() / self.usrp.decim_rate()
+
+ # set initial values
+ if options.gain is None:
+ # if no gain was specified, use the mid-point in dB
+ g = self.subdev.gain_range()
+ options.gain = float(g[0]+g[1])/2
+
+ r = self.usrp.tune(0, self.subdev, options.freq)
+ self.subdev.set_gain(options.gain)
+ return self.usrp
+
+ def _set_rates(self):
+ options = self.options
+ clock_rate = 64e6
+ self.clock_rate = clock_rate
+ self.input_rate = clock_rate / options.decim
+ self.gsm_symb_rate = 1625000.0 / 6.0
+ self.sps = self.input_rate / self.gsm_symb_rate / self.options.osr
+
+ def _set_filter(self):
+ filter_cutoff = 145e3
+ filter_t_width = 10e3
+ offset = 0
+# print "input_rate:", self.input_rate, "sample rate:", self.sps, " filter_cutoff:", filter_cutoff, " filter_t_width:", filter_t_width
+ filter_taps = gr.firdes.low_pass(1.0, self.input_rate, filter_cutoff, filter_t_width, gr.firdes.WIN_HAMMING)
+ filtr = gr.freq_xlating_fir_filter_ccf(1, filter_taps, offset, self.input_rate)
+ return filtr
+
+ def _set_converter(self):
+ v2s = gr.vector_to_stream(gr.sizeof_float, 142)
+ return v2s
+
+ def _set_interpolator(self):
+ interpolator = gr.fractional_interpolator_cc(0, self.sps)
+ return interpolator
+
+ def _set_receiver(self):
+ receiver = gsm.receiver_cf(self.tune_callback, self.options.osr)
+ return receiver
+
+ def _process_options(self):
+ parser = OptionParser(option_class=eng_option)
+ parser.add_option("-d", "--decim", type="int", default=128,
+ help="Set USRP decimation rate to DECIM [default=%default]")
+ parser.add_option("-I", "--inputfile", type="string", default="cfile",
+ help="Input filename")
+ parser.add_option("-O", "--outputfile", type="string", default="cfile2.out",
+ help="Output filename")
+ parser.add_option("-R", "--rx-subdev-spec", type="subdev", default=None,
+ help="Select USRP Rx side A or B (default=first one with a daughterboard)")
+ parser.add_option("-r", "--osr", type="int", default=4,
+ help="Oversampling ratio [default=%default]")
+ parser.add_option("-f", "--freq", type="eng_float", default="950.4M",
+ help="set frequency to FREQ", metavar="FREQ")
+ parser.add_option("-g", "--gain", type="eng_float", default=None,
+ help="Set gain in dB (default is midpoint)")
+ (options, args) = parser.parse_args ()
+ return (options, args)
+
+ def set_frequency(self, center_freq):
+ self.filtr.set_center_freq(center_freq)
+
+def main():
+ try:
+ gsm_receiver_first_blood().run()
+ except KeyboardInterrupt:
+ pass
+
+if __name__ == '__main__':
+ main()
+
+
diff --git a/gsm-receiver/src/python/test.sh b/gsm-receiver/src/python/test.sh
new file mode 100755
index 0000000..0a828e9
--- /dev/null
+++ b/gsm-receiver/src/python/test.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+./gsm_receive.py -I cfile > receiver-test.out 2> /dev/null
+echo " 01 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b\n 15 06 21 00 01 00 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b" > receiver-comp.out
+diff receiver-test.out receiver-comp.out > receiver-test-diff.out
+test_result=`cat receiver-test-diff.out`
+
+rm receiver-test.out receiver-test-diff.out receiver-comp.out
+
+if [ "x$test_result" = "x" ]; then
+ echo "Test: passed"
+ exit 0
+else
+ echo "Test: failed"
+ exit 1
+fi
personal git repositories of Harald Welte. Your mileage may vary