aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpiotr <Piotr Krysik pkrysik@elka.pw.edu.pl>2014-08-06 14:10:56 +0200
committerpiotr <Piotr Krysik pkrysik@elka.pw.edu.pl>2014-08-06 14:10:56 +0200
commit4089c1a7f3dbadf024b160667ebbd273d77984dd (patch)
tree2575805a52cd6c542a4e0911553c0114a94944a8
parent969ecbcb4cf780673866a07abfc7a96ff86cd6f9 (diff)
Added new blocks for clock freqeuncy correction
-rw-r--r--grc/CMakeLists.txt6
-rw-r--r--grc/gsm_clock_offset_control.xml33
-rw-r--r--grc/gsm_clock_offset_corrector.xml50
-rw-r--r--grc/gsm_controlled_const_source_f.xml27
-rw-r--r--grc/gsm_controlled_rotator_cc.xml38
-rw-r--r--hier_blocks/clock_offset_corrector.grc652
-rw-r--r--include/gsm/controlled_const_source_f.h57
-rw-r--r--include/gsm/controlled_rotator_cc.h59
-rw-r--r--include/gsm/message_printer.h56
-rw-r--r--lib/CMakeLists.txt3
-rw-r--r--lib/misc_utils/controlled_const_source_f_impl.cc86
-rw-r--r--lib/misc_utils/controlled_const_source_f_impl.h51
-rw-r--r--lib/misc_utils/controlled_rotator_cc_impl.cc107
-rw-r--r--lib/misc_utils/controlled_rotator_cc_impl.h53
-rw-r--r--lib/receiver/receiver_impl.cc108
-rw-r--r--lib/receiver/receiver_impl.h19
-rw-r--r--python/CMakeLists.txt2
-rw-r--r--python/__init__.py1
-rw-r--r--python/clock_offset_control.py76
-rw-r--r--python/clock_offset_corrector.py82
-rw-r--r--python/receiver_hier.py2
21 files changed, 1502 insertions, 66 deletions
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 @@ install(FILES
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 @@ list(APPEND gsm_sources
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 @@ receiver_impl::receiver_impl(feval_dd * tuner, int osr, int arfcn)
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 @@ receiver_impl::receiver_impl(feval_dd * tuner, int osr, int arfcn)
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 @@ receiver_impl::receiver_impl(feval_dd * tuner, int osr, int arfcn)
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 @@ receiver_impl::work(int noutput_items,
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 @@ receiver_impl::work(int noutput_items,
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 @@ receiver_impl::work(int noutput_items,
break;
}
-
case sch_search:
{
DCOUT("SCH search");
@@ -206,30 +226,24 @@ receiver_impl::work(int noutput_items,
{
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 @@ receiver_impl::work(int noutput_items,
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 @@ receiver_impl::work(int noutput_items,
{
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 @@ receiver_impl::work(int noutput_items,
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 @@ bool receiver_impl::find_fcch_burst(const gr_complex *input, const int nitems)
//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 @@ void receiver_impl::detect_burst(const gr_complex * input, gr_complex * chan_imp
}
}
-//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 @@ void receiver_impl::gmsk_mapper(const unsigned char * input, int nitems, gr_comp
}
}
-//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 @@ gr_complex receiver_impl::correlate_sequence(const gr_complex * sequence, int le
}
//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 @@ inline void receiver_impl::autocorrelation(const gr_complex * input, gr_complex
}
}
-//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 @@ inline void receiver_impl::mafi(const gr_complex * input, int nitems, gr_complex
}
}
-//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 @@ int receiver_impl::get_norm_chan_imp_resp(const gr_complex *input, gr_complex *
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::configure_receiver()
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 @@ namespace gr {
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 @@ namespace gr {
/**@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 @@ namespace gr {
/** 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 @@ namespace gr {
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 @@ GR_PYTHON_INSTALL(
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 receiver_hier import receiver_hier
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 @@ class receiver_hier(gr.hier_block2):
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 @@ class receiver_hier(gr.hier_block2):
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