From 452dd24c906b5d4c2300dfbb00d814032f4ddfc5 Mon Sep 17 00:00:00 2001 From: Antonio Ramos Date: Wed, 7 Feb 2018 14:26:25 +0100 Subject: [PATCH] Add Gal. E5a Pcps acquisition adapter --- .../acquisition/adapters/CMakeLists.txt | 1 + .../adapters/galileo_e5a_pcps_acquisition.cc | 331 ++++++++++++++++++ .../adapters/galileo_e5a_pcps_acquisition.h | 170 +++++++++ src/core/receiver/gnss_block_factory.cc | 13 + src/core/system_parameters/Galileo_E5a.h | 2 +- 5 files changed, 516 insertions(+), 1 deletion(-) create mode 100644 src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition.cc create mode 100644 src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition.h diff --git a/src/algorithms/acquisition/adapters/CMakeLists.txt b/src/algorithms/acquisition/adapters/CMakeLists.txt index 9b1889109..b011ee636 100644 --- a/src/algorithms/acquisition/adapters/CMakeLists.txt +++ b/src/algorithms/acquisition/adapters/CMakeLists.txt @@ -31,6 +31,7 @@ set(ACQ_ADAPTER_SOURCES galileo_e1_pcps_tong_ambiguous_acquisition.cc galileo_e1_pcps_8ms_ambiguous_acquisition.cc galileo_e5a_noncoherent_iq_acquisition_caf.cc + galileo_e5a_pcps_acquisition.cc glonass_l1_ca_pcps_acquisition.cc ) diff --git a/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition.cc b/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition.cc new file mode 100644 index 000000000..5501be409 --- /dev/null +++ b/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition.cc @@ -0,0 +1,331 @@ +/*! + * \file galileo_e5a_pcps_acquisition.cc + * \brief Adapts a PCPS acquisition block to an AcquisitionInterface for + * Galileo E5a data and pilot Signals + * \author Antonio Ramos, 2018. antonio.ramos(at)cttc.es + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2018 (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_pcps_acquisition.h" +#include +#include +#include +#include +#include "galileo_e5_signal_processing.h" +#include "Galileo_E5a.h" +#include "configuration_interface.h" + +using google::LogMessage; + +GalileoE5aPcpsAcquisition::GalileoE5aPcpsAcquisition(ConfigurationInterface* configuration, + std::string role, unsigned int in_streams, unsigned int out_streams) : + role_(role), in_streams_(in_streams), out_streams_(out_streams) +{ + 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); + + long fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 32000000); + fs_in_ = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated); + acq_pilot_ = configuration_->property(role + ".acquire_pilot", false); + dump_ = configuration_->property(role + ".dump", false); + doppler_max_ = configuration_->property(role + ".doppler_max", 5000); + sampled_ms_ = configuration_->property(role + ".coherent_integration_time_ms", 1); + if (sampled_ms_ > 3) + { + sampled_ms_ = 3; + DLOG(INFO) << "Coherent integration time should be 3 ms or less. Changing to 3ms "; + std::cout << "Too high coherent integration time. Changing to 3ms" << std::endl; + } + /* + if (Zero_padding > 0) + { + sampled_ms_ = 2; + DLOG(INFO) << "Zero padding activated. Changing to 1ms code + 1ms zero padding "; + std::cout << "Zero padding activated. Changing to 1ms code + 1ms zero padding" << std::endl; + } + */ + max_dwells_ = configuration_->property(role + ".max_dwells", 1); + dump_filename_ = configuration_->property(role + ".dump_filename", default_dump_filename); + bit_transition_flag_ = configuration_->property(role + ".bit_transition_flag", false); + use_CFAR_ = configuration_->property(role + ".use_CFAR_algorithm", false); + blocking_ = configuration_->property(role + ".blocking", true); + + //--- Find number of samples per spreading code (1ms)------------------------- + code_length_ = round(static_cast(fs_in_) / Galileo_E5a_CODE_CHIP_RATE_HZ * static_cast(Galileo_E5a_CODE_LENGTH_CHIPS)); + vector_length_ = code_length_ * sampled_ms_; + + /* + codeI_= new gr_complex[vector_length_]; + codeQ_= new gr_complex[vector_length_]; + */ + code_ = new gr_complex[vector_length_]; + + if(item_type_.compare("gr_complex") == 0) + { + item_size_ = sizeof(gr_complex); + } + else if(item_type_.compare("cshort") == 0) + { + item_size_ = sizeof(lv_16sc_t); + } + else + { + item_size_ = sizeof(gr_complex); + LOG(WARNING) << item_type_ << " unknown acquisition item type"; + } + // CHANGE PARAMETERS OF MAKE ACQ.!!!!!!! + acquisition_ = pcps_make_acquisition(sampled_ms_, max_dwells_, doppler_max_, 0, fs_in_, + code_length_, code_length_, bit_transition_flag_, use_CFAR_, dump_, blocking_, + dump_filename_,item_size_); + + stream_to_vector_ = gr::blocks::stream_to_vector::make(item_size_, vector_length_); + channel_ = 0; + threshold_ = 0.0; + doppler_step_ = 0; + gnss_synchro_ = 0; +} + + +GalileoE5aPcpsAcquisition::~GalileoE5aPcpsAcquisition() +{ + delete[] code_; +} + + +void GalileoE5aPcpsAcquisition::set_channel(unsigned int channel) +{ + channel_ = channel; + acquisition_->set_channel(channel_); +} + + +void GalileoE5aPcpsAcquisition::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 " << channel_ << " Threshold = " << threshold_; + + acquisition_->set_threshold(threshold_); +} + + +void GalileoE5aPcpsAcquisition::set_doppler_max(unsigned int doppler_max) +{ + doppler_max_ = doppler_max; + acquisition_->set_doppler_max(doppler_max_); +} + + +void GalileoE5aPcpsAcquisition::set_doppler_step(unsigned int doppler_step) +{ + doppler_step_ = doppler_step; + acquisition_->set_doppler_step(doppler_step_); +} + + +void GalileoE5aPcpsAcquisition::set_gnss_synchro(Gnss_Synchro* gnss_synchro) +{ + gnss_synchro_ = gnss_synchro; + acquisition_->set_gnss_synchro(gnss_synchro_); +} + + +signed int GalileoE5aPcpsAcquisition::mag() +{ + return acquisition_->mag(); +} + + +void GalileoE5aPcpsAcquisition::init() +{ + acquisition_->init(); + //set_local_code(); +} + + +void GalileoE5aPcpsAcquisition::set_local_code() +{ + gr_complex* code = new gr_complex[code_length_]; + char a[3]; + + if(acq_pilot_) { strcpy(a,"5Q"); } + else { strcpy(a,"5I"); } + galileo_e5_a_code_gen_complex_sampled(code, a, gnss_synchro_->PRN, fs_in_, 0); + + for(unsigned int i = 0; i < sampled_ms_; i++) + { + memcpy(code_ + i * code_length_, code, sizeof(gr_complex) * code_length_); + } + acquisition_->set_local_code(code_); + delete[] code; + + + + /* + if (item_type_.compare("gr_complex") == 0) + { + std::complex* codeI = new std::complex[code_length_]; + std::complex* codeQ = new std::complex[code_length_]; + + if (gnss_synchro_->Signal[0] == '5' && gnss_synchro_->Signal[1] == 'X') + { + char a[3]; + strcpy(a,"5I"); + galileo_e5_a_code_gen_complex_sampled(codeI, a, + gnss_synchro_->PRN, fs_in_, 0); + + strcpy(a,"5Q"); + galileo_e5_a_code_gen_complex_sampled(codeQ, a, + gnss_synchro_->PRN, fs_in_, 0); + } + else + { + galileo_e5_a_code_gen_complex_sampled(codeI, gnss_synchro_->Signal, + gnss_synchro_->PRN, fs_in_, 0); + } + // WARNING: 3ms are coherently integrated. Secondary sequence (1,1,1) + // is generated, and modulated in the 'block'. + if (Zero_padding == 0) // if no zero_padding + { + for (unsigned int i = 0; i < sampled_ms_; i++) + { + memcpy(&(codeI_[i*code_length_]), codeI, + sizeof(gr_complex)*code_length_); + if (gnss_synchro_->Signal[0] == '5' && gnss_synchro_->Signal[1] == 'X') + { + memcpy(&(codeQ_[i*code_length_]), codeQ, + sizeof(gr_complex)*code_length_); + } + } + } + else + { + // 1ms code + 1ms zero padding + memcpy(&(codeI_[0]), codeI, + sizeof(gr_complex)*code_length_); + if (gnss_synchro_->Signal[0] == '5' && gnss_synchro_->Signal[1] == 'X') + { + memcpy(&(codeQ_[0]), codeQ, + sizeof(gr_complex)*code_length_); + } + } + + acquisition_->set_local_code(codeI_,codeQ_); + delete[] codeI; + delete[] codeQ; + + } + */ +} + + +void GalileoE5aPcpsAcquisition::reset() +{ + acquisition_->set_active(true); +} + + +float GalileoE5aPcpsAcquisition::calculate_threshold(float pfa) +{ + //Calculate the threshold + unsigned int frequency_bins = 0; + for (int doppler = static_cast(-doppler_max_); doppler <= static_cast(doppler_max_); doppler += doppler_step_) + { + frequency_bins++; + } + DLOG(INFO) << "Channel " << channel_ << " Pfa = " << pfa; + unsigned int ncells = vector_length_ * frequency_bins; + double exponent = 1 / static_cast(ncells); + double val = pow(1.0 - pfa, exponent); + double lambda = double(vector_length_); + boost::math::exponential_distribution mydist (lambda); + float threshold = static_cast(quantile(mydist,val)); + + return threshold; +} + + +void GalileoE5aPcpsAcquisition::set_state(int state) +{ + acquisition_->set_state(state); +} + + +void GalileoE5aPcpsAcquisition::connect(gr::top_block_sptr top_block) +{ + if (item_type_.compare("gr_complex") == 0) + { + top_block->connect(stream_to_vector_, 0, acquisition_, 0); + } + else if (item_type_.compare("cshort") == 0) + { + top_block->connect(stream_to_vector_, 0, acquisition_, 0); + } + else + { + LOG(WARNING) << item_type_ << " unknown acquisition item type"; + } +} + + +void GalileoE5aPcpsAcquisition::disconnect(gr::top_block_sptr top_block) +{ + if (item_type_.compare("gr_complex") == 0) + { + top_block->disconnect(stream_to_vector_, 0, acquisition_, 0); + } + else if (item_type_.compare("cshort") == 0) + { + top_block->disconnect(stream_to_vector_, 0, acquisition_, 0); + } + else + { + LOG(WARNING) << item_type_ << " unknown acquisition item type"; + } +} + + +gr::basic_block_sptr GalileoE5aPcpsAcquisition::get_left_block() +{ + return stream_to_vector_; +} + + +gr::basic_block_sptr GalileoE5aPcpsAcquisition::get_right_block() +{ + return acquisition_; +} diff --git a/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition.h b/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition.h new file mode 100644 index 000000000..0c50ced70 --- /dev/null +++ b/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition.h @@ -0,0 +1,170 @@ +/*! + * \file galileo_e5a_pcps_acquisition.h + * \brief Adapts a PCPS acquisition block to an AcquisitionInterface for + * Galileo E5a data and pilot Signals + * \author Antonio Ramos, 2018. antonio.ramos(at)cttc.es + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2018 (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_PCPS_ACQUISITION_H_ +#define GALILEO_E5A_PCPS_ACQUISITION_H_ + +#include +#include +#include "gnss_synchro.h" +#include "acquisition_interface.h" +#include "pcps_acquisition.h" + +class ConfigurationInterface; + +class GalileoE5aPcpsAcquisition: public AcquisitionInterface +{ +public: + GalileoE5aPcpsAcquisition(ConfigurationInterface* configuration, + std::string role, unsigned int in_streams, + unsigned int out_streams); + + virtual ~GalileoE5aPcpsAcquisition(); + + inline std::string role() override + { + return role_; + } + + inline std::string implementation() override + { + return "Galileo_E5a_Pcps_Acquisition"; + } + + inline size_t item_size() override + { + return item_size_; + } + + void connect(gr::top_block_sptr top_block) override; + void disconnect(gr::top_block_sptr top_block) override; + gr::basic_block_sptr get_left_block() override; + gr::basic_block_sptr get_right_block() override; + + /*! + * \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) override; + + /*! + * \brief Set acquisition channel unique ID + */ + void set_channel(unsigned int channel) override; + + /*! + * \brief Set statistics threshold of PCPS algorithm + */ + void set_threshold(float threshold) override; + + /*! + * \brief Set maximum Doppler off grid search + */ + void set_doppler_max(unsigned int doppler_max) override; + + /*! + * \brief Set Doppler steps for the grid search + */ + void set_doppler_step(unsigned int doppler_step) override; + + /*! + * \brief Initializes acquisition algorithm. + */ + void init() override; + + /*! + * \brief Sets local Galileo E5a code for PCPS acquisition algorithm. + */ + void set_local_code() override; + + /*! + * \brief Returns the maximum peak of grid search + */ + signed int mag() override; + + /*! + * \brief Restart acquisition algorithm + */ + void reset() override; + + /*! + * \brief If set to 1, ensures that acquisition starts at the + * first available sample. + * \param state - int=1 forces start of acquisition + */ + void set_state(int state); + +private: + + float calculate_threshold(float pfa); + + ConfigurationInterface* configuration_; + + pcps_acquisition_sptr acquisition_; + gr::blocks::stream_to_vector::sptr stream_to_vector_; + + size_t item_size_; + + std::string item_type_; + std::string dump_filename_; + std::string role_; + + bool bit_transition_flag_; + bool dump_; + bool acq_pilot_; + bool use_CFAR_; + bool blocking_; + + unsigned int vector_length_; + unsigned int code_length_; + unsigned int channel_; + unsigned int doppler_max_; + unsigned int doppler_step_; + unsigned int sampled_ms_; + unsigned int max_dwells_; + unsigned int in_streams_; + unsigned int out_streams_; + + long fs_in_; + + float threshold_; + + /* + std::complex* codeI_; + std::complex* codeQ_; + */ + + gr_complex* code_; + + Gnss_Synchro* gnss_synchro_; + +}; +#endif /* GALILEO_E5A_PCPS_ACQUISITION_H_ */ diff --git a/src/core/receiver/gnss_block_factory.cc b/src/core/receiver/gnss_block_factory.cc index 1a3563885..02aeffeb0 100644 --- a/src/core/receiver/gnss_block_factory.cc +++ b/src/core/receiver/gnss_block_factory.cc @@ -82,6 +82,7 @@ #include "galileo_e1_pcps_cccwsr_ambiguous_acquisition.h" #include "galileo_e1_pcps_quicksync_ambiguous_acquisition.h" #include "galileo_e5a_noncoherent_iq_acquisition_caf.h" +#include "galileo_e5a_pcps_acquisition.h" #include "glonass_l1_ca_pcps_acquisition.h" #include "gps_l1_ca_dll_pll_tracking.h" #include "gps_l1_ca_dll_pll_c_aid_tracking.h" @@ -1270,6 +1271,12 @@ std::unique_ptr GNSSBlockFactory::GetBlock( out_streams)); block = std::move(block_); } + else if (implementation.compare("Galileo_E5a_Pcps_Acquisition") == 0) + { + std::unique_ptr block_(new GalileoE5aPcpsAcquisition(configuration.get(), role, in_streams, + out_streams)); + block = std::move(block_); + } else if (implementation.compare("Galileo_E1_PCPS_QuickSync_Ambiguous_Acquisition") == 0) { std::unique_ptr block_( new GalileoE1PcpsQuickSyncAmbiguousAcquisition(configuration.get(), role, in_streams, @@ -1543,6 +1550,12 @@ std::unique_ptr GNSSBlockFactory::GetAcqBlock( out_streams)); block = std::move(block_); } + else if (implementation.compare("Galileo_E5a_Pcps_Acquisition") == 0) + { + std::unique_ptr block_(new GalileoE5aPcpsAcquisition(configuration.get(), role, in_streams, + out_streams)); + block = std::move(block_); + } else if (implementation.compare("GLONASS_L1_CA_PCPS_Acquisition") == 0) { std::unique_ptr block_(new GlonassL1CaPcpsAcquisition(configuration.get(), role, in_streams, diff --git a/src/core/system_parameters/Galileo_E5a.h b/src/core/system_parameters/Galileo_E5a.h index 5663d8dc2..2a2f5a816 100644 --- a/src/core/system_parameters/Galileo_E5a.h +++ b/src/core/system_parameters/Galileo_E5a.h @@ -47,7 +47,7 @@ const int Galileo_E5a_CODE_LENGTH_CHIPS = 10230; //!< Galileo E5a prima const int Galileo_E5a_I_SECONDARY_CODE_LENGTH = 20; //!< Galileo E5a-I secondary code length [chips] const int Galileo_E5a_Q_SECONDARY_CODE_LENGTH = 100; //!< Galileo E5a-Q secondary code length [chips] const double GALILEO_E5a_CODE_PERIOD = 0.001; //!< Galileo E1 primary code period [s] -const int GALILEO_E5a_CODE_PERIOD_MS = 1; //!< Galileo E1 primary code period [ms] +const int GALILEO_E5a_CODE_PERIOD_MS = 1; //!< Galileo E1 primary code period [ms] const int Galileo_E5a_SYMBOL_RATE_BPS = 50; //!< Galileo E5a symbol rate [bits/second] const int Galileo_E5a_NUMBER_OF_CODES = 50;