Merge pull request #333 from petterreinholdtsen/install-man

Add cmake rule to generate and install the rst manual page.
diff --git a/apps/grgsm_decode b/apps/grgsm_decode
index 222d67e..9c01e66 100755
--- a/apps/grgsm_decode
+++ b/apps/grgsm_decode
@@ -284,12 +284,7 @@
     cfile_options.add_option("-f", "--fc", dest="fc", type="eng_float",
                              help="Frequency of cfile capture")
     cfile_options.add_option("-a", "--arfcn", dest="arfcn", type="intx",
-                             help="Set ARFCN instead of frequency. "
-                                  "In some cases you may have to provide the GSM band also")
-    cfile_options.add_option("--band", dest="band",
-                             help="Specify the GSM band for the frequency.\nAvailable bands are: "
-                                  + ", ".join(grgsm.arfcn.get_bands()) + "."
-                                  + "If no band is specified, it will be determined automatically, defaulting to 0.")
+                             help="Set ARFCN instead of frequency (for PCS1900 add 0x8000 (2**15) to the ARFCN number).")
     cfile_options.add_option("-s", "--samp-rate", dest="samp_rate", type="eng_float",
                              default=eng_notation.num_to_str(1e6),
                              help="Sample rate of cfile capture [default=%default]")
@@ -347,34 +342,14 @@
     arfcn = None
     fc = None
     if options.arfcn:
-        if options.band:
-            if options.band not in grgsm.arfcn.get_bands():
-                parser.error("Invalid GSM band\n")
-            elif not grgsm.arfcn.is_valid_arfcn(options.arfcn, options.band):
-                parser.error("ARFCN is not valid in the specified band\n")
-            else:
-                arfcn = options.arfcn
-                fc = grgsm.arfcn.arfcn2downlink(arfcn, options.band)
+        if not grgsm.arfcn.is_valid_arfcn(options.arfcn):
+            parser.error("ARFCN is not valid\n")
         else:
             arfcn = options.arfcn
-            for band in grgsm.arfcn.get_bands():
-                if grgsm.arfcn.is_valid_arfcn(arfcn, band):
-                    fc = grgsm.arfcn.arfcn2downlink(arfcn, band)
-                    break
+            fc = grgsm.arfcn.arfcn2downlink(arfcn)
     elif options.fc:
         fc = options.fc
-        if options.band:
-            if options.band not in grgsm.arfcn.get_bands():
-                parser.error("Invalid GSM band\n")
-            elif not grgsm.arfcn.is_valid_downlink(options.fc, options.band):
-                parser.error("Frequency is not valid in the specified band\n")
-            else:
-                arfcn = grgsm.arfcn.downlink2arfcn(options.fc, options.band)
-        else:
-            for band in grgsm.arfcn.get_bands():
-                if grgsm.arfcn.is_valid_downlink(options.fc, band):
-                    arfcn = grgsm.arfcn.downlink2arfcn(options.fc, band)
-                    break
+        arfcn = grgsm.arfcn.downlink2arfcn(options.fc)
 
     # instanciate decoder
     tb = grgsm_decoder(timeslot=options.timeslot, subslot=options.subslot, chan_mode=options.chan_mode,
@@ -389,4 +364,3 @@
     # run
     tb.start()
     tb.wait()
-
diff --git a/apps/helpers/grgsm_capture b/apps/helpers/grgsm_capture
index add42d3..b1b85a7 100755
--- a/apps/helpers/grgsm_capture
+++ b/apps/helpers/grgsm_capture
@@ -38,7 +38,7 @@
 
 class grgsm_capture(gr.top_block):
 
-    def __init__(self, fc, gain, samp_rate, ppm, arfcn, cfile=None, burst_file=None, band=None, verbose=False, rec_length=None, args=""):
+    def __init__(self, fc, gain, samp_rate, ppm, arfcn, cfile=None, burst_file=None, verbose=False, rec_length=None, args=""):
 
         gr.top_block.__init__(self, "Gr-gsm Capture")
                 
@@ -52,7 +52,6 @@
         self.arfcn = arfcn
         self.cfile = cfile
         self.burst_file = burst_file
-        self.band = band
         self.verbose = verbose
         self.shiftoff = shiftoff = 400e3
         self.rec_length = rec_length
@@ -138,13 +137,7 @@
         self.arfcn = arfcn
         if self.verbose or self.burst_file:
             self.gsm_receiver.set_cell_allocation([self.arfcn])
-            if options.band:
-                new_freq = grgsm.arfcn.arfcn2downlink(self.arfcn, self.band)
-            else:
-                for band in grgsm.arfcn.get_bands():
-                    if grgsm.arfcn.is_valid_arfcn(arfcn, band):
-                        new_freq = grgsm.arfcn.arfcn2downlink(arfcn, band)
-                        break
+            new_freq = grgsm.arfcn.arfcn2downlink(self.arfcn)
             self.set_fc(new_freq)
 
     def get_gain(self):
@@ -186,7 +179,7 @@
                       help="Set frequency [default=%default]")
     
     parser.add_option("-a", "--arfcn", dest="arfcn", type="intx", 
-                      help="Set ARFCN instead of frequency. In some cases you may have to provide the GSM band also")
+                      help="Set ARFCN instead of frequency (for PCS1900 add 0x8000 (2**15) to the ARFCN number)")
     
     parser.add_option("-g", "--gain", dest="gain", type="eng_float", 
                       default=eng_notation.num_to_str(30),
@@ -205,10 +198,6 @@
     parser.add_option("-c", "--cfile", dest="cfile", 
                       help="File where the captured data are saved")
     
-    bands_list = ", ".join(grgsm.arfcn.get_bands())
-    parser.add_option("--band", dest="band", 
-                      help="Specify the GSM band for the frequency.\nAvailable bands are: " + bands_list + ".\nIf no band is specified, it will be determined automatically, defaulting to 0." )
-    
     parser.add_option("", "--args", dest="args", type="string", default="",
         help="Set device arguments [default=%default]")
 
@@ -229,38 +218,18 @@
     arfcn = 0
     fc = 939.4e6
     if options.arfcn:
-        if options.band:
-            if options.band not in grgsm.arfcn.get_bands():
-                parser.error("Invalid GSM band\n")
-            elif not grgsm.arfcn.is_valid_arfcn(options.arfcn, options.band):
-                parser.error("ARFCN is not valid in the specified band\n")
-            else:
-                arfcn = options.arfcn
-                fc = grgsm.arfcn.arfcn2downlink(arfcn, options.band)
+        if not grgsm.arfcn.is_valid_arfcn(options.arfcn):
+            parser.error("ARFCN is not valid\n")
         else:
             arfcn = options.arfcn
-            for band in grgsm.arfcn.get_bands():
-                if grgsm.arfcn.is_valid_arfcn(arfcn, band):
-                    fc = grgsm.arfcn.arfcn2downlink(arfcn, band)
-                    break
+            fc = grgsm.arfcn.arfcn2downlink(arfcn)
     elif options.fc:
         fc = options.fc
-        if options.band:
-            if options.band not in grgsm.arfcn.get_bands():
-                parser.error("Invalid GSM band\n")
-            elif not grgsm.arfcn.is_valid_downlink(options.fc, options.band):
-                parser.error("Frequency is not valid in the specified band\n")
-            else:
-                arfcn = grgsm.arfcn.downlink2arfcn(options.fc, options.band)
-        else:
-            for band in grgsm.arfcn.get_bands():
-                if grgsm.arfcn.is_valid_downlink(options.fc, band):
-                    arfcn = grgsm.arfcn.downlink2arfcn(options.fc, band)
-                    break
+        arfcn = grgsm.arfcn.downlink2arfcn(options.fc)
      
     tb = grgsm_capture(fc=fc, gain=options.gain, samp_rate=options.samp_rate,
                          ppm=options.ppm, arfcn=arfcn, cfile=options.cfile, 
-                         burst_file=options.burst_file, band=options.band, verbose=options.verbose,
+                         burst_file=options.burst_file, verbose=options.verbose,
                          rec_length=options.rec_length, args=options.args)
     
     def signal_handler(signal, frame):
diff --git a/apps/helpers/grgsm_channelize b/apps/helpers/grgsm_channelize
index fb30334..9b00bd7 100755
--- a/apps/helpers/grgsm_channelize
+++ b/apps/helpers/grgsm_channelize
@@ -56,24 +56,16 @@
     except:
         raise ArgumentTypeError("invalid engineering notation value: {0}".format(value))
 
-def gsm_band(value):
-    choices = arfcn.get_bands()
-    if value in choices:
-        return value
-    else:
-        raise ArgumentTypeError("invalid GSM band: {0}. Possible choices are: {1}".format(value, choices))
-
 class grgsm_channelize(gr.top_block):
-    def __init__(self, channels, resamp_rate, fc, band, samp_rate, input_file, dest_dir, data_type="complex"):
+    def __init__(self, arfcns, resamp_rate, fc, samp_rate, input_file, dest_dir, data_type="complex"):
         gr.top_block.__init__(self, "grgsm_channelize")
 
         ##################################################
         # Parameters
         ##################################################
-        self.channels = channels
+        self.arfcns = arfcns
         self.resamp_rate = resamp_rate
         self.fc = fc
-        self.band = band
         self.samp_rate = samp_rate
         self.blocks_resamplers = {}
         self.blocks_rotators = {}
@@ -91,13 +83,10 @@
             self.source = blocks.file_source(gr.sizeof_gr_complex, input_file, False)
 
         fc_str = eng_notation.num_to_str(fc)
-        print("Extracting channels %s, given that the center frequency is at %s" % (str(channels), eng_notation.num_to_str(fc)))
+        print("Extracting channels %s, given that the center frequency is at %s" % (str(arfcns), eng_notation.num_to_str(fc)))
 
-        for channel in channels:
-            channel_freq = arfcn.arfcn2downlink(channel, band)
-            if channel_freq is None:
-                print("Warning: invalid ARFCN %d for band %s" % (channel, band))
-                continue
+        for channel in self.arfcns:
+            channel_freq = arfcn.arfcn2downlink(channel)
             freq_diff = channel_freq - fc
             freq_diff_str = "+" if 0 <= freq_diff else ""
             freq_diff_str += eng_notation.num_to_str(freq_diff)
@@ -115,14 +104,12 @@
 
 if __name__ == '__main__':
     parser = ArgumentParser(formatter_class=RawDescriptionHelpFormatter, description='Split wideband a GSM capture into seperate files per ARFCN.', add_help=True, epilog=EXTRA_HELP)
-    parser.add_argument(dest="channel", type=int, nargs='+',
-        help="List of ARFCNs")
+    parser.add_argument(dest="arfcns", type=int, nargs='+',
+        help="List of ARFCNs (for PCS1900 add 0x8000 (2**15) to the ARFCN number)")
     parser.add_argument("-s", "--samp-rate", dest="samp_rate", type=eng_float, default=eng_notation.num_to_str(2e6),
         help="Sample rate of the wideband capture file [default=%(default)s]")
     parser.add_argument("-f", "--fc", dest="fc", type=eng_float, default=eng_notation.num_to_str(935e6), required=True,
         help="Carrier frequency in Hz [default=%(default)s]")
-    parser.add_argument("-b", "--band", dest="band", type=gsm_band, default='E-GSM',
-        help="GSM band [default=%(default)s]") #TODO: add automatic discovery based on fc
     parser.add_argument("-o", "--out-samp-rate", dest="out_samp_rate", type=eng_float, default=eng_notation.num_to_str(1e6),
         help="Sample rate of the output capture files [default=%(default)s]")
     parser.add_argument("-i", "--input_file", dest="input_file", type=str, required=True,
@@ -133,7 +120,11 @@
         help="Destination directory - if not given defaults to input file name without extension")
         
     args = parser.parse_args()
-    
+
+    for ch in args.arfcns:
+        if not arfcn.is_valid_arfcn(ch):
+            parser.error("ARFCN "+str(ch)+" is not valid\n")
+
     if not os.path.exists(args.input_file):
         raise IOError(args.input_file + " does not exist")
 
@@ -154,10 +145,9 @@
     print("Output sample rate: " + eng_notation.num_to_str(args.out_samp_rate))
     print("==> using resample rate of " + str(resamp_rate))
 
-    tb = grgsm_channelize(channels=args.channel,
+    tb = grgsm_channelize(arfcns=args.arfcns,
          resamp_rate=resamp_rate,
          fc=args.fc,
-         band=args.band,
          samp_rate=args.samp_rate,
          input_file=args.input_file,
          dest_dir=args.dest_dir,         
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index 9880e58..6c45f51 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -17,13 +17,30 @@
 # the Free Software Foundation, Inc., 51 Franklin Street,
 # Boston, MA 02110-1301, USA.
 
-########################################################################
-# Setup library
-########################################################################
 include(GrPlatform) #define LIB_SUFFIX
 include(GrMiscUtils)
 
 ########################################################################
+# Add sources macro
+########################################################################
+set(grgsm_sources "")
+
+macro (add_sources)
+    file (RELATIVE_PATH _relPath "${PROJECT_SOURCE_DIR}/lib" "${CMAKE_CURRENT_SOURCE_DIR}")
+    foreach (_src ${ARGN})
+        if (_relPath)
+            list (APPEND grgsm_sources "${_relPath}/${_src}")
+        else()
+            list (APPEND grgsm_sources "${_src}")
+        endif()
+    endforeach()
+    if (_relPath)
+        # propagate grgsm_sources to parent directory
+        set (grgsm_sources ${grgsm_sources} PARENT_SCOPE)
+    endif()
+endmacro()
+
+########################################################################
 # Handle the generated constants
 ########################################################################
 execute_process(COMMAND ${PYTHON_EXECUTABLE} -c
@@ -44,60 +61,21 @@
 
 list(APPEND grgsm_sources ${CMAKE_CURRENT_BINARY_DIR}/constants.cc)
 #########################################################################
+# Subdirecories
+#########################################################################
+add_subdirectory(decoding)
+add_subdirectory(decryption)
+add_subdirectory(demapping)
+add_subdirectory(flow_control)
+add_subdirectory(misc_utils)
+add_subdirectory(qa_utils)
+add_subdirectory(receiver)
 
+########################################################################
+# Setup library
+########################################################################
 include_directories(${Boost_INCLUDE_DIR} receiver)
 link_directories(${Boost_LIBRARY_DIRS})
-list(APPEND grgsm_sources
-    receiver/receiver_impl.cc
-    receiver/receiver_config.cc
-    receiver/viterbi_detector.cc
-    decoding/sch.c
-    receiver/clock_offset_control_impl.cc
-    receiver/cx_channel_hopper_impl.cc
-    demapping/universal_ctrl_chans_demapper_impl.cc
-    demapping/tch_f_chans_demapper_impl.cc
-    decoding/control_channels_decoder_impl.cc
-    decoding/tch_f_decoder_impl.cc
-    decoding/openbts/AmrCoder.cpp
-    decoding/openbts/BitVector.cpp
-    decoding/openbts/GSM610Tables.cpp
-    decoding/openbts/GSM660Tables.cpp
-    decoding/openbts/GSM503Tables.cpp
-    decoding/openbts/ViterbiR204.cpp
-    decoding/osmocom/coding/gsm0503_conv.c
-    decoding/osmocom/coding/gsm0503_coding.c
-    decoding/osmocom/coding/gsm0503_interleaving.c
-    decoding/osmocom/coding/gsm0503_mapping.c
-    decoding/osmocom/coding/gsm0503_parity.c
-    decoding/osmocom/coding/gsm0503_tables.c
-    flow_control/burst_timeslot_splitter_impl.cc
-    flow_control/burst_sdcch_subslot_splitter_impl.cc
-    flow_control/burst_timeslot_filter_impl.cc
-    flow_control/burst_sdcch_subslot_filter_impl.cc
-    flow_control/burst_fnr_filter_impl.cc
-    flow_control/dummy_burst_filter_impl.cc
-    flow_control/uplink_downlink_splitter_impl.cc
-    misc_utils/collect_system_info_impl.cc
-    misc_utils/controlled_rotator_cc_impl.cc
-    misc_utils/controlled_fractional_resampler_cc_impl.cc
-    misc_utils/msg_to_tag_impl.cc
-    misc_utils/message_printer_impl.cc
-    misc_utils/tmsi_dumper_impl.cc
-    misc_utils/burst_file_sink_impl.cc
-    misc_utils/burst_file_source_impl.cc
-    misc_utils/message_file_sink_impl.cc
-    misc_utils/message_file_source_impl.cc
-    misc_utils/bursts_printer_impl.cc
-    misc_utils/extract_system_info_impl.cc
-    misc_utils/extract_immediate_assignment_impl.cc
-    misc_utils/extract_cmc_impl.cc
-    qa_utils/burst_sink_impl.cc
-    qa_utils/burst_source_impl.cc
-    qa_utils/message_source_impl.cc
-    qa_utils/message_sink_impl.cc
-    decryption/decryption_impl.cc
-)
-
 
 add_library(grgsm SHARED ${grgsm_sources})
 target_link_libraries(grgsm ${Boost_LIBRARIES} ${GNURADIO_ALL_LIBRARIES} ${VOLK_LIBRARIES} ${LIBOSMOCODEC_LIBRARIES} ${LIBOSMOCORE_LIBRARIES} 
diff --git a/lib/decoding/CMakeLists.txt b/lib/decoding/CMakeLists.txt
new file mode 100644
index 0000000..cacfc55
--- /dev/null
+++ b/lib/decoding/CMakeLists.txt
@@ -0,0 +1,31 @@
+# Copyright 2011,2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can 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.
+
+add_subdirectory(osmocom/coding)
+add_subdirectory(openbts)
+
+add_subdirectory(osmocom/coding)
+add_subdirectory(openbts)
+
+add_sources(
+    control_channels_decoder_impl.cc
+    tch_f_decoder_impl.cc
+    sch.c
+)
+
diff --git a/lib/decoding/openbts/CMakeLists.txt b/lib/decoding/openbts/CMakeLists.txt
new file mode 100644
index 0000000..18977b1
--- /dev/null
+++ b/lib/decoding/openbts/CMakeLists.txt
@@ -0,0 +1,27 @@
+# Copyright 2011,2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can 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.
+
+add_sources(
+    AmrCoder.cpp
+    BitVector.cpp
+    GSM610Tables.cpp
+    GSM660Tables.cpp
+    GSM503Tables.cpp
+    ViterbiR204.cpp
+)
diff --git a/lib/decoding/osmocom/coding/CMakeLists.txt b/lib/decoding/osmocom/coding/CMakeLists.txt
new file mode 100644
index 0000000..8e68577
--- /dev/null
+++ b/lib/decoding/osmocom/coding/CMakeLists.txt
@@ -0,0 +1,28 @@
+# Copyright 2011,2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can 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.
+
+add_sources(
+    gsm0503_conv.c
+    gsm0503_coding.c
+    gsm0503_interleaving.c
+    gsm0503_mapping.c
+    gsm0503_parity.c
+    gsm0503_tables.c
+)
+
diff --git a/lib/decryption/CMakeLists.txt b/lib/decryption/CMakeLists.txt
new file mode 100644
index 0000000..7ccd99a
--- /dev/null
+++ b/lib/decryption/CMakeLists.txt
@@ -0,0 +1,22 @@
+# Copyright 2011,2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can 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.
+
+add_sources(
+    decryption_impl.cc
+)
diff --git a/lib/demapping/CMakeLists.txt b/lib/demapping/CMakeLists.txt
new file mode 100644
index 0000000..57d2d1a
--- /dev/null
+++ b/lib/demapping/CMakeLists.txt
@@ -0,0 +1,24 @@
+# Copyright 2011,2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can 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.
+
+add_sources(
+    tch_f_chans_demapper_impl.cc
+    universal_ctrl_chans_demapper_impl.cc
+)
+
diff --git a/lib/flow_control/CMakeLists.txt b/lib/flow_control/CMakeLists.txt
new file mode 100644
index 0000000..30a5f50
--- /dev/null
+++ b/lib/flow_control/CMakeLists.txt
@@ -0,0 +1,29 @@
+# Copyright 2011,2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can 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.
+
+add_sources(
+    burst_fnr_filter_impl.cc
+    burst_sdcch_subslot_filter_impl.cc
+    burst_sdcch_subslot_splitter_impl.cc
+    burst_timeslot_filter_impl.cc
+    burst_timeslot_splitter_impl.cc
+    dummy_burst_filter_impl.cc
+    uplink_downlink_splitter_impl.cc
+)
+
diff --git a/lib/misc_utils/CMakeLists.txt b/lib/misc_utils/CMakeLists.txt
new file mode 100644
index 0000000..1c51fb6
--- /dev/null
+++ b/lib/misc_utils/CMakeLists.txt
@@ -0,0 +1,36 @@
+# Copyright 2011,2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can 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.
+
+add_sources(
+    burst_file_sink_impl.cc
+    burst_file_source_impl.cc
+    bursts_printer_impl.cc
+    collect_system_info_impl.cc
+    controlled_fractional_resampler_cc_impl.cc
+    controlled_rotator_cc_impl.cc
+    extract_cmc_impl.cc
+    extract_immediate_assignment_impl.cc
+    extract_system_info_impl.cc
+    message_file_sink_impl.cc
+    message_file_source_impl.cc
+    message_printer_impl.cc
+    msg_to_tag_impl.cc
+    tmsi_dumper_impl.cc
+)
+
diff --git a/lib/qa_utils/CMakeLists.txt b/lib/qa_utils/CMakeLists.txt
new file mode 100644
index 0000000..a70967b
--- /dev/null
+++ b/lib/qa_utils/CMakeLists.txt
@@ -0,0 +1,25 @@
+# Copyright 2011,2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can 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.
+
+add_sources(
+    burst_sink_impl.cc
+    burst_source_impl.cc
+    message_sink_impl.cc
+    message_source_impl.cc
+)
diff --git a/lib/receiver/CMakeLists.txt b/lib/receiver/CMakeLists.txt
new file mode 100644
index 0000000..343d2f8
--- /dev/null
+++ b/lib/receiver/CMakeLists.txt
@@ -0,0 +1,26 @@
+# Copyright 2011,2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can 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.
+
+add_sources(
+    clock_offset_control_impl.cc
+    cx_channel_hopper_impl.cc
+    receiver_config.cc
+    receiver_impl.cc
+    viterbi_detector.cc
+)
diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt
index df11c10..a4a4338 100644
--- a/python/CMakeLists.txt
+++ b/python/CMakeLists.txt
@@ -28,20 +28,13 @@
 ########################################################################
 # Install python sources
 ########################################################################
+add_subdirectory(misc_utils)
+add_subdirectory(receiver)
+add_subdirectory(demapping)
+
 GR_PYTHON_INSTALL(
     FILES
-    __init__.py
-    demapping/gsm_bcch_ccch_demapper.py
-    demapping/gsm_bcch_ccch_sdcch4_demapper.py
-    demapping/gsm_sdcch8_demapper.py
-    receiver/gsm_input.py
-    receiver/fcch_burst_tagger.py
-    receiver/sch_detector.py
-    receiver/fcch_detector.py
-    receiver/chirpz.py
-    misc_utils/arfcn.py
-    misc_utils/clock_offset_corrector_tagged.py
-    misc_utils/hier_block.py DESTINATION ${GR_PYTHON_DIR}/grgsm
+    __init__.py DESTINATION ${GR_PYTHON_DIR}/grgsm
 )
 
 ########################################################################
@@ -51,6 +44,7 @@
 
 set(GR_TEST_TARGET_DEPS gr-gsm)
 set(GR_TEST_PYTHON_DIRS ${CMAKE_BINARY_DIR}/swig:${CMAKE_BINARY_DIR}/python/misc_utils)
+GR_ADD_TEST(qa_arfcn ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_arfcn.py)
 GR_ADD_TEST(qa_decryption ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_decryption.py)
 GR_ADD_TEST(qa_burst_printer ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_burst_printer.py)
 GR_ADD_TEST(qa_message_printer ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_message_printer.py)
@@ -60,7 +54,6 @@
 GR_ADD_TEST(qa_burst_sdcch_subslot_filter ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_burst_sdcch_subslot_filter.py)
 GR_ADD_TEST(qa_burst_fnr_filter ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_burst_fnr_filter.py)
 GR_ADD_TEST(qa_dummy_burst_filter ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_dummy_burst_filter.py)
-GR_ADD_TEST(qa_arfcn ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_arfcn.py)
 #GR_ADD_TEST(qa_msg_to_tag ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_msg_to_tag.py)
 #GR_ADD_TEST(qa_controlled_fractional_resampler_cc ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_controlled_fractional_resampler_cc.py)
 #GR_ADD_TEST(qa_uplink_downlink_splitter ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/qa_uplink_downlink_splitter.py)
diff --git a/python/demapping/CMakeLists.txt b/python/demapping/CMakeLists.txt
new file mode 100644
index 0000000..9f0efb4
--- /dev/null
+++ b/python/demapping/CMakeLists.txt
@@ -0,0 +1,25 @@
+# Copyright 2011,2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can 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.
+
+GR_PYTHON_INSTALL(
+    FILES
+    gsm_bcch_ccch_demapper.py
+    gsm_bcch_ccch_sdcch4_demapper.py
+    gsm_sdcch8_demapper.py DESTINATION ${GR_PYTHON_DIR}/grgsm
+)
diff --git a/python/misc_utils/CMakeLists.txt b/python/misc_utils/CMakeLists.txt
new file mode 100644
index 0000000..1accda9
--- /dev/null
+++ b/python/misc_utils/CMakeLists.txt
@@ -0,0 +1,26 @@
+# Copyright 2011,2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can 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.
+
+GR_PYTHON_INSTALL(
+    FILES
+    arfcn.py
+    clock_offset_corrector_tagged.py
+    hier_block.py 
+    fn_time.py DESTINATION ${GR_PYTHON_DIR}/grgsm
+)
diff --git a/python/misc_utils/arfcn.py b/python/misc_utils/arfcn.py
old mode 100755
new mode 100644
diff --git a/python/misc_utils/fn_time.py b/python/misc_utils/fn_time.py
new file mode 100644
index 0000000..71e93db
--- /dev/null
+++ b/python/misc_utils/fn_time.py
@@ -0,0 +1,84 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# @file
+# @author Piotr Krysik <ptrkrysik@gmail.com>
+# @section LICENSE
+# 
+# Gr-gsm is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+# 
+# Gr-gsm is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with gr-gsm; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+# 
+# 
+from math import floor, ceil
+from random import uniform
+
+__hyper_frame = 26*51*2048
+__symb_rate = 13.0e6/48.0
+__ts_period = 156.25/__symb_rate
+__frame_period = 8*__ts_period
+
+#The functions below are crucial part of synchronization between
+#transmitter and receiver.
+
+#fnmod_delta computes difference between two frame numbers modulo
+#__hyper_frame. The result is correct if difference between the frame
+#numbers is not bigger than __hyper_frame/2.
+def fnmod_delta(fn1, fn2):
+    h2 = __hyper_frame/2
+    delta = (fn1%__hyper_frame)-(fn2%__hyper_frame)
+  
+    if delta >= h2:
+        delta = delta - __hyper_frame
+    elif delta < -h2:
+        delta = delta + __hyper_frame
+    
+    return delta
+  
+#fn_time_delta computes difference between reference frame number and a second frame number. It also computes timestamp of the second frame number. The full list of parameters is following:
+#* fn_ref - reference frame number modulo __hyper_frame
+#* time_ref - precise timestamp of the first sample in the frame fn_ref
+#* fn_x - second frame number modulo __hyper_frame,
+#* time_hint - coarse time for fn_x that is used as a hint to avoid ambiguities caused by modulo operation applied to frame numbers. The correct are values from range <time2_precise-__hiperframe/2, time2_precise+__hiperframe/2> (where time2_precise is exact time of the first sample in frame fn_x)
+#* ts_num - number of timeslot in the frame
+
+def fn_time_delta(fn_ref, time_ref, fn_x, time_hint=None, ts_num=None):
+    if time_hint is None:
+        time_hint = time_ref
+        
+    if ts_num is None:
+        ts_num = 0
+
+    time_diff = time_hint-time_ref
+    frames_diff = int(round(time_diff/__frame_period))
+    fn_ref = (fn_ref + frames_diff)
+    fn_delta = fnmod_delta(fn_x,fn_ref)+frames_diff
+    time2_precise = fn_delta*__frame_period+time_ref+ts_num*__ts_period
+    
+    return fn_delta, time2_precise
+
+
+if __name__ == "__main__":
+    fn1 = 10000
+    time1 = 10
+    for fn2 in xrange(__hyper_frame/2+fn1-10,__hyper_frame/2*10+fn1+10,10):
+        time2 = time1 + (fn2-fn1)*__frame_period 
+        error = uniform(-6200,6200)
+        time2_err = time2+error
+        fn_delta, time2_precise = fn_time_delta(fn1, time1, fn2, time2_err)
+        if fn_delta != fn2-fn1:
+            print "dupa:", fn2, error#, 'fn_delta:'+str(fn_delta), time2, error, frames_diff_h4, (time2-time1)/(__hyper_frame*__frame_period), time_diff_h4_prev, time_diff
+        time_diff = time2 - time2_precise
+        if time_diff > 0.1:
+            print "dupa"
+
diff --git a/python/receiver/CMakeLists.txt b/python/receiver/CMakeLists.txt
new file mode 100644
index 0000000..8ab902b
--- /dev/null
+++ b/python/receiver/CMakeLists.txt
@@ -0,0 +1,27 @@
+# Copyright 2011,2012 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can 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.
+
+GR_PYTHON_INSTALL(
+    FILES
+    gsm_input.py
+    fcch_burst_tagger.py
+    sch_detector.py
+    fcch_detector.py
+    chirpz.py DESTINATION ${GR_PYTHON_DIR}/grgsm
+)
diff --git a/swig/grgsm_swig.i b/swig/grgsm_swig.i
index 66615e6..57ed777 100644
--- a/swig/grgsm_swig.i
+++ b/swig/grgsm_swig.i
@@ -143,4 +143,3 @@
 GR_SWIG_BLOCK_MAGIC2(gsm, message_source);
 %include "grgsm/qa_utils/message_sink.h"
 GR_SWIG_BLOCK_MAGIC2(gsm, message_sink);
-