blob: 41157077a9b911266060d42ab471c55597b9e324 [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>
Piotr Krysik83afe732016-07-17 22:48:35 +020029#include <gsm_constants.h>
ptrkrysikf8c7e832015-04-04 12:28:20 +020030#include "clock_offset_control_impl.h"
31
32namespace gr
33{
34namespace gsm
35{
36clock_offset_control::sptr
Piotr Krysik83afe732016-07-17 22:48:35 +020037clock_offset_control::make(float fc, float samp_rate, unsigned int osr)
ptrkrysikf8c7e832015-04-04 12:28:20 +020038{
39 return gnuradio::get_initial_sptr
Piotr Krysik83afe732016-07-17 22:48:35 +020040 (new clock_offset_control_impl(fc, samp_rate, osr));
ptrkrysikf8c7e832015-04-04 12:28:20 +020041}
42
43
44/*
45 * The private constructor
46 */
Piotr Krysik83afe732016-07-17 22:48:35 +020047clock_offset_control_impl::clock_offset_control_impl(float fc, float samp_rate, unsigned int osr)
ptrkrysikf8c7e832015-04-04 12:28:20 +020048 : gr::block("clock_offset_control",
49 gr::io_signature::make(0, 0, 0),
ptrkrysik32c21162015-04-04 14:01:52 +020050 gr::io_signature::make(0, 0, 0))
ptrkrysikf8c7e832015-04-04 12:28:20 +020051
52{
53 message_port_register_in(pmt::mp("measurements"));
54 set_msg_handler(pmt::mp("measurements"), boost::bind(&clock_offset_control_impl::process_measurement, this, _1));
Piotr Krysik09826732016-07-15 13:14:24 +020055 message_port_register_out(pmt::mp("ctrl"));
ptrkrysikf8c7e832015-04-04 12:28:20 +020056
57 set_fc(fc);
Piotr Krysik09826732016-07-15 13:14:24 +020058 set_samp_rate(samp_rate);
Piotr Krysik83afe732016-07-17 22:48:35 +020059 set_osr(osr);
ptrkrysikf8c7e832015-04-04 12:28:20 +020060 d_alfa = 0.3;
61 d_ppm_estimate = -1e6;
62 d_last_ppm_estimate = -1e6;
63 d_first_measurement = true;
64 d_counter = 0;
65 d_last_state = "";
ptrkrysik32c21162015-04-04 14:01:52 +020066 d_current_time = 0;
67 d_last_fcch_time = 0;
68 d_first_time = true;
ptrkrysikf8c7e832015-04-04 12:28:20 +020069}
70
71/*
72 * Our virtual destructor.
73 */
74clock_offset_control_impl::~clock_offset_control_impl()
75{
76}
77
Piotr Krysik83afe732016-07-17 22:48:35 +020078void clock_offset_control_impl::set_osr(unsigned int osr)
79{
80 d_osr = osr;
81}
82
ptrkrysikf8c7e832015-04-04 12:28:20 +020083void clock_offset_control_impl::set_fc(float fc)
84{
85 d_fc = fc;
86}
87
Piotr Krysik09826732016-07-15 13:14:24 +020088void clock_offset_control_impl::set_samp_rate(float samp_rate)
89{
90 d_samp_rate = samp_rate;
91}
92
ptrkrysikf8c7e832015-04-04 12:28:20 +020093void clock_offset_control_impl::process_measurement(pmt::pmt_t msg)
94{
95 if(pmt::is_tuple(msg))
96 {
97 std::string key = pmt::symbol_to_string(pmt::tuple_ref(msg,0));
ptrkrysik32c21162015-04-04 14:01:52 +020098 if(key == "current_time")
99 {
100 d_current_time = pmt::to_double(pmt::tuple_ref(msg,1));
101 if(d_first_time==true)
102 {
103 d_last_fcch_time = d_current_time;
104 d_first_time = false;
105 }
106 else
107 if((d_current_time - d_last_fcch_time) > 0.5 && d_last_state == "fcch_search")
108 {
109 timed_reset();
110 }
111 }
112 else
ptrkrysikf8c7e832015-04-04 12:28:20 +0200113 if(key == "freq_offset")
114 {
115 float freq_offset = pmt::to_double(pmt::tuple_ref(msg,1));
116 float ppm = -freq_offset/d_fc*1.0e6;
117 std::string state = pmt::symbol_to_string(pmt::tuple_ref(msg,2));
118 d_last_state = state;
Piotr Krysik09826732016-07-15 13:14:24 +0200119 if(std::abs(ppm) < 100.0) //safeguard against flawed measurements
ptrkrysikf8c7e832015-04-04 12:28:20 +0200120 {
ptrkrysikf8c7e832015-04-04 12:28:20 +0200121
Piotr Krysik09826732016-07-15 13:14:24 +0200122 if(state == "fcch_search")
ptrkrysikf8c7e832015-04-04 12:28:20 +0200123 {
Piotr Krysik83afe732016-07-17 22:48:35 +0200124 send_ctrl_messages(freq_offset);
Piotr Krysik09826732016-07-15 13:14:24 +0200125 d_last_fcch_time = d_current_time;
126 }
127 else
128 if (state == "synchronized")
ptrkrysikf8c7e832015-04-04 12:28:20 +0200129 {
Piotr Krysik09826732016-07-15 13:14:24 +0200130 d_last_fcch_time = d_current_time;
131 if(d_first_measurement)
ptrkrysikf8c7e832015-04-04 12:28:20 +0200132 {
Piotr Krysik09826732016-07-15 13:14:24 +0200133 d_ppm_estimate = ppm;
134 d_first_measurement = false;
135 }
136 else
137 {
138 d_ppm_estimate = (1-d_alfa)*d_ppm_estimate+d_alfa*ppm;
139 }
140
141 if(d_counter == 5)
142 {
143 d_counter = 0;
144 if(std::abs(d_last_ppm_estimate-d_ppm_estimate) > 0.1)
145 {
146// pmt::pmt_t msg_ppm = pmt::from_double(ppm);
147// message_port_pub(pmt::intern("ppm"), msg_ppm);
Piotr Krysik83afe732016-07-17 22:48:35 +0200148 send_ctrl_messages(freq_offset);
Piotr Krysik09826732016-07-15 13:14:24 +0200149 d_last_ppm_estimate = d_ppm_estimate;
150 }
151 }
152 else
153 {
154 d_counter=d_counter+1;
ptrkrysikf8c7e832015-04-04 12:28:20 +0200155 }
156 }
157 else
Piotr Krysik09826732016-07-15 13:14:24 +0200158 if(state == "sync_loss")
ptrkrysikf8c7e832015-04-04 12:28:20 +0200159 {
Piotr Krysik09826732016-07-15 13:14:24 +0200160 reset();
161// pmt::pmt_t msg_ppm = pmt::from_double(0.0);
162// message_port_pub(pmt::intern("ppm"), msg_ppm);
163 send_ctrl_messages(0);
ptrkrysikf8c7e832015-04-04 12:28:20 +0200164 }
Piotr Krysik09826732016-07-15 13:14:24 +0200165 }
ptrkrysikf8c7e832015-04-04 12:28:20 +0200166 }
167 }
168}
169
Piotr Krysik83afe732016-07-17 22:48:35 +0200170void clock_offset_control_impl::send_ctrl_messages(float freq_offset)
Piotr Krysik09826732016-07-15 13:14:24 +0200171{
Piotr Krysik83afe732016-07-17 22:48:35 +0200172 double samp_rate_ratio = d_samp_rate / (d_osr * GSM_SYMBOL_RATE);
Piotr Krysik09826732016-07-15 13:14:24 +0200173
Piotr Krysik83afe732016-07-17 22:48:35 +0200174 pmt::pmt_t messages = pmt::make_dict();
175 messages = dict_add(messages, pmt::string_to_symbol("set_phase_inc"), pmt::from_double(-2*M_PI*freq_offset/(d_osr * GSM_SYMBOL_RATE)));
176 messages = dict_add(messages, pmt::string_to_symbol("set_resamp_ratio"), pmt::from_double((1-(freq_offset/d_fc))*samp_rate_ratio));
177 messages = dict_add(messages, pmt::string_to_symbol("setting_freq_offset"), pmt::from_double(-freq_offset));
Piotr Krysik5eb5db22017-07-20 09:06:08 +0200178 messages = dict_add(messages, pmt::string_to_symbol("clock_offset_in_ppm"), pmt::from_double(-freq_offset/d_fc*1.0e6));
Piotr Krysik83afe732016-07-17 22:48:35 +0200179 message_port_pub(pmt::intern("ctrl"), messages);
Piotr Krysik09826732016-07-15 13:14:24 +0200180}
181
ptrkrysikf8c7e832015-04-04 12:28:20 +0200182void clock_offset_control_impl::timed_reset()
183{
184 reset();
Piotr Krysik09826732016-07-15 13:14:24 +0200185 send_ctrl_messages(0);
ptrkrysikf8c7e832015-04-04 12:28:20 +0200186}
187
ptrkrysikf8c7e832015-04-04 12:28:20 +0200188void clock_offset_control_impl::reset()
189{
190 d_ppm_estimate = -1e6;
191 d_counter = 0;
192 d_first_measurement = true;
193}
194
195} /* namespace gsm */
196} /* namespace gr */
197