blob: e97d54244ba3e007860c31d51d6301f41eb62d13 [file] [log] [blame]
/* -*- c++ -*- */
/*
* @file
* @author Piotr Krysik <ptrkrysik@gmail.com>
* @section LICENSE
*
* Gr-gsm 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.
*
* Gr-gsm 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 gr-gsm; 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 <sch.h>
#include "clock_offset_control_impl.h"
namespace gr
{
namespace gsm
{
clock_offset_control::sptr
clock_offset_control::make(float fc)
{
return gnuradio::get_initial_sptr
(new clock_offset_control_impl(fc));
}
/*
* The private constructor
*/
clock_offset_control_impl::clock_offset_control_impl(float fc)
: gr::block("clock_offset_control",
gr::io_signature::make(0, 0, 0),
gr::io_signature::make(0, 0, 0)),
d_timer(d_io_service)
{
message_port_register_in(pmt::mp("measurements"));
set_msg_handler(pmt::mp("measurements"), boost::bind(&clock_offset_control_impl::process_measurement, this, _1));
message_port_register_out(pmt::mp("ppm"));
set_fc(fc);
d_alfa = 0.3;
d_ppm_estimate = -1e6;
d_last_ppm_estimate = -1e6;
d_first_measurement = true;
d_counter = 0;
d_last_state = "";
d_timer.async_wait(boost::bind(&clock_offset_control_impl::timed_reset, this));
}
/*
* Our virtual destructor.
*/
clock_offset_control_impl::~clock_offset_control_impl()
{
}
void clock_offset_control_impl::set_fc(float fc)
{
d_fc = fc;
}
void clock_offset_control_impl::process_measurement(pmt::pmt_t msg)
{
if(pmt::is_tuple(msg))
{
std::string key = pmt::symbol_to_string(pmt::tuple_ref(msg,0));
if(key == "freq_offset")
{
float freq_offset = pmt::to_double(pmt::tuple_ref(msg,1));
float ppm = -freq_offset/d_fc*1.0e6;
std::string state = pmt::symbol_to_string(pmt::tuple_ref(msg,2));
d_last_state = state;
if(abs(ppm) > 100) //safeguard against flawed measurements
{
ppm = 0; //!!! do poprawki ten warunek
reset();
}
if(state == "fcch_search")
{
pmt::pmt_t msg_ppm = pmt::from_double(ppm);
message_port_pub(pmt::intern("ppm"), msg_ppm);
d_timer.cancel();
d_timer.async_wait(boost::bind(&clock_offset_control_impl::timed_reset, this));
}
else
if (state == "synchronized")
{
d_timer.cancel();
if(d_first_measurement)
{
d_ppm_estimate = ppm;
d_first_measurement = false;
}
else
{
d_ppm_estimate = (1-d_alfa)*d_ppm_estimate+d_alfa*ppm;
}
if(d_counter == 5)
{
d_counter = 0;
if(abs(d_last_ppm_estimate-d_ppm_estimate) > 0.1)
{
pmt::pmt_t msg_ppm = pmt::from_double(ppm);
message_port_pub(pmt::intern("ppm"), msg_ppm);
d_last_ppm_estimate = d_ppm_estimate;
}
}
else
{
d_counter=d_counter+1;
}
}
else
if(state == "sync_loss")
{
reset();
pmt::pmt_t msg_ppm = pmt::from_double(0.0);
message_port_pub(pmt::intern("ppm"), msg_ppm);
}
}
}
}
void clock_offset_control_impl::timed_reset()
{
reset();
pmt::pmt_t msg_ppm = pmt::from_double(0.0);
message_port_pub(pmt::intern("ppm"), msg_ppm);
}
void clock_offset_control_impl::reset()
{
d_ppm_estimate = -1e6;
d_counter = 0;
d_first_measurement = true;
}
} /* namespace gsm */
} /* namespace gr */