diff --git a/src/algorithms/tracking/adapters/gps_l1_ca_dll_pll_optim_tracking.cc b/src/algorithms/tracking/adapters/gps_l1_ca_dll_pll_optim_tracking.cc new file mode 100644 index 000000000..090815031 --- /dev/null +++ b/src/algorithms/tracking/adapters/gps_l1_ca_dll_pll_optim_tracking.cc @@ -0,0 +1,163 @@ +/*! + * \file gps_l1_ca_dll_pll_optim_tracking.cc + * \brief Interface of an adapter of a speed optimized DLL+PLL tracking loop block + * for GPS L1 C/A to a TrackingInterface + * \author Javier Arribas, 2012. jarribas(at)cttc.es + * + * GPS L1 TRACKING MODULE OPTIMIZED FOR SPEED: + * - Code Doppler is not compensated in the local replica + * Code DLL + carrier PLL according to the algorithms described in: + * K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen, + * A Software-Defined GPS and Galileo Receiver. A Single-Frequency + * Approach, Birkha user, 2007 + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2012 (see AUTHORS file for a list of contributors) + * + * 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. + * + * GNSS-SDR is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNSS-SDR. If not, see . + * + * ------------------------------------------------------------------------- + */ + +#include "gps_l1_ca_dll_pll_optim_tracking.h" +#include "GPS_L1_CA.h" +#include "configuration_interface.h" +#include +#include +#include +#include + +using google::LogMessage; + +GpsL1CaDllPllOptimTracking::GpsL1CaDllPllOptimTracking( + ConfigurationInterface* configuration, std::string role, + unsigned int in_streams, unsigned int out_streams, + gr_msg_queue_sptr queue) : + role_(role), in_streams_(in_streams), out_streams_(out_streams), + queue_(queue) +{ + + DLOG(INFO) << "role " << role; + + //################# CONFIGURATION PARAMETERS ######################## + + int fs_in; + int vector_length; + int f_if; + bool dump; + std::string dump_filename; + std::string item_type; + std::string default_item_type = "gr_complex"; + float pll_bw_hz; + float dll_bw_hz; + float early_late_space_chips; + + item_type = configuration->property(role + ".item_type",default_item_type); + //vector_length = configuration->property(role + ".vector_length", 2048); + fs_in = configuration->property("GNSS-SDR.internal_fs_hz", 2048000); + f_if = configuration->property(role + ".if", 0); + dump = configuration->property(role + ".dump", false); + pll_bw_hz = configuration->property(role + ".pll_bw_hz", 50.0); + dll_bw_hz = configuration->property(role + ".dll_bw_hz", 2.0); + early_late_space_chips = configuration->property(role + ".early_late_space_chips", 0.5); + + std::string default_dump_filename = "./track_ch"; + dump_filename = configuration->property(role + ".dump_filename", + default_dump_filename); //unused! + + vector_length = round(fs_in / (GPS_L1_CA_CODE_RATE_HZ / GPS_L1_CA_CODE_LENGTH_CHIPS)); + //################# MAKE TRACKING GNURadio object ################### + if (item_type.compare("gr_complex") == 0) + { + item_size_ = sizeof(gr_complex); + tracking_ = gps_l1_ca_dll_pll_make_optim_tracking_cc( + f_if, + fs_in, + vector_length, + queue_, + dump, + dump_filename, + pll_bw_hz, + dll_bw_hz, + early_late_space_chips); + } + else + { + LOG_AT_LEVEL(WARNING) << item_type << " unknown tracking item type."; + } + + DLOG(INFO) << "tracking(" << tracking_->unique_id() << ")"; +} + +GpsL1CaDllPllOptimTracking::~GpsL1CaDllPllOptimTracking() +{ +} + +void GpsL1CaDllPllOptimTracking::start_tracking() +{ + tracking_->start_tracking(); +} + +/* + * Set tracking channel unique ID + */ +void GpsL1CaDllPllOptimTracking::set_channel(unsigned int channel) +{ + channel_ = channel; + tracking_->set_channel(channel); +} + +/* + * Set tracking channel internal queue + */ +void GpsL1CaDllPllOptimTracking::set_channel_queue( + concurrent_queue *channel_internal_queue) +{ + channel_internal_queue_ = channel_internal_queue; + + tracking_->set_channel_queue(channel_internal_queue_); + +} + +void GpsL1CaDllPllOptimTracking::set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) +{ + tracking_->set_gnss_synchro(p_gnss_synchro); +} + +void GpsL1CaDllPllOptimTracking::connect(gr_top_block_sptr top_block) +{ + //nothing to connect, now the tracking uses gr_sync_decimator +} + +void GpsL1CaDllPllOptimTracking::disconnect(gr_top_block_sptr top_block) +{ + //nothing to disconnect, now the tracking uses gr_sync_decimator +} + +gr_basic_block_sptr GpsL1CaDllPllOptimTracking::get_left_block() +{ + return tracking_; +} + +gr_basic_block_sptr GpsL1CaDllPllOptimTracking::get_right_block() +{ + return tracking_; +} + diff --git a/src/algorithms/tracking/adapters/gps_l1_ca_dll_pll_optim_tracking.h b/src/algorithms/tracking/adapters/gps_l1_ca_dll_pll_optim_tracking.h new file mode 100644 index 000000000..b848394f1 --- /dev/null +++ b/src/algorithms/tracking/adapters/gps_l1_ca_dll_pll_optim_tracking.h @@ -0,0 +1,115 @@ +/*! + * \file gps_l1_ca_dll_pll_optim_tracking.h + * \brief Interface of an adapter of a speed optimized DLL+PLL tracking loop block + * for GPS L1 C/A to a TrackingInterface + * \author Javier Arribas, 2012. jarribas(at)cttc.es + * + * GPS L1 TRACKING MODULE OPTIMIZED FOR SPEED: + * - Code Doppler is not compensated in the local replica + * Code DLL + carrier PLL according to the algorithms described in: + * K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen, + * A Software-Defined GPS and Galileo Receiver. A Single-Frequency + * Approach, Birkha user, 2007 + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2012 (see AUTHORS file for a list of contributors) + * + * 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. + * + * GNSS-SDR is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNSS-SDR. If not, see . + * + * ------------------------------------------------------------------------- + */ + +#ifndef GNSS_SDR_GPS_L1_CA_DLL_PLL_OPTIM_TRACKING_H_ +#define GNSS_SDR_GPS_L1_CA_DLL_PLL_OPTIM_TRACKING_H_ + +#include "tracking_interface.h" +#include "gps_l1_ca_dll_pll_optim_tracking_cc.h" +#include + +class ConfigurationInterface; + +/*! + * \brief This class implements a code DLL + carrier PLL tracking loop + */ +class GpsL1CaDllPllOptimTracking : public TrackingInterface +{ + +public: + + GpsL1CaDllPllOptimTracking(ConfigurationInterface* configuration, + std::string role, + unsigned int in_streams, + unsigned int out_streams, + gr_msg_queue_sptr queue); + + virtual ~GpsL1CaDllPllOptimTracking(); + + std::string role() + { + return role_; + } + std::string implementation() + { + return "GPS_L1_CA_DLL_PLL_Optim_Tracking"; + } + size_t item_size() + { + return item_size_; + } + + void connect(gr_top_block_sptr top_block); + void disconnect(gr_top_block_sptr top_block); + gr_basic_block_sptr get_left_block(); + gr_basic_block_sptr get_right_block(); + + + /*! + * \brief Set tracking channel unique ID + */ + void set_channel(unsigned int channel); + + /*! + * \brief Set acquisition/tracking common Gnss_Synchro object pointer + * to efficiently exchange synchronization data between acquisition and tracking blocks + */ + void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro); + + /*! + * \brief Set tracking channel internal queue + */ + void set_channel_queue(concurrent_queue *channel_internal_queue); + + void start_tracking(); + +private: + + gps_l1_ca_dll_pll_optim_tracking_cc_sptr tracking_; + size_t item_size_; + + unsigned int channel_; + + std::string role_; + unsigned int in_streams_; + unsigned int out_streams_; + gr_msg_queue_sptr queue_; + concurrent_queue *channel_internal_queue_; +}; + +#endif // GNSS_SDR_GPS_L1_CA_DLL_PLL_OPTIM_TRACKING_H_ diff --git a/src/algorithms/tracking/adapters/jamfile.jam b/src/algorithms/tracking/adapters/jamfile.jam index a81b55b40..5393be324 100644 --- a/src/algorithms/tracking/adapters/jamfile.jam +++ b/src/algorithms/tracking/adapters/jamfile.jam @@ -3,4 +3,5 @@ project : build-dir ../../../../build ; obj gps_l1_ca_dll_pll_tracking : gps_l1_ca_dll_pll_tracking.cc : darwin:GNSS_SDR_USE_BOOST_ROUND ; obj gps_l1_ca_dll_fll_pll_tracking : gps_l1_ca_dll_fll_pll_tracking.cc : darwin:GNSS_SDR_USE_BOOST_ROUND ; obj gps_l1_ca_tcp_connector_tracking : gps_l1_ca_tcp_connector_tracking.cc : darwin:GNSS_SDR_USE_BOOST_ROUND ; -obj galileo_e1_dll_pll_veml_tracking : galileo_e1_dll_pll_veml_tracking.cc : darwin:GNSS_SDR_USE_BOOST_ROUND ; \ No newline at end of file +obj galileo_e1_dll_pll_veml_tracking : galileo_e1_dll_pll_veml_tracking.cc : darwin:GNSS_SDR_USE_BOOST_ROUND ; +obj gps_l1_ca_dll_pll_optim_tracking : gps_l1_ca_dll_pll_optim_tracking.cc : darwin:GNSS_SDR_USE_BOOST_ROUND ; \ No newline at end of file diff --git a/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_optim_tracking_cc.cc b/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_optim_tracking_cc.cc new file mode 100644 index 000000000..a1d09810b --- /dev/null +++ b/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_optim_tracking_cc.cc @@ -0,0 +1,688 @@ +/*! + * \file gps_l1_ca_dll_pll_optim_tracking_cc.cc + * \brief Implementation of a code DLL + carrier PLL tracking block + * \author Javier Arribas, 2012. jarribas(at)cttc.es + * GPS L1 TRACKING MODULE OPTIMIZED FOR SPEED: + * - Code Doppler is not compensated in the local replica + * Code DLL + carrier PLL according to the algorithms described in: + * [1] K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen, + * A Software-Defined GPS and Galileo Receiver. A Single-Frequency + * Approach, Birkha user, 2007 + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2012 (see AUTHORS file for a list of contributors) + * + * 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. + * + * GNSS-SDR is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNSS-SDR. If not, see . + * + * ------------------------------------------------------------------------- + */ + +#include "gnss_synchro.h" +#include "gps_l1_ca_dll_pll_optim_tracking_cc.h" +#include "gps_sdr_signal_processing.h" +#include "tracking_discriminators.h" +#include "CN_estimators.h" +#include "GPS_L1_CA.h" +#include "control_message_factory.h" +#include +#include +#include +#include +#include "math.h" +#include +#include +#include +#include + +/*! + * \todo Include in definition header file + */ +#define CN0_ESTIMATION_SAMPLES 10 +#define MINIMUM_VALID_CN0 25 +#define MAXIMUM_LOCK_FAIL_COUNTER 200 + + +using google::LogMessage; + +gps_l1_ca_dll_pll_optim_tracking_cc_sptr +gps_l1_ca_dll_pll_make_optim_tracking_cc( + long if_freq, + long fs_in, + unsigned int vector_length, + gr_msg_queue_sptr queue, + bool dump, + std::string dump_filename, + float pll_bw_hz, + float dll_bw_hz, + float early_late_space_chips) +{ + return gps_l1_ca_dll_pll_optim_tracking_cc_sptr(new Gps_L1_Ca_Dll_Pll_Optim_Tracking_cc(if_freq, + fs_in, vector_length, queue, dump, dump_filename, pll_bw_hz, dll_bw_hz, early_late_space_chips)); +} + + + +void Gps_L1_Ca_Dll_Pll_Optim_Tracking_cc::forecast (int noutput_items, + gr_vector_int &ninput_items_required) +{ + ninput_items_required[0] = (int)d_vector_length*2; //set the required available samples in each call +} + + + +Gps_L1_Ca_Dll_Pll_Optim_Tracking_cc::Gps_L1_Ca_Dll_Pll_Optim_Tracking_cc( + long if_freq, + long fs_in, + unsigned int vector_length, + gr_msg_queue_sptr queue, + bool dump, + std::string dump_filename, + float pll_bw_hz, + float dll_bw_hz, + float early_late_space_chips) : + gr_block ("Gps_L1_Ca_Dll_Pll_Tracking_cc", gr_make_io_signature (1, 1, sizeof(gr_complex)), + gr_make_io_signature(1, 1, sizeof(Gnss_Synchro))) +{ + + //gr_sync_decimator ("Gps_L1_Ca_Dll_Pll_Tracking_cc", gr_make_io_signature (1, 1, sizeof(gr_complex)), + // gr_make_io_signature(3, 3, sizeof(float)),vector_length) { + // initialize internal vars + d_queue = queue; + d_dump = dump; + d_if_freq = if_freq; + d_fs_in = fs_in; + d_vector_length = vector_length; + d_dump_filename = dump_filename; + + // Initialize tracking ========================================== + + d_code_loop_filter.set_DLL_BW(dll_bw_hz); + d_carrier_loop_filter.set_PLL_BW(pll_bw_hz); + + //--- DLL variables -------------------------------------------------------- + d_early_late_spc_chips = early_late_space_chips; // Define early-late offset (in chips) + + // Initialization of local code replica + // Get space for a vector with the C/A code replica sampled 1x/chip + d_ca_code = new gr_complex[(int)GPS_L1_CA_CODE_LENGTH_CHIPS + 2]; + + + + d_carr_sign = new gr_complex[d_vector_length*2]; + + /* If an array is partitioned for more than one thread to operate on, + * having the sub-array boundaries unaligned to cache lines could lead + * to performance degradation. Here we allocate memory + * (gr_comlex array of size 2*d_vector_length) aligned to cache of 16 bytes + */ + // todo: do something if posix_memalign fails + // Get space for the resampled early / prompt / late local replicas + if (posix_memalign((void**)&d_early_code, 16, d_vector_length * sizeof(gr_complex) * 2) == 0){}; + if (posix_memalign((void**)&d_late_code, 16, d_vector_length * sizeof(gr_complex) * 2) == 0){}; + if (posix_memalign((void**)&d_prompt_code, 16, d_vector_length * sizeof(gr_complex) * 2) == 0){}; + // space for carrier wipeoff and signal baseband vectors + if (posix_memalign((void**)&d_carr_sign, 16, d_vector_length * sizeof(gr_complex) * 2) == 0){}; + // correlator outputs (scalar) + if (posix_memalign((void**)&d_Early, 16, sizeof(gr_complex)) == 0){}; + if (posix_memalign((void**)&d_Prompt, 16, sizeof(gr_complex)) == 0){}; + if (posix_memalign((void**)&d_Late, 16, sizeof(gr_complex)) == 0){}; + + + //--- Perform initializations ------------------------------ + // define initial code frequency basis of NCO + d_code_freq_hz = GPS_L1_CA_CODE_RATE_HZ; + // define residual code phase (in chips) + d_rem_code_phase_samples = 0.0; + // define residual carrier phase + d_rem_carr_phase_rad = 0.0; + + // sample synchronization + d_sample_counter = 0; + //d_sample_counter_seconds = 0; + d_acq_sample_stamp = 0; + + d_enable_tracking = false; + d_pull_in = false; + d_last_seg = 0; + + d_current_prn_length_samples = (int)d_vector_length; + + // CN0 estimation and lock detector buffers + d_cn0_estimation_counter = 0; + d_Prompt_buffer = new gr_complex[CN0_ESTIMATION_SAMPLES]; + d_carrier_lock_test = 1; + d_CN0_SNV_dB_Hz = 0; + d_carrier_lock_fail_counter = 0; + d_carrier_lock_threshold = 20; + + systemName["G"] = std::string("GPS"); + systemName["R"] = std::string("GLONASS"); + systemName["S"] = std::string("SBAS"); + systemName["E"] = std::string("Galileo"); + systemName["C"] = std::string("Compass"); +} + +void Gps_L1_Ca_Dll_Pll_Optim_Tracking_cc::start_tracking() +{ + /* + * correct the code phase according to the delay between acq and trk + */ + + d_acq_code_phase_samples = d_acquisition_gnss_synchro->Acq_delay_samples; + d_acq_carrier_doppler_hz = d_acquisition_gnss_synchro->Acq_doppler_hz; + d_acq_sample_stamp = d_acquisition_gnss_synchro->Acq_samplestamp_samples; + + unsigned long int acq_trk_diff_samples; + float acq_trk_diff_seconds; + acq_trk_diff_samples = d_sample_counter - d_acq_sample_stamp;//-d_vector_length; + std::cout << "acq_trk_diff_samples=" << acq_trk_diff_samples << std::endl; + acq_trk_diff_seconds = (float)acq_trk_diff_samples / (float)d_fs_in; + //doppler effect + // Fd=(C/(C+Vr))*F + float radial_velocity; + radial_velocity = (GPS_L1_FREQ_HZ + d_acq_carrier_doppler_hz)/GPS_L1_FREQ_HZ; + // new chip and prn sequence periods based on acq Doppler + float T_chip_mod_seconds; + float T_prn_mod_seconds; + float T_prn_mod_samples; + d_code_freq_hz = radial_velocity * GPS_L1_CA_CODE_RATE_HZ; + T_chip_mod_seconds = 1/d_code_freq_hz; + T_prn_mod_seconds = T_chip_mod_seconds * GPS_L1_CA_CODE_LENGTH_CHIPS; + T_prn_mod_samples = T_prn_mod_seconds * (float)d_fs_in; + + d_next_prn_length_samples = round(T_prn_mod_samples); + + float T_prn_true_seconds = GPS_L1_CA_CODE_LENGTH_CHIPS / GPS_L1_CA_CODE_RATE_HZ; + float T_prn_true_samples = T_prn_true_seconds * (float)d_fs_in; + float T_prn_diff_seconds; + T_prn_diff_seconds = T_prn_true_seconds - T_prn_mod_seconds; + float N_prn_diff; + N_prn_diff = acq_trk_diff_seconds / T_prn_true_seconds; + float corrected_acq_phase_samples, delay_correction_samples; + corrected_acq_phase_samples = fmod((d_acq_code_phase_samples + T_prn_diff_seconds * N_prn_diff * (float)d_fs_in), T_prn_true_samples); + if (corrected_acq_phase_samples < 0) + { + corrected_acq_phase_samples = T_prn_mod_samples + corrected_acq_phase_samples; + } + delay_correction_samples = d_acq_code_phase_samples - corrected_acq_phase_samples; + + d_acq_code_phase_samples = corrected_acq_phase_samples; + + d_carrier_doppler_hz = d_acq_carrier_doppler_hz; + // DLL/PLL filter initialization + d_carrier_loop_filter.initialize(d_carrier_doppler_hz); //initialize the carrier filter + d_code_loop_filter.initialize(d_acq_code_phase_samples); //initialize the code filter + + // generate local reference ALWAYS starting at chip 1 (1 sample per chip) + gps_l1_ca_code_gen_complex(&d_ca_code[1], d_acquisition_gnss_synchro->PRN, 0); + d_ca_code[0] = d_ca_code[(int)GPS_L1_CA_CODE_LENGTH_CHIPS]; + d_ca_code[(int)GPS_L1_CA_CODE_LENGTH_CHIPS + 1] = d_ca_code[1]; + + + //****************************************************************************** + // Experimental: pre-sampled local signal replica at nominal code frequency. + // No code doppler correction + + // unified loop for E, P, L code vectors + double code_phase_step_chips; + code_phase_step_chips = (GPS_L1_CA_CODE_RATE_HZ / (double)d_fs_in); + double tcode_chips = 0; + // Alternative EPL code generation (40% of speed improvement!) + int early_late_spc_samples; + early_late_spc_samples=round(d_early_late_spc_chips/code_phase_step_chips); + double epl_loop_length_samples; + epl_loop_length_samples=d_current_prn_length_samples+early_late_spc_samples*2; + int associated_chip_index; + int code_length_chips = (int)GPS_L1_CA_CODE_LENGTH_CHIPS; + for (int i=0; iSystem; + sys = sys_.substr(0,1); + + // DEBUG OUTPUT + std::cout << "Tracking start on channel " << d_channel << " for satellite " << Gnss_Satellite(systemName[sys], d_acquisition_gnss_synchro->PRN) << std::endl; + DLOG(INFO) << "Start tracking for satellite " << Gnss_Satellite(systemName[sys], d_acquisition_gnss_synchro->PRN) << " received" << std::endl; + + // enable tracking + d_pull_in = true; + d_enable_tracking = true; + + std::cout << "PULL-IN Doppler [Hz]=" << d_carrier_doppler_hz + << " Code Phase correction [samples]=" << delay_correction_samples + << " PULL-IN Code Phase [samples]=" << d_acq_code_phase_samples << std::endl; +} + + +void Gps_L1_Ca_Dll_Pll_Optim_Tracking_cc::update_local_code() +{ + double tcode_chips; + double rem_code_phase_chips; + int associated_chip_index; + int code_length_chips = (int)GPS_L1_CA_CODE_LENGTH_CHIPS; + double code_phase_step_chips; + int early_late_spc_samples; + int epl_loop_length_samples; + + // unified loop for E, P, L code vectors + code_phase_step_chips = ((double)d_code_freq_hz) / ((double)d_fs_in); + rem_code_phase_chips = d_rem_code_phase_samples * (d_code_freq_hz / d_fs_in); + tcode_chips = -rem_code_phase_chips; + + // Alternative EPL code generation (40% of speed improvement!) + early_late_spc_samples=round(d_early_late_spc_chips/code_phase_step_chips); + epl_loop_length_samples=d_current_prn_length_samples+early_late_spc_samples*2; + for (int i=0; itelemetry_decoder + Gnss_Synchro current_synchro_data; + // Fill the acquisition data + current_synchro_data = *d_acquisition_gnss_synchro; + + const gr_complex* in = (gr_complex*) input_items[0]; //PRN start block alignement + Gnss_Synchro **out = (Gnss_Synchro **) &output_items[0]; + + // Update the prn length based on code freq (variable) and + // sampling frequency (fixed) + // variable code PRN sample block size + d_current_prn_length_samples = d_next_prn_length_samples; + + //update_local_code(); + update_local_carrier(); + + // perform Early, Prompt and Late correlation + d_correlator.Carrier_wipeoff_and_EPL_volk(d_current_prn_length_samples, + in, + d_carr_sign, + d_early_code, + d_prompt_code, + d_late_code, + d_Early, + d_Prompt, + d_Late, + is_unaligned()); + + // check for samples consistency (this should be done before in the receiver / here only if the source is a file) + if (std::isnan((*d_Prompt).real()) == true or std::isnan((*d_Prompt).imag()) == true )// or std::isinf(in[i].real())==true or std::isinf(in[i].imag())==true) + { + const int samples_available = ninput_items[0]; + d_sample_counter = d_sample_counter + samples_available; + LOG_AT_LEVEL(WARNING) << "Detected NaN samples at sample number " << d_sample_counter; + consume_each(samples_available); + + // make an output to not stop the rest of the processing blocks + current_synchro_data.Prompt_I=0.0; + current_synchro_data.Prompt_Q=0.0; + current_synchro_data.Tracking_timestamp_secs=(double)d_sample_counter/(double)d_fs_in; + current_synchro_data.Carrier_phase_rads=0.0; + current_synchro_data.Code_phase_secs=0.0; + current_synchro_data.CN0_dB_hz=0.0; + current_synchro_data.Flag_valid_tracking=false; + + *out[0] =current_synchro_data; + + return 1; + } + + // Compute PLL error and update carrier NCO - + carr_error = pll_cloop_two_quadrant_atan(*d_Prompt) / (float)GPS_TWO_PI; + // Implement carrier loop filter and generate NCO command + carr_nco = d_carrier_loop_filter.get_carrier_nco(carr_error); + // Modify carrier freq based on NCO command + d_carrier_doppler_hz = d_acq_carrier_doppler_hz + carr_nco; + + // Compute DLL error and update code NCO + code_error = dll_nc_e_minus_l_normalized(*d_Early, *d_Late); + // Implement code loop filter and generate NCO command + code_nco = d_code_loop_filter.get_code_nco(code_error); + // Modify code freq based on NCO command + d_code_freq_hz = GPS_L1_CA_CODE_RATE_HZ - code_nco; + + // Update the phasestep based on code freq (variable) and + // sampling frequency (fixed) + d_code_phase_step_chips = d_code_freq_hz / (float)d_fs_in; //[chips] + // variable code PRN sample block size + float T_chip_seconds; + float T_prn_seconds; + float T_prn_samples; + float K_blk_samples; + T_chip_seconds = 1 / d_code_freq_hz; + T_prn_seconds = T_chip_seconds * GPS_L1_CA_CODE_LENGTH_CHIPS; + T_prn_samples = T_prn_seconds * d_fs_in; + d_rem_code_phase_samples = d_next_rem_code_phase_samples; + K_blk_samples = T_prn_samples + d_rem_code_phase_samples; + d_next_prn_length_samples = round(K_blk_samples); //round to a discrete samples + d_next_rem_code_phase_samples = K_blk_samples - d_next_prn_length_samples; //rounding error + + /*! + * \todo Improve the lock detection algorithm! + */ + // ####### CN0 ESTIMATION AND LOCK DETECTORS ###### + if (d_cn0_estimation_counter < CN0_ESTIMATION_SAMPLES) + { + // fill buffer with prompt correlator output values + d_Prompt_buffer[d_cn0_estimation_counter] = *d_Prompt; + d_cn0_estimation_counter++; + } + else + { + d_cn0_estimation_counter = 0; + d_CN0_SNV_dB_Hz = gps_l1_ca_CN0_SNV(d_Prompt_buffer, CN0_ESTIMATION_SAMPLES, d_fs_in); + d_carrier_lock_test = carrier_lock_detector(d_Prompt_buffer, CN0_ESTIMATION_SAMPLES); + // ###### TRACKING UNLOCK NOTIFICATION ##### + if (std::abs(d_carrier_lock_test) > d_carrier_lock_threshold or d_CN0_SNV_dB_Hz < MINIMUM_VALID_CN0) + { + d_carrier_lock_fail_counter++; + } + else + { + if (d_carrier_lock_fail_counter > 0) d_carrier_lock_fail_counter--; + } + if (d_carrier_lock_fail_counter > MAXIMUM_LOCK_FAIL_COUNTER) + { + std::cout << "Channel " << d_channel << " loss of lock!" << std::endl ; + //tracking_message = 3; //loss of lock + //d_channel_internal_queue->push(tracking_message); + ControlMessageFactory* cmf = new ControlMessageFactory(); + if (d_queue != gr_msg_queue_sptr()) { + d_queue->handle(cmf->GetQueueMessage(d_channel, 2)); + } + delete cmf; + d_carrier_lock_fail_counter = 0; + d_enable_tracking = false; // TODO: check if disabling tracking is consistent with the channel state machine + + } + //std::cout<<"d_carrier_lock_fail_counter"<PRN) + << ", CN0 = " << d_CN0_SNV_dB_Hz << " [dB-Hz]" << std::endl; + //std::cout<<"TRK CH "<PRN) + << ", CN0 = " << d_CN0_SNV_dB_Hz << " [dB-Hz]" << std::endl; + //std::cout<<"TRK CH "<(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 << "Tracking 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; + } + } + } +} + + + +void Gps_L1_Ca_Dll_Pll_Optim_Tracking_cc::set_channel_queue(concurrent_queue *channel_internal_queue) +{ + d_channel_internal_queue = channel_internal_queue; +} + +void Gps_L1_Ca_Dll_Pll_Optim_Tracking_cc::set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) +{ + d_acquisition_gnss_synchro = p_gnss_synchro; + +} diff --git a/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_optim_tracking_cc.h b/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_optim_tracking_cc.h new file mode 100644 index 000000000..1f7c5fb3d --- /dev/null +++ b/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_optim_tracking_cc.h @@ -0,0 +1,202 @@ +/*! + * \file gps_l1_ca_dll_pll_optim_tracking_cc.h + * \brief Implementation of a code DLL + carrier PLL tracking block + * \author Javier Arribas, 2012. jarribas(at)cttc.es + * GPS L1 TRACKING MODULE OPTIMIZED FOR SPEED: + * - Code Doppler is not compensated in the local replica + * Code DLL + carrier PLL according to the algorithms described in: + * [1] K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen, + * A Software-Defined GPS and Galileo Receiver. A Single-Frequency + * Approach, Birkha user, 2007 + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2012 (see AUTHORS file for a list of contributors) + * + * 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. + * + * GNSS-SDR is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNSS-SDR. If not, see . + * + * ------------------------------------------------------------------------- + */ + +#ifndef GNSS_SDR_GPS_L1_CA_DLL_PLL_OPTIM_TRACKING_CC_H +#define GNSS_SDR_GPS_L1_CA_DLL_PLL_TRACKING_CC_H + +#include +#include +#include +#include +#include +#include +//#include +#include "concurrent_queue.h" +#include "gps_sdr_signal_processing.h" +#include "gnss_synchro.h" +#include "tracking_2nd_DLL_filter.h" +#include "tracking_2nd_PLL_filter.h" + +#include "correlator.h" + + + +class Gps_L1_Ca_Dll_Pll_Optim_Tracking_cc; +typedef boost::shared_ptr + gps_l1_ca_dll_pll_optim_tracking_cc_sptr; + +gps_l1_ca_dll_pll_optim_tracking_cc_sptr +gps_l1_ca_dll_pll_make_optim_tracking_cc(long if_freq, + long fs_in, unsigned + int vector_length, + gr_msg_queue_sptr queue, + bool dump, + std::string dump_filename, + float pll_bw_hz, + float dll_bw_hz, + float early_late_space_chips); + +//class gps_l1_ca_dll_pll_tracking_cc: public gr_sync_decimator + +/*! + * \brief This class implements a DLL + PLL tracking loop block + */ +class Gps_L1_Ca_Dll_Pll_Optim_Tracking_cc: public gr_block +{ +public: + + ~Gps_L1_Ca_Dll_Pll_Optim_Tracking_cc(); + + void set_channel(unsigned int channel); + void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro); + void start_tracking(); + void set_channel_queue(concurrent_queue *channel_internal_queue); + + /* + * \brief just like gr_block::general_work, only this arranges to call consume_each for you + * + * The user must override work to define the signal processing code + */ + + int general_work (int noutput_items, gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); + + void forecast (int noutput_items, gr_vector_int &ninput_items_required); + + +private: + + friend gps_l1_ca_dll_pll_optim_tracking_cc_sptr + gps_l1_ca_dll_pll_make_optim_tracking_cc(long if_freq, + long fs_in, unsigned + int vector_length, + gr_msg_queue_sptr queue, + bool dump, + std::string dump_filename, + float pll_bw_hz, + float dll_bw_hz, + float early_late_space_chips); + + Gps_L1_Ca_Dll_Pll_Optim_Tracking_cc(long if_freq, + long fs_in, unsigned + int vector_length, + gr_msg_queue_sptr queue, + bool dump, + std::string dump_filename, + float pll_bw_hz, + float dll_bw_hz, + float early_late_space_chips); + void update_local_code(); + void update_local_carrier(); + + // tracking configuration vars + gr_msg_queue_sptr d_queue; + concurrent_queue *d_channel_internal_queue; + unsigned int d_vector_length; + bool d_dump; + + Gnss_Synchro* d_acquisition_gnss_synchro; + unsigned int d_channel; + int d_last_seg; + long d_if_freq; + long d_fs_in; + + double d_early_late_spc_chips; + + double d_code_phase_step_chips; + + gr_complex* d_ca_code; + + gr_complex* d_early_code; + gr_complex* d_late_code; + gr_complex* d_prompt_code; + gr_complex* d_carr_sign; + + gr_complex *d_Early; + gr_complex *d_Prompt; + gr_complex *d_Late; + + // remaining code phase and carrier phase between tracking loops + float d_rem_code_phase_samples; + float d_next_rem_code_phase_samples; + float d_rem_carr_phase_rad; + + // PLL and DLL filter library + Tracking_2nd_DLL_filter d_code_loop_filter; + Tracking_2nd_PLL_filter d_carrier_loop_filter; + + // acquisition + float d_acq_code_phase_samples; + float d_acq_carrier_doppler_hz; + // correlator + Correlator d_correlator; + + // tracking vars + float d_code_freq_hz; + float d_carrier_doppler_hz; + float d_acc_carrier_phase_rad; + float d_code_phase_samples; + + //PRN period in samples + int d_current_prn_length_samples; + int d_next_prn_length_samples; + //double d_sample_counter_seconds; + + //processing samples counters + unsigned long int d_sample_counter; + unsigned long int d_acq_sample_stamp; + + // CN0 estimation and lock detector + int d_cn0_estimation_counter; + gr_complex* d_Prompt_buffer; + float d_carrier_lock_test; + float d_CN0_SNV_dB_Hz; + float d_carrier_lock_threshold; + int d_carrier_lock_fail_counter; + + // control vars + bool d_enable_tracking; + bool d_pull_in; + + // file dump + std::string d_dump_filename; + std::ofstream d_dump_file; + + std::map systemName; + std::string sys; +}; + +#endif //GNSS_SDR_GPS_L1_CA_DLL_PLL_OPTIM_TRACKING_CC_H diff --git a/src/algorithms/tracking/gnuradio_blocks/jamfile.jam b/src/algorithms/tracking/gnuradio_blocks/jamfile.jam index 7be2fd5d6..d2d2d50e0 100644 --- a/src/algorithms/tracking/gnuradio_blocks/jamfile.jam +++ b/src/algorithms/tracking/gnuradio_blocks/jamfile.jam @@ -4,3 +4,4 @@ obj gps_l1_ca_dll_pll_tracking_cc : gps_l1_ca_dll_pll_tracking_cc.cc : obj gps_l1_ca_dll_fll_pll_tracking_cc : gps_l1_ca_dll_fll_pll_tracking_cc.cc : darwin:GNSS_SDR_USE_BOOST_ROUND ; obj gps_l1_ca_tcp_connector_tracking_cc : gps_l1_ca_tcp_connector_tracking_cc.cc : darwin:GNSS_SDR_USE_BOOST_ROUND ; obj galileo_e1_dll_pll_veml_tracking_cc : galileo_e1_dll_pll_veml_tracking_cc.cc : darwin:GNSS_SDR_USE_BOOST_ROUND ; +obj gps_l1_ca_dll_pll_optim_tracking_cc : gps_l1_ca_dll_pll_optim_tracking_cc.cc : darwin:GNSS_SDR_USE_BOOST_ROUND ; diff --git a/src/core/receiver/gnss_block_factory.cc b/src/core/receiver/gnss_block_factory.cc index 8c5a8608d..6ea2d25d8 100644 --- a/src/core/receiver/gnss_block_factory.cc +++ b/src/core/receiver/gnss_block_factory.cc @@ -56,6 +56,7 @@ #include "gps_l1_ca_pcps_acquisition.h" #include "galileo_e1_pcps_ambiguous_acquisition.h" #include "gps_l1_ca_dll_pll_tracking.h" +#include "gps_l1_ca_dll_pll_optim_tracking.h" #include "gps_l1_ca_dll_fll_pll_tracking.h" #include "gps_l1_ca_tcp_connector_tracking.h" #include "galileo_e1_dll_pll_veml_tracking.h" @@ -352,6 +353,11 @@ GNSSBlockInterface* GNSSBlockFactory::GetBlock( block = new GpsL1CaDllPllTracking(configuration, role, in_streams, out_streams, queue); } + else if (implementation.compare("GPS_L1_CA_DLL_PLL_Optim_Tracking") == 0) + { + block = new GpsL1CaDllPllOptimTracking(configuration, role, in_streams, + out_streams, queue); + } else if (implementation.compare("GPS_L1_CA_DLL_FLL_PLL_Tracking") == 0) { block = new GpsL1CaDllFllPllTracking(configuration, role, in_streams, diff --git a/src/main/jamfile.jam b/src/main/jamfile.jam index 586a5df66..c744f7850 100644 --- a/src/main/jamfile.jam +++ b/src/main/jamfile.jam @@ -51,10 +51,12 @@ exe gnss-sdr : main.cc ../algorithms/PVT/adapters//gps_l1_ca_pvt ../algorithms/PVT/gnuradio_blocks//gps_l1_ca_pvt_cc ../algorithms/tracking/adapters//gps_l1_ca_dll_pll_tracking +../algorithms/tracking/adapters//gps_l1_ca_dll_pll_optim_tracking ../algorithms/tracking/adapters//gps_l1_ca_dll_fll_pll_tracking ../algorithms/tracking/adapters//gps_l1_ca_tcp_connector_tracking ../algorithms/tracking/adapters//galileo_e1_dll_pll_veml_tracking ../algorithms/tracking/gnuradio_blocks//gps_l1_ca_dll_pll_tracking_cc +../algorithms/tracking/gnuradio_blocks//gps_l1_ca_dll_pll_optim_tracking_cc ../algorithms/tracking/gnuradio_blocks//gps_l1_ca_dll_fll_pll_tracking_cc ../algorithms/tracking/gnuradio_blocks//gps_l1_ca_tcp_connector_tracking_cc ../algorithms/tracking/gnuradio_blocks//galileo_e1_dll_pll_veml_tracking_cc diff --git a/src/tests/jamfile.jam b/src/tests/jamfile.jam index 291b4fdb5..249e0e3ae 100644 --- a/src/tests/jamfile.jam +++ b/src/tests/jamfile.jam @@ -48,10 +48,12 @@ exe run_tests : test_main.cc ../algorithms/PVT/adapters//gps_l1_ca_pvt ../algorithms/PVT/gnuradio_blocks//gps_l1_ca_pvt_cc ../algorithms/tracking/adapters//gps_l1_ca_dll_pll_tracking +../algorithms/tracking/adapters//gps_l1_ca_dll_pll_optim_tracking ../algorithms/tracking/adapters//gps_l1_ca_dll_fll_pll_tracking ../algorithms/tracking/adapters//gps_l1_ca_tcp_connector_tracking ../algorithms/tracking/adapters//galileo_e1_dll_pll_veml_tracking ../algorithms/tracking/gnuradio_blocks//gps_l1_ca_dll_pll_tracking_cc +../algorithms/tracking/gnuradio_blocks//gps_l1_ca_dll_pll_optim_tracking_cc ../algorithms/tracking/gnuradio_blocks//gps_l1_ca_dll_fll_pll_tracking_cc ../algorithms/tracking/gnuradio_blocks//gps_l1_ca_tcp_connector_tracking_cc ../algorithms/tracking/gnuradio_blocks//galileo_e1_dll_pll_veml_tracking_cc