Added new blocks for clock freqeuncy correction
diff --git a/grc/CMakeLists.txt b/grc/CMakeLists.txt
index dc25035..0f0db50 100644
--- a/grc/CMakeLists.txt
+++ b/grc/CMakeLists.txt
@@ -24,5 +24,9 @@
     gsm_fcch_detector.xml
     gsm_get_bcch_or_ccch_bursts.xml
     gsm_control_channels_decoder.xml
-    gsm_extract_system_info.xml DESTINATION share/gnuradio/grc/blocks
+    gsm_extract_system_info.xml
+    gsm_controlled_rotator_cc.xml
+    gsm_controlled_const_source_f.xml
+    gsm_clock_offset_control.xml
+    gsm_message_printer.xml DESTINATION share/gnuradio/grc/blocks
 )
diff --git a/grc/gsm_clock_offset_control.xml b/grc/gsm_clock_offset_control.xml
new file mode 100644
index 0000000..bb4dadb
--- /dev/null
+++ b/grc/gsm_clock_offset_control.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0"?>
+<block>
+  <name>Clock offset control</name>
+  <key>gsm_clock_offset_control</key>
+  <category>GSM</category>
+  <import>import gsm</import>
+  <make>gsm.clock_offset_control($fc, $samp_rate)</make>
+  <callback></callback>
+  <param>
+    <name>fc</name>
+    <key>fc</key>
+    <value>fc</value>
+    <type>float</type>
+  </param>
+
+  <param>
+    <name>samp_rate</name>
+    <key>samp_rate</key>
+    <value>samp_rate</value>
+    <type>float</type>
+  </param>
+
+  <sink>
+    <name>measurements</name>
+    <type>message</type>
+  </sink>
+
+  <source>
+    <name>ppm</name>
+    <type>message</type>
+    <optional>1</optional>
+  </source>
+</block>
diff --git a/grc/gsm_clock_offset_corrector.xml b/grc/gsm_clock_offset_corrector.xml
new file mode 100644
index 0000000..e9aa7db
--- /dev/null
+++ b/grc/gsm_clock_offset_corrector.xml
@@ -0,0 +1,50 @@
+<?xml version='1.0' encoding='ASCII'?>
+<block>
+  <name>Clock offset corrector</name>
+  <key>clock_offset_corrector</key>
+  <category>GSM</category>
+  <import>execfile("/home/piotr/.grc_gnuradio/clock_offset_corrector.py")</import>
+  <make>clock_offset_corrector(
+    ppm=$ppm,
+    samp_rate=$samp_rate,
+    fc=$fc,
+)</make>
+  <callback>set_ppm($ppm)</callback>
+  <callback>set_samp_rate($samp_rate)</callback>
+  <callback>set_fc($fc)</callback>
+  <param>
+    <name>ppm</name>
+    <key>ppm</key>
+    <value>0</value>
+    <type>raw</type>
+  </param>
+  <param>
+    <name>samp_rate</name>
+    <key>samp_rate</key>
+    <value>1625000.0/6.0*4.0</value>
+    <type>raw</type>
+  </param>
+  <param>
+    <name>fc</name>
+    <key>fc</key>
+    <value>936.6e6</value>
+    <type>raw</type>
+  </param>
+  <sink>
+    <name>in</name>
+    <type>complex</type>
+    <vlen>1</vlen>
+  </sink>
+  <sink>
+    <name>ppm_msg</name>
+    <type>message</type>
+    <optional>True</optional>
+  </sink>
+  <source>
+    <name>out</name>
+    <type>complex</type>
+    <vlen>1</vlen>
+  </source>
+  <doc>Piotr Krysik
+  <grc_source>gr-gsm/examples/clock_offset_corrector.grc</grc_source>
+</block>
diff --git a/grc/gsm_controlled_const_source_f.xml b/grc/gsm_controlled_const_source_f.xml
new file mode 100644
index 0000000..f51ef69
--- /dev/null
+++ b/grc/gsm_controlled_const_source_f.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0"?>
+<block>
+  <name>Controlled const source</name>
+  <key>gsm_controlled_const_source_f</key>
+  <category>GSM</category>
+  <import>import gsm</import>
+  <make>gsm.controlled_const_source_f($constant)</make>
+  <callback>set_constant($constant)</callback>
+  
+  <param>
+    <name>constant</name>
+    <key>constant</key>
+    <value>0</value>
+    <type>float</type>
+  </param>
+
+  <sink>
+    <name>constant_msg</name>
+    <type>message</type>
+    <optional>1</optional>
+  </sink>
+
+  <source>
+    <name>out</name>
+    <type>float</type>
+  </source>
+</block>
diff --git a/grc/gsm_controlled_rotator_cc.xml b/grc/gsm_controlled_rotator_cc.xml
new file mode 100644
index 0000000..83040d4
--- /dev/null
+++ b/grc/gsm_controlled_rotator_cc.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0"?>
+<block>
+  <name>Controlled rotator</name>
+  <key>gsm_controlled_rotator_cc</key>
+  <category>GSM</category>
+  <import>import gsm</import>
+  <make>gsm.controlled_rotator_cc($phase_inc,$samp_rate)</make>
+  <callback>set_phase_inc($phase_inc)</callback>
+  <callback>set_samp_rate($samp_rate)</callback>
+  <param>
+    <name>phase_inc</name>
+    <key>phase_inc</key>
+    <value>0</value>
+    <type>real</type>
+  </param>
+
+  <param>
+    <name>samp_rate</name>
+    <key>samp_rate</key>
+    <value>samp_rate</value>
+    <type>real</type>
+  </param>
+
+  <sink>
+    <name>in</name>
+    <type>complex</type>
+  </sink>
+  <sink>
+    <name>phase_inc</name>
+    <type>float</type>
+  </sink>
+  
+  <source>
+    <name>out</name>
+    <type>complex</type>
+  </source>
+</block>
+
diff --git a/hier_blocks/clock_offset_corrector.grc b/hier_blocks/clock_offset_corrector.grc
new file mode 100644
index 0000000..56a70d7
--- /dev/null
+++ b/hier_blocks/clock_offset_corrector.grc
@@ -0,0 +1,652 @@
+<?xml version='1.0' encoding='ASCII'?>
+<flow_graph>
+  <timestamp>Wed Aug  6 13:47:37 2014</timestamp>
+  <block>
+    <key>options</key>
+    <param>
+      <key>id</key>
+      <value>clock_offset_corrector</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>title</key>
+      <value>Clock offset corrector</value>
+    </param>
+    <param>
+      <key>author</key>
+      <value>Piotr Krysik</value>
+    </param>
+    <param>
+      <key>description</key>
+      <value></value>
+    </param>
+    <param>
+      <key>window_size</key>
+      <value>1280, 1024</value>
+    </param>
+    <param>
+      <key>generate_options</key>
+      <value>hb</value>
+    </param>
+    <param>
+      <key>category</key>
+      <value>GSM</value>
+    </param>
+    <param>
+      <key>run_options</key>
+      <value>prompt</value>
+    </param>
+    <param>
+      <key>run</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>max_nouts</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>realtime_scheduling</key>
+      <value></value>
+    </param>
+    <param>
+      <key>alias</key>
+      <value></value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(10, 10)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>parameter</key>
+    <param>
+      <key>id</key>
+      <value>ppm</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>label</key>
+      <value>ppm</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>eng_float</value>
+    </param>
+    <param>
+      <key>short_id</key>
+      <value></value>
+    </param>
+    <param>
+      <key>alias</key>
+      <value></value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(487, 22)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>parameter</key>
+    <param>
+      <key>id</key>
+      <value>samp_rate</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>label</key>
+      <value>samp_rate</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>1625000.0/6.0*4.0</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>eng_float</value>
+    </param>
+    <param>
+      <key>short_id</key>
+      <value></value>
+    </param>
+    <param>
+      <key>alias</key>
+      <value></value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(368, 19)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>parameter</key>
+    <param>
+      <key>id</key>
+      <value>fc</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>label</key>
+      <value>fc</value>
+    </param>
+    <param>
+      <key>value</key>
+      <value>936.6e6</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>eng_float</value>
+    </param>
+    <param>
+      <key>short_id</key>
+      <value></value>
+    </param>
+    <param>
+      <key>alias</key>
+      <value></value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(274, 19)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>import</key>
+    <param>
+      <key>id</key>
+      <value>math_imp</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>import</key>
+      <value>import math</value>
+    </param>
+    <param>
+      <key>alias</key>
+      <value></value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(11, 125)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>blocks_multiply_const_vxx</key>
+    <param>
+      <key>id</key>
+      <value>blocks_multiply_const_vxx_0</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>float</value>
+    </param>
+    <param>
+      <key>const</key>
+      <value>fc/samp_rate*(2*math.pi)</value>
+    </param>
+    <param>
+      <key>vlen</key>
+      <value>1</value>
+    </param>
+    <param>
+      <key>alias</key>
+      <value></value>
+    </param>
+    <param>
+      <key>affinity</key>
+      <value></value>
+    </param>
+    <param>
+      <key>minoutbuf</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>maxoutbuf</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(571, 335)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>blocks_add_const_vxx</key>
+    <param>
+      <key>id</key>
+      <value>blocks_add_const_vxx_0</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>float</value>
+    </param>
+    <param>
+      <key>const</key>
+      <value>1</value>
+    </param>
+    <param>
+      <key>vlen</key>
+      <value>1</value>
+    </param>
+    <param>
+      <key>alias</key>
+      <value></value>
+    </param>
+    <param>
+      <key>affinity</key>
+      <value></value>
+    </param>
+    <param>
+      <key>minoutbuf</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>maxoutbuf</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(779, 217)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>blocks_multiply_const_vxx</key>
+    <param>
+      <key>id</key>
+      <value>blocks_multiply_const_vxx_0_0</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>float</value>
+    </param>
+    <param>
+      <key>const</key>
+      <value>1.0/1.0e6</value>
+    </param>
+    <param>
+      <key>vlen</key>
+      <value>1</value>
+    </param>
+    <param>
+      <key>alias</key>
+      <value></value>
+    </param>
+    <param>
+      <key>affinity</key>
+      <value></value>
+    </param>
+    <param>
+      <key>minoutbuf</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>maxoutbuf</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(405, 217)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>pad_source</key>
+    <param>
+      <key>id</key>
+      <value>pad_source_0</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>label</key>
+      <value>in</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>complex</value>
+    </param>
+    <param>
+      <key>vlen</key>
+      <value>1</value>
+    </param>
+    <param>
+      <key>num_streams</key>
+      <value>1</value>
+    </param>
+    <param>
+      <key>optional</key>
+      <value>False</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(13, 301)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>pad_sink</key>
+    <param>
+      <key>id</key>
+      <value>pad_sink_1</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>label</key>
+      <value>out</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>complex</value>
+    </param>
+    <param>
+      <key>vlen</key>
+      <value>1</value>
+    </param>
+    <param>
+      <key>num_streams</key>
+      <value>1</value>
+    </param>
+    <param>
+      <key>optional</key>
+      <value>False</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(1174, 335)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>fractional_resampler_xx</key>
+    <param>
+      <key>id</key>
+      <value>fractional_resampler_xx_0</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>complex</value>
+    </param>
+    <param>
+      <key>phase_shift</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>resamp_ratio</key>
+      <value>1</value>
+    </param>
+    <param>
+      <key>alias</key>
+      <value></value>
+    </param>
+    <param>
+      <key>affinity</key>
+      <value></value>
+    </param>
+    <param>
+      <key>minoutbuf</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>maxoutbuf</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(986, 322)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>pad_source</key>
+    <param>
+      <key>id</key>
+      <value>ppm_msg</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>label</key>
+      <value>ppm_msg</value>
+    </param>
+    <param>
+      <key>type</key>
+      <value>message</value>
+    </param>
+    <param>
+      <key>vlen</key>
+      <value>1</value>
+    </param>
+    <param>
+      <key>num_streams</key>
+      <value>1</value>
+    </param>
+    <param>
+      <key>optional</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(15, 217)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>gsm_controlled_const_source_f</key>
+    <param>
+      <key>id</key>
+      <value>gsm_controlled_const_source_f_0</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>constant</key>
+      <value>ppm</value>
+    </param>
+    <param>
+      <key>alias</key>
+      <value></value>
+    </param>
+    <param>
+      <key>affinity</key>
+      <value></value>
+    </param>
+    <param>
+      <key>minoutbuf</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>maxoutbuf</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(183, 217)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <block>
+    <key>gsm_controlled_rotator_cc</key>
+    <param>
+      <key>id</key>
+      <value>gsm_controlled_rotator_cc_0</value>
+    </param>
+    <param>
+      <key>_enabled</key>
+      <value>True</value>
+    </param>
+    <param>
+      <key>phase_inc</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>samp_rate</key>
+      <value>samp_rate</value>
+    </param>
+    <param>
+      <key>alias</key>
+      <value></value>
+    </param>
+    <param>
+      <key>affinity</key>
+      <value></value>
+    </param>
+    <param>
+      <key>minoutbuf</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>maxoutbuf</key>
+      <value>0</value>
+    </param>
+    <param>
+      <key>_coordinate</key>
+      <value>(759, 305)</value>
+    </param>
+    <param>
+      <key>_rotation</key>
+      <value>0</value>
+    </param>
+  </block>
+  <connection>
+    <source_block_id>gsm_controlled_const_source_f_0</source_block_id>
+    <sink_block_id>blocks_multiply_const_vxx_0_0</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>pad_source_0</source_block_id>
+    <sink_block_id>gsm_controlled_rotator_cc_0</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>blocks_multiply_const_vxx_0_0</source_block_id>
+    <sink_block_id>blocks_multiply_const_vxx_0</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>blocks_add_const_vxx_0</source_block_id>
+    <sink_block_id>fractional_resampler_xx_0</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>1</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>gsm_controlled_rotator_cc_0</source_block_id>
+    <sink_block_id>fractional_resampler_xx_0</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>blocks_multiply_const_vxx_0</source_block_id>
+    <sink_block_id>gsm_controlled_rotator_cc_0</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>1</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>blocks_multiply_const_vxx_0_0</source_block_id>
+    <sink_block_id>blocks_add_const_vxx_0</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>fractional_resampler_xx_0</source_block_id>
+    <sink_block_id>pad_sink_1</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>0</sink_key>
+  </connection>
+  <connection>
+    <source_block_id>ppm_msg</source_block_id>
+    <sink_block_id>gsm_controlled_const_source_f_0</sink_block_id>
+    <source_key>0</source_key>
+    <sink_key>constant_msg</sink_key>
+  </connection>
+</flow_graph>
diff --git a/include/gsm/controlled_const_source_f.h b/include/gsm/controlled_const_source_f.h
new file mode 100644
index 0000000..b175578
--- /dev/null
+++ b/include/gsm/controlled_const_source_f.h
@@ -0,0 +1,57 @@
+/* -*- c++ -*- */
+/* 
+ * Copyright 2014 <+YOU OR YOUR COMPANY+>.
+ * 
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ * 
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef INCLUDED_GSM_CONTROLLED_CONST_SOURCE_F_H
+#define INCLUDED_GSM_CONTROLLED_CONST_SOURCE_F_H
+
+#include <gsm/api.h>
+#include <gnuradio/sync_block.h>
+
+namespace gr {
+  namespace gsm {
+
+    /*!
+     * \brief <+description of block+>
+     * \ingroup gsm
+     *
+     */
+    class GSM_API controlled_const_source_f : virtual public gr::sync_block
+    {
+     public:
+      typedef boost::shared_ptr<controlled_const_source_f> sptr;
+
+      /*!
+       * \brief Return a shared_ptr to a new instance of gsm::controlled_const_source_f.
+       *
+       * To avoid accidental use of raw pointers, gsm::controlled_const_source_f's
+       * constructor is in a private implementation
+       * class. gsm::controlled_const_source_f::make is the public interface for
+       * creating new instances.
+       */
+      static sptr make(float constant);
+      virtual void set_constant(float constant) = 0;
+    };
+
+  } // namespace gsm
+} // namespace gr
+
+#endif /* INCLUDED_GSM_CONTROLLED_CONST_SOURCE_F_H */
+
diff --git a/include/gsm/controlled_rotator_cc.h b/include/gsm/controlled_rotator_cc.h
new file mode 100644
index 0000000..5339660
--- /dev/null
+++ b/include/gsm/controlled_rotator_cc.h
@@ -0,0 +1,59 @@
+/* -*- c++ -*- */
+/* 
+ * Copyright 2014 <+YOU OR YOUR COMPANY+>.
+ * 
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ * 
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef INCLUDED_GSM_CONTROLLED_ROTATOR_CC_H
+#define INCLUDED_GSM_CONTROLLED_ROTATOR_CC_H
+
+#include <gsm/api.h>
+#include <gnuradio/sync_block.h>
+
+namespace gr {
+  namespace gsm {
+
+    /*!
+     * \brief <+description of block+>
+     * \ingroup gsm
+     *
+     */
+    class GSM_API controlled_rotator_cc : virtual public sync_block
+    {
+     public:
+      typedef boost::shared_ptr<controlled_rotator_cc> sptr;
+
+      /*!
+       * \brief Return a shared_ptr to a new instance of gsm::controlled_rotator_cc.
+       *
+       * To avoid accidental use of raw pointers, gsm::controlled_rotator_cc's
+       * constructor is in a private implementation
+       * class. gsm::controlled_rotator_cc::make is the public interface for
+       * creating new instances.
+       */
+      static sptr make(double phase_inc, double samp_rate);
+      
+      virtual void set_phase_inc(double phase_inc) = 0;
+      virtual void set_samp_rate(double samp_rate) = 0;
+    };
+
+  } // namespace gsm
+} // namespace gr
+
+#endif /* INCLUDED_GSM_CONTROLLED_ROTATOR_CC_H */
+
diff --git a/include/gsm/message_printer.h b/include/gsm/message_printer.h
new file mode 100644
index 0000000..e049934
--- /dev/null
+++ b/include/gsm/message_printer.h
@@ -0,0 +1,56 @@
+/* -*- c++ -*- */
+/* 
+ * Copyright 2014 <+YOU OR YOUR COMPANY+>.
+ * 
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ * 
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+
+#ifndef INCLUDED_GSM_MESSAGE_PRINTER_H
+#define INCLUDED_GSM_MESSAGE_PRINTER_H
+
+#include <gsm/api.h>
+#include <gnuradio/sync_block.h>
+
+namespace gr {
+  namespace gsm {
+
+    /*!
+     * \brief <+description of block+>
+     * \ingroup gsm
+     *
+     */
+    class GSM_API message_printer : virtual public gr::block
+    {
+     public:
+      typedef boost::shared_ptr<message_printer> sptr;
+
+      /*!
+       * \brief Return a shared_ptr to a new instance of gsm::message_printer.
+       *
+       * To avoid accidental use of raw pointers, gsm::message_printer's
+       * constructor is in a private implementation
+       * class. gsm::message_printer::make is the public interface for
+       * creating new instances.
+       */
+      static sptr make();
+    };
+
+  } // namespace gsm
+} // namespace gr
+
+#endif /* INCLUDED_GSM_MESSAGE_PRINTER_H */
+
diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt
index 5a730b9..e4ed842 100644
--- a/lib/CMakeLists.txt
+++ b/lib/CMakeLists.txt
@@ -35,6 +35,9 @@
     decoding/control_channels_decoder_impl.cc
     decoding/cch.c
     decoding/fire_crc.c
+    misc_utils/controlled_rotator_cc_impl.cc
+    misc_utils/controlled_const_source_f_impl.cc
+    misc_utils/message_printer_impl.cc
 )
 
 add_library(gnuradio-gsm SHARED ${gsm_sources})
diff --git a/lib/misc_utils/controlled_const_source_f_impl.cc b/lib/misc_utils/controlled_const_source_f_impl.cc
new file mode 100644
index 0000000..d58f04f
--- /dev/null
+++ b/lib/misc_utils/controlled_const_source_f_impl.cc
@@ -0,0 +1,86 @@
+/* -*- c++ -*- */
+/* 
+ * Copyright 2014 <+YOU OR YOUR COMPANY+>.
+ * 
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ * 
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gnuradio/io_signature.h>
+#include "controlled_const_source_f_impl.h"
+
+namespace gr {
+  namespace gsm {
+
+    controlled_const_source_f::sptr
+    controlled_const_source_f::make(float constant)
+    {
+      return gnuradio::get_initial_sptr
+        (new controlled_const_source_f_impl(constant));
+    }
+    
+    void controlled_const_source_f_impl::set_constant_msg(pmt::pmt_t msg){
+      if(pmt::is_real(msg)){
+          set_constant(pmt::to_double(msg));
+      }
+    }
+
+    /*
+     * The private constructor
+     */
+    controlled_const_source_f_impl::controlled_const_source_f_impl(float constant)
+      : gr::sync_block("controlled_const_source_f",
+              gr::io_signature::make(0, 0, 0),
+              gr::io_signature::make(1, 1, sizeof(float)))
+    {
+        set_constant(constant);
+        message_port_register_in(pmt::mp("constant_msg"));
+        set_msg_handler(pmt::mp("constant_msg"), boost::bind(&controlled_const_source_f_impl::set_constant_msg, this, _1));
+    }
+
+    /*
+     * Our virtual destructor.
+     */
+    controlled_const_source_f_impl::~controlled_const_source_f_impl()
+    {
+    }
+
+    int
+    controlled_const_source_f_impl::work(int noutput_items,
+			  gr_vector_const_void_star &input_items,
+			  gr_vector_void_star &output_items)
+    {
+      float *optr = (float*)output_items[0];
+      float t;
+      
+      t = d_constant;
+      std::fill_n(optr, noutput_items, t);
+
+      return noutput_items;
+    }
+    
+    void controlled_const_source_f_impl::set_constant(float constant){
+      d_constant = constant;
+    }
+    
+
+
+  } /* namespace gsm */
+} /* namespace gr */
+
diff --git a/lib/misc_utils/controlled_const_source_f_impl.h b/lib/misc_utils/controlled_const_source_f_impl.h
new file mode 100644
index 0000000..2abe812
--- /dev/null
+++ b/lib/misc_utils/controlled_const_source_f_impl.h
@@ -0,0 +1,51 @@
+/* -*- c++ -*- */
+/* 
+ * Copyright 2014 <+YOU OR YOUR COMPANY+>.
+ * 
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ * 
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_GSM_CONTROLLED_CONST_SOURCE_F_IMPL_H
+#define INCLUDED_GSM_CONTROLLED_CONST_SOURCE_F_IMPL_H
+
+#include <gsm/controlled_const_source_f.h>
+
+namespace gr {
+  namespace gsm {
+
+    class controlled_const_source_f_impl : public controlled_const_source_f
+    {
+     private:
+      float d_constant;
+      void set_constant_msg(pmt::pmt_t msg);
+      
+     public:
+      controlled_const_source_f_impl(float constant);
+      ~controlled_const_source_f_impl();
+
+      // Where all the action really happens
+      int work(int noutput_items,
+	       gr_vector_const_void_star &input_items,
+	       gr_vector_void_star &output_items);
+	       
+	  virtual void set_constant(float constant);
+    };
+
+  } // namespace gsm
+} // namespace gr
+
+#endif /* INCLUDED_GSM_CONTROLLED_CONST_SOURCE_F_IMPL_H */
+
diff --git a/lib/misc_utils/controlled_rotator_cc_impl.cc b/lib/misc_utils/controlled_rotator_cc_impl.cc
new file mode 100644
index 0000000..39fafb0
--- /dev/null
+++ b/lib/misc_utils/controlled_rotator_cc_impl.cc
@@ -0,0 +1,107 @@
+/* -*- c++ -*- */
+/* 
+ * Copyright 2014 <+YOU OR YOUR COMPANY+>.
+ * 
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ * 
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <gnuradio/io_signature.h>
+#include "controlled_rotator_cc_impl.h"
+#include <gnuradio/blocks/rotator_cc.h>
+#include <math.h>
+
+namespace gr {
+  namespace gsm {
+
+    controlled_rotator_cc::sptr
+    controlled_rotator_cc::make(double phase_inc, double samp_rate)
+    {
+      return gnuradio::get_initial_sptr
+        (new controlled_rotator_cc_impl(phase_inc, samp_rate));
+    }
+
+    /*
+     * The private constructor
+     */
+    controlled_rotator_cc_impl::controlled_rotator_cc_impl(double phase_inc, double samp_rate)
+      : gr::sync_block("controlled_rotator_cc",
+              gr::io_signature::make2(1, 2, sizeof(gr_complex), sizeof(float)),
+              gr::io_signature::make(1, 1, sizeof(gr_complex)))
+    {
+      set_phase_inc(phase_inc);
+      set_samp_rate(samp_rate);
+    }
+    
+    /*
+     * Our virtual destructor.
+     */
+    controlled_rotator_cc_impl::~controlled_rotator_cc_impl()
+    {
+    }
+
+    void
+    controlled_rotator_cc_impl::set_phase_inc(double phase_inc)
+    {
+      d_phase_inc = phase_inc;
+      d_r.set_phase_incr( exp(gr_complex(0, (double)phase_inc)) );
+    }
+
+    void
+    controlled_rotator_cc_impl::set_samp_rate(double samp_rate)
+    {
+      d_samp_rate = samp_rate;
+    }
+
+    int
+    controlled_rotator_cc_impl::work(int noutput_items,
+			  gr_vector_const_void_star &input_items,
+			  gr_vector_void_star &output_items)
+    {
+      const gr_complex *in = (const gr_complex *)input_items[0];
+      gr_complex *out = (gr_complex *)output_items[0];
+
+      if(input_items.size() == 2) {
+        int ii=0;
+        const float *pp = (const float *)input_items[1];
+        
+        while(ii < noutput_items){
+          //look for different values on phase increment control input
+          if(d_phase_inc != (*pp)){
+            set_phase_inc(*(pp));      //set new value of phase increment
+            
+            float freq_offset_setting = (*(pp) / (2*M_PI)) * d_samp_rate; //send stream tag with a new value of the frequency offset
+            int offset = nitems_written(0);
+            pmt::pmt_t key = pmt::string_to_symbol("setting_freq_offset");
+            pmt::pmt_t value =  pmt::from_double(freq_offset_setting);
+            add_item_tag(0,offset, key, value);
+            
+            break;
+          }
+          pp++;
+          ii++;
+        }
+      }
+      d_r.rotateN(out, in, noutput_items);
+      return noutput_items;
+    }
+
+  } /* namespace gsm */
+} /* namespace gr */
+
diff --git a/lib/misc_utils/controlled_rotator_cc_impl.h b/lib/misc_utils/controlled_rotator_cc_impl.h
new file mode 100644
index 0000000..2dbad6c
--- /dev/null
+++ b/lib/misc_utils/controlled_rotator_cc_impl.h
@@ -0,0 +1,53 @@
+/* -*- c++ -*- */
+/* 
+ * Copyright 2014 <+YOU OR YOUR COMPANY+>.
+ * 
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3, or (at your option)
+ * any later version.
+ * 
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this software; see the file COPYING.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef INCLUDED_GSM_CONTROLLED_ROTATOR_CC_IMPL_H
+#define INCLUDED_GSM_CONTROLLED_ROTATOR_CC_IMPL_H
+
+#include <gsm/controlled_rotator_cc.h>
+#include <gnuradio/blocks/rotator.h>
+
+namespace gr {
+  namespace gsm {
+
+    class controlled_rotator_cc_impl : public controlled_rotator_cc
+    {
+     private:
+      gr_complex d_phase_inc;
+      double d_samp_rate;
+      blocks::rotator d_r;
+
+     public:
+      controlled_rotator_cc_impl(double phase_inc, double samp_rate);
+      ~controlled_rotator_cc_impl();
+
+      virtual void set_phase_inc(double phase_inc);
+      virtual void set_samp_rate(double samp_rate);
+      // Where all the action really happens
+      int work(int noutput_items,
+	       gr_vector_const_void_star &input_items,
+	       gr_vector_void_star &output_items);
+    };
+
+  } // namespace gsm
+} // namespace gr
+
+#endif /* INCLUDED_GSM_CONTROLLED_ROTATOR_CC_IMPL_H */
+
diff --git a/lib/receiver/receiver_impl.cc b/lib/receiver/receiver_impl.cc
index 500113e..c333ccf 100644
--- a/lib/receiver/receiver_impl.cc
+++ b/lib/receiver/receiver_impl.cc
@@ -71,7 +71,7 @@
     d_tuner(tuner),
     d_counter(0),
     d_fcch_start_pos(0),
-    d_freq_offset(0),
+    d_freq_offset_setting(0),
     d_state(first_fcch_search),
     d_burst_nr(osr),
     d_failed_sch(0),
@@ -79,7 +79,7 @@
     d_signal_dbm(-120)
 {
     int i;
-    //set_output_multiple(floor((TS_BITS + 2 * GUARD_PERIOD) * d_OSR)); //don't send samples to the receiver until there are at least samples for one
+                                                                      //don't send samples to the receiver until there are at least samples for one
     set_output_multiple(floor((TS_BITS + 2 * GUARD_PERIOD) * d_OSR)); // burst and two gurad periods (one gurard period is an arbitrary overlap)
     gmsk_mapper(SYNC_BITS, N_SYNC_BITS, d_sch_training_seq, gr_complex(0.0, -1.0));
     for (i = 0; i < TRAIN_SEQ_NUM; i++)
@@ -89,11 +89,10 @@
         gmsk_mapper(train_seq[i], N_TRAIN_BITS, d_norm_training_seq[i], startpoint);
     }
     message_port_register_out(pmt::mp("bursts"));
+    message_port_register_out(pmt::mp("measurements"));
     configure_receiver();  //configure the receiver - tell it where to find which burst type
 }
 
-
-
 /*
  * Our virtual destructor.
  */
@@ -106,19 +105,44 @@
 	               gr_vector_const_void_star &input_items,
 	               gr_vector_void_star &output_items)
 {
-    //std::cout << noutput_items << std::endl;
     const gr_complex *input = (const gr_complex *) input_items[0];
+    std::vector<tag_t> freq_offset_tags;
+    uint64_t start = nitems_read(0);
+    uint64_t stop = start + noutput_items;
 
+    pmt::pmt_t key = pmt::string_to_symbol("setting_freq_offset");
+    get_tags_in_range(freq_offset_tags, 0, start, stop, key);
+    bool freq_offset_tag_in_fcch = false;
+    uint64_t tag_offset=-1; //-1 - just some clearly invalid value
+    
+    if(!freq_offset_tags.empty()){
+        tag_t freq_offset_tag = freq_offset_tags[0];
+        tag_offset = freq_offset_tag.offset - start;
+        
+        burst_type b_type = d_channel_conf.get_burst_type(d_burst_nr);
+        if(d_state == synchronized && b_type == fcch_burst){
+            uint64_t last_sample_nr = ceil((GUARD_PERIOD + 2.0 * TAIL_BITS + 156.25) * d_OSR) + 1;
+            if(tag_offset < last_sample_nr){
+                DCOUT("Freq change inside FCCH burst!!!!!!!!!!!!!!");
+                freq_offset_tag_in_fcch = true;
+            }
+            d_freq_offset_setting = pmt::to_double(freq_offset_tag.value);
+        } else {
+            d_freq_offset_setting = pmt::to_double(freq_offset_tag.value);
+        }
+    }
+    
     switch (d_state)
     {
         //bootstrapping
     case first_fcch_search:
         DCOUT("FCCH search");
-        if (find_fcch_burst(input, noutput_items))   //find frequency correction burst in the input buffer
+        double freq_offset_tmp;
+        if (find_fcch_burst(input, noutput_items, freq_offset_tmp))   //find frequency correction burst in the input buffer
         {
-            //set_frequency(d_freq_offset);                //if fcch search is successful set frequency offset
-            DCOUT("Freq offset " << d_freq_offset);
-            DCOUT("PPM: " << d_freq_offset/940e6);
+            pmt::pmt_t msg = pmt::make_tuple(pmt::mp("freq_offset"),pmt::from_double(freq_offset_tmp-d_freq_offset_setting),pmt::mp("first_fcch_search"));
+            message_port_pub(pmt::mp("measurements"), msg);
+            
             d_state = next_fcch_search;
         }
         else
@@ -130,15 +154,12 @@
     case next_fcch_search:                           //this state is used because it takes some time (a bunch of buffered samples)
     {
         DCOUT("NEXT FCCH search");
-        d_prev_freq_offset = d_freq_offset;        //before previous set_frequqency cause change
-        if (find_fcch_burst(input, noutput_items))
+        double freq_offset_tmp;
+        if (find_fcch_burst(input, noutput_items,freq_offset_tmp))
         {
-            if (abs(d_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
-                //COUT("Freq offset " << d_freq_offset);
-                DCOUT("PPM: " << d_freq_offset/940);
-            }
+            pmt::pmt_t msg = pmt::make_tuple(pmt::mp("freq_offset"),pmt::from_double(freq_offset_tmp-d_freq_offset_setting),pmt::mp("next_fcch_search"));
+            message_port_pub(pmt::mp("measurements"), msg);
+
             d_state = sch_search;
         }
         else
@@ -148,7 +169,6 @@
         break;
     }
 
-
     case sch_search:
     {
         DCOUT("SCH search");
@@ -206,30 +226,24 @@
         {
             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
+            double freq_offset_tmp = compute_freq_offset(input, first_sample, last_sample);       //extract frequency offset from it
 
-            d_freq_offset_vals.push_front(freq_offset);
             send_burst(d_burst_nr, fc_fb, b_type);
 
-            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();
-                DCOUT("mean offset" << mean_offset/940);
-                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("Adjusting frequency, new frequency offset: " << d_freq_offset << "\n");
-                }
-            }
+            pmt::pmt_t msg = pmt::make_tuple(pmt::mp("freq_offset"),pmt::from_double(freq_offset_tmp-d_freq_offset_setting),pmt::mp("synchronized"));
+            message_port_pub(pmt::mp("measurements"), msg);
         }
         break;
         case sch_burst:                                                                      //if it's SCH burst
         {
             int t1, t2, t3, d_ncc, d_bcc;
             burst_start = get_sch_chan_imp_resp(input, &channel_imp_resp[0]);                //get channel impulse response
+            
+            if(d_prev_burst_start != burst_start){
+                d_prev_burst_start = burst_start;
+                DCOUT("burst start" << burst_start);
+            }
+            
             detect_burst(input, &channel_imp_resp[0], burst_start, output_binary);           //MLSE detection of bits
             send_burst(d_burst_nr, output_binary, b_type);
             if (decode_sch(&output_binary[3], &t1, &t2, &t3, &d_ncc, &d_bcc) == 0)           //and decode SCH data
@@ -247,10 +261,9 @@
                 if (d_failed_sch >= MAX_SCH_ERRORS)
                 {
                     d_state = next_fcch_search; 
-                    d_freq_offset_vals.clear();
-                    d_freq_offset=0;
-                    //set_frequency(0);
-                    COUT("Re-Synchronization!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
+                    pmt::pmt_t msg = pmt::make_tuple(pmt::mp("freq_offset"),pmt::from_double(0.0),pmt::mp("sync_loss"));
+                    message_port_pub(pmt::mp("measurements"), msg);
+                    DCOUT("Re-Synchronization!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
                 }
             }
         }
@@ -268,9 +281,7 @@
         {
             unsigned int normal_burst_start;
             float dummy_corr_max, normal_corr_max;
-            DCOUT("Dummy");
             get_norm_chan_imp_resp(input, &channel_imp_resp[0], &dummy_corr_max, TS_DUMMY);
-            DCOUT("Normal");
             normal_burst_start = get_norm_chan_imp_resp(input, &channel_imp_resp[0], &normal_corr_max, d_bcc);
                         
             DCOUT("normal_corr_max: " << normal_corr_max <<  " dummy_corr_max:" << dummy_corr_max);
@@ -305,8 +316,7 @@
     return 0;
 }
 
-
-bool receiver_impl::find_fcch_burst(const gr_complex *input, const int nitems)
+bool receiver_impl::find_fcch_burst(const gr_complex *input, const int nitems, double & computed_freq_offset)
 {
     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
@@ -451,10 +461,8 @@
 
             //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;
-            d_freq_offset = freq_offset;
-            DCOUT("freq_offset: " << d_freq_offset);
+            double freq_offset = phase_offset * 1625000.0/6 / (2 * M_PI); //1625000.0/6 - GMSK symbol rate in GSM
+            computed_freq_offset = freq_offset;
 
             end = true;
             result = true;
@@ -623,7 +631,6 @@
     }
 }
 
-//TODO consider placing this funtion in a separate class for signal processing
 void receiver_impl::gmsk_mapper(const unsigned char * input, int nitems, gr_complex * gmsk_output, gr_complex start_point)
 {
     gr_complex j = gr_complex(0.0, 1.0);
@@ -645,7 +652,6 @@
     }
 }
 
-//TODO consider use of some generalized function for correlation and placing it in a separate class  for signal processing
 gr_complex receiver_impl::correlate_sequence(const gr_complex * sequence, int length, const gr_complex * input)
 {
     gr_complex result(0.0, 0.0);
@@ -662,7 +668,6 @@
 }
 
 //computes autocorrelation for positive arguments
-//TODO consider placing this funtion in a separate class for signal processing
 inline void receiver_impl::autocorrelation(const gr_complex * input, gr_complex * out, int nitems)
 {
     int i, k;
@@ -676,7 +681,6 @@
     }
 }
 
-//TODO consider use of some generalized function for filtering and placing it in a separate class  for signal processing
 inline void receiver_impl::mafi(const gr_complex * input, int nitems, gr_complex * filter, int filter_length, gr_complex * output)
 {
     int ii = 0, n, a;
@@ -698,7 +702,6 @@
     }
 }
 
-//TODO: get_norm_chan_imp_resp is similar to get_sch_chan_imp_resp - consider joining this two functions
 //especially computations of strongest_window_nr
 int receiver_impl::get_norm_chan_imp_resp(const gr_complex *input, gr_complex * chan_imp_resp, float *corr_max, int bcc)
 {
@@ -774,8 +777,6 @@
 
     DCOUT("strongest_window_nr_new: " << strongest_window_nr);
     burst_start = search_start_pos + strongest_window_nr - TRAIN_POS * d_OSR; //compute first sample posiiton which corresponds to the first sample of the impulse response
-                                                                              //TRAIN_POS=3+57+1+6
-                                                                              //TODO: describe this part in detail in documentation as this is crucial part for synchronization
 
     DCOUT("burst_start: " << burst_start);
     return burst_start;
@@ -845,7 +846,6 @@
 void receiver_impl::set_arfcn(int arfcn) //!!
 {
     d_arfcn = arfcn;
-//    std::cout << "set arfcn:"<<arfcn << std::endl;
 }
 
 void receiver_impl::reset()
diff --git a/lib/receiver/receiver_impl.h b/lib/receiver/receiver_impl.h
index d3083b2..76ad40b 100644
--- a/lib/receiver/receiver_impl.h
+++ b/lib/receiver/receiver_impl.h
@@ -34,6 +34,7 @@
     class receiver_impl : public receiver
     {
      private:
+        int d_prev_burst_start; //!!
         /**@name Configuration of the receiver */
         //@{
         const int d_OSR; ///< oversampling ratio
@@ -59,8 +60,8 @@
         /**@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
-        float d_prev_freq_offset; //!!!
+//        float d_freq_offset; ///< frequency offset of the received signal
+        float d_freq_offset_setting; ///< frequency offset set in frequency shifter located upstream
         //@}
         std::list<double> d_freq_offset_vals;
 
@@ -89,19 +90,19 @@
         /** 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);
+        bool find_fcch_burst(const gr_complex *input, const int nitems, double & computed_freq_offset);
 
         /** 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
+         * @param[in] input vector with input samples
+         * @param[in] first_sample number of the first sample of the FCCH busrt
+         * @param[in] last_sample number of the last sample of the FCCH busrt
+         * @param[out] computed_freq_offset contains frequency offset estimate if FCCH burst was located
+         * @return true if frequency offset was faound
          */
         double compute_freq_offset(const gr_complex * input, unsigned first_sample, unsigned last_sample);
 
@@ -206,8 +207,6 @@
        receiver_impl(feval_dd * tuner, int osr, int arfcn);
       ~receiver_impl();
       
-//      void forecast(int noutput_items, gr_vector_int &ninput_items_required);
-
       int work(int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items);
       virtual void set_arfcn(int arfcn);
       virtual void reset();
diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt
index 651baa5..1b24d40 100644
--- a/python/CMakeLists.txt
+++ b/python/CMakeLists.txt
@@ -36,7 +36,7 @@
     sch_detector.py
     fcch_detector.py 
     chirpz.py
-    DESTINATION ${GR_PYTHON_DIR}/gsm
+    clock_offset_control.py DESTINATION ${GR_PYTHON_DIR}/gsm
 )
 
 ########################################################################
diff --git a/python/__init__.py b/python/__init__.py
index cf25d1c..3428109 100644
--- a/python/__init__.py
+++ b/python/__init__.py
@@ -50,6 +50,7 @@
 from fcch_burst_tagger import fcch_burst_tagger
 from sch_detector import sch_detector
 from fcch_detector import fcch_detector
+from clock_offset_control import clock_offset_control
 
 #
 
diff --git a/python/clock_offset_control.py b/python/clock_offset_control.py
new file mode 100644
index 0000000..133368c
--- /dev/null
+++ b/python/clock_offset_control.py
@@ -0,0 +1,76 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# 
+# Copyright 2014 <+YOU OR YOUR COMPANY+>.
+# 
+# This is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+# 
+# This software is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+# 
+# You should have received a copy of the GNU General Public License
+# along with this software; see the file COPYING.  If not, write to
+# the Free Software Foundation, Inc., 51 Franklin Street,
+# Boston, MA 02110-1301, USA.
+# 
+
+from numpy import *
+from gnuradio import gr
+import pmt
+
+class clock_offset_control(gr.basic_block):
+    """
+    docstring for block clock_offset_control
+    """
+    def __init__(self, fc, samp_rate):
+        gr.basic_block.__init__(self,
+            name="clock_offset_control",
+            in_sig=[],
+            out_sig=[])
+        self.fc = fc
+        self.samp_rate = samp_rate
+        self.message_port_register_in(pmt.intern("measurements"))
+        self.set_msg_handler(pmt.intern("measurements"), self.process_measurement)
+        self.message_port_register_out(pmt.intern("ppm"))
+        self.alfa = 0.6
+        self.ppm_estimate = -1e6
+        self.first_measurement = True
+        self.counter = 0
+        
+    def process_measurement(self,msg):
+        if pmt.is_tuple(msg):
+            key = pmt.symbol_to_string(pmt.tuple_ref(msg,0))
+            if key == "freq_offset":
+                freq_offset = pmt.to_double(pmt.tuple_ref(msg,1))
+                ppm = -freq_offset/self.fc*1.0e6
+                state = pmt.symbol_to_string(pmt.tuple_ref(msg,2))
+
+                if state == "first_fcch_search" or state == "next_fcch_search":
+                    msg_ppm = pmt.from_double(ppm)
+                    self.message_port_pub(pmt.intern("ppm"), msg_ppm)
+                
+                if state == "synchronized":
+                    if self.first_measurement:
+                        self.ppm_estimate = ppm
+                        self.first_measurement = False
+                    else:
+                        self.ppm_estimate = (1-self.alfa)*self.ppm_estimate+self.alfa*ppm
+                    
+                    if self.counter == 5:
+                        self.counter = 0
+                        msg_ppm = pmt.from_double(ppm)
+                        self.message_port_pub(pmt.intern("ppm"), msg_ppm)
+                    else:
+                        self.counter=self.counter+1
+                    
+                if state == "sync_loss":
+                    self.ppm_estimate = -1e6
+                    self.counter = 0
+                    self.first_measurement = True
+                    msg_ppm = pmt.from_double(0.0)
+                    self.message_port_pub(pmt.intern("ppm"), msg_ppm)
diff --git a/python/clock_offset_corrector.py b/python/clock_offset_corrector.py
new file mode 100644
index 0000000..df97cca
--- /dev/null
+++ b/python/clock_offset_corrector.py
@@ -0,0 +1,82 @@
+#!/usr/bin/env python
+##################################################
+# Gnuradio Python Flow Graph
+# Title: Clock offset corrector
+# Author: Piotr Krysik
+# Generated: Wed Aug  6 13:47:38 2014
+##################################################
+
+from gnuradio import blocks
+from gnuradio import filter
+from gnuradio import gr
+from gnuradio.filter import firdes
+import gsm
+import math
+
+class clock_offset_corrector(gr.hier_block2):
+
+    def __init__(self, ppm=0, samp_rate=1625000.0/6.0*4.0, fc=936.6e6):
+        gr.hier_block2.__init__(
+            self, "Clock offset corrector",
+            gr.io_signature(1, 1, gr.sizeof_gr_complex*1),
+            gr.io_signature(1, 1, gr.sizeof_gr_complex*1),
+        )
+
+        ##################################################
+        # Parameters
+        ##################################################
+        self.ppm = ppm
+        self.samp_rate = samp_rate
+        self.fc = fc
+
+        ##################################################
+        # Blocks
+        ##################################################
+        self.ppm_msg = None;self.message_port_register_hier_out("ppm_msg")
+        self.gsm_controlled_rotator_cc_0 = gsm.controlled_rotator_cc(0,samp_rate)
+        self.gsm_controlled_const_source_f_0 = gsm.controlled_const_source_f(ppm)
+        self.fractional_resampler_xx_0 = filter.fractional_resampler_cc(0, 1)
+        self.blocks_multiply_const_vxx_0_0 = blocks.multiply_const_vff((1.0/1.0e6, ))
+        self.blocks_multiply_const_vxx_0 = blocks.multiply_const_vff((fc/samp_rate*(2*math.pi), ))
+        self.blocks_add_const_vxx_0 = blocks.add_const_vff((1, ))
+
+        ##################################################
+        # Connections
+        ##################################################
+        self.connect((self.gsm_controlled_const_source_f_0, 0), (self.blocks_multiply_const_vxx_0_0, 0))
+        self.connect((self, 0), (self.gsm_controlled_rotator_cc_0, 0))
+        self.connect((self.blocks_multiply_const_vxx_0_0, 0), (self.blocks_multiply_const_vxx_0, 0))
+        self.connect((self.blocks_add_const_vxx_0, 0), (self.fractional_resampler_xx_0, 1))
+        self.connect((self.gsm_controlled_rotator_cc_0, 0), (self.fractional_resampler_xx_0, 0))
+        self.connect((self.blocks_multiply_const_vxx_0, 0), (self.gsm_controlled_rotator_cc_0, 1))
+        self.connect((self.blocks_multiply_const_vxx_0_0, 0), (self.blocks_add_const_vxx_0, 0))
+        self.connect((self.fractional_resampler_xx_0, 0), (self, 0))
+
+        ##################################################
+        # Asynch Message Connections
+        ##################################################
+        self.msg_connect(self, "ppm_msg", self.gsm_controlled_const_source_f_0, "constant_msg")
+
+
+    def get_ppm(self):
+        return self.ppm
+
+    def set_ppm(self, ppm):
+        self.ppm = ppm
+        self.gsm_controlled_const_source_f_0.set_constant(self.ppm)
+
+    def get_samp_rate(self):
+        return self.samp_rate
+
+    def set_samp_rate(self, samp_rate):
+        self.samp_rate = samp_rate
+        self.blocks_multiply_const_vxx_0.set_k((self.fc/self.samp_rate*(2*math.pi), ))
+        self.gsm_controlled_rotator_cc_0.set_samp_rate(self.samp_rate)
+
+    def get_fc(self):
+        return self.fc
+
+    def set_fc(self, fc):
+        self.fc = fc
+        self.blocks_multiply_const_vxx_0.set_k((self.fc/self.samp_rate*(2*math.pi), ))
+
diff --git a/python/receiver_hier.py b/python/receiver_hier.py
index 6a0b77f..fe9c636 100644
--- a/python/receiver_hier.py
+++ b/python/receiver_hier.py
@@ -25,6 +25,7 @@
         gsm_symb_rate = 1625000/6.0
 
         self.message_port_register_hier_in("bursts")
+        self.message_port_register_hier_in("measurements")
 
         self.input_rate = input_rate
         self.osr = osr
@@ -40,6 +41,7 @@
         self.connect(self, self.filtr,  self.interpolator, self.receiver,  self)
 #        self.connect(self, self.interpolator, self.receiver,  self)
         self.msg_connect(self.receiver, "bursts", weakref.proxy(self), "bursts")
+        self.msg_connect(self.receiver, "measurements", weakref.proxy(self), "measurements")
 
     def _set_filter(self):
         filter_cutoff   = 125e3