From a7b1f715669eea7303cc14c76d79dc32d8e21417 Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Sun, 17 Nov 2013 10:48:27 +0000 Subject: [PATCH] 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 --- .../input_filter/adapters/fir_filter.cc | 22 +- .../adapters/freq_xlating_fir_filter.cc | 67 +- .../adapters/galileo_e1b_telemetry_decoder.cc | 8 +- .../adapters/galileo_e1b_telemetry_decoder.h | 9 +- .../galileo_e1b_telemetry_decoder_cc.cc | 758 +++++----- .../galileo_e1b_telemetry_decoder_cc.h | 27 +- .../gps_l1_ca_telemetry_decoder_cc.cc | 23 +- .../gps_l1_ca_telemetry_decoder_cc.h | 22 +- .../sbas_l1_telemetry_decoder_cc.cc | 59 +- .../sbas_l1_telemetry_decoder_cc.h | 16 +- .../telemetry_decoder/libs/convolutional.h | 1226 +++++++++-------- .../libs/gps_l1_ca_subframe_fsm.cc | 72 +- .../libs/gps_l1_ca_subframe_fsm.h | 60 +- .../telemetry_decoder/libs/viterbi_decoder.cc | 105 +- .../telemetry_decoder/libs/viterbi_decoder.h | 18 +- src/core/receiver/control_thread.cc | 855 ++++++------ src/core/receiver/control_thread.h | 20 +- 17 files changed, 1767 insertions(+), 1600 deletions(-) diff --git a/src/algorithms/input_filter/adapters/fir_filter.cc b/src/algorithms/input_filter/adapters/fir_filter.cc index b44773772..88a4beff8 100644 --- a/src/algorithms/input_filter/adapters/fir_filter.cc +++ b/src/algorithms/input_filter/adapters/fir_filter.cc @@ -47,21 +47,21 @@ FirFilter::FirFilter(ConfigurationInterface* configuration, std::string role, size_t item_size; (*this).init(); if ((taps_item_type_.compare("float") == 0) && (input_item_type_.compare("gr_complex") == 0) - && (output_item_type_.compare("gr_complex") == 0)) - { - 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_) + && (output_item_type_.compare("gr_complex") == 0)) + { + 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() << ")"; + 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"; + } } diff --git a/src/algorithms/input_filter/adapters/freq_xlating_fir_filter.cc b/src/algorithms/input_filter/adapters/freq_xlating_fir_filter.cc index 5544f4f6c..0a5d84e05 100644 --- a/src/algorithms/input_filter/adapters/freq_xlating_fir_filter.cc +++ b/src/algorithms/input_filter/adapters/freq_xlating_fir_filter.cc @@ -42,8 +42,8 @@ using google::LogMessage; FreqXlatingFirFilter::FreqXlatingFirFilter(ConfigurationInterface* configuration, std::string role, unsigned int in_streams, unsigned int out_streams, boost::shared_ptr queue) : - config_(configuration), role_(role), in_streams_(in_streams), - out_streams_(out_streams), queue_(queue) + config_(configuration), role_(role), in_streams_(in_streams), + out_streams_(out_streams), queue_(queue) { size_t item_size; (*this).init(); @@ -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_<connect(freq_xlating_fir_filter_fcf_, 0, file_sink_, 0); - }else{ - top_block->connect(freq_xlating_fir_filter_ccf_, 0, file_sink_, 0); - } + if (input_size_ == sizeof(float)) + { + top_block->connect(freq_xlating_fir_filter_fcf_, 0, file_sink_, 0); + } + else + { + top_block->connect(freq_xlating_fir_filter_ccf_, 0, file_sink_, 0); + } } else { @@ -110,12 +113,14 @@ void FreqXlatingFirFilter::disconnect(gr::top_block_sptr top_block) { if (dump_) { - if (input_size_==sizeof(float)) - { - top_block->disconnect(freq_xlating_fir_filter_fcf_, 0, file_sink_, 0); - }else{ - top_block->disconnect(freq_xlating_fir_filter_ccf_, 0, file_sink_, 0); - } + if (input_size_ == sizeof(float)) + { + top_block->disconnect(freq_xlating_fir_filter_fcf_, 0, file_sink_, 0); + } + else + { + top_block->disconnect(freq_xlating_fir_filter_ccf_, 0, file_sink_, 0); + } } } @@ -123,24 +128,28 @@ void FreqXlatingFirFilter::disconnect(gr::top_block_sptr top_block) gr::basic_block_sptr FreqXlatingFirFilter::get_left_block() { - if (input_size_==sizeof(float)) - { - return freq_xlating_fir_filter_fcf_; - }else{ - return freq_xlating_fir_filter_ccf_; - } + if (input_size_ == sizeof(float)) + { + return freq_xlating_fir_filter_fcf_; + } + else + { + return freq_xlating_fir_filter_ccf_; + } } gr::basic_block_sptr FreqXlatingFirFilter::get_right_block() { - if (input_size_==sizeof(float)) - { - return freq_xlating_fir_filter_fcf_; - }else{ - return freq_xlating_fir_filter_ccf_; - } + if (input_size_ == sizeof(float)) + { + return freq_xlating_fir_filter_fcf_; + } + else + { + return freq_xlating_fir_filter_ccf_; + } } diff --git a/src/algorithms/telemetry_decoder/adapters/galileo_e1b_telemetry_decoder.cc b/src/algorithms/telemetry_decoder/adapters/galileo_e1b_telemetry_decoder.cc index 4f5e2b539..6c0db4b02 100644 --- a/src/algorithms/telemetry_decoder/adapters/galileo_e1b_telemetry_decoder.cc +++ b/src/algorithms/telemetry_decoder/adapters/galileo_e1b_telemetry_decoder.cc @@ -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 diff --git a/src/algorithms/telemetry_decoder/adapters/galileo_e1b_telemetry_decoder.h b/src/algorithms/telemetry_decoder/adapters/galileo_e1b_telemetry_decoder.h index f3b611e63..fee7226d9 100644 --- a/src/algorithms/telemetry_decoder/adapters/galileo_e1b_telemetry_decoder.h +++ b/src/algorithms/telemetry_decoder/adapters/galileo_e1b_telemetry_decoder.h @@ -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"; diff --git a/src/algorithms/telemetry_decoder/gnuradio_blocks/galileo_e1b_telemetry_decoder_cc.cc b/src/algorithms/telemetry_decoder/gnuradio_blocks/galileo_e1b_telemetry_decoder_cc.cc index 2bf2d561c..69551e9bf 100644 --- a/src/algorithms/telemetry_decoder/gnuradio_blocks/galileo_e1b_telemetry_decoder_cc.cc +++ b/src/algorithms/telemetry_decoder/gnuradio_blocks/galileo_e1b_telemetry_decoder_cc.cc @@ -41,9 +41,7 @@ #include "control_message_factory.h" #include "galileo_navigation_message.h" #include "gnss_synchro.h" - #include "convolutional.h" - #include #include @@ -56,461 +54,489 @@ galileo_e1b_telemetry_decoder_cc_sptr galileo_e1b_make_telemetry_decoder_cc(Gnss_Satellite satellite, long if_freq, long fs_in, unsigned int vector_length, boost::shared_ptr queue, bool dump) { - return galileo_e1b_telemetry_decoder_cc_sptr(new galileo_e1b_telemetry_decoder_cc(satellite, if_freq, - fs_in, vector_length, queue, dump)); + return galileo_e1b_telemetry_decoder_cc_sptr(new galileo_e1b_telemetry_decoder_cc(satellite, if_freq, + fs_in, vector_length, queue, dump)); } void galileo_e1b_telemetry_decoder_cc::forecast (int noutput_items, gr_vector_int &ninput_items_required) { - ninput_items_required[0] = GALILEO_INAV_PAGE_SYMBOLS; //set the required sample history + ninput_items_required[0] = GALILEO_INAV_PAGE_SYMBOLS; //set the required sample history } void galileo_e1b_telemetry_decoder_cc::viterbi_decoder(double *page_part_symbols, int *page_part_bits) { + int CodeLength = 240; + int DataLength; + int nn, KK, mm, max_states; + int g_encoder[2]; - 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 - nn = 2; //Coding rate 1/n - KK = 7; //Constraint Length - 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; - mm = KK - 1; - max_states = 1 << mm; /* 2^mm */ - DataLength = (CodeLength/nn)-mm; + /* create appropriate transition matrices */ + int *out0, *out1, *state0, *state1; + out0 = (int*)calloc( max_states, sizeof(int) ); + out1 = (int*)calloc( max_states, sizeof(int) ); + state0 = (int*)calloc( max_states, sizeof(int) ); + state1 = (int*)calloc( max_states, sizeof(int) ); - /* create appropriate transition matrices */ - int *out0, *out1, *state0, *state1; - out0 = (int*)calloc( max_states, sizeof(int) ); - out1 = (int*)calloc( max_states, sizeof(int) ); - state0 = (int*)calloc( max_states, sizeof(int) ); - state1 = (int*)calloc( max_states, sizeof(int) ); + nsc_transit( out0, state0, 0, g_encoder, KK, nn ); + nsc_transit( out1, state1, 1, g_encoder, KK, nn ); - nsc_transit( out0, state0, 0, g_encoder, KK, nn ); - nsc_transit( out1, state1, 1, g_encoder, KK, nn ); - - Viterbi( page_part_bits, out0, state0, out1, state1, - page_part_symbols, KK, nn, DataLength ); + Viterbi( page_part_bits, out0, state0, out1, state1, + page_part_symbols, KK, nn, DataLength ); - /* Clean up memory */ - free( out0 ); - free( out1 ); - free( state0 ); - free( state1 ); - + /* Clean up memory */ + free( out0 ); + 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 queue, - bool dump) : - gr::block("galileo_e1b_telemetry_decoder_cc", gr::io_signature::make(1, 1, sizeof(Gnss_Synchro)), - gr::io_signature::make(1, 1, sizeof(Gnss_Synchro))) + Gnss_Satellite satellite, + long if_freq, + long fs_in, + unsigned + int vector_length, + boost::shared_ptr queue, + bool dump) : + gr::block("galileo_e1b_telemetry_decoder_cc", gr::io_signature::make(1, 1, sizeof(Gnss_Synchro)), + gr::io_signature::make(1, 1, sizeof(Gnss_Synchro))) { - // initialize internal vars - d_queue = queue; - d_dump = dump; - d_satellite = Gnss_Satellite(satellite.get_system(), satellite.get_PRN()); - DLOG(INFO) << "GALILEO E1B TELEMETRY PROCESSING: satellite " << d_satellite; - d_vector_length = vector_length; - d_samples_per_symbol = ( Galileo_E1_CODE_CHIP_RATE_HZ / Galileo_E1_B_CODE_LENGTH_CHIPS ) / Galileo_E1_B_SYMBOL_RATE_BPS; - d_fs_in = fs_in; + // initialize internal vars + d_queue = queue; + d_dump = dump; + d_satellite = Gnss_Satellite(satellite.get_system(), satellite.get_PRN()); + DLOG(INFO) << "GALILEO E1B TELEMETRY PROCESSING: satellite " << d_satellite; + d_vector_length = vector_length; + d_samples_per_symbol = ( Galileo_E1_CODE_CHIP_RATE_HZ / Galileo_E1_B_CODE_LENGTH_CHIPS ) / Galileo_E1_B_SYMBOL_RATE_BPS; + d_fs_in = fs_in; - // set the preamble - unsigned short int preambles_bits[GALILEO_INAV_PREAMBLE_LENGTH_BITS]=GALILEO_INAV_PREAMBLE; + // set the preamble + unsigned short int preambles_bits[GALILEO_INAV_PREAMBLE_LENGTH_BITS] = GALILEO_INAV_PREAMBLE; - d_symbols_per_preamble=GALILEO_INAV_PREAMBLE_LENGTH_BITS * d_samples_per_symbol; + d_symbols_per_preamble = GALILEO_INAV_PREAMBLE_LENGTH_BITS * d_samples_per_symbol; - memcpy((unsigned short int*)this->d_preambles_bits, (unsigned short int*)preambles_bits, GALILEO_INAV_PREAMBLE_LENGTH_BITS*sizeof(unsigned short int)); + memcpy((unsigned short int*)this->d_preambles_bits, (unsigned short int*)preambles_bits, GALILEO_INAV_PREAMBLE_LENGTH_BITS*sizeof(unsigned short int)); - // preamble bits to sampled symbols - d_preambles_symbols = (signed int*)malloc(sizeof(signed int) * d_symbols_per_preamble); - int n = 0; - for (int i=0; i0) - { - page_String.push_back('1'); - }else{ - page_String.push_back('0'); - } + for(int i = 0; i < (frame_length/2); i++) + { + if (page_part_bits[i] > 0) + { + page_String.push_back('1'); + } + else + { + page_String.push_back('0'); + } - } + } - //std::cout<<"ch["<push(ephemeris); - } - 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 - //std::cout<<"New Galileo IONO model (and UTC) received for SV "<push(iono); - } - 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 - //std::cout<<"New Galileo UTC model received for SV "<push(utc_model); - } + 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 + //std::cout<<"New Galileo Ephemeris received for SV "<push(ephemeris); + } + 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 + //std::cout<<"New Galileo IONO model (and UTC) received for SV "<push(iono); + } + 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 + //std::cout<<"New Galileo UTC model received for SV "<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) + gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) { - int corr_value = 0; - int preamble_diff = 0; + int corr_value = 0; + int preamble_diff = 0; - Gnss_Synchro **out = (Gnss_Synchro **) &output_items[0]; - d_sample_counter++; //count for the processed samples + Gnss_Synchro **out = (Gnss_Synchro **) &output_items[0]; + d_sample_counter++; //count for the processed samples - // ########### Output the tracking data to navigation and PVT ########## - const Gnss_Synchro **in = (const Gnss_Synchro **) &input_items[0]; //Get the input samples pointer + // ########### Output the tracking data to navigation and PVT ########## + const Gnss_Synchro **in = (const Gnss_Synchro **) &input_items[0]; //Get the input samples pointer - // TODO Optimize me! - //******* preamble correlation ******** - for (int i=0; i= d_symbols_per_preamble) - { - d_preamble_index = d_sample_counter;//record the preamble sample stamp - 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 - { - if (abs(corr_value) >= d_symbols_per_preamble) - { - //check preamble separation - preamble_diff = abs(d_sample_counter - d_preamble_index); - 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<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; - double page_part_symbols[frame_length]; + //******* frame sync ****************** + if (d_stat == 0) //no preamble information + { + if (abs(corr_value) >= d_symbols_per_preamble) + { + d_preamble_index = d_sample_counter;//record the preamble sample stamp + 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 + { + if (abs(corr_value) >= d_symbols_per_preamble) + { + //check preamble separation + preamble_diff = abs(d_sample_counter - d_preamble_index); + 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; + } + else + { + if (preamble_diff > 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; + double page_part_symbols[frame_length]; - for (int i=0;i0) - { - page_part_symbols[i]=in[0][i+d_symbols_per_preamble].Prompt_I; // because last symbol of the preamble is just received now! + for (int i = 0; i < frame_length; i++) + { + 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! - }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 - //std::cout<<"ch["<0) - // { - // std::cout<<"1"; - // }else{ - // std::cout<<"0"; - // } - // } - // std::cout<d_satellite << " with preamble start at " << d_preamble_time_seconds << " [s]" << std::endl; - } - }else{ - d_CRC_error_counter++; - d_preamble_index = d_sample_counter; //record the preamble sample stamp - 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; - } - } - } - } - consume_each(1); //one by one - // UPDATE GNSS SYNCHRO DATA - Gnss_Synchro current_synchro_data; //structure to save the synchronization information and send the output object to the next block - //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) - //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 - { - Prn_timestamp_at_preamble_ms = in[0][0].Tracking_timestamp_secs * 1000.0; - if(d_nav.flag_TOW_5 == true) //page 5 arrived and decoded, so we are in the odd page (since Tow refers to the even page, we have to add 1 sec) - { - //std::cout<< "Using TOW_5 for timestamping" << std::endl; - d_TOW_at_Preamble = d_nav.TOW_5+GALILEO_INAV_PAGE_PART_SECONDS; //TOW_5 refers to the even preamble, but when we decode it we are in the odd part, so 1 second later - /* 1 sec (GALILEO_INAV_PAGE_PART_SYMBOLS*GALIELO_E1_CODE_PERIOD) is added because - * if we have a TOW value it means that we are at the begining of the last page part - * (GNU Radio history keeps in a buffer the rest of the incomming frame part)*/ - d_TOW_at_current_symbol = d_TOW_at_Preamble;// + GALILEO_INAV_PAGE_PART_SYMBOLS*GALIELO_E1_CODE_PERIOD; - d_nav.flag_TOW_5 = false; - } + } + 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 + //std::cout<<"ch["<0) + // { + // std::cout<<"1"; + // }else{ + // std::cout<<"0"; + // } + // } + // std::cout<d_satellite << " with preamble start at " << d_preamble_time_seconds << " [s]" << std::endl; + } + } + else + { + d_CRC_error_counter++; + d_preamble_index = d_sample_counter; //record the preamble sample stamp + 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; + } + } + } + } + consume_each(1); //one by one + // UPDATE GNSS SYNCHRO DATA + Gnss_Synchro current_synchro_data; //structure to save the synchronization information and send the output object to the next block + //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) + //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 + { + Prn_timestamp_at_preamble_ms = in[0][0].Tracking_timestamp_secs * 1000.0; + if(d_nav.flag_TOW_5 == true) //page 5 arrived and decoded, so we are in the odd page (since Tow refers to the even page, we have to add 1 sec) + { + //std::cout<< "Using TOW_5 for timestamping" << std::endl; + d_TOW_at_Preamble = d_nav.TOW_5+GALILEO_INAV_PAGE_PART_SECONDS; //TOW_5 refers to the even preamble, but when we decode it we are in the odd part, so 1 second later + /* 1 sec (GALILEO_INAV_PAGE_PART_SYMBOLS*GALIELO_E1_CODE_PERIOD) is added because + * if we have a TOW value it means that we are at the begining of the last page part + * (GNU Radio history keeps in a buffer the rest of the incomming frame part)*/ + d_TOW_at_current_symbol = d_TOW_at_Preamble;// + GALILEO_INAV_PAGE_PART_SYMBOLS*GALIELO_E1_CODE_PERIOD; + d_nav.flag_TOW_5 = false; + } - else if(d_nav.flag_TOW_6 == true) //page 6 arrived and decoded, so we are in the odd page (since Tow refers to the even page, we have to add 1 sec) - { - //std::cout<< "Using TOW_6 for timestamping" << std::endl; - d_TOW_at_Preamble = d_nav.TOW_6+GALILEO_INAV_PAGE_PART_SECONDS; - //TOW_6 refers to the even preamble, but when we decode it we are in the odd part, so 1 second later - /* 1 sec (GALILEO_INAV_PAGE_PART_SYMBOLS*GALIELO_E1_CODE_PERIOD) is added because - * if we have a TOW value it means that we are at the begining of the last page part - * (GNU Radio history keeps in a buffer the rest of the incomming frame part)*/ - d_TOW_at_current_symbol = d_TOW_at_Preamble;// + GALILEO_INAV_PAGE_PART_SYMBOLS*GALIELO_E1_CODE_PERIOD; - d_nav.flag_TOW_6 = false; - } - else - { - //this page has no timming information - d_TOW_at_Preamble = d_TOW_at_Preamble + GALILEO_INAV_PAGE_SECONDS; - d_TOW_at_current_symbol = d_TOW_at_current_symbol + GALIELO_E1_CODE_PERIOD;// + GALILEO_INAV_PAGE_PART_SYMBOLS*GALIELO_E1_CODE_PERIOD; - } + else if(d_nav.flag_TOW_6 == true) //page 6 arrived and decoded, so we are in the odd page (since Tow refers to the even page, we have to add 1 sec) + { + //std::cout<< "Using TOW_6 for timestamping" << std::endl; + d_TOW_at_Preamble = d_nav.TOW_6+GALILEO_INAV_PAGE_PART_SECONDS; + //TOW_6 refers to the even preamble, but when we decode it we are in the odd part, so 1 second later + /* 1 sec (GALILEO_INAV_PAGE_PART_SYMBOLS*GALIELO_E1_CODE_PERIOD) is added because + * if we have a TOW value it means that we are at the begining of the last page part + * (GNU Radio history keeps in a buffer the rest of the incomming frame part)*/ + d_TOW_at_current_symbol = d_TOW_at_Preamble;// + GALILEO_INAV_PAGE_PART_SYMBOLS*GALIELO_E1_CODE_PERIOD; + d_nav.flag_TOW_6 = false; + } + else + { + //this page has no timming information + d_TOW_at_Preamble = d_TOW_at_Preamble + GALILEO_INAV_PAGE_SECONDS; + d_TOW_at_current_symbol = d_TOW_at_current_symbol + GALIELO_E1_CODE_PERIOD;// + GALILEO_INAV_PAGE_PART_SYMBOLS*GALIELO_E1_CODE_PERIOD; + } - } - else //if there is not a new preamble, we define the TOW of the current symbol - { - d_TOW_at_current_symbol = d_TOW_at_current_symbol + GALIELO_E1_CODE_PERIOD; - } + } + else //if there is not a new preamble, we define the TOW of the current symbol + { + d_TOW_at_current_symbol = d_TOW_at_current_symbol + GALIELO_E1_CODE_PERIOD; + } - //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) - { - current_synchro_data.Flag_valid_word = true; - }else{ - current_synchro_data.Flag_valid_word = false; - } + //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) + { + current_synchro_data.Flag_valid_word = true; + } + else + { + current_synchro_data.Flag_valid_word = false; + } - 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_preamble = d_flag_preamble; - current_synchro_data.Prn_timestamp_ms = in[0][0].Tracking_timestamp_secs * 1000.0; - current_synchro_data.Prn_timestamp_at_preamble_ms = Prn_timestamp_at_preamble_ms; + 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_preamble = d_flag_preamble; + current_synchro_data.Prn_timestamp_ms = in[0][0].Tracking_timestamp_secs * 1000.0; + current_synchro_data.Prn_timestamp_at_preamble_ms = Prn_timestamp_at_preamble_ms; - if(d_dump == true) - { - // MULTIPLEXED FILE RECORDING - Record results to file - try - { - double tmp_double; - tmp_double = d_TOW_at_current_symbol; - d_dump_file.write((char*)&tmp_double, sizeof(double)); - tmp_double = current_synchro_data.Prn_timestamp_ms; - d_dump_file.write((char*)&tmp_double, sizeof(double)); - tmp_double = d_TOW_at_Preamble; - d_dump_file.write((char*)&tmp_double, sizeof(double)); - } - catch (const std::ifstream::failure& e) - { - std::cout << "Exception writing observables dump file " << e.what() << std::endl; - } - } - //3. Make the output (copy the object contents to the GNURadio reserved memory) - *out[0] = current_synchro_data; - return 1; + if(d_dump == true) + { + // MULTIPLEXED FILE RECORDING - Record results to file + try + { + double tmp_double; + tmp_double = d_TOW_at_current_symbol; + d_dump_file.write((char*)&tmp_double, sizeof(double)); + tmp_double = current_synchro_data.Prn_timestamp_ms; + d_dump_file.write((char*)&tmp_double, sizeof(double)); + tmp_double = d_TOW_at_Preamble; + d_dump_file.write((char*)&tmp_double, sizeof(double)); + } + catch (const std::ifstream::failure& e) + { + std::cout << "Exception writing observables dump file " << e.what() << std::endl; + } + } + //3. Make the output (copy the object contents to the GNURadio reserved memory) + *out[0] = current_synchro_data; + return 1; } void galileo_e1b_telemetry_decoder_cc::set_satellite(Gnss_Satellite satellite) { - d_satellite = Gnss_Satellite(satellite.get_system(), satellite.get_PRN()); - DLOG(INFO) << "Setting decoder Finite State Machine to satellite " << d_satellite; - DLOG(INFO) << "Navigation Satellite set to " << d_satellite; + d_satellite = Gnss_Satellite(satellite.get_system(), satellite.get_PRN()); + DLOG(INFO) << "Setting decoder Finite State Machine to satellite " << d_satellite; + DLOG(INFO) << "Navigation Satellite set to " << d_satellite; } void galileo_e1b_telemetry_decoder_cc::set_channel(int channel) { - d_channel = channel; - DLOG(INFO) << "Navigation channel set to " << channel; - // ############# ENABLE DATA FILE LOG ################# - if (d_dump == true) - { - if (d_dump_file.is_open() == false) - { - try - { - d_dump_filename = "telemetry"; - d_dump_filename.append(boost::lexical_cast(d_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; - } - catch (const std::ifstream::failure& e) - { - std::cout << "channel " << d_channel << " Exception opening trk dump file " << e.what() << std::endl; - } - } - } + d_channel = channel; + DLOG(INFO) << "Navigation channel set to " << channel; + // ############# ENABLE DATA FILE LOG ################# + if (d_dump == true) + { + if (d_dump_file.is_open() == false) + { + try + { + d_dump_filename = "telemetry"; + d_dump_filename.append(boost::lexical_cast(d_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; + } + catch (const std::ifstream::failure& e) + { + 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 *ephemeris_queue) { - d_ephemeris_queue = ephemeris_queue; + d_ephemeris_queue = ephemeris_queue; } + + void galileo_e1b_telemetry_decoder_cc::set_iono_queue(concurrent_queue *iono_queue) { - d_iono_queue = iono_queue; + d_iono_queue = iono_queue; } + + void galileo_e1b_telemetry_decoder_cc::set_almanac_queue(concurrent_queue *almanac_queue) { - d_almanac_queue = almanac_queue; + d_almanac_queue = almanac_queue; } + + void galileo_e1b_telemetry_decoder_cc::set_utc_model_queue(concurrent_queue *utc_model_queue) { - d_utc_model_queue = utc_model_queue; + d_utc_model_queue = utc_model_queue; } diff --git a/src/algorithms/telemetry_decoder/gnuradio_blocks/galileo_e1b_telemetry_decoder_cc.h b/src/algorithms/telemetry_decoder/gnuradio_blocks/galileo_e1b_telemetry_decoder_cc.h index 53bf05a63..46f4909e3 100644 --- a/src/algorithms/telemetry_decoder/gnuradio_blocks/galileo_e1b_telemetry_decoder_cc.h +++ b/src/algorithms/telemetry_decoder/gnuradio_blocks/galileo_e1b_telemetry_decoder_cc.h @@ -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 #include #include - #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 *ephemeris_queue); //!< Set the satellite data queue + void set_iono_queue(concurrent_queue *iono_queue); //!< Set the iono data queue + void set_almanac_queue(concurrent_queue *almanac_queue); //!< Set the almanac data queue + void set_utc_model_queue(concurrent_queue *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 *ephemeris_queue); - void set_iono_queue(concurrent_queue *iono_queue); - void set_almanac_queue(concurrent_queue *almanac_queue); - void set_utc_model_queue(concurrent_queue *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 *d_ephemeris_queue; // ionospheric parameters queue diff --git a/src/algorithms/telemetry_decoder/gnuradio_blocks/gps_l1_ca_telemetry_decoder_cc.cc b/src/algorithms/telemetry_decoder/gnuradio_blocks/gps_l1_ca_telemetry_decoder_cc.cc index e93238eb0..c62b0f827 100644 --- a/src/algorithms/telemetry_decoder/gnuradio_blocks/gps_l1_ca_telemetry_decoder_cc.cc +++ b/src/algorithms/telemetry_decoder/gnuradio_blocks/gps_l1_ca_telemetry_decoder_cc.cc @@ -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; id_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; } } } diff --git a/src/algorithms/telemetry_decoder/gnuradio_blocks/gps_l1_ca_telemetry_decoder_cc.h b/src/algorithms/telemetry_decoder/gnuradio_blocks/gps_l1_ca_telemetry_decoder_cc.h index 3af97d0f0..08e505e4d 100644 --- a/src/algorithms/telemetry_decoder/gnuradio_blocks/gps_l1_ca_telemetry_decoder_cc.h +++ b/src/algorithms/telemetry_decoder/gnuradio_blocks/gps_l1_ca_telemetry_decoder_cc.h @@ -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 #include #include -//#include #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 *ephemeris_queue){d_GPS_FSM.d_ephemeris_queue = ephemeris_queue;} - void set_iono_queue(concurrent_queue *iono_queue){d_GPS_FSM.d_iono_queue = iono_queue;} - void set_almanac_queue(concurrent_queue *almanac_queue){d_GPS_FSM.d_almanac_queue = almanac_queue;} - void set_utc_model_queue(concurrent_queue *utc_model_queue){d_GPS_FSM.d_utc_model_queue = utc_model_queue;} + void set_ephemeris_queue(concurrent_queue *ephemeris_queue){d_GPS_FSM.d_ephemeris_queue = ephemeris_queue;} //!< Set the ephemeris data queue + void set_iono_queue(concurrent_queue *iono_queue){d_GPS_FSM.d_iono_queue = iono_queue;} //!< Set the iono data queue + void set_almanac_queue(concurrent_queue *almanac_queue){d_GPS_FSM.d_almanac_queue = almanac_queue;} //!< Set the almanac data queue + void set_utc_model_queue(concurrent_queue *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 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 queue, bool dump); + bool gps_word_parityCheck(unsigned int gpsword); // constants diff --git a/src/algorithms/telemetry_decoder/gnuradio_blocks/sbas_l1_telemetry_decoder_cc.cc b/src/algorithms/telemetry_decoder/gnuradio_blocks/sbas_l1_telemetry_decoder_cc.cc index c41fb61be..f9402718e 100644 --- a/src/algorithms/telemetry_decoder/gnuradio_blocks/sbas_l1_telemetry_decoder_cc.cc +++ b/src/algorithms/telemetry_decoder/gnuradio_blocks/sbas_l1_telemetry_decoder_cc.cc @@ -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,41 +66,42 @@ sbas_l1_telemetry_decoder_cc::sbas_l1_telemetry_decoder_cc( int vector_length, boost::shared_ptr queue, bool dump) : - gr::block("sbas_l1_telemetry_decoder_cc", gr::io_signature::make(1, 1, sizeof(Gnss_Synchro)), - gr::io_signature::make(1, 1, sizeof(Gnss_Synchro))) + gr::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 d_dump = dump; 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 symbols, std::vector &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 symbols_vd1(symbols); // aligned symbol vector -> copy input symbol vector std::vector symbols_vd2; // shifted symbol vector -> add past sample in front of input vector symbols_vd1.push_back(d_past_symbol); - for (std::vector::const_iterator symbol_it = symbols.begin(); symbol_it != symbols.end()-1; ++symbol_it) + for (std::vector::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 metric_vd2) {// symbols aligned @@ -363,8 +370,8 @@ void sbas_l1_telemetry_decoder_cc::frame_detector::get_frame_candidates(const st std::stringstream ss; unsigned int sbas_msg_length = 250; std::vector> preambles = {{0, 1, 0, 1, 0, 0, 1 ,1}, - {1, 0, 0, 1, 1, 0, 1, 0}, - {1, 1, 0, 0, 0, 1, 1, 0}}; + {1, 0, 0, 1, 1, 0, 1, 0}, + {1, 1, 0, 0, 0, 1, 1, 0}}; VLOG(FLOW) << "get_frame_candidates(): " << "d_buffer.size()=" << d_buffer.size() << "\tbits.size()=" << bits.size(); ss << "copy bits "; int count = 0; @@ -399,7 +406,7 @@ void sbas_l1_telemetry_decoder_cc::frame_detector::get_frame_candidates(const st { // invert bits for (std::vector::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>(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 - << std::setfill(' ') << std::resetiosflags(std::ios::hex); + 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,8 +491,9 @@ 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 - << std::setfill(' ') << std::resetiosflags(std::ios::hex); + VLOG(LMORE) << " -> byte=" << std::setw(2) + << std::setfill('0') << std::hex << (unsigned int)byte + << std::setfill(' ') << std::resetiosflags(std::ios::hex); } @@ -504,13 +513,15 @@ 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 - << std::setfill(' ') << std::resetiosflags(std::ios::hex); + VLOG(LMORE) << " -> byte=" << std::setw(2) + << std::setfill('0') << std::hex << (unsigned int)byte + << std::setfill(' ') << std::resetiosflags(std::ios::hex); } diff --git a/src/algorithms/telemetry_decoder/gnuradio_blocks/sbas_l1_telemetry_decoder_cc.h b/src/algorithms/telemetry_decoder/gnuradio_blocks/sbas_l1_telemetry_decoder_cc.h index db021b850..030653aba 100644 --- a/src/algorithms/telemetry_decoder/gnuradio_blocks/sbas_l1_telemetry_decoder_cc.h +++ b/src/algorithms/telemetry_decoder/gnuradio_blocks/sbas_l1_telemetry_decoder_cc.h @@ -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 *raw_msg_queue); - void set_iono_queue(concurrent_queue *iono_queue); - void set_sat_corr_queue(concurrent_queue *sat_corr_queue); - void set_ephemeris_queue(concurrent_queue *ephemeris_queue); + void set_raw_msg_queue(concurrent_queue *raw_msg_queue); //!< Set raw msg queue + void set_iono_queue(concurrent_queue *iono_queue); //!< Set iono queue + void set_sat_corr_queue(concurrent_queue *sat_corr_queue); //!< Set sat correction queue + void set_ephemeris_queue(concurrent_queue *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: diff --git a/src/algorithms/telemetry_decoder/libs/convolutional.h b/src/algorithms/telemetry_decoder/libs/convolutional.h index 0a8323c35..5fa80bd87 100644 --- a/src/algorithms/telemetry_decoder/libs/convolutional.h +++ b/src/algorithms/telemetry_decoder/libs/convolutional.h @@ -1,637 +1,659 @@ -/* 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>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 ) -{ - int counter; - int temp_parity = 0; - - for (counter=0;counter>1; - } - - return( temp_parity ); + 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; + } + return; } -/* 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[], - int input, - int state_in, - int g[], - int KK, - int nn ) +/*! + * \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) { - /* declare variables */ - int state, i; - int out = 0; + int counter; + int temp_parity = 0; - /* create a word made up of state and new input */ - state = (input<<(KK-1))^state_in; - - /* AND the word with the generators */ - for (i=0;i>1; - return(out); -} - -/* 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 ) -{ - /* declare variables */ - int state, i, out, a_k; - - /* systematic output */ - out = input; - - /* determine feedback bit */ - 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; - - /* AND the word with the generators */ - for (i=1;i>1; - return(out); -} - -/* 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 nextstate[1]; - int state, states; - 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= 0) { - for (i=LL;i> 1; + } + return(temp_parity); } -/* 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 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) +{ + /* declare variables */ + int state, i; + int out_ = 0; + + /* create a word made up of state and new input */ + state = (input << (KK - 1))^state_in; + + /* AND the word with the generators */ + for (i = 0; i < nn; i++) + { + /* update output symbol */ + 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_); +} + +/*! + * \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) +{ + /* declare variables */ + int state, i, out_, a_k; + + /* systematic output */ + out_ = input; + + /* determine feedback bit */ + 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; + + /* AND the word with the generators */ + for (i = 1; i < nn; i++) + { + /* update output symbol */ + 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_); +} + + + +/*! + * \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 nextstate[1]; + int state, states; + 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); + trans_p[state] = nextstate[0]; + } + return; +} + + + +/*! + * \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[], + int KK, + int nn ) +{ + int nextstate[1]; + int state, states; + + 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] = rsc_enc_bit( nextstate, input, state, g, KK, nn ); + trans_p[state] = nextstate[0]; + } + return; +} + + + +/*! + * \brief determines the tail for a RSC code + */ +static void rsc_tail(int tail_p[], + int g[], + int max_states, + int mm ) +{ + int state; + + /* Determine the tail for each state */ + for(state = 0; state < max_states; state++) + { + /* determine feedback word */ + tail_p[state] = parity_counter(g[0]&state, mm); + } + return; +} + + + +/*! + * \brief Perform convolutional encoding + */ +static void conv_encode(int output_p[], + int input[], + int out0[], + int state0[], + int out1[], + int state1[], + int tail[], + int KK, + int LL, + int nn) +{ + int i, j, outsym; + int *bin_vec; + int state = 0; + + /* 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]) + { + /* Determine next state */ + state = state1[state]; + } + else + { + /* Determine next state */ + state = state0[state]; + } + } + } + + bin_vec = (int*)calloc( nn, sizeof(int) ); + + /* encode data bits one bit at a time */ + 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 + { + /* Input is a zero */ + outsym = out0[state]; /* The output symbol */ + + /* Determine next state */ + state = state0[state]; + } + + /* Convert symbol to a binary vector */ + itob( bin_vec, outsym, nn ); + + /* Assign to output */ + 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]) + { + /* Input is a one */ + outsym = out1[state]; /* The output symbol */ + + /* Determine next state */ + state = state1[state]; + } + else + { + /* Input is a zero */ + outsym = out0[state]; /* The output symbol */ + + /* Determine next state */ + state = state0[state]; + } + + /* Convert symbol to a binary vector */ + itob( bin_vec, outsym, nn ); + + /* Assign to output */ + for (j = 0; j < nn; j++) + output_p[nn*i + j] = bin_vec[j]; + } + } + + free(bin_vec); + return; +} + + +/*! + * \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 symbol, + int nn) { - float rm = 0; - int i; - int mask; - - mask = 1; - for (i=0;i next_section[state0[state]] ) { - next_section[state0[state]] = metric; - 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]] ) { - next_section[state1[state]] = metric; - prev_state[t*states+state1[state]] = state; - prev_bit[t*states+state1[state]] = 1; - } - } + int i, t, state, mm, states; + int number_symbols; + float metric; + float *prev_section, *next_section; + int *prev_bit; + int *prev_state; + float *metric_c; /* Set of all possible branch metrics */ + float *rec_array; /* Received values for one trellis section */ + float max_val; - /* normalize */ - max_val = 0; - for (state=0;statemax_val){ - max_val = next_section[state]; - } - } - for (state=0;state=LL; t--) { - state = prev_state[t*states+state]; - } + /* 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) ); + rec_array = (float*)calloc( nn, sizeof(float) ); + metric_c = (float*)calloc( number_symbols, sizeof(float) ); - 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 */ - free(prev_section); - free(next_section); - free(prev_bit); - free(prev_state); - free(rec_array); - free(metric_c); - + /* initialize trellis */ + 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]; + + /* precompute all possible branch metrics */ + 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++) + { + /* 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]] ) + { + next_section[state0[state]] = metric; + 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]] ) + { + next_section[state1[state]] = metric; + 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) + { + max_val = next_section[state]; + } + } + for (state = 0; state < states; state++) + { + prev_section[state] = next_section[state] - max_val; + next_section[state] = -MAXLOG; + } + } + + /* trace-back operation */ + state = 0; + + /* tail, no need to output */ + 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]; + } + + /* free the dynamically allocated memory */ + free(prev_section); + free(next_section); + free(prev_bit); + 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[], - int out0[], - int state0[], - int out1[], - int state1[], - double input_c[], - int KK, - int nn, - int LL, - int depth - ) +/*! + * \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[], + int state1[], + double input_c[], + int KK, + int nn, + int LL, + int depth) { - int i, t, state, mm, states, max_state; - int number_symbols, starting_bit; - float metric; - float *prev_section, *next_section; - int *prev_bit; - int *prev_state; - float *metric_c; /* Set of all possible branch metrics */ - float *rec_array; /* Received values for one trellis section */ - float max_val; - - /* some derived constants */ - 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) ); - rec_array = (float*)calloc( nn, sizeof(float) ); - metric_c = (float*)calloc( number_symbols, sizeof(float) ); - - /* initialize trellis */ - for (state=0;state next_section[state0[state]] ) { - next_section[state0[state]] = metric; - if (t>=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]] ) { - next_section[state1[state]] = metric; - if (t>=0) { - prev_state[t*states+state1[state]] = state; - prev_bit[t*states+state1[state]] = 1; - } - } - } - - /* normalize */ - max_val = 0; - for (state=0;statemax_val){ - max_val = next_section[state]; - max_state = state; - } - } - for (state=0;state=LL; t--) { - state = prev_state[t*states+state]; - } + /* 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) ); + rec_array = (float*)calloc( nn, sizeof(float) ); + metric_c = (float*)calloc( number_symbols, sizeof(float) ); - 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 */ - free(prev_section); - free(next_section); - free(prev_bit); - free(prev_state); - free(rec_array); - free(metric_c); - + /* initialize trellis */ + 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++) + { + /* determine the corresponding data bits */ + starting_bit = nn*(t % LL); + if (starting_bit < 0 ) + starting_bit = nn*LL + starting_bit; + + for (i = 0; i < nn; i++) + { + rec_array[i] = (float)input_c[starting_bit+i]; + } + + /* precompute all possible branch metrics */ + 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++) + { + /* 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]] ) + { + next_section[state0[state]] = metric; + if (t >= 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]] ) + { + next_section[state1[state]] = metric; + if (t >= 0) + { + 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) + { + max_val = next_section[state]; + max_state = state; + } + } + for (state = 0; state < states; state++) + { + prev_section[state] = next_section[state] - max_val; + next_section[state] = -MAXLOG; + } + } + + /* trace-back operation */ + 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 - 1; t >= 0; t--) + { + output_u_int[t] = prev_bit[t*states + state]; + state = prev_state[t*states + state]; + } + + /* free the dynamically allocated memory */ + free(prev_section); + free(next_section); + free(prev_bit); + free(prev_state); + free(rec_array); + free(metric_c); } diff --git a/src/algorithms/telemetry_decoder/libs/gps_l1_ca_subframe_fsm.cc b/src/algorithms/telemetry_decoder/libs/gps_l1_ca_subframe_fsm.cc index 8d136e2a8..156fb40c8 100644 --- a/src/algorithms/telemetry_decoder/libs/gps_l1_ca_subframe_fsm.cc +++ b/src/algorithms/telemetry_decoder/libs/gps_l1_ca_subframe_fsm.cc @@ -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 @@ -228,22 +228,28 @@ public: GpsL1CaSubframeFsm::GpsL1CaSubframeFsm() { - d_nav.reset(); - initiate(); //start the FSM + d_nav.reset(); + 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); + // 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,48 +257,52 @@ 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) - { - // get ephemeris object for this SV (mandatory) - Gps_Ephemeris ephemeris=d_nav.get_ephemeris(); - d_ephemeris_queue->push(ephemeris); - } - break; + if (d_nav.satellite_validation() == true) + { + // get ephemeris object for this SV (mandatory) + 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) - { - 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) - { - 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; + if (d_nav.flag_iono_valid == true) + { + 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) + { + 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; case 5: - // get almanac (if available) - //TODO: implement almanac reader in navigation_message - break; + // get almanac (if available) + //TODO: implement almanac reader in navigation_message + break; default: - break; + break; } } + + void GpsL1CaSubframeFsm::Event_gps_word_valid() { - this->process_event(Ev_gps_word_valid()); + this->process_event(Ev_gps_word_valid()); } + + void GpsL1CaSubframeFsm::Event_gps_word_invalid() { - this->process_event(Ev_gps_word_invalid()); + this->process_event(Ev_gps_word_invalid()); } void GpsL1CaSubframeFsm::Event_gps_word_preamble() { - this->process_event(Ev_gps_word_preamble()); + this->process_event(Ev_gps_word_preamble()); } diff --git a/src/algorithms/telemetry_decoder/libs/gps_l1_ca_subframe_fsm.h b/src/algorithms/telemetry_decoder/libs/gps_l1_ca_subframe_fsm.h index 3f16559af..e8306a26a 100644 --- a/src/algorithms/telemetry_decoder/libs/gps_l1_ca_subframe_fsm.h +++ b/src/algorithms/telemetry_decoder/libs/gps_l1_ca_subframe_fsm.h @@ -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: - // channel and satellite info - int i_channel_ID; - unsigned int i_satellite_PRN; + GpsL1CaSubframeFsm(); //!< The constructor starts the Finite State Machine - // ephemeris queue - concurrent_queue *d_ephemeris_queue; - // ionospheric parameters queue - concurrent_queue *d_iono_queue; - // UTC model parameters queue - concurrent_queue *d_utc_model_queue; - // Almanac queue - concurrent_queue *d_almanac_queue; + // channel and satellite info + int i_channel_ID; //!< Channel id + unsigned int i_satellite_PRN; //!< Satellite PRN number - // navigation message class - Gps_Navigation_Message d_nav; + concurrent_queue *d_ephemeris_queue; //!< Ephemeris queue + concurrent_queue *d_iono_queue; //!< Ionospheric parameters queue + concurrent_queue *d_utc_model_queue; //!< UTC model parameters queue + concurrent_queue *d_almanac_queue; //!< Almanac queue - // GPS SV and System parameters - Gps_Ephemeris ephemeris; - Gps_Almanac almanac; - Gps_Utc_Model utc_model; - Gps_Iono iono; + Gps_Navigation_Message d_nav; //!< GPS L1 C/A navigation message object + // GPS SV and System parameters + 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]; + char d_subframe[GPS_SUBFRAME_LENGTH]; + char d_GPS_frame_4bytes[GPS_WORD_LENGTH]; + double d_preamble_time_ms; - double d_preamble_time_ms; + void gps_word_to_subframe(int position); //!< inserts the word in the correct position of the subframe - void gps_word_to_subframe(int position); - void gps_subframe_to_nav_msg(); + /*! + * \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(); + //FSM EVENTS + 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 diff --git a/src/algorithms/telemetry_decoder/libs/viterbi_decoder.cc b/src/algorithms/telemetry_decoder/libs/viterbi_decoder.cc index 1efcbac7d..5f7869c83 100644 --- a/src/algorithms/telemetry_decoder/libs/viterbi_decoder.cc +++ b/src/algorithms/telemetry_decoder/libs/viterbi_decoder.cc @@ -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) - + 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) - + 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::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; diff --git a/src/algorithms/telemetry_decoder/libs/viterbi_decoder.h b/src/algorithms/telemetry_decoder/libs/viterbi_decoder.h index 2e4c85b73..3956bb001 100644 --- a/src/algorithms/telemetry_decoder/libs/viterbi_decoder.h +++ b/src/algorithms/telemetry_decoder/libs/viterbi_decoder.h @@ -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 #include @@ -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_ */ diff --git a/src/core/receiver/control_thread.cc b/src/core/receiver/control_thread.cc index 42ca10304..104adb369 100644 --- a/src/core/receiver/control_thread.cc +++ b/src/core/receiver/control_thread.cc @@ -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 @@ -106,10 +104,10 @@ ControlThread::ControlThread(ConfigurationInterface *configuration) ControlThread::~ControlThread() { - // save navigation data to files - gps_ephemeris_data_write_to_XML(); - gps_iono_data_write_to_XML(); - gps_utc_model_data_write_to_XML(); + // save navigation data to files + gps_ephemeris_data_write_to_XML(); + gps_iono_data_write_to_XML(); + gps_utc_model_data_write_to_XML(); delete flowgraph_; if (delete_configuration_) delete configuration_; @@ -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!"<stop(); // Join GPS threads @@ -205,163 +203,184 @@ void ControlThread::set_control_queue(boost::shared_ptr 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 "<::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 "<first<second); - } - return false; - }else{ - std::cout<< "ERROR: SUPL client error reading XML"<::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; + 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; + return false; + } } + + + void ControlThread::init() { - // Instantiates a control queue, a GNSS flowgraph, and a control message factory - control_queue_ = gr::msg_queue::make(0); - flowgraph_ = new GNSSFlowgraph(configuration_, control_queue_); - control_message_factory_ = new ControlMessageFactory(); - stop_ = false; - processed_control_messages_ = 0; - applied_actions_ = 0; + // Instantiates a control queue, a GNSS flowgraph, and a control message factory + control_queue_ = gr::msg_queue::make(0); + flowgraph_ = new GNSSFlowgraph(configuration_, control_queue_); + control_message_factory_ = new ControlMessageFactory(); + stop_ = false; + processed_control_messages_ = 0; + applied_actions_ = 0; - //#########GNSS Asistence ################################# - // GNSS Assistance configuration - 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!"<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); + //######### GNSS Assistance ################################# + // GNSS Assistance configuration + 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::string default_lac="0x59e2"; - std::string default_ci="0x31b0"; - try { - supl_lac = boost::lexical_cast(configuration_->property("GNSS-SDR.SUPL_LAC",default_lac)); - } catch(boost::bad_lexical_cast &) { - supl_lac=0x59e2; - } - try { - supl_ci = boost::lexical_cast(configuration_->property("GNSS-SDR.SUPL_CI",default_ci)); - } catch(boost::bad_lexical_cast &) { - supl_ci=0x31b0; - } + std::string default_lac = "0x59e2"; + std::string default_ci = "0x31b0"; + try + { + supl_lac = boost::lexical_cast(configuration_->property("GNSS-SDR.SUPL_LAC", default_lac)); + } + 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) - { - // read assistance from file - read_assistance_from_XML(); - }else{ + try + { + supl_ci = boost::lexical_cast(configuration_->property("GNSS-SDR.SUPL_CI", default_ci)); + } + catch(boost::bad_lexical_cast &) + { + supl_ci = 0x31b0; + } - // Request ephemeris from SUPL server - int error; - supl_client_ephemeris_.request=1; - std::cout<< "SUPL: Try read GPS ephemeris from SUPL server.."<::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 "<first<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::cout<<"SUPL: XML Ephemeris file created"<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 + { + // Request ephemeris from SUPL server + int error; + 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::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; + 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::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) + { + 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.."<::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 "<first<second); - } - if (supl_client_ephemeris_.gps_iono.valid==true) - { - std::cout<<"SUPL: Received GPS Iono"<::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; + global_gps_almanac_queue.push(gps_alm_iter->second); + } + if (supl_client_ephemeris_.gps_iono.valid == true) + { + 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) + { + 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; + } - // Request acquisition assistance - supl_client_acquisition_.request=2; - std::cout<< "SUPL: Try read Acquisition assistance from SUPL server.."<::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 "<first<second); - } - }else{ - std::cout<< "ERROR: SUPL client for Acquisition assistance returned "<::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; + 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; + } + } + } } + + + void ControlThread::read_control_messages() { DLOG(INFO) << "Reading control messages from queue"; boost::shared_ptr 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,260 +429,286 @@ 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) + { + global_gps_acq_assist_queue.wait_and_pop(gps_acq); - // ############ 1.bis READ EPHEMERIS/UTC_MODE/IONO QUEUE #################### - Gps_Acq_Assist gps_acq; - Gps_Acq_Assist gps_acq_old; - 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; + // 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); - // DEBUG MESSAGE - std::cout << "Acquisition assistance record has arrived from SAT ID " - << gps_acq.i_satellite_PRN << " with Doppler " << gps_acq.d_Doppler0<<" [Hz] "< gps_eph_old.i_GPS_week) - { - std::cout << "Ephemeris record updated (GPS week="<gps_eph_old.d_Toe) - { - std::cout << "Ephemeris record updated (Toe="< 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 (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 + { + // 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); + } + } } 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) + { + global_galileo_ephemeris_queue.wait_and_pop(galileo_eph); - // ############ 1.bis READ EPHEMERIS/UTC_MODE/IONO QUEUE #################### - Galileo_Ephemeris galileo_eph; - Galileo_Ephemeris galileo_eph_old; - while(stop_==false) - { - global_galileo_ephemeris_queue.wait_and_pop(galileo_eph); + // DEBUG MESSAGE + std::cout << "Galileo Ephemeris record has arrived from SAT ID " + << galileo_eph.SV_ID_PRN_4 << std::endl; - // DEBUG MESSAGE - std::cout << "Galileo Ephemeris record has arrived from SAT ID " - << 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)) - { - // 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_old.IOD_ephemeris) - { - std::cout << "Galileo Ephemeris record updated in global map-- IOD_ephemeris ="< 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{ - 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); - //std::cout << "GALILEO IONO time of Week old: " << galileo_iono_old.t0t_6< 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 + { + 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); + //std::cout << "GALILEO IONO time of Week old: " << galileo_iono_old.t0t_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_old.t0t_6) - { - //std::cout << "UTC record updated --new GALILEO UTC time of Week ="< 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_old.t0t_6) + { + //std::cout << "UTC record updated --new GALILEO UTC time of Week ="< eph_copy; eph_copy = global_gps_ephemeris_map.get_map_copy(); @@ -685,53 +729,58 @@ 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::map map_copy; + //Save ephemeris to XML file + std::string xml_filename = "gps_utc_model_rx.xml"; + std::map map_copy; - map_copy=global_gps_utc_model_map.get_map_copy(); - if (map_copy.size()>0) - { - try - { - std::ofstream ofs(xml_filename.c_str(), std::ofstream::trunc | std::ofstream::out); - 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"< 0) + { + try + { + std::ofstream ofs(xml_filename.c_str(), std::ofstream::trunc | std::ofstream::out); + 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; + } + catch (std::exception& e) + { + LOG_AT_LEVEL(ERROR) << e.what(); + } + } } + + + void ControlThread::gps_iono_data_write_to_XML() { - //Save ephemeris to XML file - std::string xml_filename="gps_iono_rx.xml"; - std::map map_copy; + //Save ephemeris to XML file + std::string xml_filename = "gps_iono_rx.xml"; + std::map map_copy; std::map::iterator gps_iono_iter; - map_copy=global_gps_iono_map.get_map_copy(); - if (map_copy.size()>0) - { - try - { - std::ofstream ofs(xml_filename.c_str(), std::ofstream::trunc | std::ofstream::out); - 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"< 0) + { + try + { + std::ofstream ofs(xml_filename.c_str(), std::ofstream::trunc | std::ofstream::out); + 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; + } + catch (std::exception& e) + { + LOG_AT_LEVEL(ERROR) << e.what(); + } + } } diff --git a/src/core/receiver/control_thread.h b/src/core/receiver/control_thread.h index f248a8db5..524ccf1f4 100644 --- a/src/core/receiver/control_thread.h +++ b/src/core/receiver/control_thread.h @@ -1,5 +1,5 @@ /*! - * \file control_thread.h + * \file control_thread.h * \brief Interface of the receiver control plane * \author Carlos Aviles, 2010. carlos.avilesr(at)googlemail.com * @@ -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 control_queue */ void set_control_queue(boost::shared_ptr 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();