blob: d62c801018b274a269c03bae70ed5ca27fd21a0c [file] [log] [blame]
ptrkrysikf8c7e832015-04-04 12:28:20 +02001/* -*- c++ -*- */
2/*
3 * @file
Piotr Krysika6268a52017-08-23 16:02:19 +02004 * @author (C) 2015-2017 Piotr Krysik <ptrkrysik@gmail.com>
ptrkrysikf8c7e832015-04-04 12:28:20 +02005 * @section LICENSE
6 *
7 * Gr-gsm is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3, or (at your option)
10 * any later version.
11 *
12 * Gr-gsm is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with gr-gsm; see the file COPYING. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street,
20 * Boston, MA 02110-1301, USA.
21 */
22
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26
27#include <sch.h>
Piotr Krysikd7efc052017-11-07 19:33:22 +010028#include <grgsm/gsm_constants.h>
ptrkrysikf8c7e832015-04-04 12:28:20 +020029#include "clock_offset_control_impl.h"
30
31namespace gr
32{
33namespace gsm
34{
35clock_offset_control::sptr
Piotr Krysik83afe732016-07-17 22:48:35 +020036clock_offset_control::make(float fc, float samp_rate, unsigned int osr)
ptrkrysikf8c7e832015-04-04 12:28:20 +020037{
38 return gnuradio::get_initial_sptr
Piotr Krysik83afe732016-07-17 22:48:35 +020039 (new clock_offset_control_impl(fc, samp_rate, osr));
ptrkrysikf8c7e832015-04-04 12:28:20 +020040}
41
42
43/*
44 * The private constructor
45 */
Piotr Krysik83afe732016-07-17 22:48:35 +020046clock_offset_control_impl::clock_offset_control_impl(float fc, float samp_rate, unsigned int osr)
ptrkrysikf8c7e832015-04-04 12:28:20 +020047 : 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));
Piotr Krysik09826732016-07-15 13:14:24 +020054 message_port_register_out(pmt::mp("ctrl"));
ptrkrysikf8c7e832015-04-04 12:28:20 +020055
56 set_fc(fc);
Piotr Krysik09826732016-07-15 13:14:24 +020057 set_samp_rate(samp_rate);
Piotr Krysik83afe732016-07-17 22:48:35 +020058 set_osr(osr);
ptrkrysikf8c7e832015-04-04 12:28:20 +020059 d_alfa = 0.3;
60 d_ppm_estimate = -1e6;
61 d_last_ppm_estimate = -1e6;
62 d_first_measurement = true;
63 d_counter = 0;
64 d_last_state = "";
ptrkrysik32c21162015-04-04 14:01:52 +020065 d_current_time = 0;
66 d_last_fcch_time = 0;
67 d_first_time = true;
ptrkrysikf8c7e832015-04-04 12:28:20 +020068}
69
70/*
71 * Our virtual destructor.
72 */
73clock_offset_control_impl::~clock_offset_control_impl()
74{
75}
76
Piotr Krysik83afe732016-07-17 22:48:35 +020077void clock_offset_control_impl::set_osr(unsigned int osr)
78{
79 d_osr = osr;
80}
81
ptrkrysikf8c7e832015-04-04 12:28:20 +020082void clock_offset_control_impl::set_fc(float fc)
83{
84 d_fc = fc;
85}
86
Piotr Krysik09826732016-07-15 13:14:24 +020087void clock_offset_control_impl::set_samp_rate(float samp_rate)
88{
89 d_samp_rate = samp_rate;
90}
91
ptrkrysikf8c7e832015-04-04 12:28:20 +020092void clock_offset_control_impl::process_measurement(pmt::pmt_t msg)
93{
94 if(pmt::is_tuple(msg))
95 {
96 std::string key = pmt::symbol_to_string(pmt::tuple_ref(msg,0));
ptrkrysik32c21162015-04-04 14:01:52 +020097 if(key == "current_time")
98 {
99 d_current_time = pmt::to_double(pmt::tuple_ref(msg,1));
100 if(d_first_time==true)
101 {
102 d_last_fcch_time = d_current_time;
103 d_first_time = false;
104 }
105 else
106 if((d_current_time - d_last_fcch_time) > 0.5 && d_last_state == "fcch_search")
107 {
108 timed_reset();
109 }
110 }
111 else
ptrkrysikf8c7e832015-04-04 12:28:20 +0200112 if(key == "freq_offset")
113 {
114 float freq_offset = pmt::to_double(pmt::tuple_ref(msg,1));
115 float ppm = -freq_offset/d_fc*1.0e6;
116 std::string state = pmt::symbol_to_string(pmt::tuple_ref(msg,2));
117 d_last_state = state;
Piotr Krysik09826732016-07-15 13:14:24 +0200118 if(std::abs(ppm) < 100.0) //safeguard against flawed measurements
ptrkrysikf8c7e832015-04-04 12:28:20 +0200119 {
ptrkrysikf8c7e832015-04-04 12:28:20 +0200120
Piotr Krysik09826732016-07-15 13:14:24 +0200121 if(state == "fcch_search")
ptrkrysikf8c7e832015-04-04 12:28:20 +0200122 {
Piotr Krysik83afe732016-07-17 22:48:35 +0200123 send_ctrl_messages(freq_offset);
Piotr Krysik09826732016-07-15 13:14:24 +0200124 d_last_fcch_time = d_current_time;
125 }
126 else
127 if (state == "synchronized")
ptrkrysikf8c7e832015-04-04 12:28:20 +0200128 {
Piotr Krysik09826732016-07-15 13:14:24 +0200129 d_last_fcch_time = d_current_time;
130 if(d_first_measurement)
ptrkrysikf8c7e832015-04-04 12:28:20 +0200131 {
Piotr Krysik09826732016-07-15 13:14:24 +0200132 d_ppm_estimate = ppm;
133 d_first_measurement = false;
134 }
135 else
136 {
137 d_ppm_estimate = (1-d_alfa)*d_ppm_estimate+d_alfa*ppm;
138 }
139
140 if(d_counter == 5)
141 {
142 d_counter = 0;
143 if(std::abs(d_last_ppm_estimate-d_ppm_estimate) > 0.1)
144 {
145// pmt::pmt_t msg_ppm = pmt::from_double(ppm);
146// message_port_pub(pmt::intern("ppm"), msg_ppm);
Piotr Krysik83afe732016-07-17 22:48:35 +0200147 send_ctrl_messages(freq_offset);
Piotr Krysik09826732016-07-15 13:14:24 +0200148 d_last_ppm_estimate = d_ppm_estimate;
149 }
150 }
151 else
152 {
153 d_counter=d_counter+1;
ptrkrysikf8c7e832015-04-04 12:28:20 +0200154 }
155 }
156 else
Piotr Krysik09826732016-07-15 13:14:24 +0200157 if(state == "sync_loss")
ptrkrysikf8c7e832015-04-04 12:28:20 +0200158 {
Piotr Krysik09826732016-07-15 13:14:24 +0200159 reset();
160// pmt::pmt_t msg_ppm = pmt::from_double(0.0);
161// message_port_pub(pmt::intern("ppm"), msg_ppm);
162 send_ctrl_messages(0);
ptrkrysikf8c7e832015-04-04 12:28:20 +0200163 }
Piotr Krysik09826732016-07-15 13:14:24 +0200164 }
ptrkrysikf8c7e832015-04-04 12:28:20 +0200165 }
166 }
167}
168
Piotr Krysik83afe732016-07-17 22:48:35 +0200169void clock_offset_control_impl::send_ctrl_messages(float freq_offset)
Piotr Krysik09826732016-07-15 13:14:24 +0200170{
Piotr Krysik83afe732016-07-17 22:48:35 +0200171 double samp_rate_ratio = d_samp_rate / (d_osr * GSM_SYMBOL_RATE);
Piotr Krysik09826732016-07-15 13:14:24 +0200172
Piotr Krysik83afe732016-07-17 22:48:35 +0200173 pmt::pmt_t messages = pmt::make_dict();
174 messages = dict_add(messages, pmt::string_to_symbol("set_phase_inc"), pmt::from_double(-2*M_PI*freq_offset/(d_osr * GSM_SYMBOL_RATE)));
175 messages = dict_add(messages, pmt::string_to_symbol("set_resamp_ratio"), pmt::from_double((1-(freq_offset/d_fc))*samp_rate_ratio));
176 messages = dict_add(messages, pmt::string_to_symbol("setting_freq_offset"), pmt::from_double(-freq_offset));
Piotr Krysik5eb5db22017-07-20 09:06:08 +0200177 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 +0200178 message_port_pub(pmt::intern("ctrl"), messages);
Piotr Krysik09826732016-07-15 13:14:24 +0200179}
180
ptrkrysikf8c7e832015-04-04 12:28:20 +0200181void clock_offset_control_impl::timed_reset()
182{
183 reset();
Piotr Krysik09826732016-07-15 13:14:24 +0200184 send_ctrl_messages(0);
ptrkrysikf8c7e832015-04-04 12:28:20 +0200185}
186
ptrkrysikf8c7e832015-04-04 12:28:20 +0200187void clock_offset_control_impl::reset()
188{
189 d_ppm_estimate = -1e6;
190 d_counter = 0;
191 d_first_measurement = true;
192}
193
194} /* namespace gsm */
195} /* namespace gr */
196