blob: a590a6d086b57b44daee2c1cb5fb1c9c9699445e [file] [log] [blame]
ptrkrysik32c21162015-04-04 14:01:52 +02001
ptrkrysikf8c7e832015-04-04 12:28:20 +02002/* -*- c++ -*- */
3/*
4 * @file
5 * @author Piotr Krysik <ptrkrysik@gmail.com>
6 * @section LICENSE
7 *
8 * Gr-gsm is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3, or (at your option)
11 * any later version.
12 *
13 * Gr-gsm is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with gr-gsm; see the file COPYING. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street,
21 * Boston, MA 02110-1301, USA.
22 */
23
24#ifdef HAVE_CONFIG_H
25#include "config.h"
26#endif
27
28#include <sch.h>
29#include "clock_offset_control_impl.h"
30
31namespace gr
32{
33namespace gsm
34{
35clock_offset_control::sptr
36clock_offset_control::make(float fc)
37{
38 return gnuradio::get_initial_sptr
39 (new clock_offset_control_impl(fc));
40}
41
42
43/*
44 * The private constructor
45 */
46clock_offset_control_impl::clock_offset_control_impl(float fc)
47 : gr::block("clock_offset_control",
48 gr::io_signature::make(0, 0, 0),
ptrkrysik32c21162015-04-04 14:01:52 +020049 gr::io_signature::make(0, 0, 0))
ptrkrysikf8c7e832015-04-04 12:28:20 +020050
51{
52 message_port_register_in(pmt::mp("measurements"));
53 set_msg_handler(pmt::mp("measurements"), boost::bind(&clock_offset_control_impl::process_measurement, this, _1));
54 message_port_register_out(pmt::mp("ppm"));
55
56 set_fc(fc);
57 d_alfa = 0.3;
58 d_ppm_estimate = -1e6;
59 d_last_ppm_estimate = -1e6;
60 d_first_measurement = true;
61 d_counter = 0;
62 d_last_state = "";
ptrkrysik32c21162015-04-04 14:01:52 +020063 d_current_time = 0;
64 d_last_fcch_time = 0;
65 d_first_time = true;
ptrkrysikf8c7e832015-04-04 12:28:20 +020066}
67
68/*
69 * Our virtual destructor.
70 */
71clock_offset_control_impl::~clock_offset_control_impl()
72{
73}
74
75void clock_offset_control_impl::set_fc(float fc)
76{
77 d_fc = fc;
78}
79
80void clock_offset_control_impl::process_measurement(pmt::pmt_t msg)
81{
82 if(pmt::is_tuple(msg))
83 {
84 std::string key = pmt::symbol_to_string(pmt::tuple_ref(msg,0));
ptrkrysik32c21162015-04-04 14:01:52 +020085 if(key == "current_time")
86 {
87 d_current_time = pmt::to_double(pmt::tuple_ref(msg,1));
88 if(d_first_time==true)
89 {
90 d_last_fcch_time = d_current_time;
91 d_first_time = false;
92 }
93 else
94 if((d_current_time - d_last_fcch_time) > 0.5 && d_last_state == "fcch_search")
95 {
96 timed_reset();
97 }
98 }
99 else
ptrkrysikf8c7e832015-04-04 12:28:20 +0200100 if(key == "freq_offset")
101 {
102 float freq_offset = pmt::to_double(pmt::tuple_ref(msg,1));
103 float ppm = -freq_offset/d_fc*1.0e6;
104 std::string state = pmt::symbol_to_string(pmt::tuple_ref(msg,2));
105 d_last_state = state;
106 if(abs(ppm) > 100) //safeguard against flawed measurements
107 {
ptrkrysik32c21162015-04-04 14:01:52 +0200108 ppm=0;
ptrkrysikf8c7e832015-04-04 12:28:20 +0200109 reset();
110 }
111
112 if(state == "fcch_search")
113 {
114 pmt::pmt_t msg_ppm = pmt::from_double(ppm);
115 message_port_pub(pmt::intern("ppm"), msg_ppm);
ptrkrysik32c21162015-04-04 14:01:52 +0200116 d_last_fcch_time = d_current_time;
ptrkrysikf8c7e832015-04-04 12:28:20 +0200117 }
118 else
119 if (state == "synchronized")
120 {
ptrkrysik32c21162015-04-04 14:01:52 +0200121 d_last_fcch_time = d_current_time;
ptrkrysikf8c7e832015-04-04 12:28:20 +0200122 if(d_first_measurement)
123 {
124 d_ppm_estimate = ppm;
125 d_first_measurement = false;
126 }
127 else
128 {
129 d_ppm_estimate = (1-d_alfa)*d_ppm_estimate+d_alfa*ppm;
130 }
131
132 if(d_counter == 5)
133 {
134 d_counter = 0;
135 if(abs(d_last_ppm_estimate-d_ppm_estimate) > 0.1)
136 {
137 pmt::pmt_t msg_ppm = pmt::from_double(ppm);
138 message_port_pub(pmt::intern("ppm"), msg_ppm);
139 d_last_ppm_estimate = d_ppm_estimate;
140 }
141 }
142 else
143 {
144 d_counter=d_counter+1;
145 }
146 }
147 else
148 if(state == "sync_loss")
149 {
150 reset();
151 pmt::pmt_t msg_ppm = pmt::from_double(0.0);
152 message_port_pub(pmt::intern("ppm"), msg_ppm);
153 }
154 }
155 }
156}
157
158void clock_offset_control_impl::timed_reset()
159{
160 reset();
161 pmt::pmt_t msg_ppm = pmt::from_double(0.0);
162 message_port_pub(pmt::intern("ppm"), msg_ppm);
163}
164
165
166void clock_offset_control_impl::reset()
167{
168 d_ppm_estimate = -1e6;
169 d_counter = 0;
170 d_first_measurement = true;
171}
172
173} /* namespace gsm */
174} /* namespace gr */
175