1
0
mirror of https://github.com/gnss-sdr/gnss-sdr synced 2025-07-07 12:32:57 +00:00

Improving documentation and some code cleaning

git-svn-id: https://svn.code.sf.net/p/gnss-sdr/code/trunk@446 64b25241-fba3-4117-9849-534c7e92360d
This commit is contained in:
Carles Fernandez 2013-11-17 10:48:27 +00:00
parent 6eabb93de7
commit a7b1f71566
17 changed files with 1767 additions and 1600 deletions

View File

@ -52,16 +52,16 @@ FirFilter::FirFilter(ConfigurationInterface* configuration, std::string role,
item_size = sizeof(gr_complex); item_size = sizeof(gr_complex);
fir_filter_ccf_ = gr::filter::fir_filter_ccf::make(1, taps_); fir_filter_ccf_ = gr::filter::fir_filter_ccf::make(1, taps_);
DLOG(INFO) << "input_filter(" << fir_filter_ccf_->unique_id() << ")"; DLOG(INFO) << "input_filter(" << fir_filter_ccf_->unique_id() << ")";
}
else
{
LOG_AT_LEVEL(ERROR) << taps_item_type_ << " unknown input filter item type";
}
if (dump_) if (dump_)
{ {
DLOG(INFO) << "Dumping output into file " << dump_filename_; DLOG(INFO) << "Dumping output into file " << dump_filename_;
file_sink_ = gr::blocks::file_sink::make(item_size, dump_filename_.c_str()); file_sink_ = gr::blocks::file_sink::make(item_size, dump_filename_.c_str());
} }
}
else
{
LOG_AT_LEVEL(ERROR) << taps_item_type_ << " unknown input filter item type";
}
} }

View File

@ -55,7 +55,7 @@ FreqXlatingFirFilter::FreqXlatingFirFilter(ConfigurationInterface* configuration
&& (output_item_type_.compare("gr_complex") == 0)) && (output_item_type_.compare("gr_complex") == 0))
{ {
item_size = sizeof(gr_complex); //output item_size = sizeof(gr_complex); //output
input_size_=sizeof(gr_complex); //input input_size_ = sizeof(gr_complex); //input
freq_xlating_fir_filter_ccf_ = gr::filter::freq_xlating_fir_filter_ccf::make(decimation_factor, taps_, intermediate_freq_, sampling_freq_); freq_xlating_fir_filter_ccf_ = gr::filter::freq_xlating_fir_filter_ccf::make(decimation_factor, taps_, intermediate_freq_, sampling_freq_);
DLOG(INFO) << "input_filter(" << freq_xlating_fir_filter_ccf_->unique_id() << ")"; DLOG(INFO) << "input_filter(" << freq_xlating_fir_filter_ccf_->unique_id() << ")";
} }
@ -63,19 +63,20 @@ FreqXlatingFirFilter::FreqXlatingFirFilter(ConfigurationInterface* configuration
&& (output_item_type_.compare("gr_complex") == 0)) && (output_item_type_.compare("gr_complex") == 0))
{ {
item_size = sizeof(gr_complex); item_size = sizeof(gr_complex);
input_size_=sizeof(float); //input input_size_ = sizeof(float); //input
freq_xlating_fir_filter_fcf_ = gr::filter::freq_xlating_fir_filter_fcf::make(decimation_factor, taps_, intermediate_freq_, sampling_freq_); freq_xlating_fir_filter_fcf_ = gr::filter::freq_xlating_fir_filter_fcf::make(decimation_factor, taps_, intermediate_freq_, sampling_freq_);
DLOG(INFO) << "input_filter(" << freq_xlating_fir_filter_fcf_->unique_id() << ")"; DLOG(INFO) << "input_filter(" << freq_xlating_fir_filter_fcf_->unique_id() << ")";
} }
else else
{ {
LOG_AT_LEVEL(ERROR) << taps_item_type_ << " unknown input filter item type"; LOG_AT_LEVEL(ERROR) << taps_item_type_ << " unknown input filter item type";
item_size = sizeof(gr_complex); //avoids unitialization
} }
if (dump_) if (dump_)
{ {
DLOG(INFO) << "Dumping output into file " << dump_filename_; DLOG(INFO) << "Dumping output into file " << dump_filename_;
std::cout<<"Dumping output into file " << dump_filename_<<std::endl; std::cout << "Dumping output into file " << dump_filename_ << std::endl;
file_sink_ = gr::blocks::file_sink::make(item_size, dump_filename_.c_str()); file_sink_ = gr::blocks::file_sink::make(item_size, dump_filename_.c_str());
} }
} }
@ -91,10 +92,12 @@ void FreqXlatingFirFilter::connect(gr::top_block_sptr top_block)
{ {
if (dump_) if (dump_)
{ {
if (input_size_==sizeof(float)) if (input_size_ == sizeof(float))
{ {
top_block->connect(freq_xlating_fir_filter_fcf_, 0, file_sink_, 0); top_block->connect(freq_xlating_fir_filter_fcf_, 0, file_sink_, 0);
}else{ }
else
{
top_block->connect(freq_xlating_fir_filter_ccf_, 0, file_sink_, 0); top_block->connect(freq_xlating_fir_filter_ccf_, 0, file_sink_, 0);
} }
} }
@ -110,10 +113,12 @@ void FreqXlatingFirFilter::disconnect(gr::top_block_sptr top_block)
{ {
if (dump_) if (dump_)
{ {
if (input_size_==sizeof(float)) if (input_size_ == sizeof(float))
{ {
top_block->disconnect(freq_xlating_fir_filter_fcf_, 0, file_sink_, 0); top_block->disconnect(freq_xlating_fir_filter_fcf_, 0, file_sink_, 0);
}else{ }
else
{
top_block->disconnect(freq_xlating_fir_filter_ccf_, 0, file_sink_, 0); top_block->disconnect(freq_xlating_fir_filter_ccf_, 0, file_sink_, 0);
} }
} }
@ -123,10 +128,12 @@ void FreqXlatingFirFilter::disconnect(gr::top_block_sptr top_block)
gr::basic_block_sptr FreqXlatingFirFilter::get_left_block() gr::basic_block_sptr FreqXlatingFirFilter::get_left_block()
{ {
if (input_size_==sizeof(float)) if (input_size_ == sizeof(float))
{ {
return freq_xlating_fir_filter_fcf_; return freq_xlating_fir_filter_fcf_;
}else{ }
else
{
return freq_xlating_fir_filter_ccf_; return freq_xlating_fir_filter_ccf_;
} }
@ -135,10 +142,12 @@ gr::basic_block_sptr FreqXlatingFirFilter::get_left_block()
gr::basic_block_sptr FreqXlatingFirFilter::get_right_block() gr::basic_block_sptr FreqXlatingFirFilter::get_right_block()
{ {
if (input_size_==sizeof(float)) if (input_size_ == sizeof(float))
{ {
return freq_xlating_fir_filter_fcf_; return freq_xlating_fir_filter_fcf_;
}else{ }
else
{
return freq_xlating_fir_filter_ccf_; return freq_xlating_fir_filter_ccf_;
} }
} }

View File

@ -1,13 +1,13 @@
/*! /*!
* \file galileo_l1_ca_telemetry_decoder.cc * \file galileo_e1b_telemetry_decoder.cc
* \brief Implementation of an adapter of a Galileo INAV data decoder block * \brief Implementation of an adapter of a Galileo INAV data decoder block
* to a TelemetryDecoderInterface * to a TelemetryDecoderInterface
* \author Javier Arribas 2013. jarribas(at)cttc.es * \author Javier Arribas 2013. jarribas(at)cttc.es,
* \author Mara Branzanti 2013. mara.branzanti(at)gmail.com * Mara Branzanti 2013. mara.branzanti(at)gmail.com
* *
* ------------------------------------------------------------------------- * -------------------------------------------------------------------------
* *
* Copyright (C) 2010-2012 (see AUTHORS file for a list of contributors) * Copyright (C) 2010-2013 (see AUTHORS file for a list of contributors)
* *
* GNSS-SDR is a software defined Global Navigation * GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver * Satellite Systems receiver

View File

@ -1,9 +1,9 @@
/*! /*!
* \file galileo_l1_ca_telemetry_decoder.h * \file galileo_e1b_telemetry_decoder.h
* \brief Interface of an adapter of a GALILEO E1B NAV data decoder block * \brief Interface of an adapter of a GALILEO E1B NAV data decoder block
* to a TelemetryDecoderInterface * to a TelemetryDecoderInterface
* \author Javier Arribas 2013. jarribas(at)cttc.es * \author Javier Arribas 2013. jarribas(at)cttc.es * \author Javier Arribas 2013 jarribas(at)cttc.es,
* \author Mara Branzanti 2013. mara.branzanti(at)gmail.com * Mara Branzanti 2013. mara.branzanti(at)gmail.com
* *
* ------------------------------------------------------------------------- * -------------------------------------------------------------------------
* *
@ -59,6 +59,9 @@ public:
return role_; return role_;
} }
/*!
* \brief Returns "Galileo_E1B_Telemetry_Decoder"
*/
std::string implementation() std::string implementation()
{ {
return "Galileo_E1B_Telemetry_Decoder"; return "Galileo_E1B_Telemetry_Decoder";

View File

@ -41,9 +41,7 @@
#include "control_message_factory.h" #include "control_message_factory.h"
#include "galileo_navigation_message.h" #include "galileo_navigation_message.h"
#include "gnss_synchro.h" #include "gnss_synchro.h"
#include "convolutional.h" #include "convolutional.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -70,20 +68,19 @@ void galileo_e1b_telemetry_decoder_cc::forecast (int noutput_items, gr_vector_in
void galileo_e1b_telemetry_decoder_cc::viterbi_decoder(double *page_part_symbols, int *page_part_bits) void galileo_e1b_telemetry_decoder_cc::viterbi_decoder(double *page_part_symbols, int *page_part_bits)
{ {
int CodeLength = 240;
int CodeLength=240;
int DataLength; int DataLength;
int nn, KK, mm, max_states; int nn, KK, mm, max_states;
int g_encoder[2]; int g_encoder[2];
nn = 2; //Coding rate 1/n nn = 2; //Coding rate 1/n
KK = 7; //Constraint Length KK = 7; //Constraint Length
g_encoder[0]=121; // Polynomial G1 g_encoder[0] = 121; // Polynomial G1
g_encoder[1]=91; // Polinomial G2 g_encoder[1] = 91; // Polinomial G2
mm = KK - 1; mm = KK - 1;
max_states = 1 << mm; /* 2^mm */ max_states = 1 << mm; /* 2^mm */
DataLength = (CodeLength/nn)-mm; DataLength = (CodeLength/nn) - mm;
/* create appropriate transition matrices */ /* create appropriate transition matrices */
int *out0, *out1, *state0, *state1; int *out0, *out1, *state0, *state1;
@ -104,17 +101,16 @@ void galileo_e1b_telemetry_decoder_cc::viterbi_decoder(double *page_part_symbols
free( out1 ); free( out1 );
free( state0 ); free( state0 );
free( state1 ); free( state1 );
} }
void galileo_e1b_telemetry_decoder_cc::deinterleaver(int rows, int cols, double *in, double *out) void galileo_e1b_telemetry_decoder_cc::deinterleaver(int rows, int cols, double *in, double *out)
{ {
for (int r=0;r<rows;r++) for (int r = 0; r < rows; r++)
{ {
for(int c=0;c<cols;c++) for(int c = 0; c < cols; c++)
{ {
out[c*rows+r]=in[r*cols+c]; out[c*rows + r] = in[r*cols + c];
} }
} }
} }
@ -141,18 +137,18 @@ galileo_e1b_telemetry_decoder_cc::galileo_e1b_telemetry_decoder_cc(
d_fs_in = fs_in; d_fs_in = fs_in;
// set the preamble // set the preamble
unsigned short int preambles_bits[GALILEO_INAV_PREAMBLE_LENGTH_BITS]=GALILEO_INAV_PREAMBLE; unsigned short int preambles_bits[GALILEO_INAV_PREAMBLE_LENGTH_BITS] = GALILEO_INAV_PREAMBLE;
d_symbols_per_preamble=GALILEO_INAV_PREAMBLE_LENGTH_BITS * d_samples_per_symbol; d_symbols_per_preamble = GALILEO_INAV_PREAMBLE_LENGTH_BITS * d_samples_per_symbol;
memcpy((unsigned short int*)this->d_preambles_bits, (unsigned short int*)preambles_bits, GALILEO_INAV_PREAMBLE_LENGTH_BITS*sizeof(unsigned short int)); memcpy((unsigned short int*)this->d_preambles_bits, (unsigned short int*)preambles_bits, GALILEO_INAV_PREAMBLE_LENGTH_BITS*sizeof(unsigned short int));
// preamble bits to sampled symbols // preamble bits to sampled symbols
d_preambles_symbols = (signed int*)malloc(sizeof(signed int) * d_symbols_per_preamble); d_preambles_symbols = (signed int*)malloc(sizeof(signed int) * d_symbols_per_preamble);
int n = 0; int n = 0;
for (int i=0; i<GALILEO_INAV_PREAMBLE_LENGTH_BITS; i++) for (int i = 0; i < GALILEO_INAV_PREAMBLE_LENGTH_BITS; i++)
{ {
for (unsigned int j=0; j<d_samples_per_symbol; j++) for (unsigned int j = 0; j < d_samples_per_symbol; j++)
{ {
if (d_preambles_bits[i] == 1) if (d_preambles_bits[i] == 1)
{ {
@ -173,34 +169,38 @@ galileo_e1b_telemetry_decoder_cc::galileo_e1b_telemetry_decoder_cc(
d_flag_frame_sync = false; d_flag_frame_sync = false;
d_flag_parity = false; d_flag_parity = false;
d_TOW_at_Preamble= 0; d_TOW_at_Preamble = 0;
d_TOW_at_current_symbol = 0; d_TOW_at_current_symbol = 0;
d_CRC_error_counter=0; d_CRC_error_counter = 0;
} }
galileo_e1b_telemetry_decoder_cc::~galileo_e1b_telemetry_decoder_cc() galileo_e1b_telemetry_decoder_cc::~galileo_e1b_telemetry_decoder_cc()
{ {
delete d_preambles_symbols; delete d_preambles_symbols;
d_dump_file.close(); d_dump_file.close();
} }
void galileo_e1b_telemetry_decoder_cc::decode_word(double *page_part_symbols,int frame_length) void galileo_e1b_telemetry_decoder_cc::decode_word(double *page_part_symbols,int frame_length)
{ {
double page_part_symbols_deint[frame_length]; double page_part_symbols_deint[frame_length];
// 1. De-interleave // 1. De-interleave
deinterleaver(GALILEO_INAV_INTERLEAVER_ROWS,GALILEO_INAV_INTERLEAVER_COLS,page_part_symbols, page_part_symbols_deint); deinterleaver(GALILEO_INAV_INTERLEAVER_ROWS, GALILEO_INAV_INTERLEAVER_COLS, page_part_symbols, page_part_symbols_deint);
// 2. Viterbi decoder // 2. Viterbi decoder
// 2.1 Take into account the NOT gate in G2 polynomial (Galileo ICD Figure 13, FEC encoder) // 2.1 Take into account the NOT gate in G2 polynomial (Galileo ICD Figure 13, FEC encoder)
// 2.2 Take into account the possible inversion of the polarity due to PLL lock at 180º // 2.2 Take into account the possible inversion of the polarity due to PLL lock at 180¼
for (int i=0;i<frame_length;i++) for (int i = 0; i < frame_length; i++)
{ {
if ((i+1)%2==0) if ((i + 1) % 2 == 0)
{ {
page_part_symbols_deint[i]=-page_part_symbols_deint[i]; page_part_symbols_deint[i] = -page_part_symbols_deint[i];
} }
} }
@ -211,59 +211,67 @@ void galileo_e1b_telemetry_decoder_cc::decode_word(double *page_part_symbols,int
std::string page_String; std::string page_String;
for(int i=0; i < (frame_length/2); i++) for(int i = 0; i < (frame_length/2); i++)
{ {
if (page_part_bits[i]>0) if (page_part_bits[i] > 0)
{ {
page_String.push_back('1'); page_String.push_back('1');
}else{ }
else
{
page_String.push_back('0'); page_String.push_back('0');
} }
} }
//std::cout<<"ch["<<d_channel<<"] frame part bits: "<<page_String<<std::endl; //std::cout<<"ch["<<d_channel<<"] frame part bits: "<<page_String<<std::endl;
if (page_part_bits[0]==1) if (page_part_bits[0] == 1)
{ {
// DECODE COMPLETE WORD (even + odd) and TEST CRC // DECODE COMPLETE WORD (even + odd) and TEST CRC
d_nav.split_page(page_String, flag_even_word_arrived); d_nav.split_page(page_String, flag_even_word_arrived);
if(d_nav.flag_CRC_test==true) if(d_nav.flag_CRC_test == true)
{ {
std::cout<<"Galileo CRC correct on channel "<<d_channel<<std::endl; std::cout << "Galileo CRC correct on channel " << d_channel << std::endl;
}else{
std::cout<<"Galileo CRC error on channel "<<d_channel<<std::endl;
} }
flag_even_word_arrived=0; else
{
std::cout << "Galileo CRC error on channel " << d_channel << std::endl;
}
flag_even_word_arrived = 0;
} }
else else
{ {
// STORE HALF WORD (even page) // STORE HALF WORD (even page)
d_nav.split_page(page_String.c_str(), flag_even_word_arrived); d_nav.split_page(page_String.c_str(), flag_even_word_arrived);
flag_even_word_arrived=1; flag_even_word_arrived = 1;
} }
// 4. Push the new navigation data to the queues // 4. Push the new navigation data to the queues
if (d_nav.have_new_ephemeris()==true) if (d_nav.have_new_ephemeris() == true)
{ {
// get ephemeris object for this SV // get ephemeris object for this SV
Galileo_Ephemeris ephemeris=d_nav.get_ephemeris();//notice that the read operation will clear the valid flag Galileo_Ephemeris ephemeris = d_nav.get_ephemeris();//notice that the read operation will clear the valid flag
//std::cout<<"New Galileo Ephemeris received for SV "<<d_satellite.get_PRN()<<std::endl; //std::cout<<"New Galileo Ephemeris received for SV "<<d_satellite.get_PRN()<<std::endl;
d_ephemeris_queue->push(ephemeris); d_ephemeris_queue->push(ephemeris);
} }
if (d_nav.have_new_iono_and_GST()==true) if (d_nav.have_new_iono_and_GST() == true)
{ {
Galileo_Iono iono=d_nav.get_iono(); //notice that the read operation will clear the valid flag Galileo_Iono iono = d_nav.get_iono(); //notice that the read operation will clear the valid flag
//std::cout<<"New Galileo IONO model (and UTC) received for SV "<<d_satellite.get_PRN()<<std::endl; //std::cout<<"New Galileo IONO model (and UTC) received for SV "<<d_satellite.get_PRN()<<std::endl;
d_iono_queue->push(iono); d_iono_queue->push(iono);
} }
if (d_nav.have_new_utc_model()==true) if (d_nav.have_new_utc_model() == true)
{ {
Galileo_Utc_Model utc_model=d_nav.get_utc_model(); //notice that the read operation will clear the valid flag Galileo_Utc_Model utc_model = d_nav.get_utc_model(); //notice that the read operation will clear the valid flag
//std::cout<<"New Galileo UTC model received for SV "<<d_satellite.get_PRN()<<std::endl; //std::cout<<"New Galileo UTC model received for SV "<<d_satellite.get_PRN()<<std::endl;
d_utc_model_queue->push(utc_model); d_utc_model_queue->push(utc_model);
} }
} }
int galileo_e1b_telemetry_decoder_cc::general_work (int noutput_items, gr_vector_int &ninput_items, int galileo_e1b_telemetry_decoder_cc::general_work (int noutput_items, gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) gr_vector_const_void_star &input_items, gr_vector_void_star &output_items)
{ {
@ -278,7 +286,7 @@ int galileo_e1b_telemetry_decoder_cc::general_work (int noutput_items, gr_vector
// TODO Optimize me! // TODO Optimize me!
//******* preamble correlation ******** //******* preamble correlation ********
for (int i=0; i<d_symbols_per_preamble; i++) for (int i = 0; i < d_symbols_per_preamble; i++)
{ {
if (in[0][i].Prompt_I < 0) // symbols clipping if (in[0][i].Prompt_I < 0) // symbols clipping
{ {
@ -300,7 +308,8 @@ int galileo_e1b_telemetry_decoder_cc::general_work (int noutput_items, gr_vector
std::cout << "Preamble detection for Galileo SAT " << this->d_satellite << std::endl; std::cout << "Preamble detection for Galileo SAT " << this->d_satellite << std::endl;
d_stat = 1; // enter into frame pre-detection status d_stat = 1; // enter into frame pre-detection status
} }
}else if (d_stat == 1) // posible preamble lock }
else if (d_stat == 1) // posible preamble lock
{ {
if (abs(corr_value) >= d_symbols_per_preamble) if (abs(corr_value) >= d_symbols_per_preamble)
{ {
@ -309,34 +318,38 @@ int galileo_e1b_telemetry_decoder_cc::general_work (int noutput_items, gr_vector
if (abs(preamble_diff - GALILEO_INAV_PREAMBLE_PERIOD_SYMBOLS) == 0) if (abs(preamble_diff - GALILEO_INAV_PREAMBLE_PERIOD_SYMBOLS) == 0)
{ {
//try to decode frame //try to decode frame
std::cout<<"Starting page decoder for Galileo SAT " << this->d_satellite<<std::endl; std::cout << "Starting page decoder for Galileo SAT " << this->d_satellite << std::endl;
d_preamble_index=d_sample_counter;//record the preamble sample stamp d_preamble_index = d_sample_counter; //record the preamble sample stamp
d_stat=2; d_stat = 2;
} }
else{ else
if (preamble_diff>GALILEO_INAV_PREAMBLE_PERIOD_SYMBOLS)
{ {
d_stat=0; // start again if (preamble_diff > GALILEO_INAV_PREAMBLE_PERIOD_SYMBOLS)
}
}
}
}else if (d_stat==2)
{ {
if (d_sample_counter==d_preamble_index+GALILEO_INAV_PREAMBLE_PERIOD_SYMBOLS) d_stat = 0; // start again
}
}
}
}
else if (d_stat == 2)
{
if (d_sample_counter == d_preamble_index+GALILEO_INAV_PREAMBLE_PERIOD_SYMBOLS)
{ {
// NEW Galileo page part is received // NEW Galileo page part is received
// 0. fetch the symbols into an array // 0. fetch the symbols into an array
int frame_length=GALILEO_INAV_PAGE_PART_SYMBOLS-d_symbols_per_preamble; int frame_length = GALILEO_INAV_PAGE_PART_SYMBOLS - d_symbols_per_preamble;
double page_part_symbols[frame_length]; double page_part_symbols[frame_length];
for (int i=0;i<frame_length;i++) for (int i = 0; i < frame_length; i++)
{ {
if (corr_value>0) if (corr_value > 0)
{ {
page_part_symbols[i]=in[0][i+d_symbols_per_preamble].Prompt_I; // because last symbol of the preamble is just received now! page_part_symbols[i] = in[0][i + d_symbols_per_preamble].Prompt_I; // because last symbol of the preamble is just received now!
}else{ }
page_part_symbols[i]=-in[0][i+d_symbols_per_preamble].Prompt_I; // because last symbol of the preamble is just received now! else
{
page_part_symbols[i] = -in[0][i + d_symbols_per_preamble].Prompt_I; // because last symbol of the preamble is just received now!
} }
} }
//debug //debug
@ -354,26 +367,28 @@ int galileo_e1b_telemetry_decoder_cc::general_work (int noutput_items, gr_vector
// std::cout<<std::endl; // std::cout<<std::endl;
//end debug //end debug
//call the decoder //call the decoder
decode_word(page_part_symbols,frame_length); decode_word(page_part_symbols, frame_length);
if (d_nav.flag_CRC_test==true) if (d_nav.flag_CRC_test == true)
{ {
d_CRC_error_counter=0; d_CRC_error_counter = 0;
d_flag_preamble = true; //valid preamble indicator (initialized to false every work()) d_flag_preamble = true; //valid preamble indicator (initialized to false every work())
d_preamble_index = d_sample_counter; //record the preamble sample stamp (t_P) d_preamble_index = d_sample_counter; //record the preamble sample stamp (t_P)
d_preamble_time_seconds = in[0][0].Tracking_timestamp_secs;// - d_preamble_duration_seconds; //record the PRN start sample index associated to the preamble d_preamble_time_seconds = in[0][0].Tracking_timestamp_secs; // - d_preamble_duration_seconds; //record the PRN start sample index associated to the preamble
if (!d_flag_frame_sync) if (!d_flag_frame_sync)
{ {
d_flag_frame_sync = true; d_flag_frame_sync = true;
std::cout <<" Frame sync SAT " << this->d_satellite << " with preamble start at " << d_preamble_time_seconds << " [s]" << std::endl; std::cout <<" Frame sync SAT " << this->d_satellite << " with preamble start at " << d_preamble_time_seconds << " [s]" << std::endl;
} }
}else{ }
else
{
d_CRC_error_counter++; d_CRC_error_counter++;
d_preamble_index = d_sample_counter; //record the preamble sample stamp d_preamble_index = d_sample_counter; //record the preamble sample stamp
if (d_CRC_error_counter>CRC_ERROR_LIMIT) if (d_CRC_error_counter > CRC_ERROR_LIMIT)
{ {
std::cout << "Lost of frame sync SAT " << this->d_satellite << std::endl; std::cout << "Lost of frame sync SAT " << this->d_satellite << std::endl;
d_flag_frame_sync=false; d_flag_frame_sync = false;
d_stat=0; d_stat = 0;
} }
} }
} }
@ -384,7 +399,7 @@ int galileo_e1b_telemetry_decoder_cc::general_work (int noutput_items, gr_vector
//1. Copy the current tracking output //1. Copy the current tracking output
current_synchro_data = in[0][0]; current_synchro_data = in[0][0];
//2. Add the telemetry decoder information //2. Add the telemetry decoder information
if (this->d_flag_preamble==true and d_nav.flag_TOW_set==true) if (this->d_flag_preamble == true and d_nav.flag_TOW_set == true)
//update TOW at the preamble instant //update TOW at the preamble instant
//flag preamble is true after the all page (even and odd) is recevived. I/NAV page period is 2 SECONDS //flag preamble is true after the all page (even and odd) is recevived. I/NAV page period is 2 SECONDS
{ {
@ -425,10 +440,12 @@ int galileo_e1b_telemetry_decoder_cc::general_work (int noutput_items, gr_vector
} }
//if (d_flag_frame_sync == true and d_nav.flag_TOW_set==true and d_nav.flag_CRC_test == true) //if (d_flag_frame_sync == true and d_nav.flag_TOW_set==true and d_nav.flag_CRC_test == true)
if (d_flag_frame_sync == true and d_nav.flag_TOW_set==true) if (d_flag_frame_sync == true and d_nav.flag_TOW_set == true)
{ {
current_synchro_data.Flag_valid_word = true; current_synchro_data.Flag_valid_word = true;
}else{ }
else
{
current_synchro_data.Flag_valid_word = false; current_synchro_data.Flag_valid_word = false;
} }
@ -486,28 +503,37 @@ void galileo_e1b_telemetry_decoder_cc::set_channel(int channel)
d_dump_filename.append(".dat"); d_dump_filename.append(".dat");
d_dump_file.exceptions ( std::ifstream::failbit | std::ifstream::badbit ); d_dump_file.exceptions ( std::ifstream::failbit | std::ifstream::badbit );
d_dump_file.open(d_dump_filename.c_str(), std::ios::out | std::ios::binary); d_dump_file.open(d_dump_filename.c_str(), std::ios::out | std::ios::binary);
std::cout << "Telemetry decoder dump enabled on channel " << d_channel << " Log file: " << d_dump_filename.c_str() << std::endl; std::cout << "Telemetry decoder dump enabled on channel " << d_channel << " Log file: "
<< d_dump_filename.c_str() << std::endl;
} }
catch (const std::ifstream::failure& e) catch (const std::ifstream::failure& e)
{ {
std::cout << "channel " << d_channel << " Exception opening trk dump file " << e.what() << std::endl; std::cout << "channel " << d_channel
<< " Exception opening trk dump file " << e.what() << std::endl;
} }
} }
} }
} }
void galileo_e1b_telemetry_decoder_cc::set_ephemeris_queue(concurrent_queue<Galileo_Ephemeris> *ephemeris_queue) void galileo_e1b_telemetry_decoder_cc::set_ephemeris_queue(concurrent_queue<Galileo_Ephemeris> *ephemeris_queue)
{ {
d_ephemeris_queue = ephemeris_queue; d_ephemeris_queue = ephemeris_queue;
} }
void galileo_e1b_telemetry_decoder_cc::set_iono_queue(concurrent_queue<Galileo_Iono> *iono_queue) void galileo_e1b_telemetry_decoder_cc::set_iono_queue(concurrent_queue<Galileo_Iono> *iono_queue)
{ {
d_iono_queue = iono_queue; d_iono_queue = iono_queue;
} }
void galileo_e1b_telemetry_decoder_cc::set_almanac_queue(concurrent_queue<Galileo_Almanac> *almanac_queue) void galileo_e1b_telemetry_decoder_cc::set_almanac_queue(concurrent_queue<Galileo_Almanac> *almanac_queue)
{ {
d_almanac_queue = almanac_queue; d_almanac_queue = almanac_queue;
} }
void galileo_e1b_telemetry_decoder_cc::set_utc_model_queue(concurrent_queue<Galileo_Utc_Model> *utc_model_queue) void galileo_e1b_telemetry_decoder_cc::set_utc_model_queue(concurrent_queue<Galileo_Utc_Model> *utc_model_queue)
{ {
d_utc_model_queue = utc_model_queue; d_utc_model_queue = utc_model_queue;

View File

@ -1,8 +1,9 @@
/*! /*!
* \file galileo_e1b_telemetry_decoder_cc.h * \file galileo_e1b_telemetry_decoder_cc.h
* \brief Interface of a Galileo NAV message demodulator block * \brief Interface of a Galileo NAV message demodulator block
* \author Javier Arribas 2013. jarribas(at)cttc.es * \author Javier Arribas 2013 jarribas(at)cttc.es,
* \author Mara Branzanti 2013. mara.branzanti(at)gmail.com * Mara Branzanti 2013 mara.branzanti(at)gmail.com
*
* ------------------------------------------------------------------------- * -------------------------------------------------------------------------
* *
* Copyright (C) 2010-2011 (see AUTHORS file for a list of contributors) * Copyright (C) 2010-2011 (see AUTHORS file for a list of contributors)
@ -28,8 +29,8 @@
* ------------------------------------------------------------------------- * -------------------------------------------------------------------------
*/ */
#ifndef GNSS_SDR_galileo_e1b_TELEMETRY_DECODER_CC_H #ifndef GNSS_SDR_GALILEO_E1B_TELEMETRY_DECODER_CC_H
#define GNSS_SDR_galileo_e1b_TELEMETRY_DECODER_CC_H #define GNSS_SDR_GALILEO_E1B_TELEMETRY_DECODER_CC_H
#include "Galileo_E1.h" #include "Galileo_E1.h"
@ -38,7 +39,6 @@
#include <bitset> #include <bitset>
#include <gnuradio/block.h> #include <gnuradio/block.h>
#include <gnuradio/msg_queue.h> #include <gnuradio/msg_queue.h>
#include "gnuradio/trellis/interleaver.h" #include "gnuradio/trellis/interleaver.h"
#include "gnuradio/trellis/permutation.h" #include "gnuradio/trellis/permutation.h"
#include "gnuradio/fec/viterbi.h" #include "gnuradio/fec/viterbi.h"
@ -76,16 +76,20 @@ public:
void set_satellite(Gnss_Satellite satellite); //!< Set satellite PRN void set_satellite(Gnss_Satellite satellite); //!< Set satellite PRN
void set_channel(int channel); //!< Set receiver's channel void set_channel(int channel); //!< Set receiver's channel
int flag_even_word_arrived; int flag_even_word_arrived;
void set_ephemeris_queue(concurrent_queue<Galileo_Ephemeris> *ephemeris_queue); //!< Set the satellite data queue
void set_iono_queue(concurrent_queue<Galileo_Iono> *iono_queue); //!< Set the iono data queue
void set_almanac_queue(concurrent_queue<Galileo_Almanac> *almanac_queue); //!< Set the almanac data queue
void set_utc_model_queue(concurrent_queue<Galileo_Utc_Model> *utc_model_queue); //!< Set the UTC model queue
/*! /*!
* \brief Set the satellite data queue * \brief This is where all signal processing takes place
*/ */
void set_ephemeris_queue(concurrent_queue<Galileo_Ephemeris> *ephemeris_queue);
void set_iono_queue(concurrent_queue<Galileo_Iono> *iono_queue);
void set_almanac_queue(concurrent_queue<Galileo_Almanac> *almanac_queue);
void set_utc_model_queue(concurrent_queue<Galileo_Utc_Model> *utc_model_queue);
int general_work (int noutput_items, gr_vector_int &ninput_items, int general_work (int noutput_items, gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); gr_vector_const_void_star &input_items, gr_vector_void_star &output_items);
/*!
* \brief Function which tells the scheduler how many input items
* are required to produce noutput_items output items.
*/
void forecast (int noutput_items, gr_vector_int &ninput_items_required); void forecast (int noutput_items, gr_vector_int &ninput_items_required);
private: private:
@ -121,7 +125,6 @@ private:
// navigation message vars // navigation message vars
Galileo_Navigation_Message d_nav; Galileo_Navigation_Message d_nav;
// Galileo ephemeris queue // Galileo ephemeris queue
concurrent_queue<Galileo_Ephemeris> *d_ephemeris_queue; concurrent_queue<Galileo_Ephemeris> *d_ephemeris_queue;
// ionospheric parameters queue // ionospheric parameters queue

View File

@ -6,7 +6,7 @@
* *
* ------------------------------------------------------------------------- * -------------------------------------------------------------------------
* *
* Copyright (C) 2010-2012 (see AUTHORS file for a list of contributors) * Copyright (C) 2010-2013 (see AUTHORS file for a list of contributors)
* *
* GNSS-SDR is a software defined Global Navigation * GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver * Satellite Systems receiver
@ -103,9 +103,9 @@ gps_l1_ca_telemetry_decoder_cc::gps_l1_ca_telemetry_decoder_cc(
// preamble bits to sampled symbols // preamble bits to sampled symbols
d_preambles_symbols = (signed int*)malloc(sizeof(signed int) * GPS_CA_PREAMBLE_LENGTH_BITS * d_samples_per_bit); d_preambles_symbols = (signed int*)malloc(sizeof(signed int) * GPS_CA_PREAMBLE_LENGTH_BITS * d_samples_per_bit);
int n = 0; int n = 0;
for (int i=0; i<GPS_CA_PREAMBLE_LENGTH_BITS; i++) for (int i = 0; i < GPS_CA_PREAMBLE_LENGTH_BITS; i++)
{ {
for (unsigned int j=0; j<d_samples_per_bit; j++) for (unsigned int j = 0; j < d_samples_per_bit; j++)
{ {
if (d_preambles_bits[i] == 1) if (d_preambles_bits[i] == 1)
{ {
@ -164,7 +164,7 @@ bool gps_l1_ca_telemetry_decoder_cc::gps_word_parityCheck(unsigned int gpsword)
// Now XOR the 5 6-bit fields together to produce the 6-bit final result. // Now XOR the 5 6-bit fields together to produce the 6-bit final result.
parity = t ^ _lrotl(t,6) ^ _lrotl(t,12) ^ _lrotl(t,18) ^ _lrotl(t,24); parity = t ^ _lrotl(t,6) ^ _lrotl(t,12) ^ _lrotl(t,18) ^ _lrotl(t,24);
parity = parity & 0x3F; parity = parity & 0x3F;
if (parity == (gpsword&0x3F)) return(true); if (parity == (gpsword & 0x3F)) return(true);
else return(false); else return(false);
} }
@ -185,7 +185,7 @@ int gps_l1_ca_telemetry_decoder_cc::general_work (int noutput_items, gr_vector_i
// TODO Optimize me! // TODO Optimize me!
//******* preamble correlation ******** //******* preamble correlation ********
for (unsigned int i=0; i<d_samples_per_bit*8; i++) for (unsigned int i = 0; i < d_samples_per_bit*8; i++)
{ {
if (in[0][i].Prompt_I < 0) // symbols clipping if (in[0][i].Prompt_I < 0) // symbols clipping
{ {
@ -297,7 +297,7 @@ int gps_l1_ca_telemetry_decoder_cc::general_work (int noutput_items, gr_vector_i
} }
else else
{ {
d_GPS_frame_4bytes<<=1; //shift 1 bit left the telemetry word d_GPS_frame_4bytes <<= 1; //shift 1 bit left the telemetry word
} }
} }
// output the frame // output the frame
@ -306,12 +306,12 @@ int gps_l1_ca_telemetry_decoder_cc::general_work (int noutput_items, gr_vector_i
//1. Copy the current tracking output //1. Copy the current tracking output
current_synchro_data = in[0][0]; current_synchro_data = in[0][0];
//2. Add the telemetry decoder information //2. Add the telemetry decoder information
if (this->d_flag_preamble==true and d_GPS_FSM.d_nav.d_TOW>0) //update TOW at the preamble instant (todo: check for valid d_TOW) if (this->d_flag_preamble == true and d_GPS_FSM.d_nav.d_TOW > 0) //update TOW at the preamble instant (todo: check for valid d_TOW)
{ {
d_TOW_at_Preamble = d_GPS_FSM.d_nav.d_TOW + GPS_SUBFRAME_SECONDS; //we decoded the current TOW when the last word of the subframe arrive, so, we have a lag of ONE SUBFRAME d_TOW_at_Preamble = d_GPS_FSM.d_nav.d_TOW + GPS_SUBFRAME_SECONDS; //we decoded the current TOW when the last word of the subframe arrive, so, we have a lag of ONE SUBFRAME
d_TOW_at_current_symbol = d_TOW_at_Preamble + GPS_CA_PREAMBLE_LENGTH_BITS/GPS_CA_TELEMETRY_RATE_BITS_SECOND; d_TOW_at_current_symbol = d_TOW_at_Preamble + GPS_CA_PREAMBLE_LENGTH_BITS/GPS_CA_TELEMETRY_RATE_BITS_SECOND;
Prn_timestamp_at_preamble_ms = in[0][0].Tracking_timestamp_secs * 1000.0; Prn_timestamp_at_preamble_ms = in[0][0].Tracking_timestamp_secs * 1000.0;
if (flag_TOW_set==false) if (flag_TOW_set == false)
{ {
flag_TOW_set = true; flag_TOW_set = true;
} }
@ -321,7 +321,6 @@ int gps_l1_ca_telemetry_decoder_cc::general_work (int noutput_items, gr_vector_i
d_TOW_at_current_symbol = d_TOW_at_current_symbol + GPS_L1_CA_CODE_PERIOD; d_TOW_at_current_symbol = d_TOW_at_current_symbol + GPS_L1_CA_CODE_PERIOD;
} }
current_synchro_data.d_TOW = d_TOW_at_Preamble; current_synchro_data.d_TOW = d_TOW_at_Preamble;
current_synchro_data.d_TOW_at_current_symbol = d_TOW_at_current_symbol; current_synchro_data.d_TOW_at_current_symbol = d_TOW_at_current_symbol;
current_synchro_data.Flag_valid_word = (d_flag_frame_sync == true and d_flag_parity == true and flag_TOW_set==true); current_synchro_data.Flag_valid_word = (d_flag_frame_sync == true and d_flag_parity == true and flag_TOW_set==true);
@ -379,11 +378,13 @@ void gps_l1_ca_telemetry_decoder_cc::set_channel(int channel)
d_dump_filename.append(".dat"); d_dump_filename.append(".dat");
d_dump_file.exceptions ( std::ifstream::failbit | std::ifstream::badbit ); d_dump_file.exceptions ( std::ifstream::failbit | std::ifstream::badbit );
d_dump_file.open(d_dump_filename.c_str(), std::ios::out | std::ios::binary); d_dump_file.open(d_dump_filename.c_str(), std::ios::out | std::ios::binary);
std::cout << "Telemetry decoder dump enabled on channel " << d_channel << " Log file: " << d_dump_filename.c_str() << std::endl; std::cout << "Telemetry decoder dump enabled on channel " << d_channel
<< " Log file: " << d_dump_filename.c_str() << std::endl;
} }
catch (std::ifstream::failure e) catch (std::ifstream::failure e)
{ {
std::cout << "channel " << d_channel << " Exception opening trk dump file " << e.what() << std::endl; std::cout << "channel " << d_channel
<< " Exception opening trk dump file " << e.what() << std::endl;
} }
} }
} }

View File

@ -5,7 +5,7 @@
* \author Javier Arribas, 2011. jarribas(at)cttc.es * \author Javier Arribas, 2011. jarribas(at)cttc.es
* ------------------------------------------------------------------------- * -------------------------------------------------------------------------
* *
* Copyright (C) 2010-2011 (see AUTHORS file for a list of contributors) * Copyright (C) 2010-2013 (see AUTHORS file for a list of contributors)
* *
* GNSS-SDR is a software defined Global Navigation * GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver * Satellite Systems receiver
@ -39,7 +39,6 @@
#include <bitset> #include <bitset>
#include <gnuradio/block.h> #include <gnuradio/block.h>
#include <gnuradio/msg_queue.h> #include <gnuradio/msg_queue.h>
//#include <gnuradio/gr_sync_block.h>
#include "gnss_satellite.h" #include "gnss_satellite.h"
@ -62,24 +61,35 @@ public:
~gps_l1_ca_telemetry_decoder_cc(); ~gps_l1_ca_telemetry_decoder_cc();
void set_satellite(Gnss_Satellite satellite); //!< Set satellite PRN void set_satellite(Gnss_Satellite satellite); //!< Set satellite PRN
void set_channel(int channel); //!< Set receiver's channel void set_channel(int channel); //!< Set receiver's channel
/*! /*!
* \brief Set the satellite data queue * \brief Set the satellite data queue
*/ */
void set_ephemeris_queue(concurrent_queue<Gps_Ephemeris> *ephemeris_queue){d_GPS_FSM.d_ephemeris_queue = ephemeris_queue;} void set_ephemeris_queue(concurrent_queue<Gps_Ephemeris> *ephemeris_queue){d_GPS_FSM.d_ephemeris_queue = ephemeris_queue;} //!< Set the ephemeris data queue
void set_iono_queue(concurrent_queue<Gps_Iono> *iono_queue){d_GPS_FSM.d_iono_queue = iono_queue;} void set_iono_queue(concurrent_queue<Gps_Iono> *iono_queue){d_GPS_FSM.d_iono_queue = iono_queue;} //!< Set the iono data queue
void set_almanac_queue(concurrent_queue<Gps_Almanac> *almanac_queue){d_GPS_FSM.d_almanac_queue = almanac_queue;} void set_almanac_queue(concurrent_queue<Gps_Almanac> *almanac_queue){d_GPS_FSM.d_almanac_queue = almanac_queue;} //!< Set the almanac data queue
void set_utc_model_queue(concurrent_queue<Gps_Utc_Model> *utc_model_queue){d_GPS_FSM.d_utc_model_queue = utc_model_queue;} void set_utc_model_queue(concurrent_queue<Gps_Utc_Model> *utc_model_queue){d_GPS_FSM.d_utc_model_queue = utc_model_queue;} //!< Set the UTC model data queue
/*!
* \brief This is where all signal processing takes place
*/
int general_work (int noutput_items, gr_vector_int &ninput_items, int general_work (int noutput_items, gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); gr_vector_const_void_star &input_items, gr_vector_void_star &output_items);
/*!
* \brief Function which tells the scheduler how many input items
* are required to produce noutput_items output items.
*/
void forecast (int noutput_items, gr_vector_int &ninput_items_required); void forecast (int noutput_items, gr_vector_int &ninput_items_required);
private: private:
friend gps_l1_ca_telemetry_decoder_cc_sptr friend gps_l1_ca_telemetry_decoder_cc_sptr
gps_l1_ca_make_telemetry_decoder_cc(Gnss_Satellite satellite, long if_freq, long fs_in,unsigned gps_l1_ca_make_telemetry_decoder_cc(Gnss_Satellite satellite, long if_freq, long fs_in,unsigned
int vector_length, boost::shared_ptr<gr::msg_queue> queue, bool dump); int vector_length, boost::shared_ptr<gr::msg_queue> queue, bool dump);
gps_l1_ca_telemetry_decoder_cc(Gnss_Satellite satellite, long if_freq, long fs_in, unsigned gps_l1_ca_telemetry_decoder_cc(Gnss_Satellite satellite, long if_freq, long fs_in, unsigned
int vector_length, boost::shared_ptr<gr::msg_queue> queue, bool dump); int vector_length, boost::shared_ptr<gr::msg_queue> queue, bool dump);
bool gps_word_parityCheck(unsigned int gpsword); bool gps_word_parityCheck(unsigned int gpsword);
// constants // constants

View File

@ -56,6 +56,8 @@ sbas_l1_make_telemetry_decoder_cc(Gnss_Satellite satellite, long if_freq, long f
fs_in, vector_length, queue, dump)); fs_in, vector_length, queue, dump));
} }
sbas_l1_telemetry_decoder_cc::sbas_l1_telemetry_decoder_cc( sbas_l1_telemetry_decoder_cc::sbas_l1_telemetry_decoder_cc(
Gnss_Satellite satellite, Gnss_Satellite satellite,
long if_freq, long if_freq,
@ -64,7 +66,8 @@ sbas_l1_telemetry_decoder_cc::sbas_l1_telemetry_decoder_cc(
int vector_length, int vector_length,
boost::shared_ptr<gr::msg_queue> queue, boost::shared_ptr<gr::msg_queue> queue,
bool dump) : bool dump) :
gr::block("sbas_l1_telemetry_decoder_cc", gr::io_signature::make(1, 1, sizeof(Gnss_Synchro)), gr::block("sbas_l1_telemetry_decoder_cc",
gr::io_signature::make(1, 1, sizeof(Gnss_Synchro)),
gr::io_signature::make(1, 1, sizeof(Gnss_Synchro))) gr::io_signature::make(1, 1, sizeof(Gnss_Synchro)))
{ {
// initialize internal vars // initialize internal vars
@ -72,33 +75,33 @@ sbas_l1_telemetry_decoder_cc::sbas_l1_telemetry_decoder_cc(
d_satellite = Gnss_Satellite(satellite.get_system(), satellite.get_PRN()); d_satellite = Gnss_Satellite(satellite.get_system(), satellite.get_PRN());
DLOG(INFO) << "SBAS L1 TELEMETRY PROCESSING: satellite " << d_satellite; DLOG(INFO) << "SBAS L1 TELEMETRY PROCESSING: satellite " << d_satellite;
d_fs_in = fs_in; d_fs_in = fs_in;
d_block_size = d_samples_per_symbol * d_symbols_per_bit * d_block_size_in_bits; d_block_size = d_samples_per_symbol * d_symbols_per_bit * d_block_size_in_bits;
set_output_multiple (1); set_output_multiple (1);
} }
sbas_l1_telemetry_decoder_cc::~sbas_l1_telemetry_decoder_cc() sbas_l1_telemetry_decoder_cc::~sbas_l1_telemetry_decoder_cc()
{ {
d_dump_file.close(); d_dump_file.close();
} }
void sbas_l1_telemetry_decoder_cc::forecast (int noutput_items, gr_vector_int &ninput_items_required) void sbas_l1_telemetry_decoder_cc::forecast (int noutput_items, gr_vector_int &ninput_items_required)
{ {
unsigned ninputs = ninput_items_required.size (); unsigned ninputs = ninput_items_required.size ();
for (unsigned i = 0; i < ninputs; i++) for (unsigned i = 0; i < ninputs; i++)
ninput_items_required[i] = noutput_items; ninput_items_required[i] = noutput_items;
VLOG(LMORE) << "forecast(): " << "noutput_items=" << noutput_items << "\tninput_items_required ninput_items_required.size()=" << ninput_items_required.size(); VLOG(LMORE) << "forecast(): " << "noutput_items=" << noutput_items << "\tninput_items_required ninput_items_required.size()=" << ninput_items_required.size();
} }
int sbas_l1_telemetry_decoder_cc::general_work (int noutput_items, gr_vector_int &ninput_items, int sbas_l1_telemetry_decoder_cc::general_work (int noutput_items, gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) gr_vector_const_void_star &input_items, gr_vector_void_star &output_items)
{ {
VLOG(FLOW) << "general_work(): " << "noutput_items=" << noutput_items << "\toutput_items real size=" << output_items.size() << "\tninput_items size=" << ninput_items.size() << "\tinput_items real size=" << input_items.size() << "\tninput_items[0]=" << ninput_items[0]; VLOG(FLOW) << "general_work(): " << "noutput_items=" << noutput_items << "\toutput_items real size=" << output_items.size() << "\tninput_items size=" << ninput_items.size() << "\tinput_items real size=" << input_items.size() << "\tninput_items[0]=" << ninput_items[0];
// get pointers on in- and output gnss-synchro objects // get pointers on in- and output gnss-synchro objects
const Gnss_Synchro *in = (const Gnss_Synchro *) input_items[0]; // input const Gnss_Synchro *in = (const Gnss_Synchro *) input_items[0]; // input
Gnss_Synchro *out = (Gnss_Synchro *) output_items[0]; // output Gnss_Synchro *out = (Gnss_Synchro *) output_items[0]; // output
@ -147,7 +150,7 @@ int sbas_l1_telemetry_decoder_cc::general_work (int noutput_items, gr_vector_int
{ {
int message_sample_offset = int message_sample_offset =
(sample_alignment?0:-1) (sample_alignment?0:-1)
+ d_samples_per_symbol*(symbol_alignment?-1:0) + d_samples_per_symbol*(symbol_alignment ? -1 : 0)
+ d_samples_per_symbol * d_symbols_per_bit * it->first; + d_samples_per_symbol * d_symbols_per_bit * it->first;
double message_sample_stamp = sample_stamp + ((double)message_sample_offset)/1000; double message_sample_stamp = sample_stamp + ((double)message_sample_offset)/1000;
VLOG(EVENT) << "message_sample_stamp=" << message_sample_stamp VLOG(EVENT) << "message_sample_stamp=" << message_sample_stamp
@ -188,6 +191,7 @@ int sbas_l1_telemetry_decoder_cc::general_work (int noutput_items, gr_vector_int
} }
void sbas_l1_telemetry_decoder_cc::set_satellite(Gnss_Satellite satellite) void sbas_l1_telemetry_decoder_cc::set_satellite(Gnss_Satellite satellite)
{ {
d_satellite = Gnss_Satellite(satellite.get_system(), satellite.get_PRN()); d_satellite = Gnss_Satellite(satellite.get_system(), satellite.get_PRN());
@ -195,6 +199,7 @@ void sbas_l1_telemetry_decoder_cc::set_satellite(Gnss_Satellite satellite)
} }
void sbas_l1_telemetry_decoder_cc::set_channel(int channel) void sbas_l1_telemetry_decoder_cc::set_channel(int channel)
{ {
d_channel = channel; d_channel = channel;
@ -241,7 +246,6 @@ bool sbas_l1_telemetry_decoder_cc::sample_aligner::get_symbols(const std::vector
for (unsigned int i_sym = 0; i_sym < samples.size()/sbas_l1_telemetry_decoder_cc::d_samples_per_symbol; i_sym++) for (unsigned int i_sym = 0; i_sym < samples.size()/sbas_l1_telemetry_decoder_cc::d_samples_per_symbol; i_sym++)
{ {
// get the next samples // get the next samples
for (int i = 0; i < d_n_smpls_in_history; i++) for (int i = 0; i < d_n_smpls_in_history; i++)
{ {
@ -266,7 +270,8 @@ bool sbas_l1_telemetry_decoder_cc::sample_aligner::get_symbols(const std::vector
// sample alignment debug output // sample alignment debug output
VLOG(SAMP_SYNC) << std::setprecision(5) VLOG(SAMP_SYNC) << std::setprecision(5)
<< "smplp: " << std::setw(6) << smpls[0] << " " << "smpl0: " << std::setw(6) << smpls[1] << " " << "smpl1: " << std::setw(6) << smpls[2] << "\t" << "smplp: " << std::setw(6) << smpls[0] << " " << "smpl0: " << std::setw(6)
<< smpls[1] << " " << "smpl1: " << std::setw(6) << smpls[2] << "\t"
//<< "Flag_valid_tracking: " << std::setw(1) << in[0][0].Flag_valid_tracking << " " << std::setw(1) << in[0][0].Flag_valid_tracking << "\t" //<< "Flag_valid_tracking: " << std::setw(1) << in[0][0].Flag_valid_tracking << " " << std::setw(1) << in[0][0].Flag_valid_tracking << "\t"
<< "d_corr_paired: " << std::setw(10) << d_corr_paired << "\t" << "d_corr_paired: " << std::setw(10) << d_corr_paired << "\t"
<< "d_corr_shifted: " << std::setw(10) << d_corr_shifted << "\t" << "d_corr_shifted: " << std::setw(10) << d_corr_shifted << "\t"
@ -306,6 +311,7 @@ sbas_l1_telemetry_decoder_cc::symbol_aligner_and_decoder::~symbol_aligner_and_de
delete d_vd2; delete d_vd2;
} }
void sbas_l1_telemetry_decoder_cc::symbol_aligner_and_decoder::reset() void sbas_l1_telemetry_decoder_cc::symbol_aligner_and_decoder::reset()
{ {
d_past_symbol = 0; d_past_symbol = 0;
@ -313,6 +319,7 @@ void sbas_l1_telemetry_decoder_cc::symbol_aligner_and_decoder::reset()
d_vd2->reset(); d_vd2->reset();
} }
bool sbas_l1_telemetry_decoder_cc::symbol_aligner_and_decoder::get_bits(const std::vector<double> symbols, std::vector<int> &bits) bool sbas_l1_telemetry_decoder_cc::symbol_aligner_and_decoder::get_bits(const std::vector<double> symbols, std::vector<int> &bits)
{ {
const int traceback_depth = 5*d_KK; const int traceback_depth = 5*d_KK;
@ -322,7 +329,7 @@ bool sbas_l1_telemetry_decoder_cc::symbol_aligner_and_decoder::get_bits(const st
std::vector<double> symbols_vd1(symbols); // aligned symbol vector -> copy input symbol vector std::vector<double> symbols_vd1(symbols); // aligned symbol vector -> copy input symbol vector
std::vector<double> symbols_vd2; // shifted symbol vector -> add past sample in front of input vector std::vector<double> symbols_vd2; // shifted symbol vector -> add past sample in front of input vector
symbols_vd1.push_back(d_past_symbol); symbols_vd1.push_back(d_past_symbol);
for (std::vector<double>::const_iterator symbol_it = symbols.begin(); symbol_it != symbols.end()-1; ++symbol_it) for (std::vector<double>::const_iterator symbol_it = symbols.begin(); symbol_it != symbols.end() - 1; ++symbol_it)
{ {
symbols_vd2.push_back(*symbol_it); symbols_vd2.push_back(*symbol_it);
} }
@ -333,7 +340,7 @@ bool sbas_l1_telemetry_decoder_cc::symbol_aligner_and_decoder::get_bits(const st
float metric_vd1 = d_vd1->decode_continuous(symbols_vd1.data(), traceback_depth, bits_vd1, nbits_requested, nbits_decoded); float metric_vd1 = d_vd1->decode_continuous(symbols_vd1.data(), traceback_depth, bits_vd1, nbits_requested, nbits_decoded);
float metric_vd2 = d_vd2->decode_continuous(symbols_vd2.data(), traceback_depth, bits_vd2, nbits_requested, nbits_decoded); float metric_vd2 = d_vd2->decode_continuous(symbols_vd2.data(), traceback_depth, bits_vd2, nbits_requested, nbits_decoded);
// choose the bits with the better metric // choose the bits with the better metric
for (int i = 0; i<nbits_decoded; i++) for (int i = 0; i < nbits_decoded; i++)
{ {
if (metric_vd1 > metric_vd2) if (metric_vd1 > metric_vd2)
{// symbols aligned {// symbols aligned
@ -399,7 +406,7 @@ void sbas_l1_telemetry_decoder_cc::frame_detector::get_frame_candidates(const st
{ {
// invert bits // invert bits
for (std::vector<int>::iterator candidate_bit_it = candidate.begin(); candidate_bit_it != candidate.end(); candidate_bit_it++) for (std::vector<int>::iterator candidate_bit_it = candidate.begin(); candidate_bit_it != candidate.end(); candidate_bit_it++)
*candidate_bit_it = *candidate_bit_it == 0 ? 1:0; *candidate_bit_it = *candidate_bit_it == 0 ? 1 : 0;
} }
msg_candidates.push_back(std::pair<int,std::vector<int>>(relative_preamble_start, candidate)); msg_candidates.push_back(std::pair<int,std::vector<int>>(relative_preamble_start, candidate));
ss.str(""); ss.str("");
@ -438,12 +445,13 @@ void sbas_l1_telemetry_decoder_cc::crc_verifier::get_valid_frames(const std::vec
d_checksum_agent.reset(0); d_checksum_agent.reset(0);
d_checksum_agent.process_bytes(candidate_bytes.data(), candidate_bytes.size()); d_checksum_agent.process_bytes(candidate_bytes.data(), candidate_bytes.size());
unsigned int crc = d_checksum_agent.checksum(); unsigned int crc = d_checksum_agent.checksum();
VLOG(SAMP_SYNC) << "candidate " << candidate_it - msg_candidates.begin() << ": final crc remainder= " << std::hex << crc VLOG(SAMP_SYNC) << "candidate " << candidate_it - msg_candidates.begin()
<< ": final crc remainder= " << std::hex << crc
<< std::setfill(' ') << std::resetiosflags(std::ios::hex); << std::setfill(' ') << std::resetiosflags(std::ios::hex);
// the final remainder must be zero for a valid message, because the CRC is done over the received CRC value // the final remainder must be zero for a valid message, because the CRC is done over the received CRC value
if (crc == 0) if (crc == 0)
{ {
valid_msgs.push_back(msg_candiate_char_t(candidate_it->first,candidate_bytes)); valid_msgs.push_back(msg_candiate_char_t(candidate_it->first, candidate_bytes));
ss << "Valid message found!"; ss << "Valid message found!";
} }
else else
@ -483,7 +491,8 @@ void sbas_l1_telemetry_decoder_cc::crc_verifier::zerropad_back_and_convert_to_by
} }
} }
bytes.push_back(byte); // implies: insert 6 zeros at the end to fit the 250bits into a multiple of bytes bytes.push_back(byte); // implies: insert 6 zeros at the end to fit the 250bits into a multiple of bytes
VLOG(LMORE) << " -> byte=" << std::setw(2) << std::setfill('0') << std::hex << (unsigned int)byte VLOG(LMORE) << " -> byte=" << std::setw(2)
<< std::setfill('0') << std::hex << (unsigned int)byte
<< std::setfill(' ') << std::resetiosflags(std::ios::hex); << std::setfill(' ') << std::resetiosflags(std::ios::hex);
} }
@ -504,12 +513,14 @@ void sbas_l1_telemetry_decoder_cc::crc_verifier::zerropad_front_and_convert_to_b
if (idx_bit % bits_per_byte == bits_per_byte - 1) if (idx_bit % bits_per_byte == bits_per_byte - 1)
{ {
bytes.push_back(byte); bytes.push_back(byte);
VLOG(LMORE) << ss.str() << " -> byte=" << std::setw(2) << std::setfill('0') << std::hex << (unsigned int)byte; ss.str(""); VLOG(LMORE) << ss.str() << " -> byte=" << std::setw(2)
<< std::setfill('0') << std::hex << (unsigned int)byte; ss.str("");
byte = 0; byte = 0;
} }
idx_bit++; idx_bit++;
} }
VLOG(LMORE) << " -> byte=" << std::setw(2) << std::setfill('0') << std::hex << (unsigned int)byte VLOG(LMORE) << " -> byte=" << std::setw(2)
<< std::setfill('0') << std::hex << (unsigned int)byte
<< std::setfill(' ') << std::resetiosflags(std::ios::hex); << std::setfill(' ') << std::resetiosflags(std::ios::hex);
} }

View File

@ -59,13 +59,21 @@ public:
void set_channel(int channel); //!< Set receiver's channel void set_channel(int channel); //!< Set receiver's channel
// queues to communicate broadcasted SBAS data to other blocks of GNSS-SDR // queues to communicate broadcasted SBAS data to other blocks of GNSS-SDR
void set_raw_msg_queue(concurrent_queue<Sbas_Raw_Msg> *raw_msg_queue); void set_raw_msg_queue(concurrent_queue<Sbas_Raw_Msg> *raw_msg_queue); //!< Set raw msg queue
void set_iono_queue(concurrent_queue<Sbas_Ionosphere_Correction> *iono_queue); void set_iono_queue(concurrent_queue<Sbas_Ionosphere_Correction> *iono_queue); //!< Set iono queue
void set_sat_corr_queue(concurrent_queue<Sbas_Satellite_Correction> *sat_corr_queue); void set_sat_corr_queue(concurrent_queue<Sbas_Satellite_Correction> *sat_corr_queue); //!< Set sat correction queue
void set_ephemeris_queue(concurrent_queue<Sbas_Ephemeris> *ephemeris_queue); void set_ephemeris_queue(concurrent_queue<Sbas_Ephemeris> *ephemeris_queue); //!< Set SBAS ephemeis queue
/*!
* \brief This is where all signal processing takes place
*/
int general_work (int noutput_items, gr_vector_int &ninput_items, int general_work (int noutput_items, gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); gr_vector_const_void_star &input_items, gr_vector_void_star &output_items);
/*!
* \brief Function which tells the scheduler how many input items
* are required to produce noutput_items output items.
*/
void forecast (int noutput_items, gr_vector_int &ninput_items_required); void forecast (int noutput_items, gr_vector_int &ninput_items_required);
private: private:

View File

@ -1,208 +1,214 @@
/* File convolutional.h /*!
* \file convolutional.h
Description: General functions used to implement convolutional encoding. * \brief General functions used to implement convolutional encoding.
* \author Matthew C. Valenti
Copyright (C) 2006-2008, Matthew C. Valenti *
* -------------------------------------------------------------------------
Last updated on May 22, 2008 *
* Copyright (C) 2006-2008 Matthew C. Valenti
The functions in this file are part of the Iterative Solutions *
Coded Modulation Library. The Iterative Solutions Coded Modulation * GNSS-SDR is a software defined Global Navigation
Library is free software; you can redistribute it and/or modify it * Satellite Systems receiver
under the terms of the GNU Lesser General Public License as published *
by the Free Software Foundation; either version 2.1 of the License, * This file is part of GNSS-SDR.
or (at your option) any later version. *
* GNSS-SDR is free software: you can redistribute it and/or modify
This library is distributed in the hope that it will be useful, * it under the terms of the GNU General Public License as published by
but WITHOUT ANY WARRANTY; without even the implied warranty of * the Free Software Foundation, either version 3 of the License, or
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * at your option) any later version.
Lesser General Public License for more details. *
* This file is a derived work of the original file, which had this note:
You should have received a copy of the GNU Lesser General Public *
License along with this library; if not, write to the Free Software * Last updated on May 22, 2008
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA *
* The functions in this file are part of the Iterative Solutions
*/ * Coded Modulation Library. The Iterative Solutions Coded Modulation
* Library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the License,
* or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/* define constants used throughout the library */ /* define constants used throughout the library */
#define MAXLOG 1e7 /* Define infinity */ #define MAXLOG 1e7 /* Define infinity */
/* function itob()
Description: Converts an integer symbol into a vector of bits /*!
* \brief Converts an integer symbol into a vector of bits
Output parameters: *
binvec_p: The binary vector * \param[out] binvec_p The binary vector
* \param[in] symbol The integer-valued symbol
Input parameters: * \param[in] length The length of the binary vector
symbol: The integer-valued symbol *
length: The length of the binary vector * This function is used by conv_encode()
*/
This function is used by conv_encode() */ void itob(int binvec_p[], int symbol, int length)
void itob(
int binvec_p[],
int symbol,
int length )
{ {
int counter; int counter;
/* Go through each bit in the vector */ /* Go through each bit in the vector */
for (counter=0;counter<length;counter++) { for (counter = 0; counter < length; counter++)
binvec_p[length-counter-1] = (symbol&1); {
symbol = symbol>>1; binvec_p[length - counter - 1] = (symbol & 1);
symbol = symbol >> 1;
} }
return; return;
} }
/* function parity_counter()
Description: Determines if a symbol has odd (1) or even (0) parity
Output parameters: /*!
(returned int): The symbol's parity = 1 for odd and 0 for even * \brief Determines if a symbol has odd (1) or even (0) parity
* Output parameters:
Input parameters: * \return (returned int): The symbol's parity = 1 for odd and 0 for even
symbol: The integer-valued symbol *
length: The highest bit position in the symbol * \param[in] symbol The integer-valued symbol
* \param[in] length The highest bit position in the symbol
This function is used by nsc_enc_bit(), rsc_enc_bit(), and rsc_tail() */ *
* This function is used by nsc_enc_bit(), rsc_enc_bit(), and rsc_tail()
int parity_counter( int symbol, int length ) */
int parity_counter(int symbol, int length)
{ {
int counter; int counter;
int temp_parity = 0; int temp_parity = 0;
for (counter=0;counter<length;counter++) { for (counter = 0; counter < length; counter++)
temp_parity = temp_parity^(symbol&1); {
symbol = symbol>>1; temp_parity = temp_parity^(symbol & 1);
symbol = symbol >> 1;
} }
return(temp_parity);
return( temp_parity );
} }
/* Function nsc_enc_bit()
Description: Convolutionally encodes a single bit using a rate 1/n encoder. /*!
Takes in one input bit at a time, and produces a n-bit output. * \brief Convolutionally encodes a single bit using a rate 1/n encoder.
* Takes in one input bit at a time, and produces a n-bit output.
Input parameters: *
input The input data bit (i.e. a 0 or 1). * \param[in] input The input data bit (i.e. a 0 or 1).
state_in The starting state of the encoder (an int from 0 to 2^m-1). * \param[in] state_in The starting state of the encoder (an int from 0 to 2^m-1).
g[] An n-element vector containing the code generators in binary form. * \param[in] g[] An n-element vector containing the code generators in binary form.
KK The constraint length of the convolutional code. * \param[in] KK The constraint length of the convolutional code.
* \param[out] output_p[] An n-element vector containing the encoded bits.
Output parameters: * \param[out] state_out_p[] An integer containing the final state of the encoder
output_p[] An n-element vector containing the encoded bits. * (i.e. the state after encoding this bit)
state_out_p[] An integer containing the final state of the encoder *
(i.e. the state after encoding this bit) * This function is used by rsc_encode(), nsc_transit(), rsc_transit(), and nsc_transit()
*/
This function is used by rsc_encode(), nsc_transit(), rsc_transit(), and nsc_transit() */ static int nsc_enc_bit(int state_out_p[],
static int nsc_enc_bit(
int state_out_p[],
int input, int input,
int state_in, int state_in,
int g[], int g[],
int KK, int KK,
int nn ) int nn)
{ {
/* declare variables */ /* declare variables */
int state, i; int state, i;
int out = 0; int out_ = 0;
/* create a word made up of state and new input */ /* create a word made up of state and new input */
state = (input<<(KK-1))^state_in; state = (input << (KK - 1))^state_in;
/* AND the word with the generators */ /* AND the word with the generators */
for (i=0;i<nn;i++) for (i = 0; i < nn; i++)
{ {
/* update output symbol */ /* update output symbol */
out = (out<<1) + parity_counter( state&g[i], KK ); out_ = (out_ << 1) + parity_counter(state & g[i], KK);
} }
/* shift the state to make the new state */ /* shift the state to make the new state */
state_out_p[0] = state>>1; state_out_p[0] = state >> 1;
return(out); return(out_);
} }
/* like nsc_enc_bit() but for a RSC code */
static int rsc_enc_bit(
int state_out_p[], /*!
* \brief like nsc_enc_bit() but for a RSC code
*/
static int rsc_enc_bit(int state_out_p[],
int input, int input,
int state_in, int state_in,
int g[], int g[],
int KK, int KK,
int nn ) int nn)
{ {
/* declare variables */ /* declare variables */
int state, i, out, a_k; int state, i, out_, a_k;
/* systematic output */ /* systematic output */
out = input; out_ = input;
/* determine feedback bit */ /* determine feedback bit */
a_k = input^parity_counter( g[0]&state_in, KK ); a_k = input^parity_counter(g[0]&state_in, KK);
/* create a word made up of state and feedback bit */ /* create a word made up of state and feedback bit */
state = (a_k<<(KK-1))^state_in; state = (a_k << (KK - 1))^state_in;
/* AND the word with the generators */ /* AND the word with the generators */
for (i=1;i<nn;i++) for (i = 1; i < nn; i++)
{ {
/* update output symbol */ /* update output symbol */
out = (out<<1) + parity_counter( state&g[i], KK ); out_ = (out_ << 1) + parity_counter(state & g[i], KK);
} }
/* shift the state to make the new state */ /* shift the state to make the new state */
state_out_p[0] = state>>1; state_out_p[0] = state >> 1;
return(out); return(out_);
} }
/* function that creates the transit and output vectors */
static void nsc_transit(
int output_p[], /*!
* \brief Function that creates the transit and output vectors
*/
static void nsc_transit(int output_p[],
int trans_p[], int trans_p[],
int input, int input,
int g[], int g[],
int KK, int KK,
int nn ) int nn)
{ {
int nextstate[1]; int nextstate[1];
int state, states; int state, states;
states = (1<<(KK-1)); /* The number of states: 2^mm */ states = (1 << (KK - 1)); /* The number of states: 2^mm */
/* Determine the output and next state for each possible starting state */ /* Determine the output and next state for each possible starting state */
for(state=0;state<states;state++) { for(state = 0; state < states; state++)
output_p[state] = nsc_enc_bit( nextstate, input, state, g, KK, nn ); {
output_p[state] = nsc_enc_bit(nextstate, input, state, g, KK, nn);
trans_p[state] = nextstate[0]; trans_p[state] = nextstate[0];
} }
return; return;
} }
/* Function rsc_transit()
Description: Calculates the "transition matrix" for the trellis.
This information tells the decoder what the next state and output bits
will be given the current state and input bit.
Input parameters: /*!
input Either 0 or 1 --- the input data bit. * \brief Calculates the "transition matrix" for the trellis.
g[] A two element vector containing the code generators. * This information tells the decoder what the next state and output bits
KK The constraint length of the convolutional code. * will be given the current state and input bit.
*
Output parameters: * \param[in] input Either 0 or 1 --- the input data bit.
output_p[] A vector of length max_states = 2^(KK-1) containing * \param[in] g[] A two element vector containing the code generators.
the output symbols. * \param[in] KK The constraint length of the convolutional code.
trans_p[] A vector of length max_states that tells the decoder * \param[out] output_p[] A vector of length max_states = 2^(KK-1) containing
what the next state will be given the input and current state. * the output symbols.
* \param[out] trans_p[] A vector of length max_states that tells the decoder
This function is used by turbo_decode() */ * what the next state will be given the input and current state.
*
static void rsc_transit( * This function is used by turbo_decode()
int output_p[], */
static void rsc_transit(int output_p[],
int trans_p[], int trans_p[],
int input, int input,
int g[], int g[],
@ -212,19 +218,23 @@ static void rsc_transit(
int nextstate[1]; int nextstate[1];
int state, states; int state, states;
states = 1 << (KK-1); /* The number of states: 2^mm */ states = 1 << (KK - 1); // The number of states: 2^mm
/* Determine the output and next state for each possible starting state */ // Determine the output and next state for each possible starting state
for(state=0;state<states;state++) { for(state = 0; state < states; state++)
{
output_p[state] = rsc_enc_bit( nextstate, input, state, g, KK, nn ); output_p[state] = rsc_enc_bit( nextstate, input, state, g, KK, nn );
trans_p[state] = nextstate[0]; trans_p[state] = nextstate[0];
} }
return; return;
} }
/* determine the tail for a RSC code */
static void rsc_tail(
int tail_p[], /*!
* \brief determines the tail for a RSC code
*/
static void rsc_tail(int tail_p[],
int g[], int g[],
int max_states, int max_states,
int mm ) int mm )
@ -232,16 +242,20 @@ static void rsc_tail(
int state; int state;
/* Determine the tail for each state */ /* Determine the tail for each state */
for(state=0;state<max_states;state++) { for(state = 0; state < max_states; state++)
{
/* determine feedback word */ /* determine feedback word */
tail_p[state] = parity_counter( g[0]&state, mm ); tail_p[state] = parity_counter(g[0]&state, mm);
} }
return; return;
} }
/* perform convolutional encoding */
static void conv_encode(
int output_p[], /*!
* \brief Perform convolutional encoding
*/
static void conv_encode(int output_p[],
int input[], int input[],
int out0[], int out0[],
int state0[], int state0[],
@ -250,7 +264,7 @@ static void conv_encode(
int tail[], int tail[],
int KK, int KK,
int LL, int LL,
int nn ) int nn)
{ {
int i, j, outsym; int i, j, outsym;
int *bin_vec; int *bin_vec;
@ -259,12 +273,17 @@ static void conv_encode(
/* Negative value in "tail" is a flag that this is /* Negative value in "tail" is a flag that this is
a tail-biting NSC code. Determine initial state */ a tail-biting NSC code. Determine initial state */
if ( tail[0] < 0 ) { if ( tail[0] < 0 )
for (i=LL-KK+1;i<LL;i++) { {
if (input[i]) { for (i = LL - KK + 1; i < LL; i++)
{
if (input[i])
{
/* Determine next state */ /* Determine next state */
state = state1[state]; state = state1[state];
} else { }
else
{
/* Determine next state */ /* Determine next state */
state = state0[state]; state = state0[state];
} }
@ -274,14 +293,18 @@ static void conv_encode(
bin_vec = (int*)calloc( nn, sizeof(int) ); bin_vec = (int*)calloc( nn, sizeof(int) );
/* encode data bits one bit at a time */ /* encode data bits one bit at a time */
for (i=0;i<LL;i++) { for (i = 0; i < LL; i++)
if (input[i]) { {
if (input[i])
{
/* Input is a one */ /* Input is a one */
outsym = out1[state]; /* The output symbol */ outsym = out1[state]; /* The output symbol */
/* Determine next state */ /* Determine next state */
state = state1[state]; state = state1[state];
} else { }
else
{
/* Input is a zero */ /* Input is a zero */
outsym = out0[state]; /* The output symbol */ outsym = out0[state]; /* The output symbol */
@ -293,20 +316,25 @@ static void conv_encode(
itob( bin_vec, outsym, nn ); itob( bin_vec, outsym, nn );
/* Assign to output */ /* Assign to output */
for (j=0;j<nn;j++) for (j = 0; j < nn; j++)
output_p[nn*i+j] = bin_vec[j]; output_p[nn*i + j] = bin_vec[j];
} }
/* encode tail if needed */ /* encode tail if needed */
if (tail[0] >= 0) { if (tail[0] >= 0)
for (i=LL;i<LL+KK-1;i++) { {
if (tail[state]) { for (i = LL; i < LL + KK - 1; i++)
{
if (tail[state])
{
/* Input is a one */ /* Input is a one */
outsym = out1[state]; /* The output symbol */ outsym = out1[state]; /* The output symbol */
/* Determine next state */ /* Determine next state */
state = state1[state]; state = state1[state];
} else { }
else
{
/* Input is a zero */ /* Input is a zero */
outsym = out0[state]; /* The output symbol */ outsym = out0[state]; /* The output symbol */
@ -318,71 +346,56 @@ static void conv_encode(
itob( bin_vec, outsym, nn ); itob( bin_vec, outsym, nn );
/* Assign to output */ /* Assign to output */
for (j=0;j<nn;j++) for (j = 0; j < nn; j++)
output_p[nn*i+j] = bin_vec[j]; output_p[nn*i + j] = bin_vec[j];
} }
} }
free(bin_vec); free(bin_vec);
return; return;
} }
/* function Gamma() /*!
* \brief Computes the branch metric used for decoding.
Description: Computes the branch metric used for decoding. * \return (returned float) The metric between the hypothetical symbol and the received vector
* \param[in] rec_array The received vector, of length nn
Output parameters: * \param[in] symbol The hypothetical symbol
(returned float) The metric between the hypothetical symbol and the recevieved vector * \param[in] nn The length of the received vector
*
Input parameters: * This function is used by siso()
rec_array The received vector, of length nn */
symbol The hypothetical symbol
nn The length of the received vector
This function is used by siso() */
static float Gamma(float rec_array[], static float Gamma(float rec_array[],
int symbol, int symbol,
int nn ) int nn)
{ {
float rm = 0; float rm = 0;
int i; int i;
int mask; int mask = 1;
mask = 1; for (i = 0; i < nn; i++)
for (i=0;i<nn;i++) { {
if (symbol&mask) if (symbol & mask)
rm += rec_array[nn-i-1]; rm += rec_array[nn - i - 1];
mask = mask<<1; mask = mask << 1;
} }
return(rm); return(rm);
} }
/* Function Viterbi() /*!
* \brief Uses the Viterbi algorithm to perform hard-decision decoding of a convolutional code.
Description: Uses the Viterbi algorithm to perform hard-decision decoding of a convolutional code. * \param[in] out0[] The output bits for each state if input is a 0 (generated by rsc_transit).
* \param[in] state0[] The next state if input is a 0 (generated by rsc_transit).
Input parameters: * \param[in] out1[] The output bits for each state if input is a 1 (generated by rsc_transit).
out0[] The output bits for each state if input is a 0 (generated by rsc_transit). * \param[in] state1[] The next state if input is a 1 (generated by rsc_transit).
state0[] The next state if input is a 0 (generated by rsc_transit). * \param[in] r[] The received signal in LLR-form. For BPSK, must be in form r = 2*a*y/(sigma^2).
out1[] The output bits for each state if input is a 1 (generated by rsc_transit). * \param[in] KK The constraint length of the convolutional code.
state1[] The next state if input is a 1 (generated by rsc_transit). * \param[in] LL The number of data bits.
r[] The received signal in LLR-form. For BPSK, must be in form r = 2*a*y/(sigma^2). * \param[out] output_u_int[] Hard decisions on the data bits
KK The constraint length of the convolutional code. *
LL The number of data bits. */
static void Viterbi(int output_u_int[],
Output parameters:
output_u_int[] Hard decisions on the data bits
*/
static void Viterbi(
int output_u_int[],
int out0[], int out0[],
int state0[], int state0[],
int out1[], int out1[],
@ -390,8 +403,7 @@ static void Viterbi(
double input_c[], double input_c[],
int KK, int KK,
int nn, int nn,
int LL int LL)
)
{ {
int i, t, state, mm, states; int i, t, state, mm, states;
int number_symbols; int number_symbols;
@ -404,66 +416,73 @@ static void Viterbi(
float max_val; float max_val;
/* some derived constants */ /* some derived constants */
mm = KK-1; mm = KK - 1;
states = 1 << mm; /* 2^mm */ states = 1 << mm; /* 2^mm */
number_symbols = 1 << nn; /* 2^nn */ number_symbols = 1 << nn; /* 2^nn */
/* dynamically allocate memory */ /* dynamically allocate memory */
prev_section = (float*)calloc( states, sizeof(float) ); prev_section = (float*)calloc( states, sizeof(float) );
next_section = (float*)calloc( states, sizeof(float) ); next_section = (float*)calloc( states, sizeof(float) );
prev_bit = (int*)calloc( states*(LL+mm), sizeof(int) ); prev_bit = (int*)calloc( states*(LL + mm), sizeof(int) );
prev_state = (int*)calloc( states*(LL+mm), sizeof(int) ); prev_state = (int*)calloc( states*(LL + mm), sizeof(int) );
rec_array = (float*)calloc( nn, sizeof(float) ); rec_array = (float*)calloc( nn, sizeof(float) );
metric_c = (float*)calloc( number_symbols, sizeof(float) ); metric_c = (float*)calloc( number_symbols, sizeof(float) );
/* initialize trellis */ /* initialize trellis */
for (state=0;state<states;state++) { for (state = 0; state < states; state++)
{
prev_section[state] = -MAXLOG; prev_section[state] = -MAXLOG;
next_section[state] = -MAXLOG; next_section[state] = -MAXLOG;
} }
prev_section[0] = 0; /* start in all-zeros state */ prev_section[0] = 0; /* start in all-zeros state */
/* go through trellis */ /* go through trellis */
for (t=0;t<LL+mm;t++) { for (t = 0; t < LL + mm; t++)
for (i=0;i<nn;i++) {
rec_array[i] = (float)input_c[nn*t+i]; for (i = 0; i < nn; i++)
rec_array[i] = (float)input_c[nn*t + i];
/* precompute all possible branch metrics */ /* precompute all possible branch metrics */
for (i=0;i<number_symbols;i++) for (i = 0; i < number_symbols; i++)
metric_c[i] = Gamma( rec_array, i, nn ); metric_c[i] = Gamma( rec_array, i, nn );
/* step through all states */ /* step through all states */
for (state=0;state<states;state++) { for (state = 0; state < states; state++)
{
/* hypothesis: info bit is a zero */ /* hypothesis: info bit is a zero */
metric = prev_section[state] + metric_c[ out0[ state ] ]; metric = prev_section[state] + metric_c[ out0[ state ] ];
/* store new metric if more than metric in storage */ /* store new metric if more than metric in storage */
if ( metric > next_section[state0[state]] ) { if ( metric > next_section[state0[state]] )
{
next_section[state0[state]] = metric; next_section[state0[state]] = metric;
prev_state[t*states+state0[state]] = state; prev_state[t*states + state0[state]] = state;
prev_bit[t*states+state0[state]] = 0; prev_bit[t*states + state0[state]] = 0;
} }
/* hypothesis: info bit is a one */ /* hypothesis: info bit is a one */
metric = prev_section[state] + metric_c[ out1[ state ] ]; metric = prev_section[state] + metric_c[ out1[ state ] ];
/* store new metric if more than metric in storage */ /* store new metric if more than metric in storage */
if ( metric > next_section[state1[state]] ) { if ( metric > next_section[state1[state]] )
{
next_section[state1[state]] = metric; next_section[state1[state]] = metric;
prev_state[t*states+state1[state]] = state; prev_state[t*states + state1[state]] = state;
prev_bit[t*states+state1[state]] = 1; prev_bit[t*states + state1[state]] = 1;
} }
} }
/* normalize */ /* normalize */
max_val = 0; max_val = 0;
for (state=0;state<states;state++) { for (state = 0; state < states; state++)
if (next_section[state]>max_val){ {
if (next_section[state] > max_val)
{
max_val = next_section[state]; max_val = next_section[state];
} }
} }
for (state=0;state<states;state++) { for (state = 0; state < states; state++)
{
prev_section[state] = next_section[state] - max_val; prev_section[state] = next_section[state] - max_val;
next_section[state] = -MAXLOG; next_section[state] = -MAXLOG;
} }
@ -473,13 +492,15 @@ static void Viterbi(
state = 0; state = 0;
/* tail, no need to output */ /* tail, no need to output */
for (t=LL+mm-1; t>=LL; t--) { for (t = LL + mm - 1; t >= LL; t--)
state = prev_state[t*states+state]; {
state = prev_state[t*states + state];
} }
for (t=LL-1; t>=0; t--) { for (t = LL - 1; t >= 0; t--)
output_u_int[t] = prev_bit[t*states+state]; {
state = prev_state[t*states+state]; output_u_int[t] = prev_bit[t*states + state];
state = prev_state[t*states + state];
} }
/* free the dynamically allocated memory */ /* free the dynamically allocated memory */
@ -489,31 +510,24 @@ static void Viterbi(
free(prev_state); free(prev_state);
free(rec_array); free(rec_array);
free(metric_c); free(metric_c);
} }
/* Function ViterbiTb()
Description: Uses the Viterbi algorithm to perform hard-decision decoding of a tail-biting convolutional code. /*!
* \brief Uses the Viterbi algorithm to perform hard-decision decoding of a tail-biting convolutional code.
Input parameters: * Input parameters:
out0[] The output bits for each state if input is a 0 (generated by rsc_transit). * out0[] The output bits for each state if input is a 0 (generated by rsc_transit).
state0[] The next state if input is a 0 (generated by rsc_transit). * state0[] The next state if input is a 0 (generated by rsc_transit).
out1[] The output bits for each state if input is a 1 (generated by rsc_transit). * out1[] The output bits for each state if input is a 1 (generated by rsc_transit).
state1[] The next state if input is a 1 (generated by rsc_transit). * state1[] The next state if input is a 1 (generated by rsc_transit).
r[] The received signal in LLR-form. For BPSK, must be in form r = 2*a*y/(sigma^2). * r[] The received signal in LLR-form. For BPSK, must be in form r = 2*a*y/(sigma^2).
KK The constraint length of the convolutional code. * KK The constraint length of the convolutional code.
LL The number of data bits. * LL The number of data bits.
depth head and tail decoding length [Ref. W. Sung, Electronics Letters, vol. 36, no. 7] * depth head and tail decoding length [Ref. W. Sung, Electronics Letters, vol. 36, no. 7]
* Output parameters:
Output parameters: * output_u_int[] Hard decisions on the data bits
output_u_int[] Hard decisions on the data bits */
static void ViterbiTb(int output_u_int[],
*/
static void ViterbiTb(
int output_u_int[],
int out0[], int out0[],
int state0[], int state0[],
int out1[], int out1[],
@ -522,8 +536,7 @@ static void ViterbiTb(
int KK, int KK,
int nn, int nn,
int LL, int LL,
int depth int depth)
)
{ {
int i, t, state, mm, states, max_state; int i, t, state, mm, states, max_state;
int number_symbols, starting_bit; int number_symbols, starting_bit;
@ -536,51 +549,54 @@ static void ViterbiTb(
float max_val; float max_val;
/* some derived constants */ /* some derived constants */
mm = KK-1; mm = KK - 1;
states = 1 << mm; /* 2^mm */ states = 1 << mm; /* 2^mm */
number_symbols = 1 << nn; /* 2^nn */ number_symbols = 1 << nn; /* 2^nn */
/* dynamically allocate memory */ /* dynamically allocate memory */
prev_section = (float*)calloc( states, sizeof(float) ); prev_section = (float*)calloc( states, sizeof(float) );
next_section = (float*)calloc( states, sizeof(float) ); next_section = (float*)calloc( states, sizeof(float) );
prev_bit = (int*)calloc( states*(LL+depth), sizeof(int) ); prev_bit = (int*)calloc( states*(LL + depth), sizeof(int) );
prev_state = (int*)calloc( states*(LL+depth), sizeof(int) ); prev_state = (int*)calloc( states*(LL + depth), sizeof(int) );
rec_array = (float*)calloc( nn, sizeof(float) ); rec_array = (float*)calloc( nn, sizeof(float) );
metric_c = (float*)calloc( number_symbols, sizeof(float) ); metric_c = (float*)calloc( number_symbols, sizeof(float) );
/* initialize trellis */ /* initialize trellis */
for (state=0;state<states;state++) { for (state = 0; state < states; state++)
{
prev_section[state] = 0; /* equally likely starting state */ prev_section[state] = 0; /* equally likely starting state */
next_section[state] = -MAXLOG; next_section[state] = -MAXLOG;
} }
/* go through trellis */ /* go through trellis */
for (t=-depth;t<LL+depth;t++) { for (t = -depth; t < LL + depth; t++)
{
/* determine the corresponding data bits */ /* determine the corresponding data bits */
starting_bit = nn*(t%LL); starting_bit = nn*(t % LL);
if (starting_bit < 0 ) if (starting_bit < 0 )
starting_bit = nn*LL + starting_bit; starting_bit = nn*LL + starting_bit;
/* printf( "start at %d\n", starting_bit ); */ for (i = 0; i < nn; i++)
for (i=0;i<nn;i++) { {
rec_array[i] = (float)input_c[starting_bit+i]; rec_array[i] = (float)input_c[starting_bit+i];
/* printf( "%1f\n", rec_array[i] ); */
} }
/* precompute all possible branch metrics */ /* precompute all possible branch metrics */
for (i=0;i<number_symbols;i++) for (i = 0; i < number_symbols; i++)
metric_c[i] = Gamma( rec_array, i, nn ); metric_c[i] = Gamma( rec_array, i, nn );
/* step through all states */ /* step through all states */
for (state=0;state<states;state++) { for (state = 0; state < states; state++)
{
/* hypothesis: info bit is a zero */ /* hypothesis: info bit is a zero */
metric = prev_section[state] + metric_c[ out0[ state ] ]; metric = prev_section[state] + metric_c[ out0[ state ] ];
/* store new metric if more than metric in storage */ /* store new metric if more than metric in storage */
if ( metric > next_section[state0[state]] ) { if ( metric > next_section[state0[state]] )
{
next_section[state0[state]] = metric; next_section[state0[state]] = metric;
if (t>=0) { if (t >= 0)
{
prev_state[t*states+state0[state]] = state; prev_state[t*states+state0[state]] = state;
prev_bit[t*states+state0[state]] = 0; prev_bit[t*states+state0[state]] = 0;
} }
@ -590,9 +606,11 @@ static void ViterbiTb(
metric = prev_section[state] + metric_c[ out1[ state ] ]; metric = prev_section[state] + metric_c[ out1[ state ] ];
/* store new metric if more than metric in storage */ /* store new metric if more than metric in storage */
if ( metric > next_section[state1[state]] ) { if ( metric > next_section[state1[state]] )
{
next_section[state1[state]] = metric; next_section[state1[state]] = metric;
if (t>=0) { if (t >= 0)
{
prev_state[t*states+state1[state]] = state; prev_state[t*states+state1[state]] = state;
prev_bit[t*states+state1[state]] = 1; prev_bit[t*states+state1[state]] = 1;
} }
@ -601,13 +619,16 @@ static void ViterbiTb(
/* normalize */ /* normalize */
max_val = 0; max_val = 0;
for (state=0;state<states;state++) { for (state = 0; state < states; state++)
if (next_section[state]>max_val){ {
if (next_section[state] > max_val)
{
max_val = next_section[state]; max_val = next_section[state];
max_state = state; max_state = state;
} }
} }
for (state=0;state<states;state++) { for (state = 0; state < states; state++)
{
prev_section[state] = next_section[state] - max_val; prev_section[state] = next_section[state] - max_val;
next_section[state] = -MAXLOG; next_section[state] = -MAXLOG;
} }
@ -617,13 +638,15 @@ static void ViterbiTb(
state = max_state; state = max_state;
/* tail, no need to output */ /* tail, no need to output */
for (t=LL+depth-1; t>=LL; t--) { for (t = LL + depth - 1; t >= LL; t--)
state = prev_state[t*states+state]; {
state = prev_state[t*states + state];
} }
for (t=LL-1; t>=0; t--) { for (t = LL - 1; t >= 0; t--)
output_u_int[t] = prev_bit[t*states+state]; {
state = prev_state[t*states+state]; output_u_int[t] = prev_bit[t*states + state];
state = prev_state[t*states + state];
} }
/* free the dynamically allocated memory */ /* free the dynamically allocated memory */
@ -633,5 +656,4 @@ static void ViterbiTb(
free(prev_state); free(prev_state);
free(rec_array); free(rec_array);
free(metric_c); free(metric_c);
} }

View File

@ -5,7 +5,7 @@
* *
* ------------------------------------------------------------------------- * -------------------------------------------------------------------------
* *
* Copyright (C) 2010-2012 (see AUTHORS file for a list of contributors) * Copyright (C) 2010-2013 (see AUTHORS file for a list of contributors)
* *
* GNSS-SDR is a software defined Global Navigation * GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver * Satellite Systems receiver
@ -232,18 +232,24 @@ GpsL1CaSubframeFsm::GpsL1CaSubframeFsm()
initiate(); //start the FSM initiate(); //start the FSM
} }
void GpsL1CaSubframeFsm::gps_word_to_subframe(int position) void GpsL1CaSubframeFsm::gps_word_to_subframe(int position)
{ {
// insert the word in the correct position of the subframe // insert the word in the correct position of the subframe
std::memcpy(&d_subframe[position*GPS_WORD_LENGTH], &d_GPS_frame_4bytes, sizeof(char)*GPS_WORD_LENGTH); std::memcpy(&d_subframe[position*GPS_WORD_LENGTH], &d_GPS_frame_4bytes, sizeof(char)*GPS_WORD_LENGTH);
} }
void GpsL1CaSubframeFsm::gps_subframe_to_nav_msg() void GpsL1CaSubframeFsm::gps_subframe_to_nav_msg()
{ {
int subframe_ID; int subframe_ID;
// NEW GPS SUBFRAME HAS ARRIVED! // NEW GPS SUBFRAME HAS ARRIVED!
subframe_ID = d_nav.subframe_decoder(this->d_subframe); //decode the subframe subframe_ID = d_nav.subframe_decoder(this->d_subframe); //decode the subframe
std::cout << "NAVIGATION FSM: received subframe " << subframe_ID << " for satellite " << Gnss_Satellite(std::string("GPS"), i_satellite_PRN) << std::endl; std::cout << "NAVIGATION FSM: received subframe "
<< subframe_ID << " for satellite "
<< Gnss_Satellite(std::string("GPS"), i_satellite_PRN) << std::endl;
d_nav.i_satellite_PRN = i_satellite_PRN; d_nav.i_satellite_PRN = i_satellite_PRN;
d_nav.i_channel_ID = i_channel_ID; d_nav.i_channel_ID = i_channel_ID;
d_nav.d_subframe_timestamp_ms = this->d_preamble_time_ms; d_nav.d_subframe_timestamp_ms = this->d_preamble_time_ms;
@ -251,22 +257,22 @@ void GpsL1CaSubframeFsm::gps_subframe_to_nav_msg()
switch (subframe_ID) switch (subframe_ID)
{ {
case 3: //we have a new set of ephemeris data for the current SV case 3: //we have a new set of ephemeris data for the current SV
if (d_nav.satellite_validation()==true) if (d_nav.satellite_validation() == true)
{ {
// get ephemeris object for this SV (mandatory) // get ephemeris object for this SV (mandatory)
Gps_Ephemeris ephemeris=d_nav.get_ephemeris(); Gps_Ephemeris ephemeris = d_nav.get_ephemeris();
d_ephemeris_queue->push(ephemeris); d_ephemeris_queue->push(ephemeris);
} }
break; break;
case 4: // Possible IONOSPHERE and UTC model update (page 18) case 4: // Possible IONOSPHERE and UTC model update (page 18)
if (d_nav.flag_iono_valid==true) if (d_nav.flag_iono_valid == true)
{ {
Gps_Iono iono=d_nav.get_iono(); //notice that the read operation will clear the valid flag Gps_Iono iono = d_nav.get_iono(); //notice that the read operation will clear the valid flag
d_iono_queue->push(iono); d_iono_queue->push(iono);
} }
if (d_nav.flag_utc_model_valid==true) if (d_nav.flag_utc_model_valid == true)
{ {
Gps_Utc_Model utc_model=d_nav.get_utc_model(); //notice that the read operation will clear the valid flag Gps_Utc_Model utc_model = d_nav.get_utc_model(); //notice that the read operation will clear the valid flag
d_utc_model_queue->push(utc_model); d_utc_model_queue->push(utc_model);
} }
break; break;
@ -279,11 +285,15 @@ void GpsL1CaSubframeFsm::gps_subframe_to_nav_msg()
} }
} }
void GpsL1CaSubframeFsm::Event_gps_word_valid() void GpsL1CaSubframeFsm::Event_gps_word_valid()
{ {
this->process_event(Ev_gps_word_valid()); this->process_event(Ev_gps_word_valid());
} }
void GpsL1CaSubframeFsm::Event_gps_word_invalid() void GpsL1CaSubframeFsm::Event_gps_word_invalid()
{ {
this->process_event(Ev_gps_word_invalid()); this->process_event(Ev_gps_word_invalid());

View File

@ -67,46 +67,48 @@ struct gps_subframe_fsm_S9;
struct gps_subframe_fsm_S10; struct gps_subframe_fsm_S10;
struct gps_subframe_fsm_S11; struct gps_subframe_fsm_S11;
/*!
* \brief This class implements a Finite State Machine that handles the decoding
* of the GPS L1 C/A NAV message
*/
class GpsL1CaSubframeFsm : public sc::state_machine< GpsL1CaSubframeFsm, gps_subframe_fsm_S0 > class GpsL1CaSubframeFsm : public sc::state_machine< GpsL1CaSubframeFsm, gps_subframe_fsm_S0 >
{ {
public: public:
GpsL1CaSubframeFsm(); //!< The constructor starts the Finite State Machine
// channel and satellite info // channel and satellite info
int i_channel_ID; int i_channel_ID; //!< Channel id
unsigned int i_satellite_PRN; unsigned int i_satellite_PRN; //!< Satellite PRN number
// ephemeris queue concurrent_queue<Gps_Ephemeris> *d_ephemeris_queue; //!< Ephemeris queue
concurrent_queue<Gps_Ephemeris> *d_ephemeris_queue; concurrent_queue<Gps_Iono> *d_iono_queue; //!< Ionospheric parameters queue
// ionospheric parameters queue concurrent_queue<Gps_Utc_Model> *d_utc_model_queue; //!< UTC model parameters queue
concurrent_queue<Gps_Iono> *d_iono_queue; concurrent_queue<Gps_Almanac> *d_almanac_queue; //!< Almanac queue
// UTC model parameters queue
concurrent_queue<Gps_Utc_Model> *d_utc_model_queue;
// Almanac queue
concurrent_queue<Gps_Almanac> *d_almanac_queue;
// navigation message class Gps_Navigation_Message d_nav; //!< GPS L1 C/A navigation message object
Gps_Navigation_Message d_nav;
// GPS SV and System parameters // GPS SV and System parameters
Gps_Ephemeris ephemeris; Gps_Ephemeris ephemeris; //!< Object that handles GPS ephemeris parameters
Gps_Almanac almanac; Gps_Almanac almanac; //!< Object that handles GPS almanac data
Gps_Utc_Model utc_model; Gps_Utc_Model utc_model; //!< Object that handles UTM model parameters
Gps_Iono iono; Gps_Iono iono; //!< Object that handles ionospheric parameters
char d_subframe[GPS_SUBFRAME_LENGTH]; char d_subframe[GPS_SUBFRAME_LENGTH];
char d_GPS_frame_4bytes[GPS_WORD_LENGTH]; char d_GPS_frame_4bytes[GPS_WORD_LENGTH];
double d_preamble_time_ms; double d_preamble_time_ms;
void gps_word_to_subframe(int position); void gps_word_to_subframe(int position); //!< inserts the word in the correct position of the subframe
/*!
* \brief This function decodes a NAv message subframe and pushes the information to the right queues
*/
void gps_subframe_to_nav_msg(); void gps_subframe_to_nav_msg();
//FSM EVENTS //FSM EVENTS
void Event_gps_word_valid(); void Event_gps_word_valid(); //!< FSM event: the received word is valid
void Event_gps_word_invalid(); void Event_gps_word_invalid(); //!< FSM event: the received word is not valid
void Event_gps_word_preamble(); void Event_gps_word_preamble(); //!< FSM event: word preamble detected
GpsL1CaSubframeFsm();
}; };
#endif #endif

View File

@ -47,7 +47,6 @@
Viterbi_Decoder::Viterbi_Decoder(const int g_encoder[], const int KK, const int nn) Viterbi_Decoder::Viterbi_Decoder(const int g_encoder[], const int KK, const int nn)
{ {
d_nn = nn; //Coding rate 1/n d_nn = nn; //Coding rate 1/n
d_KK = KK; //Constraint Length d_KK = KK; //Constraint Length
@ -84,27 +83,25 @@ Viterbi_Decoder::~Viterbi_Decoder()
delete[] d_metric_c; delete[] d_metric_c;
} }
void
Viterbi_Decoder::reset()
void Viterbi_Decoder::reset()
{ {
init_trellis_state(); init_trellis_state();
} }
/* Function decode_block() /* Function decode_block()
Description: Uses the Viterbi algorithm to perform hard-decision decoding of a convolutional code. Description: Uses the Viterbi algorithm to perform hard-decision decoding of a convolutional code.
Input parameters: Input parameters:
r[] The received signal in LLR-form. For BPSK, must be in form r = 2*a*y/(sigma^2). r[] The received signal in LLR-form. For BPSK, must be in form r = 2*a*y/(sigma^2).
LL The number of data bits to be decoded (doen't inlcude the mm zero-tail-bits) LL The number of data bits to be decoded (doen't inlcude the mm zero-tail-bits)
Output parameters: Output parameters:
output_u_int[] Hard decisions on the data bits (without the mm zero-tail-bits) output_u_int[] Hard decisions on the data bits (without the mm zero-tail-bits)
*/ */
float Viterbi_Decoder::decode_block(const double input_c[], int output_u_int[], const int LL)
float
Viterbi_Decoder::decode_block(const double input_c[], int output_u_int[], const int LL)
{ {
int state; int state;
int decoding_length_mismatch; int decoding_length_mismatch;
@ -125,9 +122,13 @@ Viterbi_Decoder::decode_block(const double input_c[], int output_u_int[], const
return d_indicator_metric; return d_indicator_metric;
} }
float
Viterbi_Decoder::decode_continuous(const double sym[], const int traceback_depth, int bits[],
const int nbits_requested, int &nbits_decoded) float Viterbi_Decoder::decode_continuous(const double sym[],
const int traceback_depth,
int bits[],
const int nbits_requested,
int &nbits_decoded)
{ {
int state; int state;
int decoding_length_mismatch; int decoding_length_mismatch;
@ -150,11 +151,11 @@ Viterbi_Decoder::decode_continuous(const double sym[], const int traceback_depth
return d_indicator_metric; return d_indicator_metric;
} }
void
Viterbi_Decoder::init_trellis_state()
void Viterbi_Decoder::init_trellis_state()
{ {
int state; int state;
// if trellis state has been initialised, free old state memory // if trellis state has been initialised, free old state memory
if(d_trellis_state_is_initialised) if(d_trellis_state_is_initialised)
{ {
@ -182,8 +183,10 @@ Viterbi_Decoder::init_trellis_state()
d_indicator_metric = 0; d_indicator_metric = 0;
} }
int
Viterbi_Decoder::do_acs(const double sym[], int nbits)
int Viterbi_Decoder::do_acs(const double sym[], int nbits)
{ {
int t, i, state_at_t; int t, i, state_at_t;
float metric; float metric;
@ -202,11 +205,9 @@ Viterbi_Decoder::do_acs(const double sym[], int nbits)
pm_t_next[state_at_t] = -MAXLOG; pm_t_next[state_at_t] = -MAXLOG;
} }
/* go through trellis */ /* go through trellis */
for (t = 0; t < nbits; t++) for (t = 0; t < nbits; t++)
{ {
/* Temporarily store the received symbols current decoding step */ /* Temporarily store the received symbols current decoding step */
for (i = 0; i < d_nn; i++) for (i = 0; i < d_nn; i++)
d_rec_array[i] = (float) sym[d_nn * t + i]; d_rec_array[i] = (float) sym[d_nn * t + i];
@ -223,7 +224,6 @@ Viterbi_Decoder::do_acs(const double sym[], int nbits)
/* step through all states */ /* step through all states */
for (state_at_t = 0; state_at_t < d_states; state_at_t++) for (state_at_t = 0; state_at_t < d_states; state_at_t++)
{ {
int next_state_if_0 = d_state0[state_at_t]; int next_state_if_0 = d_state0[state_at_t];
int next_state_if_1 = d_state1[state_at_t]; int next_state_if_1 = d_state1[state_at_t];
@ -256,7 +256,6 @@ Viterbi_Decoder::do_acs(const double sym[], int nbits)
d_trellis_paths.push_front(next_trellis_states); d_trellis_paths.push_front(next_trellis_states);
/* normalize -> afterwards, the largest metric value is always 0 */ /* normalize -> afterwards, the largest metric value is always 0 */
//max_val = 0; //max_val = 0;
max_val = -MAXLOG; max_val = -MAXLOG;
@ -275,14 +274,14 @@ Viterbi_Decoder::do_acs(const double sym[], int nbits)
} }
} }
delete[] pm_t_next; delete[] pm_t_next;
return t; return t;
} }
int
Viterbi_Decoder::do_traceback(size_t traceback_length)
int Viterbi_Decoder::do_traceback(size_t traceback_length)
{ {
// traceback_length is in bits // traceback_length is in bits
int state; int state;
@ -303,17 +302,17 @@ Viterbi_Decoder::do_traceback(size_t traceback_length)
return state; return state;
} }
int
Viterbi_Decoder::do_tb_and_decode(int traceback_length, int requested_decoding_length, int state, int output_u_int[], float& indicator_metric)
int Viterbi_Decoder::do_tb_and_decode(int traceback_length, int requested_decoding_length, int state, int output_u_int[], float& indicator_metric)
{ {
int n_of_branches_for_indicator_metric = 500; int n_of_branches_for_indicator_metric = 500;
int t_out; int t_out;
std::deque<Prev>::iterator it; std::deque<Prev>::iterator it;
int decoding_length_mismatch; int decoding_length_mismatch;
int overstep_length; int overstep_length;
int n_im = 0;
int n_im=0;
VLOG(FLOW) << "do_tb_and_decode(): requested_decoding_length=" << requested_decoding_length; VLOG(FLOW) << "do_tb_and_decode(): requested_decoding_length=" << requested_decoding_length;
@ -323,12 +322,13 @@ Viterbi_Decoder::do_tb_and_decode(int traceback_length, int requested_decoding_l
overstep_length = decoding_length_mismatch >= 0 ? decoding_length_mismatch : 0; overstep_length = decoding_length_mismatch >= 0 ? decoding_length_mismatch : 0;
VLOG(BLOCK) << "overstep_length=" << overstep_length; VLOG(BLOCK) << "overstep_length=" << overstep_length;
for (it = d_trellis_paths.begin() + traceback_length; it < d_trellis_paths.begin()+traceback_length + overstep_length; ++it) for (it = d_trellis_paths.begin() + traceback_length;
it < d_trellis_paths.begin() + traceback_length + overstep_length; ++it)
{ {
state = it->get_anchestor_state_of_current_state(state); state = it->get_anchestor_state_of_current_state(state);
} }
t_out = d_trellis_paths.end()-(d_trellis_paths.begin() + traceback_length + overstep_length)-1;//requested_decoding_length-1; t_out = d_trellis_paths.end() - (d_trellis_paths.begin() + traceback_length + overstep_length) - 1;//requested_decoding_length-1;
indicator_metric = 0; indicator_metric = 0;
for (it = d_trellis_paths.begin() + traceback_length + overstep_length; it < d_trellis_paths.end(); ++it) for (it = d_trellis_paths.begin() + traceback_length + overstep_length; it < d_trellis_paths.end(); ++it)
{ {
@ -342,19 +342,20 @@ Viterbi_Decoder::do_tb_and_decode(int traceback_length, int requested_decoding_l
} }
output_u_int[t_out] = it->get_bit_of_current_state(state); output_u_int[t_out] = it->get_bit_of_current_state(state);
state = it->get_anchestor_state_of_current_state(state); state = it->get_anchestor_state_of_current_state(state);
t_out--; t_out--;
} }
indicator_metric/=n_im; indicator_metric /= n_im;
VLOG(BLOCK) << "indicator metric: " << indicator_metric; VLOG(BLOCK) << "indicator metric: " << indicator_metric;
// remove old states // remove old states
if (d_trellis_paths.begin() + traceback_length+overstep_length <= d_trellis_paths.end()) if (d_trellis_paths.begin() + traceback_length + overstep_length <= d_trellis_paths.end())
{ {
d_trellis_paths.erase(d_trellis_paths.begin()+traceback_length+overstep_length, d_trellis_paths.end()); d_trellis_paths.erase(d_trellis_paths.begin() + traceback_length+overstep_length, d_trellis_paths.end());
} }
return decoding_length_mismatch; return decoding_length_mismatch;
} }
/* function Gamma() /* function Gamma()
Description: Computes the branch metric used for decoding. Description: Computes the branch metric used for decoding.
@ -426,8 +427,7 @@ Viterbi_Decoder::nsc_transit(int output_p[], int trans_p[], int input, const int
This function is used by rsc_encode(), nsc_transit(), rsc_transit(), and nsc_transit() */ This function is used by rsc_encode(), nsc_transit(), rsc_transit(), and nsc_transit() */
int int Viterbi_Decoder::nsc_enc_bit(int state_out_p[], int input, int state_in,
Viterbi_Decoder::nsc_enc_bit(int state_out_p[], int input, int state_in,
const int g[], int KK, int nn) const int g[], int KK, int nn)
{ {
/* declare variables */ /* declare variables */
@ -462,18 +462,15 @@ Viterbi_Decoder::nsc_enc_bit(int state_out_p[], int input, int state_in,
This function is used by nsc_enc_bit(), rsc_enc_bit(), and rsc_tail() */ This function is used by nsc_enc_bit(), rsc_enc_bit(), and rsc_tail() */
int int Viterbi_Decoder::parity_counter(int symbol, int length)
Viterbi_Decoder::parity_counter(int symbol, int length)
{ {
int counter; int counter;
int temp_parity = 0; int temp_parity = 0;
for (counter = 0; counter < length; counter++) for (counter = 0; counter < length; counter++)
{ {
temp_parity = temp_parity ^ (symbol & 1); temp_parity = temp_parity ^ (symbol & 1);
symbol = symbol >> 1; symbol = symbol >> 1;
} }
return (temp_parity); return (temp_parity);
} }
@ -486,27 +483,26 @@ Viterbi_Decoder::Prev::Prev(int states, int t)
state = new int[states]; state = new int[states];
bit = new int[states]; bit = new int[states];
metric = new float[states]; metric = new float[states];
refcount = new int; refcount = new int;
*refcount = 1; *refcount = 1;
//std::cout << "Prev(" << states << ", " << t << ")" << " constructor" << std::endl;
} }
// copy constructor // copy constructor
Viterbi_Decoder::Prev::Prev(const Prev& prev) Viterbi_Decoder::Prev::Prev(const Prev& prev)
{ {
refcount = prev.refcount; refcount = prev.refcount;
(*refcount)++; (*refcount)++;
t = prev.t; t = prev.t;
state = prev.state; state = prev.state;
bit = prev.bit; bit = prev.bit;
metric = prev.metric; metric = prev.metric;
VLOG(LMORE) << "Prev(" << "?" << ", " << t << ")" << " copy, new refcount = " << *refcount; VLOG(LMORE) << "Prev(" << "?" << ", " << t << ")" << " copy, new refcount = " << *refcount;
} }
// assignment constructor // assignment constructor
Viterbi_Decoder::Prev& Viterbi_Decoder::Prev::operator=(const Prev& other) Viterbi_Decoder::Prev& Viterbi_Decoder::Prev::operator=(const Prev& other)
{ {
@ -517,7 +513,7 @@ Viterbi_Decoder::Prev& Viterbi_Decoder::Prev::operator=(const Prev& other)
} }
// handle old resources // handle old resources
if(*refcount==1) if(*refcount == 1)
{ // if they are not used anymore -> unallocate them { // if they are not used anymore -> unallocate them
delete[] state; delete[] state;
delete[] bit; delete[] bit;
@ -543,6 +539,9 @@ Viterbi_Decoder::Prev& Viterbi_Decoder::Prev::operator=(const Prev& other)
return *this; return *this;
} }
Viterbi_Decoder::Prev::~Prev() Viterbi_Decoder::Prev::~Prev()
{ {
if (*refcount == 1) if (*refcount == 1)
@ -560,12 +559,16 @@ Viterbi_Decoder::Prev::~Prev()
} }
} }
int Viterbi_Decoder::Prev::get_anchestor_state_of_current_state(int current_state) int Viterbi_Decoder::Prev::get_anchestor_state_of_current_state(int current_state)
{ {
//std::cout << "get prev state: for state " << current_state << " at time " << t << ", the prev state at time " << t-1 << " is " << state[current_state] << std::endl; //std::cout << "get prev state: for state " << current_state << " at time " << t << ", the prev state at time " << t-1 << " is " << state[current_state] << std::endl;
return state[current_state]; return state[current_state];
} }
int Viterbi_Decoder::Prev::get_bit_of_current_state(int current_state) int Viterbi_Decoder::Prev::get_bit_of_current_state(int current_state)
{ {
//std::cout << "get prev bit : for state " << current_state << " at time " << t << ", the send bit is " << bit[current_state] << std::endl; //std::cout << "get prev bit : for state " << current_state << " at time " << t << ", the send bit is " << bit[current_state] << std::endl;

View File

@ -29,8 +29,8 @@
* ------------------------------------------------------------------------- * -------------------------------------------------------------------------
*/ */
#ifndef GNSS_SDR_VITERBIDECODER_H_ #ifndef GNSS_SDR_VITERBI_DECODER_H_
#define GNSS_SDR_VITERBIDECODER_H_ #define GNSS_SDR_VITERBI_DECODER_H_
#include <deque> #include <deque>
#include <iostream> #include <iostream>
@ -41,12 +41,22 @@ public:
Viterbi_Decoder(const int g_encoder[], const int KK, const int nn); Viterbi_Decoder(const int g_encoder[], const int KK, const int nn);
~Viterbi_Decoder(); ~Viterbi_Decoder();
void reset(); void reset();
/*!
* \brief Uses the Viterbi algorithm to perform hard-decision decoding of a convolutional code.
*
* \param input_c[] The received signal in LLR-form. For BPSK, must be in form r = 2*a*y/(sigma^2).
* \param LL The number of data bits to be decoded (does not include the mm zero-tail-bits)
*
* \return output_u_int[] Hard decisions on the data bits (without the mm zero-tail-bits)
*/
float decode_block(const double input_c[], int* output_u_int, const int LL); float decode_block(const double input_c[], int* output_u_int, const int LL);
float decode_continuous(const double sym[], const int traceback_depth, int output_u_int[], float decode_continuous(const double sym[], const int traceback_depth, int output_u_int[],
const int nbits_requested, int &nbits_decoded); const int nbits_requested, int &nbits_decoded);
private: private:
class Prev class Prev
{ {
public: public:
@ -111,4 +121,4 @@ private:
int parity_counter(int symbol, int length); int parity_counter(int symbol, int length);
}; };
#endif /* GNSS_SDR_VITERBIDECODER_H_ */ #endif /* GNSS_SDR_VITERBI_DECODER_H_ */

View File

@ -9,7 +9,7 @@
* *
* ------------------------------------------------------------------------- * -------------------------------------------------------------------------
* *
* Copyright (C) 2010-2012 (see AUTHORS file for a list of contributors) * Copyright (C) 2010-2013 (see AUTHORS file for a list of contributors)
* *
* GNSS-SDR is a software defined Global Navigation * GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver * Satellite Systems receiver
@ -38,12 +38,10 @@
#include "gps_iono.h" #include "gps_iono.h"
#include "gps_utc_model.h" #include "gps_utc_model.h"
#include "gps_almanac.h" #include "gps_almanac.h"
#include "galileo_ephemeris.h" #include "galileo_ephemeris.h"
#include "galileo_iono.h" #include "galileo_iono.h"
#include "galileo_utc_model.h" #include "galileo_utc_model.h"
#include "galileo_almanac.h" #include "galileo_almanac.h"
#include "concurrent_queue.h" #include "concurrent_queue.h"
#include "concurrent_map.h" #include "concurrent_map.h"
#include <unistd.h> #include <unistd.h>
@ -155,14 +153,14 @@ void ControlThread::run()
keyboard_thread_ = boost::thread(&ControlThread::keyboard_listener, this); keyboard_thread_ = boost::thread(&ControlThread::keyboard_listener, this);
//start the GNSS SV data collector thread //start the GNSS SV data collector thread
gps_ephemeris_data_collector_thread_ =boost::thread(&ControlThread::gps_ephemeris_data_collector, this); gps_ephemeris_data_collector_thread_ = boost::thread(&ControlThread::gps_ephemeris_data_collector, this);
gps_iono_data_collector_thread_ =boost::thread(&ControlThread::gps_iono_data_collector, this); gps_iono_data_collector_thread_ = boost::thread(&ControlThread::gps_iono_data_collector, this);
gps_utc_model_data_collector_thread_ =boost::thread(&ControlThread::gps_utc_model_data_collector, this); gps_utc_model_data_collector_thread_ = boost::thread(&ControlThread::gps_utc_model_data_collector, this);
gps_acq_assist_data_collector_thread_=boost::thread(&ControlThread::gps_acq_assist_data_collector,this); gps_acq_assist_data_collector_thread_= boost::thread(&ControlThread::gps_acq_assist_data_collector, this);
galileo_ephemeris_data_collector_thread_ =boost::thread(&ControlThread::galileo_ephemeris_data_collector, this); galileo_ephemeris_data_collector_thread_ = boost::thread(&ControlThread::galileo_ephemeris_data_collector, this);
galileo_iono_data_collector_thread_ =boost::thread(&ControlThread::galileo_iono_data_collector, this); galileo_iono_data_collector_thread_ = boost::thread(&ControlThread::galileo_iono_data_collector, this);
galileo_utc_model_data_collector_thread_ =boost::thread(&ControlThread::galileo_utc_model_data_collector, this); galileo_utc_model_data_collector_thread_ = boost::thread(&ControlThread::galileo_utc_model_data_collector, this);
// Main loop to read and process the control messages // Main loop to read and process the control messages
while (flowgraph_->running() && !stop_) while (flowgraph_->running() && !stop_)
{ {
@ -170,7 +168,7 @@ void ControlThread::run()
read_control_messages(); read_control_messages();
if (control_messages_ != 0) process_control_messages(); if (control_messages_ != 0) process_control_messages();
} }
std::cout<<"Stopping GNSS-SDR, please wait!"<<std::endl; std::cout << "Stopping GNSS-SDR, please wait!" << std::endl;
flowgraph_->stop(); flowgraph_->stop();
// Join GPS threads // Join GPS threads
@ -205,25 +203,30 @@ void ControlThread::set_control_queue(boost::shared_ptr<gr::msg_queue> control_q
bool ControlThread::read_assistance_from_XML() bool ControlThread::read_assistance_from_XML()
{ {
std::string eph_xml_filename="gps_ephemeris.xml"; std::string eph_xml_filename = "gps_ephemeris.xml";
std::cout<< "SUPL: Try read GPS ephemeris from XML file "<<eph_xml_filename<<std::endl; std::cout << "SUPL: Try read GPS ephemeris from XML file " << eph_xml_filename << std::endl;
if (supl_client_ephemeris_.load_ephemeris_xml(eph_xml_filename)==true) if (supl_client_ephemeris_.load_ephemeris_xml(eph_xml_filename) == true)
{ {
std::map<int,Gps_Ephemeris>::iterator gps_eph_iter; std::map<int,Gps_Ephemeris>::iterator gps_eph_iter;
for(gps_eph_iter = supl_client_ephemeris_.gps_ephemeris_map.begin(); for(gps_eph_iter = supl_client_ephemeris_.gps_ephemeris_map.begin();
gps_eph_iter != supl_client_ephemeris_.gps_ephemeris_map.end(); gps_eph_iter != supl_client_ephemeris_.gps_ephemeris_map.end();
gps_eph_iter++) gps_eph_iter++)
{ {
std::cout<<"SUPL: Read XML Ephemeris for GPS SV "<<gps_eph_iter->first<<std::endl; std::cout << "SUPL: Read XML Ephemeris for GPS SV " << gps_eph_iter->first << std::endl;
global_gps_ephemeris_queue.push(gps_eph_iter->second); global_gps_ephemeris_queue.push(gps_eph_iter->second);
} }
return false; return false;
}else{ }
std::cout<< "ERROR: SUPL client error reading XML"<<std::endl; else
std::cout<< "Disabling SUPL assistance.."<<std::endl; {
std::cout << "ERROR: SUPL client error reading XML" << std::endl;
std::cout << "Disabling SUPL assistance.." << std::endl;
return false; return false;
} }
} }
void ControlThread::init() void ControlThread::init()
{ {
// Instantiates a control queue, a GNSS flowgraph, and a control message factory // Instantiates a control queue, a GNSS flowgraph, and a control message factory
@ -234,134 +237,150 @@ void ControlThread::init()
processed_control_messages_ = 0; processed_control_messages_ = 0;
applied_actions_ = 0; applied_actions_ = 0;
//#########GNSS Asistence ################################# //######### GNSS Assistance #################################
// GNSS Assistance configuration // GNSS Assistance configuration
bool enable_gps_supl_assistance=configuration_->property("GNSS-SDR.SUPL_gps_enabled",false); bool enable_gps_supl_assistance = configuration_->property("GNSS-SDR.SUPL_gps_enabled", false);
if (enable_gps_supl_assistance==true) if (enable_gps_supl_assistance == true)
//SUPL SERVER TEST. Not operational yet! //SUPL SERVER TEST. Not operational yet!
{ {
std::cout<< "SUPL RRLP GPS assistance enabled!"<<std::endl; std::cout << "SUPL RRLP GPS assistance enabled!" << std::endl;
std::string default_acq_server="supl.nokia.com"; std::string default_acq_server = "supl.nokia.com";
std::string default_eph_server="supl.google.com"; std::string default_eph_server = "supl.google.com";
supl_client_ephemeris_.server_name=configuration_->property("GNSS-SDR.SUPL_gps_ephemeris_server",default_acq_server); supl_client_ephemeris_.server_name = configuration_->property("GNSS-SDR.SUPL_gps_ephemeris_server", default_acq_server);
supl_client_acquisition_.server_name=configuration_->property("GNSS-SDR.SUPL_gps_acquisition_server",default_eph_server); supl_client_acquisition_.server_name = configuration_->property("GNSS-SDR.SUPL_gps_acquisition_server", default_eph_server);
supl_client_ephemeris_.server_port=configuration_->property("GNSS-SDR.SUPL_gps_ephemeris_port",7275); supl_client_ephemeris_.server_port = configuration_->property("GNSS-SDR.SUPL_gps_ephemeris_port", 7275);
supl_client_acquisition_.server_port=configuration_->property("GNSS-SDR.SUPL_gps_acquisition_port",7275); supl_client_acquisition_.server_port = configuration_->property("GNSS-SDR.SUPL_gps_acquisition_port", 7275);
supl_mcc=configuration_->property("GNSS-SDR.SUPL_MCC",244); supl_mcc = configuration_->property("GNSS-SDR.SUPL_MCC", 244);
supl_mns=configuration_->property("GNSS-SDR.SUPL_MNS",5); supl_mns = configuration_->property("GNSS-SDR.SUPL_MNS", 5);
std::string default_lac="0x59e2"; std::string default_lac = "0x59e2";
std::string default_ci="0x31b0"; std::string default_ci = "0x31b0";
try { try
supl_lac = boost::lexical_cast<int>(configuration_->property("GNSS-SDR.SUPL_LAC",default_lac)); {
} catch(boost::bad_lexical_cast &) { supl_lac = boost::lexical_cast<int>(configuration_->property("GNSS-SDR.SUPL_LAC", default_lac));
supl_lac=0x59e2;
} }
try { catch(boost::bad_lexical_cast &)
supl_ci = boost::lexical_cast<int>(configuration_->property("GNSS-SDR.SUPL_CI",default_ci)); {
} catch(boost::bad_lexical_cast &) { supl_lac = 0x59e2;
supl_ci=0x31b0;
} }
bool SUPL_read_gps_assistance_xml=configuration_->property("GNSS-SDR.SUPL_read_gps_assistance_xml",false); try
if (SUPL_read_gps_assistance_xml==true) {
supl_ci = boost::lexical_cast<int>(configuration_->property("GNSS-SDR.SUPL_CI", default_ci));
}
catch(boost::bad_lexical_cast &)
{
supl_ci = 0x31b0;
}
bool SUPL_read_gps_assistance_xml = configuration_->property("GNSS-SDR.SUPL_read_gps_assistance_xml", false);
if (SUPL_read_gps_assistance_xml == true)
{ {
// read assistance from file // read assistance from file
read_assistance_from_XML(); read_assistance_from_XML();
}else{ }
else
{
// Request ephemeris from SUPL server // Request ephemeris from SUPL server
int error; int error;
supl_client_ephemeris_.request=1; supl_client_ephemeris_.request = 1;
std::cout<< "SUPL: Try read GPS ephemeris from SUPL server.."<<std::endl; std::cout << "SUPL: Try to read GPS ephemeris from SUPL server.." << std::endl;
error=supl_client_ephemeris_.get_assistance(supl_mcc,supl_mns,supl_lac,supl_ci); error = supl_client_ephemeris_.get_assistance(supl_mcc, supl_mns, supl_lac, supl_ci);
if (error==0) if (error == 0)
{ {
std::map<int,Gps_Ephemeris>::iterator gps_eph_iter; std::map<int,Gps_Ephemeris>::iterator gps_eph_iter;
for(gps_eph_iter = supl_client_ephemeris_.gps_ephemeris_map.begin(); for(gps_eph_iter = supl_client_ephemeris_.gps_ephemeris_map.begin();
gps_eph_iter != supl_client_ephemeris_.gps_ephemeris_map.end(); gps_eph_iter != supl_client_ephemeris_.gps_ephemeris_map.end();
gps_eph_iter++) gps_eph_iter++)
{ {
std::cout<<"SUPL: Received Ephemeris for GPS SV "<<gps_eph_iter->first<<std::endl; std::cout << "SUPL: Received Ephemeris for GPS SV " << gps_eph_iter->first << std::endl;
global_gps_ephemeris_queue.push(gps_eph_iter->second); global_gps_ephemeris_queue.push(gps_eph_iter->second);
} }
//Save ephemeris to XML file //Save ephemeris to XML file
std::string eph_xml_filename="gps_ephemeris.xml"; std::string eph_xml_filename = "gps_ephemeris.xml";
if (supl_client_ephemeris_.save_ephemeris_xml(eph_xml_filename)==true) if (supl_client_ephemeris_.save_ephemeris_xml(eph_xml_filename) == true)
{ {
std::cout<<"SUPL: XML Ephemeris file created"<<std::endl; std::cout << "SUPL: XML Ephemeris file created" << std::endl;
} }
}else{ }
std::cout<< "ERROR: SUPL client for Ephemeris returned "<<error<<std::endl; else
std::cout<< "Please check internet connection and SUPL server configuration"<<error<<std::endl;
std::cout<< "Trying to read ephemeris from XML file"<<std::endl;
if (read_assistance_from_XML()==false)
{ {
std::cout<< "ERROR: Could not read Ephemeris file: Disabling SUPL assistance.."<<std::endl; std::cout << "ERROR: SUPL client for Ephemeris returned " << error << std::endl;
std::cout << "Please check internet connection and SUPL server configuration" << error << std::endl;
std::cout << "Trying to read ephemeris from XML file" << std::endl;
if (read_assistance_from_XML() == false)
{
std::cout << "ERROR: Could not read Ephemeris file: Disabling SUPL assistance.." << std::endl;
} }
} }
// Request almanac , IONO and UTC Model // Request almanac , IONO and UTC Model
supl_client_ephemeris_.request=0; supl_client_ephemeris_.request = 0;
std::cout<< "SUPL: Try read Almanac, Iono, Utc Model, Ref Time and Ref Location from SUPL server.."<<std::endl; std::cout << "SUPL: Try read Almanac, Iono, Utc Model, Ref Time and Ref Location from SUPL server..." << std::endl;
error=supl_client_ephemeris_.get_assistance(supl_mcc,supl_mns,supl_lac,supl_ci); error = supl_client_ephemeris_.get_assistance(supl_mcc, supl_mns, supl_lac, supl_ci);
if (error==0) if (error == 0)
{ {
std::map<int,Gps_Almanac>::iterator gps_alm_iter; std::map<int,Gps_Almanac>::iterator gps_alm_iter;
for(gps_alm_iter = supl_client_ephemeris_.gps_almanac_map.begin(); for(gps_alm_iter = supl_client_ephemeris_.gps_almanac_map.begin();
gps_alm_iter != supl_client_ephemeris_.gps_almanac_map.end(); gps_alm_iter != supl_client_ephemeris_.gps_almanac_map.end();
gps_alm_iter++) gps_alm_iter++)
{ {
std::cout<<"SUPL: Received Almanac for GPS SV "<<gps_alm_iter->first<<std::endl; std::cout << "SUPL: Received Almanac for GPS SV " << gps_alm_iter->first << std::endl;
global_gps_almanac_queue.push(gps_alm_iter->second); global_gps_almanac_queue.push(gps_alm_iter->second);
} }
if (supl_client_ephemeris_.gps_iono.valid==true) if (supl_client_ephemeris_.gps_iono.valid == true)
{ {
std::cout<<"SUPL: Received GPS Iono"<<std::endl; std::cout << "SUPL: Received GPS Iono" << std::endl;
global_gps_iono_queue.push(supl_client_ephemeris_.gps_iono); global_gps_iono_queue.push(supl_client_ephemeris_.gps_iono);
} }
if (supl_client_ephemeris_.gps_utc.valid==true) if (supl_client_ephemeris_.gps_utc.valid == true)
{ {
std::cout<<"SUPL: Received GPS UTC Model"<<std::endl; std::cout << "SUPL: Received GPS UTC Model" << std::endl;
global_gps_utc_model_queue.push(supl_client_ephemeris_.gps_utc); global_gps_utc_model_queue.push(supl_client_ephemeris_.gps_utc);
} }
}else{ }
std::cout<< "ERROR: SUPL client for Almanac returned "<<error<<std::endl; else
std::cout<< "Please check internet connection and SUPL server configuration"<<error<<std::endl; {
std::cout<< "Disabling SUPL assistance.."<<std::endl; std::cout << "ERROR: SUPL client for Almanac returned " << error << std::endl;
std::cout << "Please check internet connection and SUPL server configuration" << error << std::endl;
std::cout << "Disabling SUPL assistance.." << std::endl;
} }
// Request acquisition assistance // Request acquisition assistance
supl_client_acquisition_.request=2; supl_client_acquisition_.request = 2;
std::cout<< "SUPL: Try read Acquisition assistance from SUPL server.."<<std::endl; std::cout << "SUPL: Try read Acquisition assistance from SUPL server.." << std::endl;
error=supl_client_acquisition_.get_assistance(supl_mcc,supl_mns,supl_lac,supl_ci); error = supl_client_acquisition_.get_assistance(supl_mcc, supl_mns, supl_lac, supl_ci);
if (error==0) if (error == 0)
{ {
std::map<int,Gps_Acq_Assist>::iterator gps_acq_iter; std::map<int, Gps_Acq_Assist>::iterator gps_acq_iter;
for(gps_acq_iter = supl_client_acquisition_.gps_acq_map.begin(); for(gps_acq_iter = supl_client_acquisition_.gps_acq_map.begin();
gps_acq_iter != supl_client_acquisition_.gps_acq_map.end(); gps_acq_iter != supl_client_acquisition_.gps_acq_map.end();
gps_acq_iter++) gps_acq_iter++)
{ {
std::cout<<"SUPL: Received Acquisition assistance for GPS SV "<<gps_acq_iter->first<<std::endl; std::cout << "SUPL: Received Acquisition assistance for GPS SV " << gps_acq_iter->first << std::endl;
global_gps_acq_assist_queue.push(gps_acq_iter->second); global_gps_acq_assist_queue.push(gps_acq_iter->second);
} }
}else{ }
std::cout<< "ERROR: SUPL client for Acquisition assistance returned "<<error<<std::endl; else
std::cout<< "Please check internet connection and SUPL server configuration"<<error<<std::endl; {
std::cout<< "Disabling SUPL assistance.."<<std::endl; std::cout << "ERROR: SUPL client for Acquisition assistance returned " << error << std::endl;
std::cout << "Please check internet connection and SUPL server configuration" << error << std::endl;
std::cout << "Disabling SUPL assistance.." << std::endl;
} }
} }
} }
} }
void ControlThread::read_control_messages() void ControlThread::read_control_messages()
{ {
DLOG(INFO) << "Reading control messages from queue"; DLOG(INFO) << "Reading control messages from queue";
boost::shared_ptr<gr::message> queue_message = control_queue_->delete_head(); boost::shared_ptr<gr::message> queue_message = control_queue_->delete_head();
if (queue_message != 0) if (queue_message != 0)
{ {
control_messages_ = control_message_factory_->GetControlMessages( control_messages_ = control_message_factory_->GetControlMessages(queue_message);
queue_message);
} }
else else
{ {
@ -383,8 +402,7 @@ void ControlThread::process_control_messages()
} }
else else
{ {
flowgraph_->apply_action(control_messages_->at(i)->who, flowgraph_->apply_action(control_messages_->at(i)->who, control_messages_->at(i)->what);
control_messages_->at(i)->what);
} }
delete control_messages_->at(i); delete control_messages_->at(i);
processed_control_messages_++; processed_control_messages_++;
@ -411,30 +429,37 @@ void ControlThread::apply_action(unsigned int what)
} }
} }
void ControlThread::gps_acq_assist_data_collector() void ControlThread::gps_acq_assist_data_collector()
{ {
// ############ 1.bis READ EPHEMERIS/UTC_MODE/IONO QUEUE #################### // ############ 1.bis READ EPHEMERIS/UTC_MODE/IONO QUEUE ####################
Gps_Acq_Assist gps_acq; Gps_Acq_Assist gps_acq;
Gps_Acq_Assist gps_acq_old; Gps_Acq_Assist gps_acq_old;
while(stop_==false) while(stop_ == false)
{ {
global_gps_acq_assist_queue.wait_and_pop(gps_acq); global_gps_acq_assist_queue.wait_and_pop(gps_acq);
// DEBUG MESSAGE // DEBUG MESSAGE
std::cout << "Acquisition assistance record has arrived from SAT ID " std::cout << "Acquisition assistance record has arrived from SAT ID "
<< gps_acq.i_satellite_PRN << " with Doppler " << gps_acq.d_Doppler0<<" [Hz] "<<std::endl; << gps_acq.i_satellite_PRN
<< " with Doppler "
<< gps_acq.d_Doppler0
<< " [Hz] "<< std::endl;
// insert new acq record to the global ephemeris map // insert new acq record to the global ephemeris map
if (global_gps_acq_assist_map.read(gps_acq.i_satellite_PRN,gps_acq_old)) if (global_gps_acq_assist_map.read(gps_acq.i_satellite_PRN,gps_acq_old))
{ {
std::cout << "Acquisition assistance record updated" << std::endl;
global_gps_acq_assist_map.write(gps_acq.i_satellite_PRN, gps_acq);
std::cout << "Acquisition assistance record updated"<<std::endl; }
global_gps_acq_assist_map.write(gps_acq.i_satellite_PRN,gps_acq); else
{
}else{
// insert new acq record // insert new acq record
std::cout << "New acq assist record inserted"<<std::endl; std::cout << "New acq assist record inserted" << std::endl;
global_gps_acq_assist_map.write(gps_acq.i_satellite_PRN,gps_acq); global_gps_acq_assist_map.write(gps_acq.i_satellite_PRN, gps_acq);
} }
} }
} }
@ -442,11 +467,10 @@ void ControlThread::gps_acq_assist_data_collector()
void ControlThread::gps_ephemeris_data_collector() void ControlThread::gps_ephemeris_data_collector()
{ {
// ############ 1.bis READ EPHEMERIS/UTC_MODE/IONO QUEUE #################### // ############ 1.bis READ EPHEMERIS/UTC_MODE/IONO QUEUE ####################
Gps_Ephemeris gps_eph; Gps_Ephemeris gps_eph;
Gps_Ephemeris gps_eph_old; Gps_Ephemeris gps_eph_old;
while(stop_==false) while(stop_ == false)
{ {
global_gps_ephemeris_queue.wait_and_pop(gps_eph); global_gps_ephemeris_queue.wait_and_pop(gps_eph);
@ -456,27 +480,34 @@ void ControlThread::gps_ephemeris_data_collector()
<< gps_eph.satelliteBlock[gps_eph.i_satellite_PRN] << gps_eph.satelliteBlock[gps_eph.i_satellite_PRN]
<< ")" << std::endl; << ")" << std::endl;
// insert new ephemeris record to the global ephemeris map // insert new ephemeris record to the global ephemeris map
if (global_gps_ephemeris_map.read(gps_eph.i_satellite_PRN,gps_eph_old)) if (global_gps_ephemeris_map.read(gps_eph.i_satellite_PRN, gps_eph_old))
{ {
// Check the EPHEMERIS timestamp. If it is newer, then update the ephemeris // Check the EPHEMERIS timestamp. If it is newer, then update the ephemeris
if (gps_eph.i_GPS_week > gps_eph_old.i_GPS_week) if (gps_eph.i_GPS_week > gps_eph_old.i_GPS_week)
{ {
std::cout << "Ephemeris record updated (GPS week="<<gps_eph.i_GPS_week<<std::endl; std::cout << "Ephemeris record updated (GPS week=" << gps_eph.i_GPS_week << std::endl;
global_gps_ephemeris_map.write(gps_eph.i_satellite_PRN,gps_eph); global_gps_ephemeris_map.write(gps_eph.i_satellite_PRN, gps_eph);
}else{ }
if (gps_eph.d_Toe>gps_eph_old.d_Toe) else
{ {
std::cout << "Ephemeris record updated (Toe="<<gps_eph.d_Toe<<std::endl; if (gps_eph.d_Toe > gps_eph_old.d_Toe)
global_gps_ephemeris_map.write(gps_eph.i_satellite_PRN,gps_eph); {
}else{ std::cout << "Ephemeris record updated (Toe=" << gps_eph.d_Toe << std::endl;
std::cout<<"Not updating the existing ephemeris"<<std::endl; global_gps_ephemeris_map.write(gps_eph.i_satellite_PRN, gps_eph);
}
else
{
std::cout << "Not updating the existing ephemeris" << std::endl;
} }
} }
}
}else{ else
{
// insert new ephemeris record // insert new ephemeris record
std::cout << "New Ephemeris record inserted with Toe="<<gps_eph.d_Toe<<" and GPS Week="<<gps_eph.i_GPS_week<<std::endl; std::cout << "New Ephemeris record inserted with Toe="
global_gps_ephemeris_map.write(gps_eph.i_satellite_PRN,gps_eph); << gps_eph.d_Toe<<" and GPS Week="
<< gps_eph.i_GPS_week << std::endl;
global_gps_ephemeris_map.write(gps_eph.i_satellite_PRN, gps_eph);
} }
} }
} }
@ -484,11 +515,10 @@ void ControlThread::gps_ephemeris_data_collector()
void ControlThread::galileo_ephemeris_data_collector() void ControlThread::galileo_ephemeris_data_collector()
{ {
// ############ 1.bis READ EPHEMERIS/UTC_MODE/IONO QUEUE #################### // ############ 1.bis READ EPHEMERIS/UTC_MODE/IONO QUEUE ####################
Galileo_Ephemeris galileo_eph; Galileo_Ephemeris galileo_eph;
Galileo_Ephemeris galileo_eph_old; Galileo_Ephemeris galileo_eph_old;
while(stop_==false) while(stop_ == false)
{ {
global_galileo_ephemeris_queue.wait_and_pop(galileo_eph); global_galileo_ephemeris_queue.wait_and_pop(galileo_eph);
@ -497,32 +527,36 @@ void ControlThread::galileo_ephemeris_data_collector()
<< galileo_eph.SV_ID_PRN_4 << std::endl; << galileo_eph.SV_ID_PRN_4 << std::endl;
// insert new ephemeris record to the global ephemeris map // insert new ephemeris record to the global ephemeris map
if (global_galileo_ephemeris_map.read(galileo_eph.SV_ID_PRN_4,galileo_eph_old)) if (global_galileo_ephemeris_map.read(galileo_eph.SV_ID_PRN_4, galileo_eph_old))
{ {
// Check the EPHEMERIS timestamp. If it is newer, then update the ephemeris // Check the EPHEMERIS timestamp. If it is newer, then update the ephemeris
if (galileo_eph.WN_5 > galileo_eph_old.WN_5) //further check because it is not clear when IOD is reset if (galileo_eph.WN_5 > galileo_eph_old.WN_5) //further check because it is not clear when IOD is reset
{ {
std::cout << "Galileo Ephemeris record in global map updated -- GALILEO Week Number ="<<galileo_eph.WN_5<<std::endl; std::cout << "Galileo Ephemeris record in global map updated -- GALILEO Week Number ="
<< galileo_eph.WN_5 << std::endl;
global_galileo_ephemeris_map.write(galileo_eph.SV_ID_PRN_4,galileo_eph); global_galileo_ephemeris_map.write(galileo_eph.SV_ID_PRN_4,galileo_eph);
}else{ }
else
{
if (galileo_eph.IOD_ephemeris > galileo_eph_old.IOD_ephemeris) if (galileo_eph.IOD_ephemeris > galileo_eph_old.IOD_ephemeris)
{ {
std::cout << "Galileo Ephemeris record updated in global map-- IOD_ephemeris ="<<galileo_eph.IOD_ephemeris<<std::endl; std::cout << "Galileo Ephemeris record updated in global map-- IOD_ephemeris ="
global_galileo_ephemeris_map.write(galileo_eph.SV_ID_PRN_4,galileo_eph); << galileo_eph.IOD_ephemeris << std::endl;
global_galileo_ephemeris_map.write(galileo_eph.SV_ID_PRN_4, galileo_eph);
std::cout << "IOD_ephemeris OLD: " << galileo_eph_old.IOD_ephemeris<<std::endl; std::cout << "IOD_ephemeris OLD: " << galileo_eph_old.IOD_ephemeris << std::endl;
std::cout << "satellite: " << galileo_eph.SV_ID_PRN_4<<std::endl; std::cout << "satellite: " << galileo_eph.SV_ID_PRN_4 << std::endl;
} }
else{ else
std::cout<<"Not updating the existing Galileo ephemeris, IOD is not changing"<<std::endl; {
std::cout << "Not updating the existing Galileo ephemeris, IOD is not changing" << std::endl;
} }
} }
}
// else
}else{ {
// insert new ephemeris record // insert new ephemeris record
std::cout << "Galileo New Ephemeris record inserted in global map with TOW ="<<galileo_eph.TOW_5 std::cout << "Galileo New Ephemeris record inserted in global map with TOW =" << galileo_eph.TOW_5
<<", GALILEO Week Number ="<< galileo_eph.WN_5 << ", GALILEO Week Number =" << galileo_eph.WN_5
<< " and Ephemeris IOD = " << galileo_eph.IOD_ephemeris << std::endl; << " and Ephemeris IOD = " << galileo_eph.IOD_ephemeris << std::endl;
global_galileo_ephemeris_map.write(galileo_eph.SV_ID_PRN_4, galileo_eph); global_galileo_ephemeris_map.write(galileo_eph.SV_ID_PRN_4, galileo_eph);
} }
@ -533,63 +567,66 @@ void ControlThread::galileo_ephemeris_data_collector()
void ControlThread::gps_iono_data_collector() void ControlThread::gps_iono_data_collector()
{ {
// ############ 1.bis READ EPHEMERIS/UTC_MODE/IONO QUEUE #################### // ############ 1.bis READ EPHEMERIS/UTC_MODE/IONO QUEUE ####################
Gps_Iono gps_iono; Gps_Iono gps_iono;
Gps_Iono gps_iono_old; Gps_Iono gps_iono_old;
while(stop_==false) while(stop_ == false)
{ {
global_gps_iono_queue.wait_and_pop(gps_iono); global_gps_iono_queue.wait_and_pop(gps_iono);
std::cout << "New IONO record has arrived " << std::endl;
std::cout << "New IONO record has arrived "<< std::endl;
// insert new ephemeris record to the global ephemeris map // insert new ephemeris record to the global ephemeris map
if (global_gps_iono_map.read(0,gps_iono_old)) if (global_gps_iono_map.read(0, gps_iono_old))
{ {
// TODO: Check the IONO timestamp. If it is newer, then update the iono // TODO: Check the IONO timestamp. If it is newer, then update the iono
global_gps_iono_map.write(0,gps_iono); global_gps_iono_map.write(0, gps_iono);
}else{ }
else
{
// insert new ephemeris record // insert new ephemeris record
global_gps_iono_map.write(0,gps_iono); global_gps_iono_map.write(0 ,gps_iono);
} }
} }
} }
void ControlThread::galileo_iono_data_collector() void ControlThread::galileo_iono_data_collector()
{ {
Galileo_Iono galileo_iono; Galileo_Iono galileo_iono;
Galileo_Iono galileo_iono_old; Galileo_Iono galileo_iono_old;
while(stop_==false) while(stop_ == false)
{ {
global_galileo_iono_queue.wait_and_pop(galileo_iono); global_galileo_iono_queue.wait_and_pop(galileo_iono);
// DEBUG MESSAGE // DEBUG MESSAGE
std::cout << "Iono record has arrived"<<std::endl; std::cout << "Iono record has arrived" << std::endl;
// insert new Iono record to the global Iono map // insert new Iono record to the global Iono map
if (global_galileo_iono_map.read(0,galileo_iono_old)) if (global_galileo_iono_map.read(0, galileo_iono_old))
{ {
// Check the Iono timestamp from UTC page (page 6). If it is newer, then update the Iono parameters // Check the Iono timestamp from UTC page (page 6). If it is newer, then update the Iono parameters
if (galileo_iono.WN_5 > galileo_iono_old.WN_5) if (galileo_iono.WN_5 > galileo_iono_old.WN_5)
{ {
std::cout << "IONO record updated in global map--new GALILEO UTC-IONO Week Number"<< std::endl; std::cout << "IONO record updated in global map--new GALILEO UTC-IONO Week Number" << std::endl;
global_galileo_iono_map.write(0,galileo_iono); global_galileo_iono_map.write(0, galileo_iono);
}else{ }
else
{
if (galileo_iono.TOW_5 > galileo_iono_old.TOW_5) if (galileo_iono.TOW_5 > galileo_iono_old.TOW_5)
{ {
std::cout << "IONO record updated in global map--new GALILEO UTC-IONO time of Week" << std::endl; std::cout << "IONO record updated in global map--new GALILEO UTC-IONO time of Week" << std::endl;
global_galileo_iono_map.write(0,galileo_iono); global_galileo_iono_map.write(0, galileo_iono);
//std::cout << "GALILEO IONO time of Week old: " << galileo_iono_old.t0t_6<<std::endl; //std::cout << "GALILEO IONO time of Week old: " << galileo_iono_old.t0t_6<<std::endl;
} }
else{ else
std::cout<<"Not updating the existing Iono parameters in global map, Iono timestamp is not changing"<<std::endl; {
std::cout << "Not updating the existing Iono parameters in global map, Iono timestamp is not changing" << std::endl;
} }
} }
}
else
}else{ {
// insert new ephemeris record // insert new ephemeris record
std::cout << "New IONO record inserted in global map" << std::endl; std::cout << "New IONO record inserted in global map" << std::endl;
global_galileo_iono_map.write(0, galileo_iono); global_galileo_iono_map.write(0, galileo_iono);
@ -600,60 +637,65 @@ void ControlThread::galileo_iono_data_collector()
void ControlThread::gps_utc_model_data_collector() void ControlThread::gps_utc_model_data_collector()
{ {
// ############ 1.bis READ EPHEMERIS/UTC_MODE/IONO QUEUE #################### // ############ 1.bis READ EPHEMERIS/UTC_MODE/IONO QUEUE ####################
Gps_Utc_Model gps_utc; Gps_Utc_Model gps_utc;
Gps_Utc_Model gps_utc_old; Gps_Utc_Model gps_utc_old;
while(stop_==false) while(stop_ == false)
{ {
global_gps_utc_model_queue.wait_and_pop(gps_utc); global_gps_utc_model_queue.wait_and_pop(gps_utc);
std::cout << "New UTC MODEL record has arrived with A0="<< gps_utc.d_A0<< std::endl; std::cout << "New UTC MODEL record has arrived with A0=" << gps_utc.d_A0 << std::endl;
// insert new ephemeris record to the global ephemeris map // insert new ephemeris record to the global ephemeris map
if (global_gps_utc_model_map.read(0,gps_utc_old)) if (global_gps_utc_model_map.read(0, gps_utc_old))
{ {
// TODO: Check the UTC MODEL timestamp. If it is newer, then update the UTC MODEL // TODO: Check the UTC MODEL timestamp. If it is newer, then update the UTC MODEL
global_gps_utc_model_map.write(0,gps_utc); global_gps_utc_model_map.write(0, gps_utc);
}else{ }
else
{
// insert new ephemeris record // insert new ephemeris record
global_gps_utc_model_map.write(0,gps_utc); global_gps_utc_model_map.write(0, gps_utc);
} }
} }
} }
void ControlThread::galileo_utc_model_data_collector() void ControlThread::galileo_utc_model_data_collector()
{ {
Galileo_Utc_Model galileo_utc; Galileo_Utc_Model galileo_utc;
Galileo_Utc_Model galileo_utc_old; Galileo_Utc_Model galileo_utc_old;
while(stop_==false) while(stop_ == false)
{ {
global_galileo_utc_model_queue.wait_and_pop(galileo_utc); global_galileo_utc_model_queue.wait_and_pop(galileo_utc);
// DEBUG MESSAGE // DEBUG MESSAGE
std::cout << "UTC record has arrived"<<std::endl; std::cout << "UTC record has arrived" << std::endl;
// insert new UTC record to the global UTC map // insert new UTC record to the global UTC map
if (global_galileo_utc_model_map.read(0,galileo_utc_old)) if (global_galileo_utc_model_map.read(0, galileo_utc_old))
{ {
// Check the UTC timestamp. If it is newer, then update the ephemeris // Check the UTC timestamp. If it is newer, then update the ephemeris
if (galileo_utc.WNot_6 > galileo_utc_old.WNot_6) //further check because it is not clear when IOD is reset if (galileo_utc.WNot_6 > galileo_utc_old.WNot_6) //further check because it is not clear when IOD is reset
{ {
//std::cout << "UTC record updated --new GALILEO UTC Week Number ="<<galileo_utc.WNot_6<<std::endl; //std::cout << "UTC record updated --new GALILEO UTC Week Number ="<<galileo_utc.WNot_6<<std::endl;
global_galileo_utc_model_map.write(0,galileo_utc); global_galileo_utc_model_map.write(0, galileo_utc);
}else{ }
else
{
if (galileo_utc.t0t_6 > galileo_utc_old.t0t_6) if (galileo_utc.t0t_6 > galileo_utc_old.t0t_6)
{ {
//std::cout << "UTC record updated --new GALILEO UTC time of Week ="<<galileo_utc.t0t_6<<std::endl; //std::cout << "UTC record updated --new GALILEO UTC time of Week ="<<galileo_utc.t0t_6<<std::endl;
global_galileo_utc_model_map.write(0,galileo_utc); global_galileo_utc_model_map.write(0, galileo_utc);
//std::cout << "GALILEO UTC time of Week old: " << galileo_utc_old.t0t_6<<std::endl; //std::cout << "GALILEO UTC time of Week old: " << galileo_utc_old.t0t_6<<std::endl;
} }
else{ else
std::cout<<"Not updating the existing UTC in global map, timestamp is not changing"<<std::endl; {
std::cout << "Not updating the existing UTC in global map, timestamp is not changing" << std::endl;
} }
} }
}
}else{ else
{
// insert new ephemeris record // insert new ephemeris record
std::cout << "New UTC record inserted in global map" << std::endl; std::cout << "New UTC record inserted in global map" << std::endl;
global_galileo_utc_model_map.write(0, galileo_utc); global_galileo_utc_model_map.write(0, galileo_utc);
@ -661,10 +703,12 @@ void ControlThread::galileo_utc_model_data_collector()
} }
} }
void ControlThread::gps_ephemeris_data_write_to_XML() void ControlThread::gps_ephemeris_data_write_to_XML()
{ {
//Save ephemeris to XML file //Save ephemeris to XML file
std::string eph_xml_filename ="gps_ephemeris_rx.xml"; std::string eph_xml_filename = "gps_ephemeris_rx.xml";
std::map<int,Gps_Ephemeris> eph_copy; std::map<int,Gps_Ephemeris> eph_copy;
eph_copy = global_gps_ephemeris_map.get_map_copy(); eph_copy = global_gps_ephemeris_map.get_map_copy();
@ -685,14 +729,16 @@ void ControlThread::gps_ephemeris_data_write_to_XML()
} }
} }
void ControlThread::gps_utc_model_data_write_to_XML() void ControlThread::gps_utc_model_data_write_to_XML()
{ {
//Save ephemeris to XML file //Save ephemeris to XML file
std::string xml_filename="gps_utc_model_rx.xml"; std::string xml_filename = "gps_utc_model_rx.xml";
std::map<int,Gps_Utc_Model> map_copy; std::map<int,Gps_Utc_Model> map_copy;
map_copy=global_gps_utc_model_map.get_map_copy(); map_copy = global_gps_utc_model_map.get_map_copy();
if (map_copy.size()>0) if (map_copy.size() > 0)
{ {
try try
{ {
@ -700,7 +746,7 @@ void ControlThread::gps_utc_model_data_write_to_XML()
boost::archive::xml_oarchive xml(ofs); boost::archive::xml_oarchive xml(ofs);
xml << boost::serialization::make_nvp("GNSS-SDR_utc_map", map_copy); xml << boost::serialization::make_nvp("GNSS-SDR_utc_map", map_copy);
ofs.close(); ofs.close();
std::cout<<"Saved UTC Model data"<<std::endl; std::cout << "Saved UTC Model data" << std::endl;
} }
catch (std::exception& e) catch (std::exception& e)
{ {
@ -709,15 +755,18 @@ void ControlThread::gps_utc_model_data_write_to_XML()
} }
} }
void ControlThread::gps_iono_data_write_to_XML() void ControlThread::gps_iono_data_write_to_XML()
{ {
//Save ephemeris to XML file //Save ephemeris to XML file
std::string xml_filename="gps_iono_rx.xml"; std::string xml_filename = "gps_iono_rx.xml";
std::map<int,Gps_Iono> map_copy; std::map<int,Gps_Iono> map_copy;
std::map<int,Gps_Iono>::iterator gps_iono_iter; std::map<int,Gps_Iono>::iterator gps_iono_iter;
map_copy=global_gps_iono_map.get_map_copy(); map_copy = global_gps_iono_map.get_map_copy();
if (map_copy.size()>0) if (map_copy.size() > 0)
{ {
try try
{ {
@ -725,7 +774,7 @@ void ControlThread::gps_iono_data_write_to_XML()
boost::archive::xml_oarchive xml(ofs); boost::archive::xml_oarchive xml(ofs);
xml << boost::serialization::make_nvp("GNSS-SDR_iono_map", map_copy); xml << boost::serialization::make_nvp("GNSS-SDR_iono_map", map_copy);
ofs.close(); ofs.close();
std::cout<<"Saved IONO Model data"<<std::endl; std::cout << "Saved IONO Model data" << std::endl;
} }
catch (std::exception& e) catch (std::exception& e)
{ {

View File

@ -68,9 +68,13 @@ public:
/*! \brief Runs the control thread /*! \brief Runs the control thread
* *
* This is the main loop that reads and process the control messages: * This is the main loop that reads and process the control messages:
*
* - Connect the GNSS receiver flowgraph; * - Connect the GNSS receiver flowgraph;
*
* - Start the GNSS receiver flowgraph; * - Start the GNSS receiver flowgraph;
* while (flowgraph_->running() && !stop)_{ *
* while (flowgraph_->running() && !stop_){
*
* - Read control messages and process them; } * - Read control messages and process them; }
*/ */
void run(); void run();
@ -78,7 +82,7 @@ public:
/*! /*!
* \brief Sets the control_queue * \brief Sets the control_queue
* *
* \param[in] gr_msg_queue_sptr control_queue * \param[in] boost::shared_ptr<gr::msg_queue> control_queue
*/ */
void set_control_queue(boost::shared_ptr<gr::msg_queue> control_queue); void set_control_queue(boost::shared_ptr<gr::msg_queue> control_queue);
@ -105,10 +109,7 @@ public:
private: private:
//SUPL assistance classes
/*!
* \brief SUPL assistance classes
*/
gnss_sdr_supl_client supl_client_acquisition_; gnss_sdr_supl_client supl_client_acquisition_;
gnss_sdr_supl_client supl_client_ephemeris_; gnss_sdr_supl_client supl_client_ephemeris_;
int supl_mcc; // Current network MCC (Mobile country code), 3 digits. int supl_mcc; // Current network MCC (Mobile country code), 3 digits.
@ -117,9 +118,8 @@ private:
int supl_ci; // Cell Identity (16 bits, 0-65535 are valid values). int supl_ci; // Cell Identity (16 bits, 0-65535 are valid values).
void init(); void init();
/*
* \brief Read ephemeris assistance from a local XML file previously recorded // Read ephemeris assistance from a local XML file previously recorded
*/
bool read_assistance_from_XML(); bool read_assistance_from_XML();
void read_control_messages(); void read_control_messages();