From 7d6ec42f2436d3b281380cf85076f1b8c2de7c9f Mon Sep 17 00:00:00 2001 From: marc-sales Date: Mon, 7 Jul 2014 21:06:26 +0200 Subject: [PATCH] coherent 2or3 ms adding noncoherently I+Q acquisition, dll+pll tracking still diverges --- conf/gnss-sdr_Galileo_E5a.conf | 7 +- .../acquisition/adapters/CMakeLists.txt | 2 + ...ileo_e5a_3ms_noncoherent_iq_acquisition.cc | 316 ++++++++++ ...lileo_e5a_3ms_noncoherent_iq_acquisition.h | 157 +++++ .../gnuradio_blocks/CMakeLists.txt | 2 + ...o_e5a_3ms_noncoherent_iq_acquisition_cc.cc | 592 ++++++++++++++++++ ...eo_e5a_3ms_noncoherent_iq_acquisition_cc.h | 237 +++++++ .../libs/galileo_e5_signal_processing.cc | 2 +- .../gnuradio_blocks/signal_generator_c.cc | 34 +- .../galileo_e5a_dll_pll_tracking_cc.cc | 428 ++++++++----- .../galileo_e5a_dll_pll_tracking_cc.h | 38 +- src/core/receiver/gnss_block_factory.cc | 13 + ...cps_acquisition_gsoc2014_gensource_test.cc | 236 ++++--- .../gnss_block/galileo_e5a_tracking_test.cc | 82 ++- 14 files changed, 1886 insertions(+), 260 deletions(-) create mode 100644 src/algorithms/acquisition/adapters/galileo_e5a_3ms_noncoherent_iq_acquisition.cc create mode 100644 src/algorithms/acquisition/adapters/galileo_e5a_3ms_noncoherent_iq_acquisition.h create mode 100644 src/algorithms/acquisition/gnuradio_blocks/galileo_e5a_3ms_noncoherent_iq_acquisition_cc.cc create mode 100644 src/algorithms/acquisition/gnuradio_blocks/galileo_e5a_3ms_noncoherent_iq_acquisition_cc.h diff --git a/conf/gnss-sdr_Galileo_E5a.conf b/conf/gnss-sdr_Galileo_E5a.conf index 1a1c494af..5ba2daa46 100644 --- a/conf/gnss-sdr_Galileo_E5a.conf +++ b/conf/gnss-sdr_Galileo_E5a.conf @@ -31,7 +31,10 @@ SignalSource.implementation=File_Signal_Source ;#filename: path to file with the captured GNSS signal samples to be processed ;SignalSource.filename=/home/marc/E5a_acquisitions/signal_source_5X_primary.dat ;SignalSource.filename=/home/marc/E5a_acquisitions/galileo_E5_8M_r2_upsampled_12.dat -SignalSource.filename=/home/marc/E5a_acquisitions/Tiered_sim_4sat_stup4_2s_up.dat +;SignalSource.filename=/home/marc/E5a_acquisitions/Tiered_sim_4sat_stup4_2s_up.dat +SignalSource.filename=/home/marc/E5a_acquisitions/signal_source_sec21M_long.dat + + ;#item_type: Type and resolution for each of the signal samples. Use only gr_complex in this version. SignalSource.item_type=gr_complex @@ -288,7 +291,7 @@ Acquisition.if=0 ;#sampled_ms: Signal block duration for the acquisition signal detection [ms] Acquisition.coherent_integration_time_ms=2 ;#implementation: Acquisition algorithm selection for this channel: [GPS_L1_CA_PCPS_Acquisition] or [Galileo_E1_PCPS_Ambiguous_Acquisition] -Acquisition.implementation=Galileo_E5ax_2ms_Pcps_Acquisition +Acquisition.implementation=Galileo_E5a_3ms_Noncoherent_IQ_Acquisition ;#threshold: Acquisition threshold. It will be ignored if pfa is defined. Acquisition.threshold=0.0005 ;#pfa: Acquisition false alarm probability. This option overrides the threshold option. Only use with implementations: [GPS_L1_CA_PCPS_Acquisition] or [Galileo_E1_PCPS_Ambiguous_Acquisition] diff --git a/src/algorithms/acquisition/adapters/CMakeLists.txt b/src/algorithms/acquisition/adapters/CMakeLists.txt index 2618844ee..16dc96583 100644 --- a/src/algorithms/acquisition/adapters/CMakeLists.txt +++ b/src/algorithms/acquisition/adapters/CMakeLists.txt @@ -31,6 +31,7 @@ if(OPENCL_FOUND) galileo_e5a_pcps_acquisition.cc galileo_e5a_pilot_3ms_acquisition.cc galileo_e5ax_2ms_pcps_acquisition.cc + galileo_e5a_3ms_noncoherent_iq_acquisition.cc ) else(OPENCL_FOUND) set(ACQ_ADAPTER_SOURCES @@ -46,6 +47,7 @@ else(OPENCL_FOUND) galileo_e5a_pcps_acquisition.cc galileo_e5a_pilot_3ms_acquisition.cc galileo_e5ax_2ms_pcps_acquisition.cc + galileo_e5a_3ms_noncoherent_iq_acquisition.cc ) endif(OPENCL_FOUND) diff --git a/src/algorithms/acquisition/adapters/galileo_e5a_3ms_noncoherent_iq_acquisition.cc b/src/algorithms/acquisition/adapters/galileo_e5a_3ms_noncoherent_iq_acquisition.cc new file mode 100644 index 000000000..9690e0282 --- /dev/null +++ b/src/algorithms/acquisition/adapters/galileo_e5a_3ms_noncoherent_iq_acquisition.cc @@ -0,0 +1,316 @@ +/*! + * \file galileo_e5a_3ms_noncoherent_iq_acquisition.cc + * \brief Adapts a PCPS acquisition block to an AcquisitionInterface for + * Galileo E5a data and pilot Signals + * \author Marc Sales, 2014. marcsales92(at)gmail.com + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2014 (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 "galileo_e5a_3ms_noncoherent_iq_acquisition.h" +#include +#include +#include +#include +#include +#include +#include "galileo_e5_signal_processing.h" +#include "Galileo_E5a.h" +#include "configuration_interface.h" +//#include + +using google::LogMessage; + +GalileoE5a3msNoncoherentIQAcquisition::GalileoE5a3msNoncoherentIQAcquisition( + ConfigurationInterface* configuration, std::string role, + unsigned int in_streams, unsigned int out_streams, + boost::shared_ptr queue) : + role_(role), in_streams_(in_streams), out_streams_(out_streams), queue_(queue) +{ + configuration_ = configuration; + std::string default_item_type = "gr_complex"; + std::string default_dump_filename = "../data/acquisition.dat"; + + DLOG(INFO) << "role " << role; + + item_type_ = configuration_->property(role + ".item_type", + default_item_type); + + fs_in_ = configuration_->property("GNSS-SDR.internal_fs_hz", 21000000); + if_ = configuration_->property(role + ".ifreq", 0); + dump_ = configuration_->property(role + ".dump", false); + shift_resolution_ = configuration_->property(role + ".doppler_max", 15); + sampled_ms_ = configuration_->property(role + ".coherent_integration_time_ms", 3); + if (sampled_ms_ < 2) + { + sampled_ms_=2; + DLOG(INFO) << "Coherent integration time should be 2 or 3 ms. Changing to 2ms "; + std::cout<<"Too low coherent integration time. Changing to 2ms" << std::endl; + } + else if (sampled_ms_ > 3) + { + sampled_ms_=3; + DLOG(INFO) << "Coherent integration time should be 2 or 3 ms. Changing to 3ms "; + std::cout<<"Too low coherent integration time. Changing to 3ms" << std::endl; + } + //bit_transition_flag_ = configuration_->property(role + ".bit_transition_flag", false); + max_dwells_ = configuration_->property(role + ".max_dwells", 1); + + dump_filename_ = configuration_->property(role + ".dump_filename", + default_dump_filename); + + //--- Find number of samples per spreading code (1ms)------------------------- + code_length_ = round(fs_in_/ Galileo_E5a_CODE_CHIP_RATE_HZ*Galileo_E5a_CODE_LENGTH_CHIPS); + + // WARNING: In presence of secondary codes, 2ms must be correlated with 1ms + // of primary code and 1ms of padded zeros. + vector_length_=code_length_ * sampled_ms_; +// vector_length_=15*code_length_; + + //std::cout << sampled_ms_ << " sampledms" << code_length_ << " cdelength" << std::endl; + + //if (posix_memalign((void**)&(code_), 16,vector_length_ * sizeof(gr_complex)) == 0){}; + + codeI_= new gr_complex[vector_length_]; + codeQ_= new gr_complex[vector_length_]; + + if (item_type_.compare("gr_complex") == 0) + { + item_size_ = sizeof(gr_complex); + acquisition_cc_ = galileo_e5a_3ms_noncoherentIQ_make_acquisition_cc(sampled_ms_, max_dwells_, + shift_resolution_, if_, fs_in_, code_length_, code_length_, + bit_transition_flag_, queue_, dump_, dump_filename_); + +// stream_to_vector_ = gr::blocks::stream_to_vector::make(item_size_, vector_length_); +// +// DLOG(INFO) << "stream_to_vector(" << stream_to_vector_->unique_id() +// << ")"; +// DLOG(INFO) << "acquisition(" << acquisition_cc_->unique_id() +// << ")"; + } + else + { + LOG(WARNING) << item_type_ + << " unknown acquisition item type"; + } + +} + +GalileoE5a3msNoncoherentIQAcquisition::~GalileoE5a3msNoncoherentIQAcquisition() +{ + delete[] codeI_; + delete[] codeQ_; +} + +void GalileoE5a3msNoncoherentIQAcquisition::set_channel(unsigned int channel) +{ + channel_ = channel; + if (item_type_.compare("gr_complex") == 0) + { + acquisition_cc_->set_channel(channel_); + } +} + +void GalileoE5a3msNoncoherentIQAcquisition::set_threshold(float threshold) +{ + + float pfa = configuration_->property(role_+ boost::lexical_cast(channel_) + ".pfa", 0.0); + + if(pfa==0.0) pfa = configuration_->property(role_+".pfa", 0.0); + + if(pfa==0.0) + { + threshold_ = threshold; + } + else + { + threshold_ = calculate_threshold(pfa); + } + + DLOG(INFO) <<"Channel "<set_threshold(threshold_); + } +} + + +void GalileoE5a3msNoncoherentIQAcquisition::set_doppler_max(unsigned int doppler_max) +{ + doppler_max_ = doppler_max; + + if (item_type_.compare("gr_complex") == 0) + { + acquisition_cc_->set_doppler_max(doppler_max_); + } +} + +void GalileoE5a3msNoncoherentIQAcquisition::set_doppler_step(unsigned int doppler_step) +{ + doppler_step_ = doppler_step; + if (item_type_.compare("gr_complex") == 0) + { + acquisition_cc_->set_doppler_step(doppler_step_); + } +} + +void GalileoE5a3msNoncoherentIQAcquisition::set_channel_queue( + concurrent_queue *channel_internal_queue) +{ + channel_internal_queue_ = channel_internal_queue; + if (item_type_.compare("gr_complex") == 0) + { + acquisition_cc_->set_channel_queue(channel_internal_queue_); + } +} + + +void GalileoE5a3msNoncoherentIQAcquisition::set_gnss_synchro( + Gnss_Synchro* gnss_synchro) +{ + gnss_synchro_ = gnss_synchro; + if (item_type_.compare("gr_complex") == 0) + { + acquisition_cc_->set_gnss_synchro(gnss_synchro_); + } +} + + +signed int GalileoE5a3msNoncoherentIQAcquisition::mag() +{ + if (item_type_.compare("gr_complex") == 0) + { + return acquisition_cc_->mag(); + } + else + { + return 0; + } +} + + +void GalileoE5a3msNoncoherentIQAcquisition::init() +{ + acquisition_cc_->init(); + set_local_code(); +} + +void GalileoE5a3msNoncoherentIQAcquisition::set_local_code() +{ + if (item_type_.compare("gr_complex")==0) + { + + std::complex* codeI = new std::complex[code_length_]; + std::complex* codeQ = new std::complex[code_length_]; + + std::cout << "ADAPTER E5a 3ms noncoherentIQ. SIGNAL = " << gnss_synchro_->Signal << " PRN = " << gnss_synchro_->PRN << std::endl; + + char a[3]; + strcpy(a,"5I"); + galileo_e5_a_code_gen_complex_sampled(codeI, a, + gnss_synchro_->PRN, fs_in_, 0, false); + + strcpy(a,"5Q"); + galileo_e5_a_code_gen_complex_sampled(codeQ, a, + gnss_synchro_->PRN, fs_in_, 0, false); + + // WARNING: 3ms are coherently integrated. Secondary sequence (1,1,1) + // is generated, and modulated in the 'block'. + for (unsigned int i = 0; i < sampled_ms_; i++) + { + memcpy(&(codeI_[i*code_length_]), codeI, + sizeof(gr_complex)*code_length_); + + memcpy(&(codeQ_[i*code_length_]), codeQ, + sizeof(gr_complex)*code_length_); + } + + + acquisition_cc_->set_local_code(codeI_,codeQ_); + delete[] codeI; + delete[] codeQ; + + } + +} + +void GalileoE5a3msNoncoherentIQAcquisition::reset() +{ + if (item_type_.compare("gr_complex") == 0) + { + acquisition_cc_->set_active(true); + } +} + + +float GalileoE5a3msNoncoherentIQAcquisition::calculate_threshold(float pfa) +{ + //Calculate the threshold + unsigned int frequency_bins = 0; + for (int doppler = (int)(-doppler_max_); doppler <= (int)doppler_max_; doppler += doppler_step_) + { + frequency_bins++; + } + DLOG(INFO) << "Channel " << channel_<< " Pfa = " << pfa; + unsigned int ncells = vector_length_*frequency_bins; + double exponent = 1/(double)ncells; + double val = pow(1.0 - pfa, exponent); + double lambda = double(vector_length_); + boost::math::exponential_distribution mydist (lambda); + float threshold = (float)quantile(mydist,val); + + return threshold; +} + + +void GalileoE5a3msNoncoherentIQAcquisition::connect(gr::top_block_sptr top_block) +{ +// if (item_type_.compare("gr_complex") == 0) +// { +// top_block->connect(stream_to_vector_, 0, acquisition_cc_, 0); +// } +} + + +void GalileoE5a3msNoncoherentIQAcquisition::disconnect(gr::top_block_sptr top_block) +{ +// if (item_type_.compare("gr_complex") == 0) +// { +// top_block->disconnect(stream_to_vector_, 0, acquisition_cc_, 0); +// } +} + +gr::basic_block_sptr GalileoE5a3msNoncoherentIQAcquisition::get_left_block() +{ + return acquisition_cc_; + //return stream_to_vector_; +} + + +gr::basic_block_sptr GalileoE5a3msNoncoherentIQAcquisition::get_right_block() +{ + return acquisition_cc_; +} diff --git a/src/algorithms/acquisition/adapters/galileo_e5a_3ms_noncoherent_iq_acquisition.h b/src/algorithms/acquisition/adapters/galileo_e5a_3ms_noncoherent_iq_acquisition.h new file mode 100644 index 000000000..c08361424 --- /dev/null +++ b/src/algorithms/acquisition/adapters/galileo_e5a_3ms_noncoherent_iq_acquisition.h @@ -0,0 +1,157 @@ +/*! + * \file galileo_e5a_3ms_noncoherent_iq_acquisition.h + * \brief Adapts a PCPS acquisition block to an AcquisitionInterface for + * Galileo E5a data and pilot Signals + * \author Marc Sales, 2014. marcsales92(at)gmail.com + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2014 (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 GALILEO_E5A_3MS_NONCOHERENT_IQ_ACQUISITION_H_ +#define GALILEO_E5A_3MS_NONCOHERENT_IQ_ACQUISITION_H_ + +#include +#include +#include +#include "gnss_synchro.h" +#include "acquisition_interface.h" +#include "galileo_e5a_3ms_noncoherent_iq_acquisition_cc.h" + +class ConfigurationInterface; + +class GalileoE5a3msNoncoherentIQAcquisition: public AcquisitionInterface +{ +public: + GalileoE5a3msNoncoherentIQAcquisition(ConfigurationInterface* configuration, + std::string role, unsigned int in_streams, + unsigned int out_streams, boost::shared_ptr queue); + + virtual ~GalileoE5a3msNoncoherentIQAcquisition(); + + std::string role() + { + return role_; + } + /*! + * \brief Returns "Galileo_E5a_3ms_Noncoherent_IQ_Acquisition" + */ + std::string implementation() + { + return "Galileo_E5a_3ms_Noncoherent_IQ_Acquisition"; + } + 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 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 acquisition channel unique ID + */ + void set_channel(unsigned int channel); + + /*! + * \brief Set statistics threshold of PCPS algorithm + */ + void set_threshold(float threshold); + + /*! + * \brief Set maximum Doppler off grid search + */ + void set_doppler_max(unsigned int doppler_max); + + /*! + * \brief Set Doppler steps for the grid search + */ + void set_doppler_step(unsigned int doppler_step); + + /*! + * \brief Set tracking channel internal queue + */ + void set_channel_queue(concurrent_queue *channel_internal_queue); + + /*! + * \brief Initializes acquisition algorithm. + */ + void init(); + + /*! + * \brief Sets local Galileo E5a code for PCPS acquisition algorithm. + */ + void set_local_code(); + + /*! + * \brief Returns the maximum peak of grid search + */ + signed int mag(); + + /*! + * \brief Restart acquisition algorithm + */ + void reset(); + +private: + ConfigurationInterface* configuration_; + galileo_e5a_3ms_noncoherentIQ_acquisition_cc_sptr acquisition_cc_; + gr::blocks::stream_to_vector::sptr stream_to_vector_; + size_t item_size_; + std::string item_type_; + unsigned int vector_length_; + unsigned int code_length_; + bool bit_transition_flag_; + unsigned int channel_; + float threshold_; + unsigned int doppler_max_; + unsigned int doppler_step_; + unsigned int shift_resolution_; + unsigned int sampled_ms_; + unsigned int max_dwells_; + long fs_in_; + long if_; + bool dump_; + std::string dump_filename_; + std::complex * codeI_; + std::complex * codeQ_; + Gnss_Synchro * gnss_synchro_; + std::string role_; + unsigned int in_streams_; + unsigned int out_streams_; + boost::shared_ptr queue_; + concurrent_queue *channel_internal_queue_; + float calculate_threshold(float pfa); +}; +#endif /* GALILEO_E5A_3MS_NONCOHERENT_IQ_ACQUISITION_H_ */ diff --git a/src/algorithms/acquisition/gnuradio_blocks/CMakeLists.txt b/src/algorithms/acquisition/gnuradio_blocks/CMakeLists.txt index 2a06f9955..f9dac7a74 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/CMakeLists.txt +++ b/src/algorithms/acquisition/gnuradio_blocks/CMakeLists.txt @@ -27,6 +27,7 @@ if(OPENCL_FOUND) galileo_pcps_8ms_acquisition_cc.cc galileo_e5a_pilot_3ms_acquisition_cc.cc galileo_e5ax_2ms_pcps_acquisition_cc.cc + galileo_e5a_3ms_noncoherent_iq_acquisition_cc.cc pcps_opencl_acquisition_cc.cc # Needs OpenCL ) else(OPENCL_FOUND) @@ -40,6 +41,7 @@ else(OPENCL_FOUND) galileo_pcps_8ms_acquisition_cc.cc galileo_e5a_pilot_3ms_acquisition_cc.cc galileo_e5ax_2ms_pcps_acquisition_cc.cc + galileo_e5a_3ms_noncoherent_iq_acquisition_cc.cc ) endif(OPENCL_FOUND) diff --git a/src/algorithms/acquisition/gnuradio_blocks/galileo_e5a_3ms_noncoherent_iq_acquisition_cc.cc b/src/algorithms/acquisition/gnuradio_blocks/galileo_e5a_3ms_noncoherent_iq_acquisition_cc.cc new file mode 100644 index 000000000..e28dd7a62 --- /dev/null +++ b/src/algorithms/acquisition/gnuradio_blocks/galileo_e5a_3ms_noncoherent_iq_acquisition_cc.cc @@ -0,0 +1,592 @@ +/*! + * \file galileo_e5a_3ms_noncoherent_iq_acquisition_cc.cc + * \brief Adapts a PCPS acquisition block to an AcquisitionInterface for + * Galileo E5a data and pilot Signals + * \author Marc Sales, 2014. marcsales92(at)gmail.com + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2014 (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 "galileo_e5a_3ms_noncoherent_iq_acquisition_cc.h" +#include +#include +#include +#include +#include +#include "gnss_signal_processing.h" +#include "control_message_factory.h" + +using google::LogMessage; + +galileo_e5a_3ms_noncoherentIQ_acquisition_cc_sptr galileo_e5a_3ms_noncoherentIQ_make_acquisition_cc( + unsigned int sampled_ms, + unsigned int max_dwells, + unsigned int doppler_max, long freq, long fs_in, + int samples_per_ms, int samples_per_code, + bool bit_transition_flag, + gr::msg_queue::sptr queue, bool dump, + std::string dump_filename) +{ + + return galileo_e5a_3ms_noncoherentIQ_acquisition_cc_sptr( + new galileo_e5a_3ms_noncoherentIQ_acquisition_cc(sampled_ms, max_dwells, doppler_max, freq, fs_in, samples_per_ms, + samples_per_code, bit_transition_flag, queue, dump, dump_filename)); +} + +galileo_e5a_3ms_noncoherentIQ_acquisition_cc::galileo_e5a_3ms_noncoherentIQ_acquisition_cc( + unsigned int sampled_ms, + unsigned int max_dwells, + unsigned int doppler_max, long freq, long fs_in, + int samples_per_ms, int samples_per_code, + bool bit_transition_flag, + gr::msg_queue::sptr queue, bool dump, + std::string dump_filename) : + gr::block("galileo_e5a_3ms_noncoherentIQ_acquisition_cc", + gr::io_signature::make(1, 1, sizeof(gr_complex)), + gr::io_signature::make(0, 0, sizeof(gr_complex))) + //gr::io_signature::make(1, 1, sizeof(gr_complex) * 3 * samples_per_ms), + //gr::io_signature::make(0, 0, sizeof(gr_complex) * 3 * samples_per_ms)) +{ + //this->set_relative_rate(1.0/1*samples_per_ms); + d_sample_counter = 0; // SAMPLE COUNTER + d_active = false; + d_state = 0; + d_queue = queue; + d_freq = freq; + d_fs_in = fs_in; + d_samples_per_ms = samples_per_ms; + d_samples_per_code = samples_per_code; + d_max_dwells = max_dwells; + d_well_count = 0; + d_doppler_max = doppler_max; + d_fft_size = sampled_ms * d_samples_per_ms; + d_mag = 0; + d_input_power = 0.0; + d_num_doppler_bins = 0; + d_bit_transition_flag = bit_transition_flag; + d_buffer_count=0; + d_gr_stream_buffer = 7000; // number of samples entering each general work, arbitrary number. Works with all numbers below gnu radio maximum buffer + + //todo: do something if posix_memalign fails + if (posix_memalign((void**)&d_inbuffer, 16, ceil((double)d_fft_size/(double)d_gr_stream_buffer)*d_gr_stream_buffer * sizeof(gr_complex)) == 0){}; + if (posix_memalign((void**)&d_fft_code_I_A, 16, d_fft_size * sizeof(gr_complex)) == 0){}; + if (posix_memalign((void**)&d_fft_code_I_B, 16, d_fft_size * sizeof(gr_complex)) == 0){}; + if (posix_memalign((void**)&d_fft_code_Q_A, 16, d_fft_size * sizeof(gr_complex)) == 0){}; + if (posix_memalign((void**)&d_fft_code_Q_B, 16, d_fft_size * sizeof(gr_complex)) == 0){}; + if (posix_memalign((void**)&d_magnitudeIA, 16, d_fft_size * sizeof(float)) == 0){}; + if (posix_memalign((void**)&d_magnitudeIB, 16, d_fft_size * sizeof(float)) == 0){}; + if (posix_memalign((void**)&d_magnitudeQA, 16, d_fft_size * sizeof(float)) == 0){}; + if (posix_memalign((void**)&d_magnitudeQB, 16, d_fft_size * sizeof(float)) == 0){}; + + // Direct FFT + d_fft_if = new gr::fft::fft_complex(d_fft_size, true); + + // Inverse FFT + d_ifft = new gr::fft::fft_complex(d_fft_size, false); +// d_ifft = new gr::fft::fft_complex(d_fft_size, true); + + // For dumping samples into a file + d_dump = dump; + d_dump_filename = dump_filename; +} + +galileo_e5a_3ms_noncoherentIQ_acquisition_cc::~galileo_e5a_3ms_noncoherentIQ_acquisition_cc() +{ + if (d_num_doppler_bins > 0) + { + for (unsigned int i = 0; i < d_num_doppler_bins; i++) + { + free(d_grid_doppler_wipeoffs[i]); + } + delete[] d_grid_doppler_wipeoffs; + } + + free(d_fft_code_I_A); + free(d_fft_code_I_B); + free(d_fft_code_Q_A); + free(d_fft_code_Q_B); + free(d_magnitudeIA); + free(d_magnitudeIB); + free(d_magnitudeQA); + free(d_magnitudeQB); + + + delete d_fft_if; + delete d_ifft; + + + if (d_dump) + { + d_dump_file.close(); + } +} + +void galileo_e5a_3ms_noncoherentIQ_acquisition_cc::forecast (int noutput_items, + gr_vector_int &ninput_items_required) +{ + ninput_items_required[0] = d_gr_stream_buffer ; //set the required available samples in each call +} + +void galileo_e5a_3ms_noncoherentIQ_acquisition_cc::set_local_code(std::complex * codeI, std::complex * codeQ ) +{ + // DATA SIGNAL + // Three replicas of data primary code. CODE A: (1,1,1) + memcpy(d_fft_if->get_inbuf(), codeI, sizeof(gr_complex)*d_fft_size); + + d_fft_if->execute(); // We need the FFT of local code + + //Conjugate the local code + if (is_unaligned()) + { + volk_32fc_conjugate_32fc_u(d_fft_code_I_A,d_fft_if->get_outbuf(),d_fft_size); + } + else + { + volk_32fc_conjugate_32fc_a(d_fft_code_I_A,d_fft_if->get_outbuf(),d_fft_size); + } + + // CODE B: First replica is inverted (0,1,1) + volk_32fc_s32fc_multiply_32fc_a(&(d_fft_if->get_inbuf())[0], + &codeI[0], gr_complex(-1,0), + d_samples_per_code); + d_fft_if->execute(); // We need the FFT of local code + + //Conjugate the local code + if (is_unaligned()) + { + volk_32fc_conjugate_32fc_u(d_fft_code_I_B,d_fft_if->get_outbuf(),d_fft_size); + } + else + { + volk_32fc_conjugate_32fc_a(d_fft_code_I_B,d_fft_if->get_outbuf(),d_fft_size); + } + + // SAME FOR PILOT SIGNAL + // Three replicas of pilot primary code. CODE A: (1,1,1) + memcpy(d_fft_if->get_inbuf(), codeQ, sizeof(gr_complex)*d_fft_size); + + d_fft_if->execute(); // We need the FFT of local code + + //Conjugate the local code + if (is_unaligned()) + { + volk_32fc_conjugate_32fc_u(d_fft_code_Q_A,d_fft_if->get_outbuf(),d_fft_size); + } + else + { + volk_32fc_conjugate_32fc_a(d_fft_code_Q_A,d_fft_if->get_outbuf(),d_fft_size); + } + + // CODE B: First replica is inverted (0,1,1) + volk_32fc_s32fc_multiply_32fc_a(&(d_fft_if->get_inbuf())[0], + &codeQ[0], gr_complex(-1,0), + d_samples_per_code); + d_fft_if->execute(); // We need the FFT of local code + + //Conjugate the local code + if (is_unaligned()) + { + volk_32fc_conjugate_32fc_u(d_fft_code_Q_B,d_fft_if->get_outbuf(),d_fft_size); + } + else + { + volk_32fc_conjugate_32fc_a(d_fft_code_Q_B,d_fft_if->get_outbuf(),d_fft_size); + } + + +} + +void galileo_e5a_3ms_noncoherentIQ_acquisition_cc::init() +{ + d_gnss_synchro->Acq_delay_samples = 0.0; + d_gnss_synchro->Acq_doppler_hz = 0.0; + d_gnss_synchro->Acq_samplestamp_samples = 0; + d_mag = 0.0; + d_input_power = 0.0; + + // Count the number of bins + d_num_doppler_bins = 0; + for (int doppler = (int)(-d_doppler_max); + doppler <= (int)d_doppler_max; + doppler += d_doppler_step) + { + d_num_doppler_bins++; + } + + // Create the carrier Doppler wipeoff signals + d_grid_doppler_wipeoffs = new gr_complex*[d_num_doppler_bins]; + for (unsigned int doppler_index = 0; doppler_index < d_num_doppler_bins; doppler_index++) + { + if (posix_memalign((void**)&(d_grid_doppler_wipeoffs[doppler_index]), 16, + d_fft_size * sizeof(gr_complex)) == 0){}; + + int doppler = -(int)d_doppler_max + d_doppler_step*doppler_index; + complex_exp_gen_conj(d_grid_doppler_wipeoffs[doppler_index], + d_freq + doppler, d_fs_in, d_fft_size); + } +} + + +int galileo_e5a_3ms_noncoherentIQ_acquisition_cc::general_work(int noutput_items, + gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + /* + * By J.Arribas, L.Esteve, M.Molina and M.Sales + * Acquisition strategy (Kay Borre book + CFAR threshold): + * 1. Compute the input signal power estimation + * 2. Doppler serial search loop + * 3. Perform the FFT-based circular convolution (parallel time search) + * 4. Record the maximum peak and the associated synchronization parameters + * 5. Compute the test statistics and compare to the threshold + * 6. Declare positive or negative acquisition using a message queue + */ + + int acquisition_message = -1; //0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL + /* States: 0 Reset and load first stream + * 1 Load the buffer until it reaches fft_size + * 2 Acquisition algorithm + * 3 Positive acquisition + * 4 Negative acquisition + */ + + d_sample_counter += d_gr_stream_buffer; + std::cout << d_state <<" "<< d_sample_counter << std::endl; + switch (d_state) + { + case 0: + { + if (d_active) + { + //restart acquisition variables + d_gnss_synchro->Acq_delay_samples = 0.0; + d_gnss_synchro->Acq_doppler_hz = 0.0; + d_gnss_synchro->Acq_samplestamp_samples = 0; + d_well_count = 0; + d_mag = 0.0; + d_input_power = 0.0; + d_test_statistics = 0.0; + d_state = 1; + } + const gr_complex *in = (const gr_complex *)input_items[0]; //Get the input samples pointer + memcpy(&d_inbuffer[d_buffer_count*d_gr_stream_buffer], in, sizeof(gr_complex)*d_gr_stream_buffer); + d_buffer_count++; + //d_sample_counter += ninput_items[0]; // sample counter + //consume_each(ninput_items[0]); + break; + } + case 1: + { + const gr_complex *in = (const gr_complex *)input_items[0]; //Get the input samples pointer + memcpy(&d_inbuffer[d_buffer_count*d_gr_stream_buffer], in, sizeof(gr_complex)*d_gr_stream_buffer); + d_buffer_count++; + if (d_buffer_count*d_gr_stream_buffer >= d_fft_size-d_gr_stream_buffer) + { + d_state=2; + } +// volk_32fc_x2_multiply_32fc_a(d_fft_if->get_inbuf(), in, +// d_grid_doppler_wipeoffs[0], d_fft_size); + //consume_each(7000); + break; + } + case 2: + { + // Fill last part of the buffer and reset counter + const gr_complex *in = (const gr_complex *)input_items[0]; //Get the input samples pointer + memcpy(&d_inbuffer[d_buffer_count*d_gr_stream_buffer], in, sizeof(gr_complex)*d_gr_stream_buffer); + d_buffer_count = 0; + // initialize acquisition algorithm + int doppler; + unsigned int indext = 0; + unsigned int indext_IA = 0; + unsigned int indext_IB = 0; + unsigned int indext_QA = 0; + unsigned int indext_QB = 0; + float magt = 0.0; + float magt_IA = 0.0; + float magt_IB = 0.0; + float magt_QA = 0.0; + float magt_QB = 0.0; + //const gr_complex *in = (const gr_complex *)input_items[0]; //Get the input samples pointer + float fft_normalization_factor = (float)d_fft_size * (float)d_fft_size; + d_input_power = 0.0; + d_mag = 0.0; + int comb = 0; + + //d_sample_counter += d_fft_size; // sample counter + + d_well_count++; + + DLOG(INFO) << "Channel: " << d_channel + << " , doing acquisition of satellite: " << d_gnss_synchro->System << " "<< d_gnss_synchro->PRN + << " ,sample stamp: " << d_sample_counter << ", threshold: " + << d_threshold << ", doppler_max: " << d_doppler_max + << ", doppler_step: " << d_doppler_step; + + // 1- Compute the input signal power estimation + volk_32fc_magnitude_squared_32f_a(d_magnitudeIA, d_inbuffer, d_fft_size); + volk_32f_accumulator_s32f_a(&d_input_power, d_magnitudeIA, d_fft_size); + d_input_power /= (float)d_fft_size; + + // 2- Doppler frequency search loop + for (unsigned int doppler_index=0;doppler_indexget_inbuf(), d_inbuffer, + d_grid_doppler_wipeoffs[doppler_index], d_fft_size); + + // 3- Perform the FFT-based convolution (parallel time search) + // Compute the FFT of the carrier wiped--off incoming signal + d_fft_if->execute(); + + // CODE IA + // Multiply carrier wiped--off, Fourier transformed incoming signal + // with the local FFT'd code reference using SIMD operations with VOLK library + volk_32fc_x2_multiply_32fc_a(d_ifft->get_inbuf(), + d_fft_if->get_outbuf(), d_fft_code_I_A, d_fft_size); + + // compute the inverse FFT + d_ifft->execute(); + + // Search maximum + volk_32fc_magnitude_squared_32f_a(d_magnitudeIA, d_ifft->get_outbuf(), d_fft_size); + volk_32f_index_max_16u_a(&indext_IA, d_magnitudeIA, d_fft_size); + + // Normalize the maximum value to correct the scale factor introduced by FFTW + magt_IA = d_magnitudeIA[indext_IA] / (fft_normalization_factor * fft_normalization_factor); + + // only 1 ms + //magt=magt_A; + //indext=indext_A; + + + // REPEAT FOR ALL CODES. CODE_IB + volk_32fc_x2_multiply_32fc_a(d_ifft->get_inbuf(), + d_fft_if->get_outbuf(), d_fft_code_I_B, d_fft_size); + d_ifft->execute(); + volk_32fc_magnitude_squared_32f_a(d_magnitudeIB, d_ifft->get_outbuf(), d_fft_size); + volk_32f_index_max_16u_a(&indext_IB, d_magnitudeIB, d_fft_size); + magt_IB = d_magnitudeIB[indext_IB] / (fft_normalization_factor * fft_normalization_factor); + + // REPEAT FOR ALL CODES. CODE_QA + volk_32fc_x2_multiply_32fc_a(d_ifft->get_inbuf(), + d_fft_if->get_outbuf(), d_fft_code_Q_A, d_fft_size); + d_ifft->execute(); + volk_32fc_magnitude_squared_32f_a(d_magnitudeQA, d_ifft->get_outbuf(), d_fft_size); + volk_32f_index_max_16u_a(&indext_QA, d_magnitudeQA, d_fft_size); + magt_QA = d_magnitudeQA[indext_QA] / (fft_normalization_factor * fft_normalization_factor); + + // REPEAT FOR ALL CODES. CODE_QB + volk_32fc_x2_multiply_32fc_a(d_ifft->get_inbuf(), + d_fft_if->get_outbuf(), d_fft_code_Q_B, d_fft_size); + d_ifft->execute(); + volk_32fc_magnitude_squared_32f_a(d_magnitudeQB, d_ifft->get_outbuf(), d_fft_size); + volk_32f_index_max_16u_a(&indext_QB, d_magnitudeQB, d_fft_size); + magt_QB = d_magnitudeIB[indext_QB] / (fft_normalization_factor * fft_normalization_factor); + + // Integrate noncoherently the two best combinations (I² + Q²) + // and store the result in the I channel. + if (magt_IA >= magt_IB) + { + if (magt_QA >= magt_QB) + { + for (unsigned int i=0; i= magt_QB) + { + for (unsigned int i=0; iAcq_delay_samples = (double)(indext % d_samples_per_code); + d_gnss_synchro->Acq_doppler_hz = (double)doppler; + d_gnss_synchro->Acq_samplestamp_samples = d_sample_counter; + + // 5- Compute the test statistics and compare to the threshold + //d_test_statistics = 2 * d_fft_size * d_mag / d_input_power; + d_test_statistics = d_mag / d_input_power; + } + } + + // Record results to file if required + if (d_dump) + { + std::stringstream filename; + std::streamsize n = sizeof(float) * (d_fft_size); // noncomplex file write + filename.str(""); + filename << "../data/test_statistics_" << d_gnss_synchro->System + <<"_" << d_gnss_synchro->Signal << "_sat_" + << d_gnss_synchro->PRN << "_doppler_" << doppler << ".dat"; + d_dump_file.open(filename.str().c_str(), std::ios::out | std::ios::binary); + if (magt_IA >= magt_IB) + { + d_dump_file.write((char*)d_magnitudeIA, n); + } + else + { + d_dump_file.write((char*)d_magnitudeIB, n); + } + //d_dump_file.write((char*)d_magnitudeIA, n); + d_dump_file.close(); + } + } + + if (!d_bit_transition_flag) + { + if (d_test_statistics > d_threshold) + { + d_state = 3; // Positive acquisition + } + else if (d_well_count == d_max_dwells) + { + d_state = 4; // Negative acquisition + } + else + { + d_state = 2; + } + } + else + { + if (d_well_count == d_max_dwells) // d_max_dwells = 2 + { + if (d_test_statistics > d_threshold) + { + d_state = 3; // Positive acquisition + } + else + { + d_state = 4; // Negative acquisition + } + } + else + { + d_state = 2; + } + } + + //consume_each(1); + //consume_each(d_fft_size); + break; + } + case 3: + { + // 6.1- Declare positive acquisition using a message queue + DLOG(INFO) << "positive acquisition"; + DLOG(INFO) << "satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN; + DLOG(INFO) << "sample_stamp " << d_sample_counter; + DLOG(INFO) << "test statistics value " << d_test_statistics; + DLOG(INFO) << "test statistics threshold " << d_threshold; + DLOG(INFO) << "code phase " << d_gnss_synchro->Acq_delay_samples; + DLOG(INFO) << "doppler " << d_gnss_synchro->Acq_doppler_hz; + DLOG(INFO) << "magnitude " << d_mag; + DLOG(INFO) << "input signal power " << d_input_power; + + d_active = false; + d_state = 0; + + //d_sample_counter += 7000; + //d_sample_counter += d_fft_size * ninput_items[0]; // sample counter + //consume_each(ninput_items[0]); + //consume_each(d_fft_size); + acquisition_message = 1; + d_channel_internal_queue->push(acquisition_message); + break; + } + case 4: + { + // 6.2- Declare negative acquisition using a message queue + DLOG(INFO) << "negative acquisition"; + DLOG(INFO) << "satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN; + DLOG(INFO) << "sample_stamp " << d_sample_counter; + DLOG(INFO) << "test statistics value " << d_test_statistics; + DLOG(INFO) << "test statistics threshold " << d_threshold; + DLOG(INFO) << "code phase " << d_gnss_synchro->Acq_delay_samples; + DLOG(INFO) << "doppler " << d_gnss_synchro->Acq_doppler_hz; + DLOG(INFO) << "magnitude " << d_mag; + DLOG(INFO) << "input signal power " << d_input_power; + + d_active = false; + d_state = 0; + + //d_sample_counter += 7000; + //d_sample_counter += d_fft_size * ninput_items[0]; // sample counter + //consume_each(ninput_items[0]); + //consume_each(d_fft_size); + acquisition_message = 2; + d_channel_internal_queue->push(acquisition_message); + break; + } + } + + consume_each(d_gr_stream_buffer); + return 0; +} + diff --git a/src/algorithms/acquisition/gnuradio_blocks/galileo_e5a_3ms_noncoherent_iq_acquisition_cc.h b/src/algorithms/acquisition/gnuradio_blocks/galileo_e5a_3ms_noncoherent_iq_acquisition_cc.h new file mode 100644 index 000000000..11506f2ea --- /dev/null +++ b/src/algorithms/acquisition/gnuradio_blocks/galileo_e5a_3ms_noncoherent_iq_acquisition_cc.h @@ -0,0 +1,237 @@ +/*! + * \file galileo_e5a_3ms_noncoherent_iq_acquisition_cc.h + * \brief Adapts a PCPS acquisition block to an AcquisitionInterface for + * Galileo E5a data and pilot Signals + * \author Marc Sales, 2014. marcsales92(at)gmail.com + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2014 (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 GALILEO_E5A_3MS_NONCOHERENT_IQ_ACQUISITION_CC_H_ +#define GALILEO_E5A_3MS_NONCOHERENT_IQ_ACQUISITION_CC_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "concurrent_queue.h" +#include "gnss_synchro.h" + +class galileo_e5a_3ms_noncoherentIQ_acquisition_cc; + +typedef boost::shared_ptr galileo_e5a_3ms_noncoherentIQ_acquisition_cc_sptr; + +galileo_e5a_3ms_noncoherentIQ_acquisition_cc_sptr +galileo_e5a_3ms_noncoherentIQ_make_acquisition_cc(unsigned int sampled_ms, + unsigned int max_dwells, + unsigned int doppler_max, long freq, long fs_in, + int samples_per_ms, int samples_per_code, + bool bit_transition_flag, + gr::msg_queue::sptr queue, bool dump, + std::string dump_filename); + +/*! + * \brief This class implements a Parallel Code Phase Search Acquisition. + * + * Check \ref Navitec2012 "An Open Source Galileo E1 Software Receiver", + * Algorithm 1, for a pseudocode description of this implementation. + */ +class galileo_e5a_3ms_noncoherentIQ_acquisition_cc: public gr::block +{ +private: + friend galileo_e5a_3ms_noncoherentIQ_acquisition_cc_sptr + galileo_e5a_3ms_noncoherentIQ_make_acquisition_cc( + unsigned int sampled_ms, + unsigned int max_dwells, + unsigned int doppler_max, long freq, long fs_in, + int samples_per_ms, int samples_per_code, + bool bit_transition_flag, + gr::msg_queue::sptr queue, bool dump, + std::string dump_filename); + + galileo_e5a_3ms_noncoherentIQ_acquisition_cc( + unsigned int sampled_ms, + unsigned int max_dwells, + unsigned int doppler_max, long freq, long fs_in, + int samples_per_ms, int samples_per_code, + bool bit_transition_flag, + gr::msg_queue::sptr queue, bool dump, + std::string dump_filename); + + void calculate_magnitudes(gr_complex* fft_begin, int doppler_shift, + int doppler_offset); + float estimate_input_power(gr_complex *in ); + + long d_fs_in; + long d_freq; + int d_samples_per_ms; + int d_samples_per_code; + unsigned int d_doppler_resolution; + float d_threshold; + std::string d_satellite_str; + unsigned int d_doppler_max; + unsigned int d_doppler_step; + unsigned int d_max_dwells; + unsigned int d_well_count; + unsigned int d_fft_size; + unsigned long int d_sample_counter; + gr_complex** d_grid_doppler_wipeoffs; + unsigned int d_num_doppler_bins; + gr_complex* d_fft_code_I_A; + gr_complex* d_fft_code_I_B; + gr_complex* d_fft_code_Q_A; + gr_complex* d_fft_code_Q_B; + gr_complex* d_inbuffer; + gr::fft::fft_complex* d_fft_if; + gr::fft::fft_complex* d_ifft; + Gnss_Synchro *d_gnss_synchro; + unsigned int d_code_phase; + float d_doppler_freq; + float d_mag; + float* d_magnitudeIA; + float* d_magnitudeIB; + float* d_magnitudeQA; + float* d_magnitudeQB; + float d_input_power; + float d_test_statistics; + bool d_bit_transition_flag; + gr::msg_queue::sptr d_queue; + concurrent_queue *d_channel_internal_queue; + std::ofstream d_dump_file; + bool d_active; + int d_state; + bool d_dump; + unsigned int d_channel; + std::string d_dump_filename; + unsigned int d_buffer_count; + unsigned int d_gr_stream_buffer; + +public: + /*! + * \brief Default destructor. + */ + ~galileo_e5a_3ms_noncoherentIQ_acquisition_cc(); + + /*! + * \brief Set acquisition/tracking common Gnss_Synchro object pointer + * to exchange synchronization data between acquisition and tracking blocks. + * \param p_gnss_synchro Satellite information shared by the processing blocks. + */ + void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) + { + d_gnss_synchro = p_gnss_synchro; + } + + /*! + * \brief Returns the maximum peak of grid search. + */ + unsigned int mag() + { + return d_mag; + } + + /*! + * \brief Initializes acquisition algorithm. + */ + void init(); + + /*! + * \brief Sets local code for PCPS acquisition algorithm. + * \param code - Pointer to the PRN code. + */ + void set_local_code(std::complex * code, std::complex * codeQ); + + /*! + * \brief Starts acquisition algorithm, turning from standby mode to + * active mode + * \param active - bool that activates/deactivates the block. + */ + void set_active(bool active) + { + d_active = active; + } + + /*! + * \brief Set acquisition channel unique ID + * \param channel - receiver channel. + */ + void set_channel(unsigned int channel) + { + d_channel = channel; + } + + /*! + * \brief Set statistics threshold of PCPS algorithm. + * \param threshold - Threshold for signal detection (check \ref Navitec2012, + * Algorithm 1, for a definition of this threshold). + */ + void set_threshold(float threshold) + { + d_threshold = threshold; + } + + /*! + * \brief Set maximum Doppler grid search + * \param doppler_max - Maximum Doppler shift considered in the grid search [Hz]. + */ + void set_doppler_max(unsigned int doppler_max) + { + d_doppler_max = doppler_max; + } + + /*! + * \brief Set Doppler steps for the grid search + * \param doppler_step - Frequency bin of the search grid [Hz]. + */ + void set_doppler_step(unsigned int doppler_step) + { + d_doppler_step = doppler_step; + } + + + /*! + * \brief Set tracking channel internal queue. + * \param channel_internal_queue - Channel's internal blocks information queue. + */ + void set_channel_queue(concurrent_queue *channel_internal_queue) + { + d_channel_internal_queue = channel_internal_queue; + } + + /*! + * \brief Parallel Code Phase Search Acquisition signal processing. + */ + 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); +}; +#endif /* GALILEO_E5A_3MS_NONCOHERENT_IQ_ACQUISITION_CC_H_ */ diff --git a/src/algorithms/libs/galileo_e5_signal_processing.cc b/src/algorithms/libs/galileo_e5_signal_processing.cc index 2425029c3..e22445a0e 100644 --- a/src/algorithms/libs/galileo_e5_signal_processing.cc +++ b/src/algorithms/libs/galileo_e5_signal_processing.cc @@ -97,7 +97,7 @@ void galileo_e5_a_code_gen_complex_primary(std::complex* _dest, signed in // last 2 bits are filled up zeros hex_to_binary_converter(a, Galileo_E5a_I_PRIMARY_CODE[prn].at(Galileo_E5a_I_PRIMARY_CODE[prn].length()-1)); - hex_to_binary_converter(a, + hex_to_binary_converter(b, Galileo_E5a_Q_PRIMARY_CODE[prn].at(Galileo_E5a_Q_PRIMARY_CODE[prn].length()-1)); _dest[index]=std::complex(float(a[0]),float(b[0])); _dest[index+1]=std::complex(float(a[1]),float(b[1])); diff --git a/src/algorithms/signal_generator/gnuradio_blocks/signal_generator_c.cc b/src/algorithms/signal_generator/gnuradio_blocks/signal_generator_c.cc index 55402067a..b703505c7 100644 --- a/src/algorithms/signal_generator/gnuradio_blocks/signal_generator_c.cc +++ b/src/algorithms/signal_generator/gnuradio_blocks/signal_generator_c.cc @@ -209,10 +209,22 @@ void signal_generator_c::generate_codes() // (int)Galileo_E5a_Q_SECONDARY_CODE_LENGTH - delay_chips_[sat], true); galileo_e5_a_code_gen_complex_sampled(sampled_code_data_[sat] , signal, PRN_[sat], fs_in_, - (int)Galileo_E5a_CODE_LENGTH_CHIPS - delay_chips_[sat],false); + (int)Galileo_E5a_CODE_LENGTH_CHIPS-delay_chips_[sat],false); std::cout << "PRN "<< PRN_[sat] << " first two bytes "<< sampled_code_data_[sat][0] << sampled_code_data_[sat][1] << sampled_code_data_[sat][2] << sampled_code_data_[sat][3] << sampled_code_data_[sat][4] << sampled_code_data_[sat][5] << sampled_code_data_[sat][6] << sampled_code_data_[sat][7] << std::endl; -//// std::ofstream myfile; + /////////// + /* + std::ofstream d_dump_file; + std::stringstream filename; + std::streamsize n = 2 * sizeof(float) * (Galileo_E5a_CODE_LENGTH_CHIPS); // complex file write + filename.str(""); + filename << "../data/PRN11_Xcode_noiseless" << ".dat"; + d_dump_file.open(filename.str().c_str(), std::ios::out | std::ios::binary); + d_dump_file.write((char*)&sampled_code_data_[sat][0], n); + d_dump_file.close(); + */ + ///////////////////// + //// std::ofstream myfile; // //myfile.open ("example_sink_gencode.dat"); // std::ofstream myfile("example_sink_gencode.bin",std::ios_base::binary); //// for (int k=0; k< vector_length_; k++) @@ -399,8 +411,8 @@ gr_vector_void_star &output_items) // if (work_counter_==1) // { - std::cout << "ms " << ms_counter_[sat] << " sat " << sat << " PRN" << PRN_[sat]; - std::cout << " delay_secI " << (ms_counter_[sat]+delay_sec_[sat])%20 << " delay_secQ " << (ms_counter_[sat]+delay_sec_[sat])%100 << std::endl;//" pilot mod " << pilot_modulation_[sat] << " data bit " << current_data_bit_int_[sat] << " data mod " << data_modulation_[sat] << std::endl; + //std::cout << "ms " << ms_counter_[sat] << " sat " << sat << " PRN" << PRN_[sat]; + //std::cout << " delay_secI " << (ms_counter_[sat]+delay_sec_[sat])%20 << " delay_secQ " << (ms_counter_[sat]+delay_sec_[sat])%100 << std::endl;//" pilot mod " << pilot_modulation_[sat] << " data bit " << current_data_bit_int_[sat] << " data mod " << data_modulation_[sat] << std::endl; //std::cout << "code 1st 2 byte " << out[0] << out[1] << out[2] << out[3] << out[4] << out[5] << out[6] << out[7] << std::endl; // } ms_counter_[sat] = ms_counter_[sat] + (int)round(1e3*GALILEO_E5a_CODE_PERIOD); @@ -461,7 +473,19 @@ gr_vector_void_star &output_items) out[out_idx] += gr_complex(random_->gasdev(),random_->gasdev()); } } - +/* +if (work_counter_==1) + { + std::ofstream d_dump_file; + std::stringstream filename; + std::streamsize n = 2 * sizeof(float) * (samples_per_code_[0]); // complex file write + filename.str(""); + filename << "../data/PRN11_Xcode_genwork" << ".dat"; + d_dump_file.open(filename.str().c_str(), std::ios::out | std::ios::binary); + d_dump_file.write((char*)out, n); + d_dump_file.close(); + } +*/ // Tell runtime system how many output items we produced. return 1; } diff --git a/src/algorithms/tracking/gnuradio_blocks/galileo_e5a_dll_pll_tracking_cc.cc b/src/algorithms/tracking/gnuradio_blocks/galileo_e5a_dll_pll_tracking_cc.cc index d07e88298..7a90a5f03 100644 --- a/src/algorithms/tracking/gnuradio_blocks/galileo_e5a_dll_pll_tracking_cc.cc +++ b/src/algorithms/tracking/gnuradio_blocks/galileo_e5a_dll_pll_tracking_cc.cc @@ -1,8 +1,32 @@ -/* - * galileo_e5a_dll_pll_tracking_cc.cc +/*! + * \file galileo_e5a_dll_fll_pll_tracking_cc.h + * \brief Implementation of a code DLL + carrier PLL + * tracking block for Galileo E5a signals + * \author Marc Sales, 2014. marcsales92(at)gmail.com * - * Created on: Jun 19, 2014 - * Author: marc + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2014 (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 "galileo_e5a_dll_pll_tracking_cc.h" @@ -24,7 +48,8 @@ /*! * \todo Include in definition header file */ -#define CN0_ESTIMATION_SAMPLES 20 +//#define CN0_ESTIMATION_SAMPLES 20 +#define CN0_ESTIMATION_SAMPLES 80 #define MINIMUM_VALID_CN0 25 #define MAXIMUM_LOCK_FAIL_COUNTER 50 #define CARRIER_LOCK_THRESHOLD 0.85 @@ -77,8 +102,8 @@ Galileo_E5a_Dll_Pll_Tracking_cc::Galileo_E5a_Dll_Pll_Tracking_cc( d_fs_in = fs_in; d_vector_length = vector_length; d_dump_filename = dump_filename; - d_code_loop_filter = Tracking_2nd_DLL_filter(Galileo_E1_CODE_PERIOD); - d_carrier_loop_filter = Tracking_2nd_PLL_filter(Galileo_E1_CODE_PERIOD); + d_code_loop_filter = Tracking_2nd_DLL_filter(GALILEO_E5a_CODE_PERIOD); + d_carrier_loop_filter = Tracking_2nd_PLL_filter(GALILEO_E5a_CODE_PERIOD); // Initialize tracking ========================================== d_code_loop_filter.set_DLL_BW(dll_bw_hz); @@ -124,6 +149,9 @@ Galileo_E5a_Dll_Pll_Tracking_cc::Galileo_E5a_Dll_Pll_Tracking_cc( d_pull_in = false; d_last_seg = 0; + d_secondary_lock=false; + d_secondary_delay=0; + d_current_prn_length_samples = (int)d_vector_length; // CN0 estimation and lock detector buffers @@ -210,7 +238,9 @@ void Galileo_E5a_Dll_Pll_Tracking_cc::start_tracking() d_code_loop_filter.initialize(); // initialize the code filter // generate local reference ALWAYS starting at chip 1 (1 sample per chip) - galileo_e5_a_code_gen_complex_primary(&d_code[1], d_acquisition_gnss_synchro->PRN, d_acquisition_gnss_synchro->Signal); + char sig_pilot[3]; + strcpy(sig_pilot,"5Q"); + galileo_e5_a_code_gen_complex_primary(&d_code[1], d_acquisition_gnss_synchro->PRN, sig_pilot); d_code[0] = d_code[(int)Galileo_E5a_CODE_LENGTH_CHIPS]; d_code[(int)Galileo_E5a_CODE_LENGTH_CHIPS + 1] = d_code[1]; @@ -239,7 +269,71 @@ void Galileo_E5a_Dll_Pll_Tracking_cc::start_tracking() << " Code Phase correction [samples]=" << delay_correction_samples << " PULL-IN Code Phase [samples]=" << d_acq_code_phase_samples; } - +void Galileo_E5a_Dll_Pll_Tracking_cc::acquire_secondary() +{ + //d_Prompt_buffer + //CN0_ESTIMATION_SAMPLES + //d_secondary_lock + //d_secondary_delay + // 1. Transform replica to 1 and -1 + int sec_code_signed[Galileo_E5a_Q_SECONDARY_CODE_LENGTH]; + for (unsigned int i=0; iPRN-1].at(i) == '0') + { + sec_code_signed[i]=1; + } + else + { + sec_code_signed[i]=-1; + } + } + // 2. Transform buffer to 1 and -1 + int in_corr[CN0_ESTIMATION_SAMPLES]; + for (unsigned int i=0; i0) + { + in_corr[i]=1; + } + else + { + in_corr[i]=-1; + } + } + // 3. Serial search + int out_corr; + int current_best_=0; + for (unsigned int i=0; i current_best_) + { + current_best_ = abs(out_corr); + d_secondary_delay=i; + } + } + //if (current_best_ > SECONDARY_THRESHOLD) + if (current_best_ >= 0.8*CN0_ESTIMATION_SAMPLES) + { + d_secondary_lock = true; + } +} void Galileo_E5a_Dll_Pll_Tracking_cc::update_local_code() { double tcode_chips; @@ -254,7 +348,10 @@ void Galileo_E5a_Dll_Pll_Tracking_cc::update_local_code() code_phase_step_chips = ((double)d_code_freq_chips) / ((double)d_fs_in); rem_code_phase_chips = d_rem_code_phase_samples * (d_code_freq_chips / d_fs_in); tcode_chips = -rem_code_phase_chips; +// SPACING USING QUADRATURE COMPONENT as 0.5 CHIP + double corr_spc_samples = d_early_late_spc_chips / code_phase_step_chips; +// CONVENTIONAL // 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; @@ -267,6 +364,11 @@ void Galileo_E5a_Dll_Pll_Tracking_cc::update_local_code() memcpy(d_prompt_code,&d_early_code[early_late_spc_samples],d_current_prn_length_samples* sizeof(gr_complex)); memcpy(d_late_code,&d_early_code[early_late_spc_samples*2],d_current_prn_length_samples* sizeof(gr_complex)); + +//EXPERIMENTAL + + + } @@ -296,159 +398,187 @@ int Galileo_E5a_Dll_Pll_Tracking_cc::general_work (int noutput_items, gr_vector_ if (d_enable_tracking == true) { - // Receiver signal alignment - if (d_pull_in == true) - { - int samples_offset; - float acq_trk_shif_correction_samples; - int acq_to_trk_delay_samples; - acq_to_trk_delay_samples = d_sample_counter - d_acq_sample_stamp; - acq_trk_shif_correction_samples = d_current_prn_length_samples - fmod((float)acq_to_trk_delay_samples, (float)d_current_prn_length_samples); - samples_offset = round(d_acq_code_phase_samples + acq_trk_shif_correction_samples); - // /todo: Check if the sample counter sent to the next block as a time reference should be incremented AFTER sended or BEFORE - //d_sample_counter_seconds = d_sample_counter_seconds + (((double)samples_offset) / (double)d_fs_in); - d_sample_counter = d_sample_counter + samples_offset; //count for the processed samples - d_pull_in = false; - //std::cout<<" samples_offset="<telemetry_decoder - Gnss_Synchro current_synchro_data; - // Fill the acquisition data - current_synchro_data = *d_acquisition_gnss_synchro; + // GNSS_SYNCHRO OBJECT to interchange data between tracking->telemetry_decoder + Gnss_Synchro current_synchro_data; + // Fill the acquisition data + current_synchro_data = *d_acquisition_gnss_synchro; - // Block input data and block output stream pointers - const gr_complex* in = (gr_complex*) input_items[0]; //PRN start block alignment - Gnss_Synchro **out = (Gnss_Synchro **) &output_items[0]; + // Block input data and block output stream pointers + const gr_complex* in = (gr_complex*) input_items[0]; //PRN start block alignment + Gnss_Synchro **out = (Gnss_Synchro **) &output_items[0]; - // Generate local code and carrier replicas (using \hat{f}_d(k-1)) - update_local_code(); - update_local_carrier(); + // Generate local code and carrier replicas (using \hat{f}_d(k-1)) + update_local_code(); + update_local_carrier(); - // perform carrier wipe-off and compute 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()); + // perform carrier wipe-off and compute 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(WARNING) << "Detected NaN samples at sample number " << d_sample_counter; - consume_each(samples_available); + // 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(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; + // 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; + *out[0] = current_synchro_data; - return 1; - } + return 1; + } - // ################## PLL ########################################################## - // PLL discriminator - carr_error_hz = pll_cloop_two_quadrant_atan(*d_Prompt) / (float)GALILEO_PI*2; - // Carrier discriminator filter - carr_error_filt_hz = d_carrier_loop_filter.get_carrier_nco(carr_error_hz); - // New carrier Doppler frequency estimation - d_carrier_doppler_hz = d_acq_carrier_doppler_hz + carr_error_filt_hz; - // New code Doppler frequency estimation - d_code_freq_chips = Galileo_E5a_CODE_CHIP_RATE_HZ + ((d_carrier_doppler_hz * Galileo_E5a_CODE_CHIP_RATE_HZ) / Galileo_E5a_FREQ_HZ); - //carrier phase accumulator for (K) doppler estimation - d_acc_carrier_phase_rad = d_acc_carrier_phase_rad + 2*GALILEO_PI*d_carrier_doppler_hz*GPS_L1_CA_CODE_PERIOD; - //remanent carrier phase to prevent overflow in the code NCO - d_rem_carr_phase_rad = d_rem_carr_phase_rad+2*GALILEO_PI*d_carrier_doppler_hz*GALILEO_E5a_CODE_PERIOD; - d_rem_carr_phase_rad = fmod(d_rem_carr_phase_rad, 2*GALILEO_PI); + // ################## PLL ########################################################## + // PLL discriminator + carr_error_hz = pll_cloop_two_quadrant_atan(*d_Prompt) / (float)GALILEO_PI*2; + // Carrier discriminator filter + carr_error_filt_hz = d_carrier_loop_filter.get_carrier_nco(carr_error_hz); + // New carrier Doppler frequency estimation + d_carrier_doppler_hz = d_acq_carrier_doppler_hz + carr_error_filt_hz; + // New code Doppler frequency estimation + d_code_freq_chips = Galileo_E5a_CODE_CHIP_RATE_HZ + ((d_carrier_doppler_hz * Galileo_E5a_CODE_CHIP_RATE_HZ) / Galileo_E5a_FREQ_HZ); + //carrier phase accumulator for (K) doppler estimation + d_acc_carrier_phase_rad = d_acc_carrier_phase_rad + 2*GALILEO_PI*d_carrier_doppler_hz*GALILEO_E5a_CODE_PERIOD; + //remanent carrier phase to prevent overflow in the code NCO + d_rem_carr_phase_rad = d_rem_carr_phase_rad+2*GALILEO_PI*d_carrier_doppler_hz*GALILEO_E5a_CODE_PERIOD; + d_rem_carr_phase_rad = fmod(d_rem_carr_phase_rad, 2*GALILEO_PI); - // ################## DLL ########################################################## - // DLL discriminator - code_error_chips = dll_nc_e_minus_l_normalized(*d_Early, *d_Late); //[chips/Ti] - // Code discriminator filter - code_error_filt_chips = d_code_loop_filter.get_code_nco(code_error_chips); //[chips/second] - //Code phase accumulator - float code_error_filt_secs; - code_error_filt_secs = (GALILEO_E5a_CODE_PERIOD*code_error_filt_chips)/Galileo_E5a_CODE_CHIP_RATE_HZ; //[seconds] - d_acc_code_phase_secs = d_acc_code_phase_secs + code_error_filt_secs; + // ################## DLL ########################################################## + // DLL discriminator + code_error_chips = dll_nc_e_minus_l_normalized(*d_Early, *d_Late); //[chips/Ti] + // Code discriminator filter + code_error_filt_chips = d_code_loop_filter.get_code_nco(code_error_chips); //[chips/second] + //Code phase accumulator + float code_error_filt_secs; + code_error_filt_secs = (GALILEO_E5a_CODE_PERIOD*code_error_filt_chips)/Galileo_E5a_CODE_CHIP_RATE_HZ; //[seconds] + d_acc_code_phase_secs = d_acc_code_phase_secs + code_error_filt_secs; - // ################## CARRIER AND CODE NCO BUFFER ALIGNEMENT ####################### - // keep alignment parameters for the next input buffer - float T_chip_seconds; - float T_prn_seconds; - float T_prn_samples; - float K_blk_samples; - // Compute the next buffer length based in the new period of the PRN sequence and the code phase error estimation - T_chip_seconds = 1 / d_code_freq_chips; - T_prn_seconds = T_chip_seconds * Galileo_E5a_CODE_LENGTH_CHIPS; - T_prn_samples = T_prn_seconds * (float)d_fs_in; - K_blk_samples = T_prn_samples + d_rem_code_phase_samples + code_error_filt_secs*(float)d_fs_in; - d_current_prn_length_samples = round(K_blk_samples); //round to a discrete samples - d_rem_code_phase_samples = K_blk_samples - d_current_prn_length_samples; //rounding error < 1 sample + std::cout<< "Early " << *d_Early << std::endl; + std::cout<< "Prompt " << *d_Prompt << std::endl; + std::cout<< "Late " << *d_Late << std::endl; + // ################## CARRIER AND CODE NCO BUFFER ALIGNEMENT ####################### + // keep alignment parameters for the next input buffer + float T_chip_seconds; + float T_prn_seconds; + float T_prn_samples; + float K_blk_samples; + // Compute the next buffer length based in the new period of the PRN sequence and the code phase error estimation + T_chip_seconds = 1 / d_code_freq_chips; + T_prn_seconds = T_chip_seconds * Galileo_E5a_CODE_LENGTH_CHIPS; + T_prn_samples = T_prn_seconds * (float)d_fs_in; + K_blk_samples = T_prn_samples + d_rem_code_phase_samples + code_error_filt_secs*(float)d_fs_in; + d_current_prn_length_samples = round(K_blk_samples); //round to a discrete samples + d_rem_code_phase_samples = K_blk_samples - d_current_prn_length_samples; //rounding error < 1 sample - // ####### 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; - // Code lock indicator - d_CN0_SNV_dB_Hz = cn0_svn_estimator(d_Prompt_buffer, CN0_ESTIMATION_SAMPLES, d_fs_in, Galileo_E5a_CODE_LENGTH_CHIPS); - // Carrier lock indicator - d_carrier_lock_test = carrier_lock_detector(d_Prompt_buffer, CN0_ESTIMATION_SAMPLES); - // Loss of lock detection - if (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 << "Loss of lock in channel " << d_channel << "!" << std::endl; - LOG(INFO) << "Loss of lock in channel " << d_channel << "!"; - 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 - } - } - // ########### Output the tracking data to navigation and PVT ########## - current_synchro_data.Prompt_I = (double)(*d_Prompt).real(); - current_synchro_data.Prompt_Q = (double)(*d_Prompt).imag(); - // Tracking_timestamp_secs is aligned with the PRN start sample - current_synchro_data.Tracking_timestamp_secs = ((double)d_sample_counter + (double)d_current_prn_length_samples + (double)d_rem_code_phase_samples)/(double)d_fs_in; - // This tracking block aligns the Tracking_timestamp_secs with the start sample of the PRN, thus, Code_phase_secs=0 - current_synchro_data.Code_phase_secs = 0; - current_synchro_data.Carrier_phase_rads = (double)d_acc_carrier_phase_rad; - current_synchro_data.Carrier_Doppler_hz = (double)d_carrier_doppler_hz; - current_synchro_data.CN0_dB_hz = (double)d_CN0_SNV_dB_Hz; - *out[0] = current_synchro_data; + // ####### 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 + { + // ATTEMPT SECONDARY CODE ACQUISITION + acquire_secondary(); // changes d_secondary_lock and d_secondary_delay + // + d_cn0_estimation_counter = 0; + // Code lock indicator + d_CN0_SNV_dB_Hz = cn0_svn_estimator(d_Prompt_buffer, CN0_ESTIMATION_SAMPLES, d_fs_in, Galileo_E5a_CODE_LENGTH_CHIPS); + // Carrier lock indicator + d_carrier_lock_test = carrier_lock_detector(d_Prompt_buffer, CN0_ESTIMATION_SAMPLES); + // Loss of lock detection + if (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 << "Loss of lock in channel " << d_channel << "!" << std::endl; + LOG(INFO) << "Loss of lock in channel " << d_channel << "!"; + 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 + } + } + // 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; + + + + } + else + { + // code with known secondary chip delay + // ########### Output the tracking data to navigation and PVT ########## + /* + current_synchro_data.Prompt_I = (double)(*d_Prompt).real(); + current_synchro_data.Prompt_Q = (double)(*d_Prompt).imag(); + // Tracking_timestamp_secs is aligned with the PRN start sample + current_synchro_data.Tracking_timestamp_secs = ((double)d_sample_counter + (double)d_current_prn_length_samples + (double)d_rem_code_phase_samples)/(double)d_fs_in; + // This tracking block aligns the Tracking_timestamp_secs with the start sample of the PRN, thus, Code_phase_secs=0 + current_synchro_data.Code_phase_secs = 0; + current_synchro_data.Carrier_phase_rads = (double)d_acc_carrier_phase_rad; + current_synchro_data.Carrier_Doppler_hz = (double)d_carrier_doppler_hz; + current_synchro_data.CN0_dB_hz = (double)d_CN0_SNV_dB_Hz; + *out[0] = current_synchro_data; + */ + } // ########## DEBUG OUTPUT /*! * \todo The stop timer has to be moved to the signal source! diff --git a/src/algorithms/tracking/gnuradio_blocks/galileo_e5a_dll_pll_tracking_cc.h b/src/algorithms/tracking/gnuradio_blocks/galileo_e5a_dll_pll_tracking_cc.h index b260c1297..cb2d17bf4 100644 --- a/src/algorithms/tracking/gnuradio_blocks/galileo_e5a_dll_pll_tracking_cc.h +++ b/src/algorithms/tracking/gnuradio_blocks/galileo_e5a_dll_pll_tracking_cc.h @@ -1,8 +1,32 @@ -/* - * galileo_e5a_dll_pll_tracking_cc.h +/*! + * \file galileo_e5a_dll_fll_pll_tracking_cc.h + * \brief Implementation of a code DLL + carrier PLL + * tracking block for Galileo E5a signals + * \author Marc Sales, 2014. marcsales92(at)gmail.com * - * Created on: Jun 19, 2014 - * Author: marc + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2014 (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_GALILEO_E5A_DLL_PLL_TRACKING_CC_H_ @@ -82,7 +106,7 @@ private: float early_late_space_chips); void update_local_code(); void update_local_carrier(); - + void acquire_secondary(); // tracking configuration vars boost::shared_ptr d_queue; concurrent_queue *d_channel_internal_queue; @@ -148,6 +172,10 @@ private: bool d_enable_tracking; bool d_pull_in; + // Secondary code acquisition + bool d_secondary_lock; + int d_secondary_delay; + // file dump std::string d_dump_filename; std::ofstream d_dump_file; diff --git a/src/core/receiver/gnss_block_factory.cc b/src/core/receiver/gnss_block_factory.cc index f67a36218..d74290fda 100644 --- a/src/core/receiver/gnss_block_factory.cc +++ b/src/core/receiver/gnss_block_factory.cc @@ -68,6 +68,7 @@ #include "galileo_e5a_pcps_acquisition.h" // #include "galileo_e5a_pilot_3ms_acquisition.h" #include "galileo_e5ax_2ms_pcps_acquisition.h" +#include "galileo_e5a_3ms_noncoherent_iq_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" @@ -477,6 +478,12 @@ std::unique_ptr GNSSBlockFactory::GetBlock( out_streams, queue)); block = std::move(block_); } + else if (implementation.compare("Galileo_E5a_3ms_Noncoherent_IQ_Acquisition") == 0) + { + std::unique_ptr block_(new GalileoE5a3msNoncoherentIQAcquisition(configuration.get(), role, in_streams, + out_streams, queue)); + block = std::move(block_); + } // TRACKING BLOCKS ------------------------------------------------------------- @@ -703,6 +710,12 @@ std::unique_ptr GNSSBlockFactory::GetAcqBlock( out_streams, queue)); block = std::move(block_); } + else if (implementation.compare("Galileo_E5a_3ms_Noncoherent_IQ_Acquisition") == 0) + { + std::unique_ptr block_(new GalileoE5a3msNoncoherentIQAcquisition(configuration.get(), role, in_streams, + out_streams, queue)); + block = std::move(block_); + } else { // Log fatal. This causes execution to stop. diff --git a/src/tests/gnss_block/galileo_e5a_pcps_acquisition_gsoc2014_gensource_test.cc b/src/tests/gnss_block/galileo_e5a_pcps_acquisition_gsoc2014_gensource_test.cc index 1e6bc40c1..b856a95dc 100644 --- a/src/tests/gnss_block/galileo_e5a_pcps_acquisition_gsoc2014_gensource_test.cc +++ b/src/tests/gnss_block/galileo_e5a_pcps_acquisition_gsoc2014_gensource_test.cc @@ -1,8 +1,32 @@ -/* - * galileo_e5a_pcps_acquisition_gsoc2014_test.cc +/*! + * \file galileo_e5a_pcps_acquisition_gsoc2014_gensource_test.cc + * \brief This class implements an acquisition test for + * GalileoE5a3msNoncoherentIQAcquisition class. + * \author Marc Sales, 2014. marcsales92(at)gmail.com * - * Created on: Jun 6, 2014 - * Author: marc + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2014 (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 @@ -13,6 +37,7 @@ #include #include #include +#include "gnss_block_factory.h" #include "gnss_block_interface.h" #include "in_memory_configuration.h" #include "configuration_interface.h" @@ -20,6 +45,7 @@ #include "galileo_e5a_pcps_acquisition.h" #include "galileo_e5a_pilot_3ms_acquisition.h" #include "galileo_e5ax_2ms_pcps_acquisition.h" +#include "galileo_e5a_3ms_noncoherent_iq_acquisition.h" #include "signal_generator.h" #include "signal_generator_c.h" #include "fir_filter.h" @@ -38,6 +64,7 @@ protected: { queue = gr::msg_queue::make(0); top_block = gr::make_top_block("Acquisition test"); + item_size = sizeof(gr_complex); stop = false; message = 0; @@ -58,9 +85,11 @@ protected: gr::msg_queue::sptr queue; gr::top_block_sptr top_block; - //GalileoE5aPcpsAcquisition *acquisition; - GalileoE5aPilot_3msAcquisition *acquisition; + //std::shared_ptr factory = std::make_shared(); +// GalileoE5aPcpsAcquisition *acquisition; + //GalileoE5aPilot_3msAcquisition *acquisition; //GalileoE5ax2msPcpsAcquisition *acquisition; + GalileoE5a3msNoncoherentIQAcquisition *acquisition; std::shared_ptr config; Gnss_Synchro gnss_synchro; size_t item_size; @@ -123,21 +152,25 @@ void GalileoE5aPcpsAcquisitionGSoC2014GensourceTest::config_1() { gnss_synchro.Channel_ID = 0; gnss_synchro.System = 'E'; + std::string signal = "5I"; //std::string signal = "5Q"; - std::string signal = "5X"; + //std::string signal = "5X"; signal.copy(gnss_synchro.Signal,2,0); - integration_time_ms = 1; + integration_time_ms = 3; //fs_in = 10.24e6; - //fs_in = 12e6; - fs_in = 12e6; + //fs_in = 18e6; + fs_in = 32e6; - //expected_delay_chips = 600; - //expected_doppler_hz = 750; +// unsigned int delay_samples = (delay_chips_[sat] % codelen) +// * samples_per_code_[sat] / codelen; + expected_delay_chips = round(14000*((double)10230000/(double)fs_in)); + expected_doppler_hz = 2800; + expected_delay_sec = 94; - expected_delay_chips = 1000; - expected_doppler_hz = 250; + //expected_delay_chips = 1000; + //expected_doppler_hz = 250; max_doppler_error_hz = 2/(3*integration_time_ms*1e-3); max_delay_error_chips = 0.50; @@ -159,9 +192,10 @@ void GalileoE5aPcpsAcquisitionGSoC2014GensourceTest::config_1() config->set_property("SignalSource.system_0", "E"); config->set_property("SignalSource.signal_0", "5X"); config->set_property("SignalSource.PRN_0", "11"); - config->set_property("SignalSource.CN0_dB_0", "44"); + config->set_property("SignalSource.CN0_dB_0", "50"); config->set_property("SignalSource.doppler_Hz_0", std::to_string(expected_doppler_hz)); config->set_property("SignalSource.delay_chips_0", std::to_string(expected_delay_chips)); + config->set_property("SignalSource.delay_sec_0", std::to_string(expected_delay_sec)); config->set_property("SignalSource.noise_flag", "false"); config->set_property("SignalSource.data_flag", "false"); @@ -194,15 +228,18 @@ void GalileoE5aPcpsAcquisitionGSoC2014GensourceTest::config_1() config->set_property("Acquisition.coherent_integration_time_ms", std::to_string(integration_time_ms)); config->set_property("Acquisition.max_dwells", "1"); - config->set_property("Acquisition.implementation", "Galileo_E5a_PCPS_Acquisition"); +// config->set_property("Acquisition.implementation", "Galileo_E5a_PCPS_Acquisition"); + //config->set_property("Acquisition.implementation", "Galileo_E5a_Pilot_3ms_Acquisition"); + + config->set_property("Acquisition.implementation", "Galileo_E5a_3ms_Noncoherent_IQ_Acquisition"); config->set_property("Acquisition.threshold", "0.1"); config->set_property("Acquisition.doppler_max", "10000"); config->set_property("Acquisition.doppler_step", "250"); - config->set_property("Acquisition.bit_transition_flag", "true"); + config->set_property("Acquisition.bit_transition_flag", "false"); config->set_property("Acquisition.dump", "true"); config->set_property("SignalSource.dump_filename", "../data/acquisition.dat"); - } + void GalileoE5aPcpsAcquisitionGSoC2014GensourceTest::config_2() { gnss_synchro.Channel_ID = 0; @@ -477,23 +514,26 @@ void GalileoE5aPcpsAcquisitionGSoC2014GensourceTest::stop_queue() /* TEST_F(GalileoE5aPcpsAcquisitionGSoC2014GensourceTest, Instantiate) { - config_2(); + config_1(); // acquisition = new GalileoE5aPilot_3msAcquisition(config.get(), "Acquisition", 1, 1, queue); - acquisition = new GalileoE5ax2msPcpsAcquisition(config.get(), "Acquisition", 1, 1, queue); + acquisition = new GalileoE5a3msNoncoherentIQAcquisition(config.get(), "Acquisition", 1, 1, queue); + delete acquisition; + } - - +*/ +/* TEST_F(GalileoE5aPcpsAcquisitionGSoC2014GensourceTest, ConnectAndRun) { - int nsamples = floor(fs_in*integration_time_ms*1e-3); + config_1(); + //int nsamples = floor(5*fs_in*integration_time_ms*1e-3); + int nsamples = 21000*3; struct timeval tv; long long int begin = 0; long long int end = 0; - - config_1(); + //acquisition = new GalileoE5aPcpsAcquisition(config.get(), "Acquisition", 1, 1, queue); //acquisition = new GalileoE5aPilot_3msAcquisition(config.get(), "Acquisition", 1, 1, queue); - acquisition = new GalileoE5ax2msPcpsAcquisition(config.get(), "Acquisition", 1, 1, queue); + acquisition = new GalileoE5a3msNoncoherentIQAcquisition(config.get(), "Acquisition", 1, 1, queue); ASSERT_NO_THROW( { @@ -556,13 +596,15 @@ TEST_F(GalileoE5aPcpsAcquisitionGSoC2014GensourceTest, SOURCEValidationTOFILE) }) << "Failure generating signal" << std::endl; } */ -/* + TEST_F(GalileoE5aPcpsAcquisitionGSoC2014GensourceTest, ValidationOfSIM) { config_1(); - int nsamples = floor(fs_in*integration_time_ms*1e-3); - acquisition = new GalileoE5aPcpsAcquisition(config.get(), "Acquisition", 1, 1, queue); + //int nsamples = floor(fs_in*integration_time_ms*1e-3); +// acquisition = new GalileoE5aPcpsAcquisition(config.get(), "Acquisition", 1, 1, queue); + acquisition = new GalileoE5a3msNoncoherentIQAcquisition(config.get(), "Acquisition", 1, 1, queue); + unsigned int skiphead_sps = 0; // 32 Msps ASSERT_NO_THROW( { acquisition->set_channel(1); @@ -593,10 +635,10 @@ TEST_F(GalileoE5aPcpsAcquisitionGSoC2014GensourceTest, ValidationOfSIM) }) << "Failure connecting acquisition to the top_block."<< std::endl; acquisition->init(); - +/* ASSERT_NO_THROW( { - std::string filename_ = "../data/Tiered_sink.dat"; - boost::shared_ptr file_sink_; + //std::string filename_ = "../data/Tiered_sink.dat"; + //boost::shared_ptr file_sink_; boost::shared_ptr signal_source; SignalGenerator* signal_generator = new SignalGenerator(config.get(), "SignalSource", 0, 1, queue); @@ -605,37 +647,78 @@ TEST_F(GalileoE5aPcpsAcquisitionGSoC2014GensourceTest, ValidationOfSIM) signal_source.reset(new GenSignalSource(config.get(), signal_generator, filter, "SignalSource", queue)); signal_source->connect(top_block); // - file_sink_=gr::blocks::file_sink::make(sizeof(gr_complex), filename_.c_str()); + //signal_generator->connect(top_block); + // + //file_sink_=gr::blocks::file_sink::make(sizeof(gr_complex), filename_.c_str()); top_block->connect(signal_source->get_right_block(), 0, acquisition->get_left_block(), 0); - top_block->connect(signal_source->get_right_block(), 0, file_sink_, 0); + //top_block->connect(signal_source->get_right_block(), 0, file_sink_, 0); + // + //top_block->connect(signal_generator->get_right_block(), 0, acquisition->get_left_block(), 0); + //top_block->connect(signal_generator->get_right_block(), 0, file_sink_, 0); + // }) << "Failure connecting the blocks of acquisition test." << std::endl; +*/ + ASSERT_NO_THROW( { + //std::string path = std::string(TEST_PATH); + //std::string file = "/home/marc/E5a_acquisitions/signal_source_21MPrimary.dat"; + //noiseless + std::string file = "/home/marc/E5a_acquisitions/sim_32M_sec94_PRN11.dat"; + //std::string file = "/home/marc/E5a_acquisitions/signal_source_21MSecondary.dat"; + //std::string file = "/home/marc/E5a_acquisitions/32MS_complex.dat"; + //std::string file = "/home/marc/E5a_acquisitions/galileo_E5_8M_r2_upsampled_12.dat"; + //CN040 -// ASSERT_NO_THROW( { -// //std::string path = std::string(TEST_PATH); -// //std::string file = "/home/marc/E5a_acquisitions/signal_source_5X_primary.dat"; -// std::string file = "/home/marc/E5a_acquisitions/galileo_E5_8M_r2_upsampled_12.dat"; -// const char * file_name = file.c_str(); -// gr::blocks::file_source::sptr file_source = gr::blocks::file_source::make(sizeof(gr_complex), file_name, false); -// top_block->connect(file_source, 0, acquisition->get_left_block(), 0); -// }) << "Failure connecting the blocks of acquisition test." << std::endl; + const char * file_name = file.c_str(); + gr::blocks::file_source::sptr file_source = gr::blocks::file_source::make(sizeof(gr_complex), file_name, false); + +// gr::blocks::skiphead::sptr skip_head = gr::blocks::skiphead::make(sizeof(gr_complex), skiphead_sps); +// top_block->connect(file_source, 0, skip_head, 0); +// top_block->connect(skip_head, 0, acquisition->get_left_block(), 0); + + top_block->connect(file_source, 0, acquisition->get_left_block(), 0); + }) << "Failure connecting the blocks of acquisition test." << std::endl; // i = 0 --> satellite in acquisition is visible // i = 1 --> satellite in acquisition is not visible - for (unsigned int i = 0; i < 2; i++) + for (unsigned int i = 0; i < 1; i++) { init(); - if (i == 0) - { - gnss_synchro.PRN = 11; // This satellite is visible - } - else if (i == 1) - { - gnss_synchro.PRN = 20; // This satellite is not visible - } + switch (i) + { + case 0: + { + //gnss_synchro.PRN = 19; //real + gnss_synchro.PRN = 11; //sim + break; + } +// case 1: +// { +// gnss_synchro.PRN = 11; +// break; +// } +// case 2: +// { +// gnss_synchro.PRN = 12; +// break; +// } +// case 3: +// { +// gnss_synchro.PRN = 20; +// break; +// } + } +// if (i == 0) +// { +// gnss_synchro.PRN = 11;// This satellite is visible +// } +// else if (i == 1) +// { +// gnss_synchro.PRN = 19; // This satellite is not visible +// } acquisition->set_local_code(); @@ -645,37 +728,40 @@ TEST_F(GalileoE5aPcpsAcquisitionGSoC2014GensourceTest, ValidationOfSIM) top_block->run(); // Start threads and wait }) << "Failure running he top_block."<< std::endl; - if (i == 0) - { - EXPECT_EQ(1, message) << "Acquisition failure. Expected message: 1=ACQ SUCCESS."; - if (message == 1) - { - std::cout << gnss_synchro.Acq_delay_samples << "acq delay" <. + * + * ------------------------------------------------------------------------- */ @@ -61,20 +86,23 @@ void GalileoE5aTrackingTest::init() gnss_synchro.System = 'E'; std::string signal = "5X"; signal.copy(gnss_synchro.Signal, 2, 0); - gnss_synchro.PRN = 11; + //gnss_synchro.PRN = 19;//real + gnss_synchro.PRN = 11;//sim - config->set_property("GNSS-SDR.internal_fs_hz", "12000000"); + config->set_property("GNSS-SDR.internal_fs_hz", "32000000"); config->set_property("Tracking.item_type", "gr_complex"); config->set_property("Tracking.dump", "true"); config->set_property("Tracking.dump_filename", "../data/e5a_tracking_ch_"); config->set_property("Tracking.implementation", "Galileo_E5a_DLL_PLL_Tracking"); config->set_property("Tracking.early_late_space_chips", "0.5"); - config->set_property("Tracking.pll_bw_hz", "50.0"); + config->set_property("Tracking.pll_bw_hz", "5.0"); config->set_property("Tracking.dll_bw_hz", "2.0"); - config->set_property("Tracking.fll_bw_hz", "10.0"); + //config->set_property("Tracking.fll_bw_hz", "10.0"); +// config->set_property("Tracking.pll_bw_hz", "20.0"); +// config->set_property("Tracking.dll_bw_hz", "1.0"); } - +/* TEST_F(GalileoE5aTrackingTest, InstantiateTrack) { @@ -84,12 +112,12 @@ TEST_F(GalileoE5aTrackingTest, InstantiateTrack) // auto tracking = factory->GetBlock(config, "Tracking", "Galileo_E1_DLL_PLL_VEML_Tracking", 1, 1, queue); // EXPECT_STREQ("Galileo_E1_DLL_PLL_VEML_Tracking", tracking->implementation().c_str()); -} - +}*/ +/* TEST_F(GalileoE5aTrackingTest, ConnectAndRun) { - int fs_in = 16000000; - int nsamples = 160000000; + int fs_in = 21000000; + int nsamples = 21000000; struct timeval tv; long long int begin; long long int end; @@ -135,28 +163,33 @@ TEST_F(GalileoE5aTrackingTest, ConnectAndRun) std::cout << "Processed " << nsamples << " samples in " << (end - begin) << " microseconds" << std::endl; } - +*/ TEST_F(GalileoE5aTrackingTest, ValidationOfResults) { struct timeval tv; long long int begin = 0; long long int end = 0; - // int num_samples = 40000000; // 4 Msps - // unsigned int skiphead_sps = 24000000; // 4 Msps - int num_samples = 120000000; // 12 Msps - unsigned int skiphead_sps = 1000000; // 1 Msample + int num_samples = 3200000000; // 32 Msps + //unsigned int skiphead_sps = 98000; // 1 Msample + unsigned int skiphead_sps = 0; // 1 Msample init(); // Example using smart pointers and the block factory std::shared_ptr trk_ = factory->GetBlock(config, "Tracking", "Galileo_E5a_DLL_PLL_Tracking", 1, 1, queue); std::shared_ptr tracking = std::dynamic_pointer_cast(trk_); - // gnss_synchro.Acq_delay_samples = 1753; // 4 Msps - // gnss_synchro.Acq_doppler_hz = -9500; // 4 Msps - gnss_synchro.Acq_delay_samples = 17256; // 8 Msps - gnss_synchro.Acq_doppler_hz = -8750; // 8 Msps +//REAL +// gnss_synchro.Acq_delay_samples = 15579; // 32 Msps +// gnss_synchro.Acq_doppler_hz = 3500; // 32 Msps +//// gnss_synchro.Acq_samplestamp_samples = 98000; +// gnss_synchro.Acq_samplestamp_samples = 0; +//SIM + gnss_synchro.Acq_delay_samples = 14001; // 32 Msps + gnss_synchro.Acq_doppler_hz = 2750; // 32 Msps (real 2800) +// gnss_synchro.Acq_samplestamp_samples = 98000; gnss_synchro.Acq_samplestamp_samples = 0; + ASSERT_NO_THROW( { tracking->set_channel(gnss_synchro.Channel_ID); }) << "Failure setting channel." << std::endl; @@ -174,7 +207,10 @@ TEST_F(GalileoE5aTrackingTest, ValidationOfResults) }) << "Failure connecting tracking to the top_block." << std::endl; ASSERT_NO_THROW( { - std::string file = "/home/marc/E5a_acquisitions/Tiered_sink_4sat.dat"; + //std::string file = "/home/marc/E5a_acquisitions/Tiered_sink_4sat.dat"; + //std::string file = "/home/marc/E5a_acquisitions/32MS_complex.dat"; + std::string file = "/home/marc/E5a_acquisitions/sim_32M_sec94_PRN11.dat"; + const char * file_name = file.c_str(); gr::blocks::file_source::sptr file_source = gr::blocks::file_source::make(sizeof(gr_complex),file_name,false); gr::blocks::skiphead::sptr skip_head = gr::blocks::skiphead::make(sizeof(gr_complex), skiphead_sps);