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);
fir_filter_ccf_ = gr::filter::fir_filter_ccf::make(1, taps_);
DLOG(INFO) << "input_filter(" << fir_filter_ccf_->unique_id() << ")";
}
else
{
LOG_AT_LEVEL(ERROR) << taps_item_type_ << " unknown input filter item type";
}
if (dump_)
{
DLOG(INFO) << "Dumping output into file " << dump_filename_;
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))
{
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_);
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))
{
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_);
DLOG(INFO) << "input_filter(" << freq_xlating_fir_filter_fcf_->unique_id() << ")";
}
else
{
LOG_AT_LEVEL(ERROR) << taps_item_type_ << " unknown input filter item type";
item_size = sizeof(gr_complex); //avoids unitialization
}
if (dump_)
{
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());
}
}
@ -91,10 +92,12 @@ void FreqXlatingFirFilter::connect(gr::top_block_sptr top_block)
{
if (dump_)
{
if (input_size_==sizeof(float))
if (input_size_ == sizeof(float))
{
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);
}
}
@ -110,10 +113,12 @@ void FreqXlatingFirFilter::disconnect(gr::top_block_sptr top_block)
{
if (dump_)
{
if (input_size_==sizeof(float))
if (input_size_ == sizeof(float))
{
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);
}
}
@ -123,10 +128,12 @@ void FreqXlatingFirFilter::disconnect(gr::top_block_sptr top_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_;
}else{
}
else
{
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()
{
if (input_size_==sizeof(float))
if (input_size_ == sizeof(float))
{
return freq_xlating_fir_filter_fcf_;
}else{
}
else
{
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
* to a TelemetryDecoderInterface
* \author Javier Arribas 2013. jarribas(at)cttc.es
* \author Mara Branzanti 2013. mara.branzanti(at)gmail.com
* \author Javier Arribas 2013. jarribas(at)cttc.es,
* 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
* 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
* 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
* \author Javier Arribas 2013 jarribas(at)cttc.es,
* Mara Branzanti 2013. mara.branzanti(at)gmail.com
*
* -------------------------------------------------------------------------
*
@ -59,6 +59,9 @@ public:
return role_;
}
/*!
* \brief Returns "Galileo_E1B_Telemetry_Decoder"
*/
std::string implementation()
{
return "Galileo_E1B_Telemetry_Decoder";

View File

@ -41,9 +41,7 @@
#include "control_message_factory.h"
#include "galileo_navigation_message.h"
#include "gnss_synchro.h"
#include "convolutional.h"
#include <stdio.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)
{
int CodeLength=240;
int CodeLength = 240;
int DataLength;
int nn, KK, mm, max_states;
int g_encoder[2];
nn = 2; //Coding rate 1/n
KK = 7; //Constraint Length
g_encoder[0]=121; // Polynomial G1
g_encoder[1]=91; // Polinomial G2
g_encoder[0] = 121; // Polynomial G1
g_encoder[1] = 91; // Polinomial G2
mm = KK - 1;
max_states = 1 << mm; /* 2^mm */
DataLength = (CodeLength/nn)-mm;
DataLength = (CodeLength/nn) - mm;
/* create appropriate transition matrices */
int *out0, *out1, *state0, *state1;
@ -104,17 +101,16 @@ void galileo_e1b_telemetry_decoder_cc::viterbi_decoder(double *page_part_symbols
free( out1 );
free( state0 );
free( state1 );
}
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;
// 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));
// preamble bits to sampled symbols
d_preambles_symbols = (signed int*)malloc(sizeof(signed int) * d_symbols_per_preamble);
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)
{
@ -173,34 +169,38 @@ galileo_e1b_telemetry_decoder_cc::galileo_e1b_telemetry_decoder_cc(
d_flag_frame_sync = false;
d_flag_parity = false;
d_TOW_at_Preamble= 0;
d_TOW_at_Preamble = 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()
{
delete d_preambles_symbols;
d_dump_file.close();
}
void galileo_e1b_telemetry_decoder_cc::decode_word(double *page_part_symbols,int frame_length)
{
double page_part_symbols_deint[frame_length];
// 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.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º
for (int i=0;i<frame_length;i++)
// 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++)
{
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;
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');
}else{
}
else
{
page_String.push_back('0');
}
}
//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
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;
}else{
std::cout<<"Galileo CRC error on channel "<<d_channel<<std::endl;
std::cout << "Galileo CRC correct 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
{
// STORE HALF WORD (even page)
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
if (d_nav.have_new_ephemeris()==true)
if (d_nav.have_new_ephemeris() == true)
{
// 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;
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;
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;
d_utc_model_queue->push(utc_model);
}
}
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)
{
@ -278,7 +286,7 @@ int galileo_e1b_telemetry_decoder_cc::general_work (int noutput_items, gr_vector
// TODO Optimize me!
//******* 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
{
@ -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;
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)
{
@ -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)
{
//try to decode frame
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_stat=2;
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_stat = 2;
}
else{
if (preamble_diff>GALILEO_INAV_PREAMBLE_PERIOD_SYMBOLS)
else
{
d_stat=0; // start again
}
}
}
}else if (d_stat==2)
if (preamble_diff > GALILEO_INAV_PREAMBLE_PERIOD_SYMBOLS)
{
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
// 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];
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
@ -354,26 +367,28 @@ int galileo_e1b_telemetry_decoder_cc::general_work (int noutput_items, gr_vector
// std::cout<<std::endl;
//end debug
//call the decoder
decode_word(page_part_symbols,frame_length);
if (d_nav.flag_CRC_test==true)
decode_word(page_part_symbols, frame_length);
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_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)
{
d_flag_frame_sync = true;
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_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;
d_flag_frame_sync=false;
d_stat=0;
d_flag_frame_sync = false;
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
current_synchro_data = in[0][0];
//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
//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)
if (d_flag_frame_sync == true and d_nav.flag_TOW_set == true)
{
current_synchro_data.Flag_valid_word = true;
}else{
}
else
{
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_file.exceptions ( std::ifstream::failbit | std::ifstream::badbit );
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)
{
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)
{
d_ephemeris_queue = ephemeris_queue;
}
void galileo_e1b_telemetry_decoder_cc::set_iono_queue(concurrent_queue<Galileo_Iono> *iono_queue)
{
d_iono_queue = iono_queue;
}
void galileo_e1b_telemetry_decoder_cc::set_almanac_queue(concurrent_queue<Galileo_Almanac> *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)
{
d_utc_model_queue = utc_model_queue;

View File

@ -1,8 +1,9 @@
/*!
* \file galileo_e1b_telemetry_decoder_cc.h
* \brief Interface of a Galileo NAV message demodulator block
* \author Javier Arribas 2013. jarribas(at)cttc.es
* \author Mara Branzanti 2013. mara.branzanti(at)gmail.com
* \author Javier Arribas 2013 jarribas(at)cttc.es,
* Mara Branzanti 2013 mara.branzanti(at)gmail.com
*
* -------------------------------------------------------------------------
*
* 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
#define 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
#include "Galileo_E1.h"
@ -38,7 +39,6 @@
#include <bitset>
#include <gnuradio/block.h>
#include <gnuradio/msg_queue.h>
#include "gnuradio/trellis/interleaver.h"
#include "gnuradio/trellis/permutation.h"
#include "gnuradio/fec/viterbi.h"
@ -76,16 +76,20 @@ public:
void set_satellite(Gnss_Satellite satellite); //!< Set satellite PRN
void set_channel(int channel); //!< Set receiver's channel
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,
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);
private:
@ -121,7 +125,6 @@ private:
// navigation message vars
Galileo_Navigation_Message d_nav;
// Galileo ephemeris queue
concurrent_queue<Galileo_Ephemeris> *d_ephemeris_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
* Satellite Systems receiver
@ -103,9 +103,9 @@ gps_l1_ca_telemetry_decoder_cc::gps_l1_ca_telemetry_decoder_cc(
// preamble bits to sampled symbols
d_preambles_symbols = (signed int*)malloc(sizeof(signed int) * GPS_CA_PREAMBLE_LENGTH_BITS * d_samples_per_bit);
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)
{
@ -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.
parity = t ^ _lrotl(t,6) ^ _lrotl(t,12) ^ _lrotl(t,18) ^ _lrotl(t,24);
parity = parity & 0x3F;
if (parity == (gpsword&0x3F)) return(true);
if (parity == (gpsword & 0x3F)) return(true);
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!
//******* 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
{
@ -297,7 +297,7 @@ int gps_l1_ca_telemetry_decoder_cc::general_work (int noutput_items, gr_vector_i
}
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
@ -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
current_synchro_data = in[0][0];
//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_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;
if (flag_TOW_set==false)
if (flag_TOW_set == false)
{
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;
}
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.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_file.exceptions ( std::ifstream::failbit | std::ifstream::badbit );
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)
{
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
* -------------------------------------------------------------------------
*
* 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
* Satellite Systems receiver
@ -39,7 +39,6 @@
#include <bitset>
#include <gnuradio/block.h>
#include <gnuradio/msg_queue.h>
//#include <gnuradio/gr_sync_block.h>
#include "gnss_satellite.h"
@ -62,24 +61,35 @@ public:
~gps_l1_ca_telemetry_decoder_cc();
void set_satellite(Gnss_Satellite satellite); //!< Set satellite PRN
void set_channel(int channel); //!< Set receiver's channel
/*!
* \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_iono_queue(concurrent_queue<Gps_Iono> *iono_queue){d_GPS_FSM.d_iono_queue = iono_queue;}
void set_almanac_queue(concurrent_queue<Gps_Almanac> *almanac_queue){d_GPS_FSM.d_almanac_queue = almanac_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_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;} //!< Set the iono data 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;} //!< 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,
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);
private:
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
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
int vector_length, boost::shared_ptr<gr::msg_queue> queue, bool dump);
bool gps_word_parityCheck(unsigned int gpsword);
// 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));
}
sbas_l1_telemetry_decoder_cc::sbas_l1_telemetry_decoder_cc(
Gnss_Satellite satellite,
long if_freq,
@ -64,7 +66,8 @@ sbas_l1_telemetry_decoder_cc::sbas_l1_telemetry_decoder_cc(
int vector_length,
boost::shared_ptr<gr::msg_queue> queue,
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)))
{
// 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());
DLOG(INFO) << "SBAS L1 TELEMETRY PROCESSING: satellite " << d_satellite;
d_fs_in = fs_in;
d_block_size = d_samples_per_symbol * d_symbols_per_bit * d_block_size_in_bits;
set_output_multiple (1);
}
sbas_l1_telemetry_decoder_cc::~sbas_l1_telemetry_decoder_cc()
{
d_dump_file.close();
}
void sbas_l1_telemetry_decoder_cc::forecast (int noutput_items, gr_vector_int &ninput_items_required)
{
unsigned ninputs = ninput_items_required.size ();
for (unsigned i = 0; i < ninputs; i++)
ninput_items_required[i] = noutput_items;
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,
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];
// get pointers on in- and output gnss-synchro objects
const Gnss_Synchro *in = (const Gnss_Synchro *) input_items[0]; // input
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 =
(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;
double message_sample_stamp = sample_stamp + ((double)message_sample_offset)/1000;
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)
{
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)
{
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++)
{
// get the next samples
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
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"
<< "d_corr_paired: " << std::setw(10) << d_corr_paired << "\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;
}
void sbas_l1_telemetry_decoder_cc::symbol_aligner_and_decoder::reset()
{
d_past_symbol = 0;
@ -313,6 +319,7 @@ void sbas_l1_telemetry_decoder_cc::symbol_aligner_and_decoder::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)
{
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_vd2; // shifted symbol vector -> add past sample in front of input vector
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);
}
@ -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_vd2 = d_vd2->decode_continuous(symbols_vd2.data(), traceback_depth, bits_vd2, nbits_requested, nbits_decoded);
// 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)
{// symbols aligned
@ -399,7 +406,7 @@ void sbas_l1_telemetry_decoder_cc::frame_detector::get_frame_candidates(const st
{
// invert bits
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));
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.process_bytes(candidate_bytes.data(), candidate_bytes.size());
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);
// the final remainder must be zero for a valid message, because the CRC is done over the received CRC value
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!";
}
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
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);
}
@ -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)
{
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;
}
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);
}

View File

@ -59,13 +59,21 @@ public:
void set_channel(int channel); //!< Set receiver's channel
// 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_iono_queue(concurrent_queue<Sbas_Ionosphere_Correction> *iono_queue);
void set_sat_corr_queue(concurrent_queue<Sbas_Satellite_Correction> *sat_corr_queue);
void set_ephemeris_queue(concurrent_queue<Sbas_Ephemeris> *ephemeris_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); //!< Set iono 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); //!< Set SBAS ephemeis queue
/*!
* \brief This is where all signal processing takes place
*/
int general_work (int noutput_items, gr_vector_int &ninput_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);
private:

View File

@ -1,208 +1,214 @@
/* File convolutional.h
Description: General functions used to implement convolutional encoding.
Copyright (C) 2006-2008, Matthew C. Valenti
Last updated on May 22, 2008
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
*/
/*!
* \file convolutional.h
* \brief General functions used to implement convolutional encoding.
* \author Matthew C. Valenti
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2006-2008 Matthew C. Valenti
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* at your option) any later version.
*
* This file is a derived work of the original file, which had this note:
*
* Last updated on May 22, 2008
*
* 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 MAXLOG 1e7 /* Define infinity */
/* function itob()
Description: Converts an integer symbol into a vector of bits
Output parameters:
binvec_p: The binary vector
Input parameters:
symbol: The integer-valued symbol
length: The length of the binary vector
This function is used by conv_encode() */
void itob(
int binvec_p[],
int symbol,
int length )
/*!
* \brief Converts an integer symbol into a vector of bits
*
* \param[out] binvec_p The binary vector
* \param[in] symbol The integer-valued symbol
* \param[in] length The length of the binary vector
*
* This function is used by conv_encode()
*/
void itob(int binvec_p[], int symbol, int length)
{
int counter;
/* Go through each bit in the vector */
for (counter=0;counter<length;counter++) {
binvec_p[length-counter-1] = (symbol&1);
symbol = symbol>>1;
for (counter = 0; counter < length; counter++)
{
binvec_p[length - counter - 1] = (symbol & 1);
symbol = symbol >> 1;
}
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
Input parameters:
symbol: The integer-valued symbol
length: The highest bit position in the symbol
This function is used by nsc_enc_bit(), rsc_enc_bit(), and rsc_tail() */
int parity_counter( int symbol, int length )
/*!
* \brief Determines if a symbol has odd (1) or even (0) parity
* Output parameters:
* \return (returned int): The symbol's parity = 1 for odd and 0 for even
*
* \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()
*/
int parity_counter(int symbol, int length)
{
int counter;
int temp_parity = 0;
for (counter=0;counter<length;counter++) {
temp_parity = temp_parity^(symbol&1);
symbol = symbol>>1;
for (counter = 0; counter < length; counter++)
{
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.
Input parameters:
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).
g[] An n-element vector containing the code generators in binary form.
KK The constraint length of the convolutional code.
Output parameters:
output_p[] An n-element vector containing the encoded bits.
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() */
static int nsc_enc_bit(
int state_out_p[],
/*!
* \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.
*
* \param[in] input The input data bit (i.e. a 0 or 1).
* \param[in] state_in The starting state of the encoder (an int from 0 to 2^m-1).
* \param[in] g[] An n-element vector containing the code generators in binary form.
* \param[in] KK The constraint length of the convolutional code.
* \param[out] output_p[] An n-element vector containing the encoded bits.
* \param[out] 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()
*/
static int nsc_enc_bit(int state_out_p[],
int input,
int state_in,
int g[],
int KK,
int nn )
int nn)
{
/* declare variables */
int state, i;
int out = 0;
int out_ = 0;
/* 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 */
for (i=0;i<nn;i++)
for (i = 0; i < nn; i++)
{
/* 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 */
state_out_p[0] = state>>1;
return(out);
state_out_p[0] = state >> 1;
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 state_in,
int g[],
int KK,
int nn )
int nn)
{
/* declare variables */
int state, i, out, a_k;
int state, i, out_, a_k;
/* systematic output */
out = input;
out_ = input;
/* 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 */
state = (a_k<<(KK-1))^state_in;
state = (a_k << (KK - 1))^state_in;
/* AND the word with the generators */
for (i=1;i<nn;i++)
for (i = 1; i < nn; i++)
{
/* 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 */
state_out_p[0] = state>>1;
return(out);
state_out_p[0] = state >> 1;
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 input,
int g[],
int KK,
int nn )
int nn)
{
int nextstate[1];
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 */
for(state=0;state<states;state++) {
output_p[state] = nsc_enc_bit( nextstate, input, state, g, KK, nn );
for(state = 0; state < states; state++)
{
output_p[state] = nsc_enc_bit(nextstate, input, state, g, KK, nn);
trans_p[state] = nextstate[0];
}
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.
g[] A two element vector containing the code generators.
KK The constraint length of the convolutional code.
Output parameters:
output_p[] A vector of length max_states = 2^(KK-1) containing
the output symbols.
trans_p[] A vector of length max_states that tells the decoder
what the next state will be given the input and current state.
This function is used by turbo_decode() */
static void rsc_transit(
int output_p[],
/*!
* \brief 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.
*
* \param[in] input Either 0 or 1 --- the input data bit.
* \param[in] g[] A two element vector containing the code generators.
* \param[in] KK The constraint length of the convolutional code.
* \param[out] output_p[] A vector of length max_states = 2^(KK-1) containing
* the output symbols.
* \param[out] trans_p[] A vector of length max_states that tells the decoder
* what the next state will be given the input and current state.
*
* This function is used by turbo_decode()
*/
static void rsc_transit(int output_p[],
int trans_p[],
int input,
int g[],
@ -212,19 +218,23 @@ static void rsc_transit(
int nextstate[1];
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 */
for(state=0;state<states;state++) {
// Determine the output and next state for each possible starting state
for(state = 0; state < states; state++)
{
output_p[state] = rsc_enc_bit( nextstate, input, state, g, KK, nn );
trans_p[state] = nextstate[0];
}
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 max_states,
int mm )
@ -232,16 +242,20 @@ static void rsc_tail(
int state;
/* Determine the tail for each state */
for(state=0;state<max_states;state++) {
for(state = 0; state < max_states; state++)
{
/* determine feedback word */
tail_p[state] = parity_counter( g[0]&state, mm );
tail_p[state] = parity_counter(g[0]&state, mm);
}
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 out0[],
int state0[],
@ -250,7 +264,7 @@ static void conv_encode(
int tail[],
int KK,
int LL,
int nn )
int nn)
{
int i, j, outsym;
int *bin_vec;
@ -259,12 +273,17 @@ static void conv_encode(
/* Negative value in "tail" is a flag that this is
a tail-biting NSC code. Determine initial state */
if ( tail[0] < 0 ) {
for (i=LL-KK+1;i<LL;i++) {
if (input[i]) {
if ( tail[0] < 0 )
{
for (i = LL - KK + 1; i < LL; i++)
{
if (input[i])
{
/* Determine next state */
state = state1[state];
} else {
}
else
{
/* Determine next state */
state = state0[state];
}
@ -274,14 +293,18 @@ static void conv_encode(
bin_vec = (int*)calloc( nn, sizeof(int) );
/* encode data bits one bit at a time */
for (i=0;i<LL;i++) {
if (input[i]) {
for (i = 0; i < LL; i++)
{
if (input[i])
{
/* Input is a one */
outsym = out1[state]; /* The output symbol */
/* Determine next state */
state = state1[state];
} else {
}
else
{
/* Input is a zero */
outsym = out0[state]; /* The output symbol */
@ -293,20 +316,25 @@ static void conv_encode(
itob( bin_vec, outsym, nn );
/* Assign to output */
for (j=0;j<nn;j++)
output_p[nn*i+j] = bin_vec[j];
for (j = 0; j < nn; j++)
output_p[nn*i + j] = bin_vec[j];
}
/* encode tail if needed */
if (tail[0] >= 0) {
for (i=LL;i<LL+KK-1;i++) {
if (tail[state]) {
if (tail[0] >= 0)
{
for (i = LL; i < LL + KK - 1; i++)
{
if (tail[state])
{
/* Input is a one */
outsym = out1[state]; /* The output symbol */
/* Determine next state */
state = state1[state];
} else {
}
else
{
/* Input is a zero */
outsym = out0[state]; /* The output symbol */
@ -318,71 +346,56 @@ static void conv_encode(
itob( bin_vec, outsym, nn );
/* Assign to output */
for (j=0;j<nn;j++)
output_p[nn*i+j] = bin_vec[j];
for (j = 0; j < nn; j++)
output_p[nn*i + j] = bin_vec[j];
}
}
free(bin_vec);
return;
}
/* function Gamma()
Description: Computes the branch metric used for decoding.
Output parameters:
(returned float) The metric between the hypothetical symbol and the recevieved vector
Input parameters:
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() */
/*!
* \brief 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
* \param[in] symbol The hypothetical symbol
* \param[in] nn The length of the received vector
*
* This function is used by siso()
*/
static float Gamma(float rec_array[],
int symbol,
int nn )
int nn)
{
float rm = 0;
int i;
int mask;
int mask = 1;
mask = 1;
for (i=0;i<nn;i++) {
if (symbol&mask)
rm += rec_array[nn-i-1];
mask = mask<<1;
for (i = 0; i < nn; i++)
{
if (symbol & mask)
rm += rec_array[nn - i - 1];
mask = mask << 1;
}
return(rm);
}
/* Function Viterbi()
Description: Uses the Viterbi algorithm to perform hard-decision decoding of a convolutional code.
Input parameters:
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).
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).
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.
LL The number of data bits.
Output parameters:
output_u_int[] Hard decisions on the data bits
*/
static void Viterbi(
int output_u_int[],
/*!
* \brief 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).
* \param[in] out1[] The output bits for each state if input is a 1 (generated by rsc_transit).
* \param[in] state1[] The next state if input is a 1 (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).
* \param[in] KK The constraint length of the convolutional code.
* \param[in] LL The number of data bits.
* \param[out] output_u_int[] Hard decisions on the data bits
*
*/
static void Viterbi(int output_u_int[],
int out0[],
int state0[],
int out1[],
@ -390,8 +403,7 @@ static void Viterbi(
double input_c[],
int KK,
int nn,
int LL
)
int LL)
{
int i, t, state, mm, states;
int number_symbols;
@ -404,66 +416,73 @@ static void Viterbi(
float max_val;
/* some derived constants */
mm = KK-1;
mm = KK - 1;
states = 1 << mm; /* 2^mm */
number_symbols = 1 << nn; /* 2^nn */
/* dynamically allocate memory */
prev_section = (float*)calloc( states, sizeof(float) );
next_section = (float*)calloc( states, sizeof(float) );
prev_bit = (int*)calloc( states*(LL+mm), sizeof(int) );
prev_state = (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) );
rec_array = (float*)calloc( nn, sizeof(float) );
metric_c = (float*)calloc( number_symbols, sizeof(float) );
/* initialize trellis */
for (state=0;state<states;state++) {
for (state = 0; state < states; state++)
{
prev_section[state] = -MAXLOG;
next_section[state] = -MAXLOG;
}
prev_section[0] = 0; /* start in all-zeros state */
/* go through trellis */
for (t=0;t<LL+mm;t++) {
for (i=0;i<nn;i++)
rec_array[i] = (float)input_c[nn*t+i];
for (t = 0; t < LL + mm; t++)
{
for (i = 0; i < nn; i++)
rec_array[i] = (float)input_c[nn*t + i];
/* 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 );
/* step through all states */
for (state=0;state<states;state++) {
for (state = 0; state < states; state++)
{
/* hypothesis: info bit is a zero */
metric = prev_section[state] + metric_c[ out0[ state ] ];
/* 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;
prev_state[t*states+state0[state]] = state;
prev_bit[t*states+state0[state]] = 0;
prev_state[t*states + state0[state]] = state;
prev_bit[t*states + state0[state]] = 0;
}
/* hypothesis: info bit is a one */
metric = prev_section[state] + metric_c[ out1[ state ] ];
/* 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;
prev_state[t*states+state1[state]] = state;
prev_bit[t*states+state1[state]] = 1;
prev_state[t*states + state1[state]] = state;
prev_bit[t*states + state1[state]] = 1;
}
}
/* normalize */
max_val = 0;
for (state=0;state<states;state++) {
if (next_section[state]>max_val){
for (state = 0; state < states; state++)
{
if (next_section[state] > max_val)
{
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;
next_section[state] = -MAXLOG;
}
@ -473,13 +492,15 @@ static void Viterbi(
state = 0;
/* tail, no need to output */
for (t=LL+mm-1; t>=LL; t--) {
state = prev_state[t*states+state];
for (t = LL + mm - 1; t >= LL; t--)
{
state = prev_state[t*states + state];
}
for (t=LL-1; t>=0; t--) {
output_u_int[t] = prev_bit[t*states+state];
state = prev_state[t*states+state];
for (t = LL - 1; t >= 0; t--)
{
output_u_int[t] = prev_bit[t*states + state];
state = prev_state[t*states + state];
}
/* free the dynamically allocated memory */
@ -489,31 +510,24 @@ static void Viterbi(
free(prev_state);
free(rec_array);
free(metric_c);
}
/* Function ViterbiTb()
Description: Uses the Viterbi algorithm to perform hard-decision decoding of a tail-biting convolutional code.
Input parameters:
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).
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).
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.
LL The number of data bits.
depth head and tail decoding length [Ref. W. Sung, Electronics Letters, vol. 36, no. 7]
Output parameters:
output_u_int[] Hard decisions on the data bits
*/
static void ViterbiTb(
int output_u_int[],
/*!
* \brief Uses the Viterbi algorithm to perform hard-decision decoding of a tail-biting convolutional code.
* Input parameters:
* 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).
* 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).
* 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.
* LL The number of data bits.
* depth head and tail decoding length [Ref. W. Sung, Electronics Letters, vol. 36, no. 7]
* Output parameters:
* output_u_int[] Hard decisions on the data bits
*/
static void ViterbiTb(int output_u_int[],
int out0[],
int state0[],
int out1[],
@ -522,8 +536,7 @@ static void ViterbiTb(
int KK,
int nn,
int LL,
int depth
)
int depth)
{
int i, t, state, mm, states, max_state;
int number_symbols, starting_bit;
@ -536,51 +549,54 @@ static void ViterbiTb(
float max_val;
/* some derived constants */
mm = KK-1;
mm = KK - 1;
states = 1 << mm; /* 2^mm */
number_symbols = 1 << nn; /* 2^nn */
/* dynamically allocate memory */
prev_section = (float*)calloc( states, sizeof(float) );
next_section = (float*)calloc( states, sizeof(float) );
prev_bit = (int*)calloc( states*(LL+depth), sizeof(int) );
prev_state = (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) );
rec_array = (float*)calloc( nn, sizeof(float) );
metric_c = (float*)calloc( number_symbols, sizeof(float) );
/* initialize trellis */
for (state=0;state<states;state++) {
for (state = 0; state < states; state++)
{
prev_section[state] = 0; /* equally likely starting state */
next_section[state] = -MAXLOG;
}
/* go through trellis */
for (t=-depth;t<LL+depth;t++) {
for (t = -depth; t < LL + depth; t++)
{
/* determine the corresponding data bits */
starting_bit = nn*(t%LL);
starting_bit = nn*(t % LL);
if (starting_bit < 0 )
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];
/* printf( "%1f\n", rec_array[i] ); */
}
/* 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 );
/* step through all states */
for (state=0;state<states;state++) {
for (state = 0; state < states; state++)
{
/* hypothesis: info bit is a zero */
metric = prev_section[state] + metric_c[ out0[ state ] ];
/* 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;
if (t>=0) {
if (t >= 0)
{
prev_state[t*states+state0[state]] = state;
prev_bit[t*states+state0[state]] = 0;
}
@ -590,9 +606,11 @@ static void ViterbiTb(
metric = prev_section[state] + metric_c[ out1[ state ] ];
/* 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;
if (t>=0) {
if (t >= 0)
{
prev_state[t*states+state1[state]] = state;
prev_bit[t*states+state1[state]] = 1;
}
@ -601,13 +619,16 @@ static void ViterbiTb(
/* normalize */
max_val = 0;
for (state=0;state<states;state++) {
if (next_section[state]>max_val){
for (state = 0; state < states; state++)
{
if (next_section[state] > max_val)
{
max_val = next_section[state];
max_state = state;
}
}
for (state=0;state<states;state++) {
for (state = 0; state < states; state++)
{
prev_section[state] = next_section[state] - max_val;
next_section[state] = -MAXLOG;
}
@ -617,13 +638,15 @@ static void ViterbiTb(
state = max_state;
/* tail, no need to output */
for (t=LL+depth-1; t>=LL; t--) {
state = prev_state[t*states+state];
for (t = LL + depth - 1; t >= LL; t--)
{
state = prev_state[t*states + state];
}
for (t=LL-1; t>=0; t--) {
output_u_int[t] = prev_bit[t*states+state];
state = prev_state[t*states+state];
for (t = LL - 1; t >= 0; t--)
{
output_u_int[t] = prev_bit[t*states + state];
state = prev_state[t*states + state];
}
/* free the dynamically allocated memory */
@ -633,5 +656,4 @@ static void ViterbiTb(
free(prev_state);
free(rec_array);
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
* Satellite Systems receiver
@ -232,18 +232,24 @@ GpsL1CaSubframeFsm::GpsL1CaSubframeFsm()
initiate(); //start the FSM
}
void GpsL1CaSubframeFsm::gps_word_to_subframe(int position)
{
// 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);
}
void GpsL1CaSubframeFsm::gps_subframe_to_nav_msg()
{
int subframe_ID;
// NEW GPS SUBFRAME HAS ARRIVED!
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_channel_ID = i_channel_ID;
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)
{
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)
Gps_Ephemeris ephemeris=d_nav.get_ephemeris();
Gps_Ephemeris ephemeris = d_nav.get_ephemeris();
d_ephemeris_queue->push(ephemeris);
}
break;
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);
}
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);
}
break;
@ -279,11 +285,15 @@ void GpsL1CaSubframeFsm::gps_subframe_to_nav_msg()
}
}
void GpsL1CaSubframeFsm::Event_gps_word_valid()
{
this->process_event(Ev_gps_word_valid());
}
void GpsL1CaSubframeFsm::Event_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_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 >
{
public:
GpsL1CaSubframeFsm(); //!< The constructor starts the Finite State Machine
// channel and satellite info
int i_channel_ID;
unsigned int i_satellite_PRN;
int i_channel_ID; //!< Channel id
unsigned int i_satellite_PRN; //!< Satellite PRN number
// ephemeris queue
concurrent_queue<Gps_Ephemeris> *d_ephemeris_queue;
// ionospheric parameters queue
concurrent_queue<Gps_Iono> *d_iono_queue;
// UTC model parameters queue
concurrent_queue<Gps_Utc_Model> *d_utc_model_queue;
// Almanac queue
concurrent_queue<Gps_Almanac> *d_almanac_queue;
concurrent_queue<Gps_Ephemeris> *d_ephemeris_queue; //!< Ephemeris queue
concurrent_queue<Gps_Iono> *d_iono_queue; //!< Ionospheric parameters queue
concurrent_queue<Gps_Utc_Model> *d_utc_model_queue; //!< UTC model parameters queue
concurrent_queue<Gps_Almanac> *d_almanac_queue; //!< Almanac queue
// navigation message class
Gps_Navigation_Message d_nav;
Gps_Navigation_Message d_nav; //!< GPS L1 C/A navigation message object
// GPS SV and System parameters
Gps_Ephemeris ephemeris;
Gps_Almanac almanac;
Gps_Utc_Model utc_model;
Gps_Iono iono;
Gps_Ephemeris ephemeris; //!< Object that handles GPS ephemeris parameters
Gps_Almanac almanac; //!< Object that handles GPS almanac data
Gps_Utc_Model utc_model; //!< Object that handles UTM model parameters
Gps_Iono iono; //!< Object that handles ionospheric parameters
char d_subframe[GPS_SUBFRAME_LENGTH];
char d_GPS_frame_4bytes[GPS_WORD_LENGTH];
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();
//FSM EVENTS
void Event_gps_word_valid();
void Event_gps_word_invalid();
void Event_gps_word_preamble();
GpsL1CaSubframeFsm();
void Event_gps_word_valid(); //!< FSM event: the received word is valid
void Event_gps_word_invalid(); //!< FSM event: the received word is not valid
void Event_gps_word_preamble(); //!< FSM event: word preamble detected
};
#endif

View File

@ -47,7 +47,6 @@
Viterbi_Decoder::Viterbi_Decoder(const int g_encoder[], const int KK, const int nn)
{
d_nn = nn; //Coding rate 1/n
d_KK = KK; //Constraint Length
@ -84,27 +83,25 @@ Viterbi_Decoder::~Viterbi_Decoder()
delete[] d_metric_c;
}
void
Viterbi_Decoder::reset()
void Viterbi_Decoder::reset()
{
init_trellis_state();
}
/* Function decode_block()
Description: Uses the Viterbi algorithm to perform hard-decision decoding of a convolutional code.
Input parameters:
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)
Output parameters:
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 decoding_length_mismatch;
@ -125,9 +122,13 @@ Viterbi_Decoder::decode_block(const double input_c[], int output_u_int[], const
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 decoding_length_mismatch;
@ -150,11 +151,11 @@ Viterbi_Decoder::decode_continuous(const double sym[], const int traceback_depth
return d_indicator_metric;
}
void
Viterbi_Decoder::init_trellis_state()
void Viterbi_Decoder::init_trellis_state()
{
int state;
// if trellis state has been initialised, free old state memory
if(d_trellis_state_is_initialised)
{
@ -182,8 +183,10 @@ Viterbi_Decoder::init_trellis_state()
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;
float metric;
@ -202,11 +205,9 @@ Viterbi_Decoder::do_acs(const double sym[], int nbits)
pm_t_next[state_at_t] = -MAXLOG;
}
/* go through trellis */
for (t = 0; t < nbits; t++)
{
/* Temporarily store the received symbols current decoding step */
for (i = 0; i < d_nn; 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 */
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_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);
/* normalize -> afterwards, the largest metric value is always 0 */
//max_val = 0;
max_val = -MAXLOG;
@ -275,14 +274,14 @@ Viterbi_Decoder::do_acs(const double sym[], int nbits)
}
}
delete[] pm_t_next;
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
int state;
@ -303,17 +302,17 @@ Viterbi_Decoder::do_traceback(size_t traceback_length)
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 t_out;
std::deque<Prev>::iterator it;
int decoding_length_mismatch;
int overstep_length;
int n_im=0;
int n_im = 0;
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;
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);
}
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;
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);
state = it->get_anchestor_state_of_current_state(state);
t_out--;
}
indicator_metric/=n_im;
indicator_metric /= n_im;
VLOG(BLOCK) << "indicator metric: " << indicator_metric;
// 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;
}
/* function Gamma()
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() */
int
Viterbi_Decoder::nsc_enc_bit(int state_out_p[], int input, int state_in,
int Viterbi_Decoder::nsc_enc_bit(int state_out_p[], int input, int state_in,
const int g[], int KK, int nn)
{
/* 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() */
int
Viterbi_Decoder::parity_counter(int symbol, int length)
int Viterbi_Decoder::parity_counter(int symbol, int length)
{
int counter;
int temp_parity = 0;
for (counter = 0; counter < length; counter++)
{
temp_parity = temp_parity ^ (symbol & 1);
symbol = symbol >> 1;
}
return (temp_parity);
}
@ -486,27 +483,26 @@ Viterbi_Decoder::Prev::Prev(int states, int t)
state = new int[states];
bit = new int[states];
metric = new float[states];
refcount = new int;
*refcount = 1;
//std::cout << "Prev(" << states << ", " << t << ")" << " constructor" << std::endl;
}
// copy constructor
Viterbi_Decoder::Prev::Prev(const Prev& prev)
{
refcount = prev.refcount;
(*refcount)++;
t = prev.t;
state = prev.state;
bit = prev.bit;
metric = prev.metric;
VLOG(LMORE) << "Prev(" << "?" << ", " << t << ")" << " copy, new refcount = " << *refcount;
}
// assignment constructor
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
if(*refcount==1)
if(*refcount == 1)
{ // if they are not used anymore -> unallocate them
delete[] state;
delete[] bit;
@ -543,6 +539,9 @@ Viterbi_Decoder::Prev& Viterbi_Decoder::Prev::operator=(const Prev& other)
return *this;
}
Viterbi_Decoder::Prev::~Prev()
{
if (*refcount == 1)
@ -560,12 +559,16 @@ Viterbi_Decoder::Prev::~Prev()
}
}
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;
return state[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;

View File

@ -29,8 +29,8 @@
* -------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_VITERBIDECODER_H_
#define GNSS_SDR_VITERBIDECODER_H_
#ifndef GNSS_SDR_VITERBI_DECODER_H_
#define GNSS_SDR_VITERBI_DECODER_H_
#include <deque>
#include <iostream>
@ -41,12 +41,22 @@ public:
Viterbi_Decoder(const int g_encoder[], const int KK, const int nn);
~Viterbi_Decoder();
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_continuous(const double sym[], const int traceback_depth, int output_u_int[],
const int nbits_requested, int &nbits_decoded);
private:
class Prev
{
public:
@ -111,4 +121,4 @@ private:
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
* Satellite Systems receiver
@ -38,12 +38,10 @@
#include "gps_iono.h"
#include "gps_utc_model.h"
#include "gps_almanac.h"
#include "galileo_ephemeris.h"
#include "galileo_iono.h"
#include "galileo_utc_model.h"
#include "galileo_almanac.h"
#include "concurrent_queue.h"
#include "concurrent_map.h"
#include <unistd.h>
@ -155,14 +153,14 @@ void ControlThread::run()
keyboard_thread_ = boost::thread(&ControlThread::keyboard_listener, this);
//start the GNSS SV data collector thread
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_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_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_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);
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_utc_model_data_collector_thread_ =boost::thread(&ControlThread::galileo_utc_model_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_utc_model_data_collector_thread_ = boost::thread(&ControlThread::galileo_utc_model_data_collector, this);
// Main loop to read and process the control messages
while (flowgraph_->running() && !stop_)
{
@ -170,7 +168,7 @@ void ControlThread::run()
read_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();
// 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()
{
std::string eph_xml_filename="gps_ephemeris.xml";
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)
std::string eph_xml_filename = "gps_ephemeris.xml";
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)
{
std::map<int,Gps_Ephemeris>::iterator gps_eph_iter;
for(gps_eph_iter = supl_client_ephemeris_.gps_ephemeris_map.begin();
gps_eph_iter != supl_client_ephemeris_.gps_ephemeris_map.end();
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);
}
return false;
}else{
std::cout<< "ERROR: SUPL client error reading XML"<<std::endl;
std::cout<< "Disabling SUPL assistance.."<<std::endl;
}
else
{
std::cout << "ERROR: SUPL client error reading XML" << std::endl;
std::cout << "Disabling SUPL assistance.." << std::endl;
return false;
}
}
void ControlThread::init()
{
// Instantiates a control queue, a GNSS flowgraph, and a control message factory
@ -234,134 +237,150 @@ void ControlThread::init()
processed_control_messages_ = 0;
applied_actions_ = 0;
//#########GNSS Asistence #################################
//######### GNSS Assistance #################################
// GNSS Assistance configuration
bool enable_gps_supl_assistance=configuration_->property("GNSS-SDR.SUPL_gps_enabled",false);
if (enable_gps_supl_assistance==true)
bool enable_gps_supl_assistance = configuration_->property("GNSS-SDR.SUPL_gps_enabled", false);
if (enable_gps_supl_assistance == true)
//SUPL SERVER TEST. Not operational yet!
{
std::cout<< "SUPL RRLP GPS assistance enabled!"<<std::endl;
std::string default_acq_server="supl.nokia.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_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_acquisition_.server_port=configuration_->property("GNSS-SDR.SUPL_gps_acquisition_port",7275);
supl_mcc=configuration_->property("GNSS-SDR.SUPL_MCC",244);
supl_mns=configuration_->property("GNSS-SDR.SUPL_MNS",5);
std::cout << "SUPL RRLP GPS assistance enabled!" << std::endl;
std::string default_acq_server = "supl.nokia.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_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_acquisition_.server_port = configuration_->property("GNSS-SDR.SUPL_gps_acquisition_port", 7275);
supl_mcc = configuration_->property("GNSS-SDR.SUPL_MCC", 244);
supl_mns = configuration_->property("GNSS-SDR.SUPL_MNS", 5);
std::string default_lac="0x59e2";
std::string default_ci="0x31b0";
try {
supl_lac = boost::lexical_cast<int>(configuration_->property("GNSS-SDR.SUPL_LAC",default_lac));
} catch(boost::bad_lexical_cast &) {
supl_lac=0x59e2;
std::string default_lac = "0x59e2";
std::string default_ci = "0x31b0";
try
{
supl_lac = boost::lexical_cast<int>(configuration_->property("GNSS-SDR.SUPL_LAC", default_lac));
}
try {
supl_ci = boost::lexical_cast<int>(configuration_->property("GNSS-SDR.SUPL_CI",default_ci));
} catch(boost::bad_lexical_cast &) {
supl_ci=0x31b0;
catch(boost::bad_lexical_cast &)
{
supl_lac = 0x59e2;
}
bool SUPL_read_gps_assistance_xml=configuration_->property("GNSS-SDR.SUPL_read_gps_assistance_xml",false);
if (SUPL_read_gps_assistance_xml==true)
try
{
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_XML();
}else{
}
else
{
// Request ephemeris from SUPL server
int error;
supl_client_ephemeris_.request=1;
std::cout<< "SUPL: Try read GPS ephemeris from SUPL server.."<<std::endl;
error=supl_client_ephemeris_.get_assistance(supl_mcc,supl_mns,supl_lac,supl_ci);
if (error==0)
supl_client_ephemeris_.request = 1;
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);
if (error == 0)
{
std::map<int,Gps_Ephemeris>::iterator gps_eph_iter;
for(gps_eph_iter = supl_client_ephemeris_.gps_ephemeris_map.begin();
gps_eph_iter != supl_client_ephemeris_.gps_ephemeris_map.end();
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);
}
//Save ephemeris to XML file
std::string eph_xml_filename="gps_ephemeris.xml";
if (supl_client_ephemeris_.save_ephemeris_xml(eph_xml_filename)==true)
std::string eph_xml_filename = "gps_ephemeris.xml";
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;
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)
}
else
{
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
supl_client_ephemeris_.request=0;
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);
if (error==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;
error = supl_client_ephemeris_.get_assistance(supl_mcc, supl_mns, supl_lac, supl_ci);
if (error == 0)
{
std::map<int,Gps_Almanac>::iterator gps_alm_iter;
for(gps_alm_iter = supl_client_ephemeris_.gps_almanac_map.begin();
gps_alm_iter != supl_client_ephemeris_.gps_almanac_map.end();
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);
}
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);
}
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);
}
}else{
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;
}
else
{
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
supl_client_acquisition_.request=2;
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);
if (error==0)
supl_client_acquisition_.request = 2;
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);
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();
gps_acq_iter != supl_client_acquisition_.gps_acq_map.end();
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);
}
}else{
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;
}
else
{
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()
{
DLOG(INFO) << "Reading control messages from queue";
boost::shared_ptr<gr::message> queue_message = control_queue_->delete_head();
if (queue_message != 0)
{
control_messages_ = control_message_factory_->GetControlMessages(
queue_message);
control_messages_ = control_message_factory_->GetControlMessages(queue_message);
}
else
{
@ -383,8 +402,7 @@ void ControlThread::process_control_messages()
}
else
{
flowgraph_->apply_action(control_messages_->at(i)->who,
control_messages_->at(i)->what);
flowgraph_->apply_action(control_messages_->at(i)->who, control_messages_->at(i)->what);
}
delete control_messages_->at(i);
processed_control_messages_++;
@ -411,30 +429,37 @@ void ControlThread::apply_action(unsigned int what)
}
}
void ControlThread::gps_acq_assist_data_collector()
{
// ############ 1.bis READ EPHEMERIS/UTC_MODE/IONO QUEUE ####################
Gps_Acq_Assist gps_acq;
Gps_Acq_Assist gps_acq_old;
while(stop_==false)
while(stop_ == false)
{
global_gps_acq_assist_queue.wait_and_pop(gps_acq);
// DEBUG MESSAGE
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
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
std::cout << "New acq assist record inserted"<<std::endl;
global_gps_acq_assist_map.write(gps_acq.i_satellite_PRN,gps_acq);
std::cout << "New acq assist record inserted" << std::endl;
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()
{
// ############ 1.bis READ EPHEMERIS/UTC_MODE/IONO QUEUE ####################
Gps_Ephemeris gps_eph;
Gps_Ephemeris gps_eph_old;
while(stop_==false)
while(stop_ == false)
{
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]
<< ")" << std::endl;
// 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
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;
global_gps_ephemeris_map.write(gps_eph.i_satellite_PRN,gps_eph);
}else{
if (gps_eph.d_Toe>gps_eph_old.d_Toe)
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);
}
else
{
std::cout << "Ephemeris record updated (Toe="<<gps_eph.d_Toe<<std::endl;
global_gps_ephemeris_map.write(gps_eph.i_satellite_PRN,gps_eph);
}else{
std::cout<<"Not updating the existing ephemeris"<<std::endl;
if (gps_eph.d_Toe > gps_eph_old.d_Toe)
{
std::cout << "Ephemeris record updated (Toe=" << gps_eph.d_Toe << 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
std::cout << "New Ephemeris record inserted with Toe="<<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);
std::cout << "New Ephemeris record inserted with Toe="
<< 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()
{
// ############ 1.bis READ EPHEMERIS/UTC_MODE/IONO QUEUE ####################
Galileo_Ephemeris galileo_eph;
Galileo_Ephemeris galileo_eph_old;
while(stop_==false)
while(stop_ == false)
{
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;
// 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
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);
}else{
}
else
{
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;
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 << "satellite: " << galileo_eph.SV_ID_PRN_4<<std::endl;
std::cout << "Galileo Ephemeris record updated in global map-- IOD_ephemeris ="
<< 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 << "satellite: " << galileo_eph.SV_ID_PRN_4 << std::endl;
}
else{
std::cout<<"Not updating the existing Galileo ephemeris, IOD is not changing"<<std::endl;
else
{
std::cout << "Not updating the existing Galileo ephemeris, IOD is not changing" << std::endl;
}
}
//
}else{
}
else
{
// insert new ephemeris record
std::cout << "Galileo New Ephemeris record inserted in global map with TOW ="<<galileo_eph.TOW_5
<<", GALILEO Week Number ="<< galileo_eph.WN_5
std::cout << "Galileo New Ephemeris record inserted in global map with TOW =" << galileo_eph.TOW_5
<< ", GALILEO Week Number =" << galileo_eph.WN_5
<< " and Ephemeris IOD = " << galileo_eph.IOD_ephemeris << std::endl;
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()
{
// ############ 1.bis READ EPHEMERIS/UTC_MODE/IONO QUEUE ####################
Gps_Iono gps_iono;
Gps_Iono gps_iono_old;
while(stop_==false)
while(stop_ == false)
{
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
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
global_gps_iono_map.write(0,gps_iono);
}else{
global_gps_iono_map.write(0, gps_iono);
}
else
{
// 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()
{
Galileo_Iono galileo_iono;
Galileo_Iono galileo_iono_old;
while(stop_==false)
while(stop_ == false)
{
global_galileo_iono_queue.wait_and_pop(galileo_iono);
// 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
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
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;
global_galileo_iono_map.write(0,galileo_iono);
}else{
std::cout << "IONO record updated in global map--new GALILEO UTC-IONO Week Number" << std::endl;
global_galileo_iono_map.write(0, galileo_iono);
}
else
{
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;
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;
}
else{
std::cout<<"Not updating the existing Iono parameters in global map, Iono timestamp is not changing"<<std::endl;
else
{
std::cout << "Not updating the existing Iono parameters in global map, Iono timestamp is not changing" << std::endl;
}
}
}else{
}
else
{
// insert new ephemeris record
std::cout << "New IONO record inserted in global map" << std::endl;
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()
{
// ############ 1.bis READ EPHEMERIS/UTC_MODE/IONO QUEUE ####################
Gps_Utc_Model gps_utc;
Gps_Utc_Model gps_utc_old;
while(stop_==false)
while(stop_ == false)
{
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
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
global_gps_utc_model_map.write(0,gps_utc);
}else{
global_gps_utc_model_map.write(0, gps_utc);
}
else
{
// 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()
{
Galileo_Utc_Model galileo_utc;
Galileo_Utc_Model galileo_utc_old;
while(stop_==false)
while(stop_ == false)
{
global_galileo_utc_model_queue.wait_and_pop(galileo_utc);
// 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
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
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;
global_galileo_utc_model_map.write(0,galileo_utc);
}else{
global_galileo_utc_model_map.write(0, galileo_utc);
}
else
{
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;
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;
}
else{
std::cout<<"Not updating the existing UTC in global map, timestamp is not changing"<<std::endl;
else
{
std::cout << "Not updating the existing UTC in global map, timestamp is not changing" << std::endl;
}
}
}else{
}
else
{
// insert new ephemeris record
std::cout << "New UTC record inserted in global map" << std::endl;
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()
{
//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;
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()
{
//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;
map_copy=global_gps_utc_model_map.get_map_copy();
if (map_copy.size()>0)
map_copy = global_gps_utc_model_map.get_map_copy();
if (map_copy.size() > 0)
{
try
{
@ -700,7 +746,7 @@ void ControlThread::gps_utc_model_data_write_to_XML()
boost::archive::xml_oarchive xml(ofs);
xml << boost::serialization::make_nvp("GNSS-SDR_utc_map", map_copy);
ofs.close();
std::cout<<"Saved UTC Model data"<<std::endl;
std::cout << "Saved UTC Model data" << std::endl;
}
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()
{
//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>::iterator gps_iono_iter;
map_copy=global_gps_iono_map.get_map_copy();
if (map_copy.size()>0)
map_copy = global_gps_iono_map.get_map_copy();
if (map_copy.size() > 0)
{
try
{
@ -725,7 +774,7 @@ void ControlThread::gps_iono_data_write_to_XML()
boost::archive::xml_oarchive xml(ofs);
xml << boost::serialization::make_nvp("GNSS-SDR_iono_map", map_copy);
ofs.close();
std::cout<<"Saved IONO Model data"<<std::endl;
std::cout << "Saved IONO Model data" << std::endl;
}
catch (std::exception& e)
{

View File

@ -68,9 +68,13 @@ public:
/*! \brief Runs the control thread
*
* This is the main loop that reads and process the control messages:
*
* - Connect the GNSS receiver flowgraph;
*
* - Start the GNSS receiver flowgraph;
* while (flowgraph_->running() && !stop)_{
*
* while (flowgraph_->running() && !stop_){
*
* - Read control messages and process them; }
*/
void run();
@ -78,7 +82,7 @@ public:
/*!
* \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);
@ -105,10 +109,7 @@ public:
private:
/*!
* \brief SUPL assistance classes
*/
//SUPL assistance classes
gnss_sdr_supl_client supl_client_acquisition_;
gnss_sdr_supl_client supl_client_ephemeris_;
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).
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();
void read_control_messages();