diff --git a/src/algorithms/acquisition/adapters/CMakeLists.txt b/src/algorithms/acquisition/adapters/CMakeLists.txt index f8c6b34b1..9df3ba982 100644 --- a/src/algorithms/acquisition/adapters/CMakeLists.txt +++ b/src/algorithms/acquisition/adapters/CMakeLists.txt @@ -19,7 +19,6 @@ set(ACQ_ADAPTER_SOURCES gps_l1_ca_pcps_acquisition.cc - gps_l1_ca_pcps_multithread_acquisition.cc gps_l1_ca_pcps_assisted_acquisition.cc gps_l1_ca_pcps_acquisition_fine_doppler.cc gps_l1_ca_pcps_tong_acquisition.cc diff --git a/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.cc b/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.cc index a322def0e..f2060aebb 100644 --- a/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.cc +++ b/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.cc @@ -56,6 +56,7 @@ GalileoE1PcpsAmbiguousAcquisition::GalileoE1PcpsAmbiguousAcquisition( fs_in_ = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated); if_ = configuration_->property(role + ".if", 0); dump_ = configuration_->property(role + ".dump", false); + blocking_ = configuration_->property(role + ".blocking", true); doppler_max_ = configuration_->property(role + ".doppler_max", 5000); sampled_ms_ = configuration_->property(role + ".coherent_integration_time_ms", 4); @@ -91,7 +92,8 @@ GalileoE1PcpsAmbiguousAcquisition::GalileoE1PcpsAmbiguousAcquisition( item_size_ = sizeof(lv_16sc_t); acquisition_sc_ = pcps_make_acquisition_sc(sampled_ms_, max_dwells_, doppler_max_, if_, fs_in_, samples_per_ms, code_length_, - bit_transition_flag_, use_CFAR_algorithm_flag_, dump_, dump_filename_); + bit_transition_flag_, use_CFAR_algorithm_flag_, dump_, blocking_, + dump_filename_); DLOG(INFO) << "acquisition(" << acquisition_sc_->unique_id() << ")"; } @@ -100,7 +102,8 @@ GalileoE1PcpsAmbiguousAcquisition::GalileoE1PcpsAmbiguousAcquisition( item_size_ = sizeof(gr_complex); acquisition_cc_ = pcps_make_acquisition_cc(sampled_ms_, max_dwells_, doppler_max_, if_, fs_in_, samples_per_ms, code_length_, - bit_transition_flag_, use_CFAR_algorithm_flag_, dump_, dump_filename_); + bit_transition_flag_, use_CFAR_algorithm_flag_, dump_, blocking_, + dump_filename_); DLOG(INFO) << "acquisition(" << acquisition_cc_->unique_id() << ")"; } diff --git a/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.h b/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.h index 3874e4df9..da8d2e742 100644 --- a/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.h +++ b/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.h @@ -155,6 +155,7 @@ private: long fs_in_; long if_; bool dump_; + bool blocking_; std::string dump_filename_; std::complex * code_; Gnss_Synchro * gnss_synchro_; diff --git a/src/algorithms/acquisition/adapters/glonass_l1_ca_pcps_acquisition.cc b/src/algorithms/acquisition/adapters/glonass_l1_ca_pcps_acquisition.cc index 1066eae1f..5afc7e073 100644 --- a/src/algorithms/acquisition/adapters/glonass_l1_ca_pcps_acquisition.cc +++ b/src/algorithms/acquisition/adapters/glonass_l1_ca_pcps_acquisition.cc @@ -24,6 +24,7 @@ GlonassL1CaPcpsAcquisition::GlonassL1CaPcpsAcquisition( fs_in_ = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated); if_ = configuration_->property(role + ".if", 0); dump_ = configuration_->property(role + ".dump", false); + blocking_ = configuration_->property(role + ".blocking", true); doppler_max_ = configuration_->property(role + ".doppler_max", 5000); sampled_ms_ = configuration_->property(role + ".coherent_integration_time_ms", 1); @@ -51,14 +52,14 @@ GlonassL1CaPcpsAcquisition::GlonassL1CaPcpsAcquisition( item_size_ = sizeof(lv_16sc_t); acquisition_sc_ = pcps_make_acquisition_sc(sampled_ms_, max_dwells_, doppler_max_, if_, fs_in_, code_length_, code_length_, - bit_transition_flag_, use_CFAR_algorithm_flag_, dump_, dump_filename_); + bit_transition_flag_, use_CFAR_algorithm_flag_, dump_, blocking_, dump_filename_); DLOG(INFO) << "acquisition(" << acquisition_sc_->unique_id() << ")"; }else{ item_size_ = sizeof(gr_complex); acquisition_cc_ = pcps_make_acquisition_cc(sampled_ms_, max_dwells_, doppler_max_, if_, fs_in_, code_length_, code_length_, - bit_transition_flag_, use_CFAR_algorithm_flag_, dump_, dump_filename_); + bit_transition_flag_, use_CFAR_algorithm_flag_, dump_, blocking_, dump_filename_); DLOG(INFO) << "acquisition(" << acquisition_cc_->unique_id() << ")"; } diff --git a/src/algorithms/acquisition/adapters/glonass_l1_ca_pcps_acquisition.h b/src/algorithms/acquisition/adapters/glonass_l1_ca_pcps_acquisition.h index ff01d7364..65f6b9874 100644 --- a/src/algorithms/acquisition/adapters/glonass_l1_ca_pcps_acquisition.h +++ b/src/algorithms/acquisition/adapters/glonass_l1_ca_pcps_acquisition.h @@ -126,6 +126,7 @@ private: long fs_in_; long if_; bool dump_; + bool blocking_; std::string dump_filename_; std::complex * code_; Gnss_Synchro * gnss_synchro_; diff --git a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition.cc b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition.cc index f0cded2ba..2cacaae60 100644 --- a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition.cc +++ b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition.cc @@ -59,6 +59,7 @@ GpsL1CaPcpsAcquisition::GpsL1CaPcpsAcquisition( fs_in_ = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated); if_ = configuration_->property(role + ".if", 0); dump_ = configuration_->property(role + ".dump", false); + blocking_ = configuration_->property(role + ".blocking", true); doppler_max_ = configuration_->property(role + ".doppler_max", 5000); sampled_ms_ = configuration_->property(role + ".coherent_integration_time_ms", 1); @@ -86,7 +87,7 @@ GpsL1CaPcpsAcquisition::GpsL1CaPcpsAcquisition( item_size_ = sizeof(lv_16sc_t); acquisition_sc_ = pcps_make_acquisition_sc(sampled_ms_, max_dwells_, doppler_max_, if_, fs_in_, code_length_, code_length_, - bit_transition_flag_, use_CFAR_algorithm_flag_, dump_, dump_filename_); + bit_transition_flag_, use_CFAR_algorithm_flag_, dump_, blocking_, dump_filename_); DLOG(INFO) << "acquisition(" << acquisition_sc_->unique_id() << ")"; } else @@ -94,7 +95,7 @@ GpsL1CaPcpsAcquisition::GpsL1CaPcpsAcquisition( item_size_ = sizeof(gr_complex); acquisition_cc_ = pcps_make_acquisition_cc(sampled_ms_, max_dwells_, doppler_max_, if_, fs_in_, code_length_, code_length_, - bit_transition_flag_, use_CFAR_algorithm_flag_, dump_, dump_filename_); + bit_transition_flag_, use_CFAR_algorithm_flag_, dump_, blocking_, dump_filename_); DLOG(INFO) << "acquisition(" << acquisition_cc_->unique_id() << ")"; } diff --git a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition.h b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition.h index 0ff27c87f..183a9212c 100644 --- a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition.h +++ b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition.h @@ -160,6 +160,7 @@ private: long fs_in_; long if_; bool dump_; + bool blocking_; std::string dump_filename_; std::complex * code_; Gnss_Synchro * gnss_synchro_; diff --git a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_multithread_acquisition.cc b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_multithread_acquisition.cc deleted file mode 100644 index e2216bb60..000000000 --- a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_multithread_acquisition.cc +++ /dev/null @@ -1,287 +0,0 @@ -/*! - * \file gps_l1_ca_pcps_multithread_acquisition.cc - * \brief Adapts a multithread PCPS acquisition block to an - * AcquisitionInterface for GPS L1 C/A signals - * \author Marc Molina, 2013. marc.molina.pena(at)gmail.com - * - * ------------------------------------------------------------------------- - * - * Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors) - * - * GNSS-SDR is a software defined Global Navigation - * Satellite Systems receiver - * - * This file is part of GNSS-SDR. - * - * GNSS-SDR is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GNSS-SDR is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNSS-SDR. If not, see . - * - * ------------------------------------------------------------------------- - */ - -#include "gps_l1_ca_pcps_multithread_acquisition.h" -#include -#include -#include "gps_sdr_signal_processing.h" -#include "GPS_L1_CA.h" -#include "configuration_interface.h" - - -using google::LogMessage; - -GpsL1CaPcpsMultithreadAcquisition::GpsL1CaPcpsMultithreadAcquisition( - 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", 2048000); - fs_in_ = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated); - if_ = configuration_->property(role + ".if", 0); - dump_ = configuration_->property(role + ".dump", false); - doppler_max_ = configuration->property(role + ".doppler_max", 5000); - sampled_ms_ = configuration_->property(role + ".coherent_integration_time_ms", 1); - - bit_transition_flag_ = configuration_->property("Acquisition.bit_transition_flag", false); - - if (!bit_transition_flag_) - { - max_dwells_ = configuration_->property(role + ".max_dwells", 1); - } - else - { - max_dwells_ = 2; - } - - dump_filename_ = configuration_->property(role + ".dump_filename", - default_dump_filename); - - //--- Find number of samples per spreading code ------------------------- - code_length_ = round(fs_in_ - / (GPS_L1_CA_CODE_RATE_HZ / GPS_L1_CA_CODE_LENGTH_CHIPS)); - - vector_length_ = code_length_ * sampled_ms_; - - code_ = new gr_complex[vector_length_]; - - if (item_type_.compare("gr_complex") == 0) - { - item_size_ = sizeof(gr_complex); - acquisition_cc_ = pcps_make_multithread_acquisition_cc(sampled_ms_, max_dwells_, - doppler_max_, if_, fs_in_, code_length_, code_length_, - bit_transition_flag_, 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 - { - item_size_ = sizeof(gr_complex); - LOG(WARNING) << item_type_ << " unknown acquisition item type"; - } - - channel_ = 0; - threshold_ = 0.0; - doppler_step_ = 0; - gnss_synchro_ = 0; -} - - -GpsL1CaPcpsMultithreadAcquisition::~GpsL1CaPcpsMultithreadAcquisition() -{ - delete[] code_; -} - - -void GpsL1CaPcpsMultithreadAcquisition::set_channel(unsigned int channel) -{ - channel_ = channel; - if (item_type_.compare("gr_complex") == 0) - { - acquisition_cc_->set_channel(channel_); - } -} - - -void GpsL1CaPcpsMultithreadAcquisition::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_; - - if (item_type_.compare("gr_complex") == 0) - { - acquisition_cc_->set_threshold(threshold_); - } -} - - -void GpsL1CaPcpsMultithreadAcquisition::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 GpsL1CaPcpsMultithreadAcquisition::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 GpsL1CaPcpsMultithreadAcquisition::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 GpsL1CaPcpsMultithreadAcquisition::mag() -{ - if (item_type_.compare("gr_complex") == 0) - { - return acquisition_cc_->mag(); - } - else - { - return 0; - } -} - - -void GpsL1CaPcpsMultithreadAcquisition::init() -{ - acquisition_cc_->init(); - //set_local_code(); -} - - -void GpsL1CaPcpsMultithreadAcquisition::set_local_code() -{ - if (item_type_.compare("gr_complex") == 0) - { - std::complex* code = new std::complex[code_length_]; - - gps_l1_ca_code_gen_complex_sampled(code, 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_cc_->set_local_code(code_); - - delete[] code; - } -} - - -void GpsL1CaPcpsMultithreadAcquisition::reset() -{ - if (item_type_.compare("gr_complex") == 0) - { - acquisition_cc_->set_active(true); - } -} - - -float GpsL1CaPcpsMultithreadAcquisition::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 GpsL1CaPcpsMultithreadAcquisition::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 GpsL1CaPcpsMultithreadAcquisition::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 GpsL1CaPcpsMultithreadAcquisition::get_left_block() -{ - return stream_to_vector_; -} - - -gr::basic_block_sptr GpsL1CaPcpsMultithreadAcquisition::get_right_block() -{ - return acquisition_cc_; -} - diff --git a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_multithread_acquisition.h b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_multithread_acquisition.h deleted file mode 100644 index 210fe0749..000000000 --- a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_multithread_acquisition.h +++ /dev/null @@ -1,156 +0,0 @@ -/*! - * \file gps_l1_ca_pcps_multithread_acquisition.h - * \brief Adapts a multithread PCPS acquisition block to an - * AcquisitionInterface for GPS L1 C/A signals - * \author Marc Molina, 2013. marc.molina.pena(at)gmail.com - * - * ------------------------------------------------------------------------- - * - * Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors) - * - * GNSS-SDR is a software defined Global Navigation - * Satellite Systems receiver - * - * This file is part of GNSS-SDR. - * - * GNSS-SDR is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GNSS-SDR is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNSS-SDR. If not, see . - * - * ------------------------------------------------------------------------- - */ - -#ifndef GNSS_SDR_GPS_L1_CA_PCPS_MULTITHREAD_ACQUISITION_H_ -#define GNSS_SDR_GPS_L1_CA_PCPS_MULTITHREAD_ACQUISITION_H_ - -#include -#include -#include "gnss_synchro.h" -#include "acquisition_interface.h" -#include "pcps_multithread_acquisition_cc.h" - - - -class ConfigurationInterface; - -/*! - * \brief This class adapts a multithread PCPS acquisition block to an - * AcquisitionInterface for GPS L1 C/A signals - */ -class GpsL1CaPcpsMultithreadAcquisition: public AcquisitionInterface -{ -public: - GpsL1CaPcpsMultithreadAcquisition(ConfigurationInterface* configuration, - std::string role, unsigned int in_streams, - unsigned int out_streams); - - virtual ~GpsL1CaPcpsMultithreadAcquisition(); - - inline std::string role() override - { - return role_; - } - - /*! - * \brief Returns "GPS_L1_CA_PCPS_Multithread_Acquisition" - */ - inline std::string implementation() override - { - return "GPS_L1_CA_PCPS_Multithread_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 code for GPS L1/CA 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; - -private: - ConfigurationInterface* configuration_; - pcps_multithread_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 sampled_ms_; - unsigned int max_dwells_; - long fs_in_; - long if_; - bool dump_; - std::string dump_filename_; - std::complex * code_; - Gnss_Synchro * gnss_synchro_; - std::string role_; - unsigned int in_streams_; - unsigned int out_streams_; - - float calculate_threshold(float pfa); -}; - -#endif /* GNSS_SDR_GPS_L1_CA_PCPS_MULTITHREAD_ACQUISITION_H_ */ diff --git a/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition.cc b/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition.cc index e0ff10757..b9443a4e8 100644 --- a/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition.cc +++ b/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition.cc @@ -59,6 +59,7 @@ GpsL2MPcpsAcquisition::GpsL2MPcpsAcquisition( fs_in_ = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated); if_ = configuration_->property(role + ".if", 0); dump_ = configuration_->property(role + ".dump", false); + blocking_ = configuration_->property(role + ".blocking", true); doppler_max_ = configuration->property(role + ".doppler_max", 5000); bit_transition_flag_ = configuration_->property(role + ".bit_transition_flag", false); @@ -86,7 +87,7 @@ GpsL2MPcpsAcquisition::GpsL2MPcpsAcquisition( item_size_ = sizeof(lv_16sc_t); acquisition_sc_ = pcps_make_acquisition_sc(1, max_dwells_, doppler_max_, if_, fs_in_, code_length_, code_length_, - bit_transition_flag_, use_CFAR_algorithm_flag_, dump_, dump_filename_); + bit_transition_flag_, use_CFAR_algorithm_flag_, dump_, blocking_, dump_filename_); DLOG(INFO) << "acquisition(" << acquisition_sc_->unique_id() << ")"; } @@ -95,7 +96,8 @@ GpsL2MPcpsAcquisition::GpsL2MPcpsAcquisition( item_size_ = sizeof(gr_complex); acquisition_cc_ = pcps_make_acquisition_cc(1, max_dwells_, doppler_max_, if_, fs_in_, code_length_, code_length_, - bit_transition_flag_, use_CFAR_algorithm_flag_, dump_, dump_filename_); + bit_transition_flag_, use_CFAR_algorithm_flag_, dump_, blocking_, + dump_filename_); DLOG(INFO) << "acquisition(" << acquisition_cc_->unique_id() << ")"; } diff --git a/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition.h b/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition.h index cbe2a09a1..544737e79 100644 --- a/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition.h +++ b/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition.h @@ -157,6 +157,7 @@ private: long fs_in_; long if_; bool dump_; + bool blocking_; std::string dump_filename_; std::complex * code_; Gnss_Synchro * gnss_synchro_; diff --git a/src/algorithms/acquisition/gnuradio_blocks/CMakeLists.txt b/src/algorithms/acquisition/gnuradio_blocks/CMakeLists.txt index c67c6106d..8a22651c4 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/CMakeLists.txt +++ b/src/algorithms/acquisition/gnuradio_blocks/CMakeLists.txt @@ -20,7 +20,6 @@ set(ACQ_GR_BLOCKS_SOURCES pcps_acquisition_cc.cc pcps_acquisition_sc.cc - pcps_multithread_acquisition_cc.cc pcps_assisted_acquisition_cc.cc pcps_acquisition_fine_doppler_cc.cc pcps_tong_acquisition_cc.cc diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.cc b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.cc index b61c6d4a1..cf8ec8936 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.cc +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.cc @@ -5,11 +5,12 @@ *
  • Javier Arribas, 2011. jarribas(at)cttc.es *
  • Luis Esteve, 2012. luis(at)epsilon-formacion.com *
  • Marc Molina, 2013. marc.molina.pena@gmail.com + *
  • Cillian O'Driscoll, 2017. cillian(at)ieee.org * * * ------------------------------------------------------------------------- * - * Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors) + * Copyright (C) 2010-2017 (see AUTHORS file for a list of contributors) * * GNSS-SDR is a software defined Global Navigation * Satellite Systems receiver @@ -52,12 +53,12 @@ pcps_acquisition_cc_sptr pcps_make_acquisition_cc( unsigned int doppler_max, long freq, long fs_in, int samples_per_ms, int samples_per_code, bool bit_transition_flag, bool use_CFAR_algorithm_flag, - bool dump, + bool dump, bool blocking, std::string dump_filename) { return pcps_acquisition_cc_sptr( new pcps_acquisition_cc(sampled_ms, max_dwells, doppler_max, freq, fs_in, samples_per_ms, - samples_per_code, bit_transition_flag, use_CFAR_algorithm_flag, dump, dump_filename)); + samples_per_code, bit_transition_flag, use_CFAR_algorithm_flag, dump, blocking, dump_filename)); } @@ -66,7 +67,7 @@ pcps_acquisition_cc::pcps_acquisition_cc( unsigned int doppler_max, long freq, long fs_in, int samples_per_ms, int samples_per_code, bool bit_transition_flag, bool use_CFAR_algorithm_flag, - bool dump, + bool dump, bool blocking, std::string dump_filename) : gr::block("pcps_acquisition_cc", gr::io_signature::make(1, 1, sizeof(gr_complex) * sampled_ms * samples_per_ms * ( bit_transition_flag ? 2 : 1 )), @@ -132,6 +133,12 @@ pcps_acquisition_cc::pcps_acquisition_cc( d_gnss_synchro = 0; d_grid_doppler_wipeoffs = 0; + + d_done = false; + d_blocking = blocking; + d_new_data_available = false; + d_worker_active = false; + d_data_buffer = static_cast(volk_gnsssdr_malloc(d_fft_size * sizeof(gr_complex), volk_gnsssdr_get_alignment())); } @@ -156,6 +163,20 @@ pcps_acquisition_cc::~pcps_acquisition_cc() { d_dump_file.close(); } + + // Let the worker thread know that we are done and then wait to join + if( d_worker_thread.joinable() ) + { + { + std::lock_guard lk( d_mutex ); + d_done = true; + d_cond.notify_one(); + } + + d_worker_thread.join(); + } + + volk_gnsssdr_free( d_data_buffer ); } @@ -175,7 +196,7 @@ void pcps_acquisition_cc::set_local_code(std::complex * code) gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler if( d_bit_transition_flag ) { - int offset = d_fft_size/2; + int offset = d_fft_size / 2; std::fill_n( d_fft_if->get_inbuf(), offset, gr_complex( 0.0, 0.0 ) ); memcpy(d_fft_if->get_inbuf() + offset, code, sizeof(gr_complex) * offset); } @@ -238,6 +259,10 @@ void pcps_acquisition_cc::init() int doppler = -static_cast(d_doppler_max) + d_doppler_step * doppler_index; update_local_carrier(d_grid_doppler_wipeoffs[doppler_index], d_fft_size, d_freq + doppler); } + + d_new_data_available = false; + d_done = false; + d_worker_active = false; } @@ -283,17 +308,16 @@ void pcps_acquisition_cc::send_positive_acquisition() // 6.1- Declare positive acquisition using a message port //0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL DLOG(INFO) << "positive acquisition" - << "satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN - << "sample_stamp " << d_sample_counter - << "test statistics value " << d_test_statistics - << "test statistics threshold " << d_threshold - << "code phase " << d_gnss_synchro->Acq_delay_samples - << "doppler " << d_gnss_synchro->Acq_doppler_hz - << "magnitude " << d_mag - << "input signal power " << d_input_power; + << ", satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN + << ", sample_stamp " << d_sample_counter + << ", test statistics value " << d_test_statistics + << ", test statistics threshold " << d_threshold + << ", code phase " << d_gnss_synchro->Acq_delay_samples + << ", doppler " << d_gnss_synchro->Acq_doppler_hz + << ", magnitude " << d_mag + << ", input signal power " << d_input_power; this->message_port_pub(pmt::mp("events"), pmt::from_long(1)); - } @@ -302,17 +326,16 @@ void pcps_acquisition_cc::send_negative_acquisition() // 6.2- Declare negative acquisition using a message port //0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL DLOG(INFO) << "negative acquisition" - << "satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN - << "sample_stamp " << d_sample_counter - << "test statistics value " << d_test_statistics - << "test statistics threshold " << d_threshold - << "code phase " << d_gnss_synchro->Acq_delay_samples - << "doppler " << d_gnss_synchro->Acq_doppler_hz - << "magnitude " << d_mag - << "input signal power " << d_input_power; + << ", satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN + << ", sample_stamp " << d_sample_counter + << ", test statistics value " << d_test_statistics + << ", test statistics threshold " << d_threshold + << ", code phase " << d_gnss_synchro->Acq_delay_samples + << ", doppler " << d_gnss_synchro->Acq_doppler_hz + << ", magnitude " << d_mag + << ", input signal power " << d_input_power; this->message_port_pub(pmt::mp("events"), pmt::from_long(2)); - } @@ -356,11 +379,72 @@ int pcps_acquisition_cc::general_work(int noutput_items, case 1: { + std::unique_lock lk( d_mutex ); + + int num_items_consumed = 1; + + if( d_worker_active ) + { + if( d_blocking ) + { + // Should never get here: + std::string msg = "pcps_acquisition_cc: Entered general work with worker active in blocking mode, should never happen"; + LOG(WARNING) << msg; + std::cout << msg << std::endl; + d_cond.wait( lk, [&]{ return !this->d_worker_active; } ); + } + else + { + num_items_consumed = ninput_items[0]; + d_sample_counter += d_fft_size * num_items_consumed; + } + } + else + { + // Copy the data to the core and let it know that new data is available + memcpy( d_data_buffer, input_items[0], d_fft_size * sizeof( gr_complex ) ); + d_new_data_available = true; + d_cond.notify_one(); + + if( d_blocking ) + { + d_cond.wait( lk, [&]{ return !this->d_new_data_available; } ); + + } + } + + consume_each(num_items_consumed); + + break; + } // case 1, switch d_state + + } // switch d_state + + return noutput_items; +} + + +void pcps_acquisition_cc::acquisition_core( void ) +{ + d_worker_active = false; + while( 1 ) + { + std::unique_lock lk( d_mutex ); + d_cond.wait( lk, [&]{ return this->d_new_data_available or this->d_done; } ); + d_worker_active = !d_done; + unsigned long int sample_counter = d_sample_counter; // sample counter + lk.unlock(); + + if( d_done ) + { + break; + } + // initialize acquisition algorithm int doppler; uint32_t indext = 0; float magt = 0.0; - const gr_complex *in = reinterpret_cast(input_items[0]); + const gr_complex *in = d_data_buffer; //Get the input samples pointer int effective_fft_size = ( d_bit_transition_flag ? d_fft_size/2 : d_fft_size ); @@ -368,14 +452,14 @@ int pcps_acquisition_cc::general_work(int noutput_items, d_input_power = 0.0; d_mag = 0.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<System << " " << d_gnss_synchro->PRN + << " ,sample stamp: " << sample_counter << ", threshold: " + << d_threshold << ", doppler_max: " << d_doppler_max + << ", doppler_step: " << d_doppler_step + << ", use_CFAR_algorithm_flag: " << ( d_use_CFAR_algorithm_flag ? "true" : "false" ); if (d_use_CFAR_algorithm_flag == true) { @@ -440,7 +524,7 @@ int pcps_acquisition_cc::general_work(int noutput_items, { d_gnss_synchro->Acq_delay_samples = static_cast(indext % d_samples_per_code); d_gnss_synchro->Acq_doppler_hz = static_cast(doppler); - d_gnss_synchro->Acq_samplestamp_samples = d_sample_counter; + d_gnss_synchro->Acq_samplestamp_samples = sample_counter; // 5- Compute the test statistics and compare to the threshold //d_test_statistics = 2 * d_fft_size * d_mag / d_input_power; @@ -457,13 +541,13 @@ int pcps_acquisition_cc::general_work(int noutput_items, boost::filesystem::path p = d_dump_filename; filename << p.parent_path().string() - << boost::filesystem::path::preferred_separator - << p.stem().string() - << "_" << d_gnss_synchro->System - <<"_" << d_gnss_synchro->Signal << "_sat_" - << d_gnss_synchro->PRN << "_doppler_" - << doppler - << p.extension().string(); + << boost::filesystem::path::preferred_separator + << p.stem().string() + << "_" << d_gnss_synchro->System + <<"_" << d_gnss_synchro->Signal << "_sat_" + << d_gnss_synchro->PRN << "_doppler_" + << doppler + << p.extension().string(); DLOG(INFO) << "Writing ACQ out to " << filename.str(); @@ -507,25 +591,40 @@ int pcps_acquisition_cc::general_work(int noutput_items, } } - consume_each(1); - break; + lk.lock(); + d_worker_active = false; + d_new_data_available = false; + lk.unlock(); + d_cond.notify_one(); } - } - - return noutput_items; } -//void pcps_acquisition_cc::forecast (int noutput_items, gr_vector_int &ninput_items_required) -//{ - //// COD: - //// For zero-padded case we need one extra code period - //if( d_bit_transition_flag ) - //{ - //ninput_items_required[0] = noutput_items*(d_samples_per_code * d_max_dwells + d_samples_per_code); - //} - //else - //{ - //ninput_items_required[0] = noutput_items*d_fft_size*d_max_dwells; - //} -//} +bool pcps_acquisition_cc::start( void ) +{ + d_worker_active = false; + d_done = false; + + // Start the worker thread and wait for it to acknowledge: + d_worker_thread = std::move( std::thread( &pcps_acquisition_cc::acquisition_core, this ) ); + + return gr::block::start(); +} + + +bool pcps_acquisition_cc::stop( void ) +{ + // Let the worker thread know that we are done and then wait to join + if( d_worker_thread.joinable() ) + { + { + std::lock_guard lk( d_mutex ); + d_done = true; + d_cond.notify_one(); + } + + d_worker_thread.join(); + } + return gr::block::stop(); +} + diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.h b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.h index 272a0f9bc..c3d525d37 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.h +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.h @@ -20,11 +20,12 @@ *
  • Javier Arribas, 2011. jarribas(at)cttc.es *
  • Luis Esteve, 2012. luis(at)epsilon-formacion.com *
  • Marc Molina, 2013. marc.molina.pena@gmail.com + *
  • Cillian O'Driscoll, 2017. cillian(at)ieee.org * * * ------------------------------------------------------------------------- * - * Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors) + * Copyright (C) 2010-2017 (see AUTHORS file for a list of contributors) * * GNSS-SDR is a software defined Global Navigation * Satellite Systems receiver @@ -52,6 +53,9 @@ #include #include +#include +#include +#include #include #include #include @@ -67,7 +71,7 @@ pcps_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, bool use_CFAR_algorithm_flag, - bool dump, + bool dump, bool blocking, std::string dump_filename); /*! @@ -84,20 +88,22 @@ private: unsigned int doppler_max, long freq, long fs_in, int samples_per_ms, int samples_per_code, bool bit_transition_flag, bool use_CFAR_algorithm_flag, - bool dump, + bool dump, bool blocking, std::string dump_filename); pcps_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, bool use_CFAR_algorithm_flag, - bool dump, + bool dump, bool blocking, std::string dump_filename); void update_local_carrier(gr_complex* carrier_vector, int correlator_length_samples, float freq); void update_grid_doppler_wipeoffs(); bool is_fdma(); + void acquisition_core( void ); + void send_negative_acquisition(); void send_positive_acquisition(); long d_fs_in; @@ -136,6 +142,17 @@ private: unsigned int d_channel; std::string d_dump_filename; + std::thread d_worker_thread; + std::mutex d_mutex; + + std::condition_variable d_cond; + bool d_done; + bool d_new_data_available; + bool d_worker_active; + bool d_blocking; + + gr_complex *d_data_buffer; + public: /*! * \brief Default destructor. @@ -237,6 +254,16 @@ public: int general_work(int noutput_items, gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); + + /*! + * Called by the flowgraph when processing is about to start. + */ + bool start( void ); + + /*! + * Called by the flowgraph when processing is done. + */ + bool stop( void ); }; #endif /* GNSS_SDR_PCPS_ACQUISITION_CC_H_*/ diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_sc.cc b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_sc.cc index 5a15e2037..c7869741b 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_sc.cc +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_sc.cc @@ -5,11 +5,12 @@ *
  • Javier Arribas, 2011. jarribas(at)cttc.es *
  • Luis Esteve, 2012. luis(at)epsilon-formacion.com *
  • Marc Molina, 2013. marc.molina.pena@gmail.com + *
  • Cillian O'Driscoll, 2017. cillian(at)ieee.org * * * ------------------------------------------------------------------------- * - * Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors) + * Copyright (C) 2010-2017 (see AUTHORS file for a list of contributors) * * GNSS-SDR is a software defined Global Navigation * Satellite Systems receiver @@ -32,18 +33,19 @@ * ------------------------------------------------------------------------- */ + #include "pcps_acquisition_sc.h" #include #include #include #include #include -#include #include "control_message_factory.h" #include "GPS_L1_CA.h" //GPS_TWO_PI #include "GLONASS_L1_CA.h" //GLONASS_TWO_PI + using google::LogMessage; pcps_acquisition_sc_sptr pcps_make_acquisition_sc( @@ -51,27 +53,28 @@ pcps_acquisition_sc_sptr pcps_make_acquisition_sc( unsigned int doppler_max, long freq, long fs_in, int samples_per_ms, int samples_per_code, bool bit_transition_flag, bool use_CFAR_algorithm_flag, - bool dump, + bool dump, bool blocking, std::string dump_filename) { - return pcps_acquisition_sc_sptr( new pcps_acquisition_sc(sampled_ms, max_dwells, doppler_max, freq, fs_in, samples_per_ms, - samples_per_code, bit_transition_flag, use_CFAR_algorithm_flag, dump, dump_filename)); + samples_per_code, bit_transition_flag, use_CFAR_algorithm_flag, dump, blocking, dump_filename)); } + pcps_acquisition_sc::pcps_acquisition_sc( 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, bool use_CFAR_algorithm_flag, - bool dump, + bool dump, bool blocking, std::string dump_filename) : gr::block("pcps_acquisition_sc", gr::io_signature::make(1, 1, sizeof(lv_16sc_t) * sampled_ms * samples_per_ms * ( bit_transition_flag ? 2 : 1 )), - gr::io_signature::make(0, 0, 0)) + gr::io_signature::make(0, 0, sizeof(lv_16sc_t) * sampled_ms * samples_per_ms * ( bit_transition_flag ? 2 : 1 )) ) { this->message_port_register_out(pmt::mp("events")); + d_sample_counter = 0; // SAMPLE COUNTER d_active = false; d_state = 0; @@ -91,7 +94,7 @@ pcps_acquisition_sc::pcps_acquisition_sc( d_bit_transition_flag = bit_transition_flag; d_use_CFAR_algorithm_flag = use_CFAR_algorithm_flag; d_threshold = 0.0; - d_doppler_step = 250; + d_doppler_step = 0; d_code_phase = 0; d_test_statistics = 0.0; d_channel = 0; @@ -112,11 +115,12 @@ pcps_acquisition_sc::pcps_acquisition_sc( if( d_bit_transition_flag ) { d_fft_size *= 2; - d_max_dwells = 1; + d_max_dwells = 1; //Activation of d_bit_transition_flag invalidates the value of d_max_dwells } d_fft_codes = static_cast(volk_gnsssdr_malloc(d_fft_size * sizeof(gr_complex), volk_gnsssdr_get_alignment())); d_magnitude = static_cast(volk_gnsssdr_malloc(d_fft_size * sizeof(float), volk_gnsssdr_get_alignment())); + //temporary storage for the input conversion from 16sc to float 32fc d_in_32fc = static_cast(volk_gnsssdr_malloc(d_fft_size * sizeof(gr_complex), volk_gnsssdr_get_alignment())); @@ -132,6 +136,12 @@ pcps_acquisition_sc::pcps_acquisition_sc( d_gnss_synchro = 0; d_grid_doppler_wipeoffs = 0; + + d_done = false; + d_blocking = blocking; + d_new_data_available = false; + d_worker_active = false; + d_data_buffer = static_cast(volk_gnsssdr_malloc(d_fft_size * sizeof(lv_16sc_t), volk_gnsssdr_get_alignment())); } @@ -157,6 +167,20 @@ pcps_acquisition_sc::~pcps_acquisition_sc() { d_dump_file.close(); } + + // Let the worker thread know that we are done and then wait to join + if( d_worker_thread.joinable() ) + { + { + std::lock_guard lk( d_mutex ); + d_done = true; + d_cond.notify_one(); + } + + d_worker_thread.join(); + } + + volk_gnsssdr_free( d_data_buffer ); } @@ -173,13 +197,18 @@ void pcps_acquisition_sc::set_local_code(std::complex * code) // Here we want to create a buffer that looks like this: // [ 0 0 0 ... 0 c_0 c_1 ... c_L] // where c_i is the local code and there are L zeros and L chips - int offset = 0; + gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler if( d_bit_transition_flag ) { - std::fill_n( d_fft_if->get_inbuf(), d_samples_per_code, gr_complex( 0.0, 0.0 ) ); - offset = d_samples_per_code; + int offset = d_fft_size / 2; + std::fill_n( d_fft_if->get_inbuf(), offset, gr_complex( 0.0, 0.0 ) ); + memcpy(d_fft_if->get_inbuf() + offset, code, sizeof(gr_complex) * offset); } - memcpy(d_fft_if->get_inbuf() + offset, code, sizeof(gr_complex) * d_samples_per_code); + else + { + memcpy(d_fft_if->get_inbuf(), code, sizeof(gr_complex) * d_fft_size); + } + d_fft_if->execute(); // We need the FFT of local code volk_32fc_conjugate_32fc(d_fft_codes, d_fft_if->get_outbuf(), d_fft_size); } @@ -234,8 +263,11 @@ void pcps_acquisition_sc::init() int doppler = -static_cast(d_doppler_max) + d_doppler_step * doppler_index; update_local_carrier(d_grid_doppler_wipeoffs[doppler_index], d_fft_size, d_freq + doppler); } -} + d_new_data_available = false; + d_done = false; + d_worker_active = false; +} void pcps_acquisition_sc::update_grid_doppler_wipeoffs() { @@ -253,6 +285,7 @@ void pcps_acquisition_sc::update_grid_doppler_wipeoffs() void pcps_acquisition_sc::set_state(int state) { + gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler d_state = state; if (d_state == 1) { @@ -272,6 +305,43 @@ void pcps_acquisition_sc::set_state(int state) } } + +void pcps_acquisition_sc::send_positive_acquisition() +{ + // 6.1- Declare positive acquisition using a message port + //0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL + DLOG(INFO) << "positive acquisition" + << ", satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN + << ", sample_stamp " << d_sample_counter + << ", test statistics value " << d_test_statistics + << ", test statistics threshold " << d_threshold + << ", code phase " << d_gnss_synchro->Acq_delay_samples + << ", doppler " << d_gnss_synchro->Acq_doppler_hz + << ", magnitude " << d_mag + << ", input signal power " << d_input_power; + + this->message_port_pub(pmt::mp("events"), pmt::from_long(1)); +} + + +void pcps_acquisition_sc::send_negative_acquisition() +{ + // 6.2- Declare negative acquisition using a message port + //0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL + DLOG(INFO) << "negative acquisition" + << ", satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN + << ", sample_stamp " << d_sample_counter + << ", test statistics value " << d_test_statistics + << ", test statistics threshold " << d_threshold + << ", code phase " << d_gnss_synchro->Acq_delay_samples + << ", doppler " << d_gnss_synchro->Acq_doppler_hz + << ", magnitude " << d_mag + << ", input signal power " << d_input_power; + + this->message_port_pub(pmt::mp("events"), pmt::from_long(2)); +} + + int pcps_acquisition_sc::general_work(int noutput_items, gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items __attribute__((unused))) @@ -287,8 +357,6 @@ int pcps_acquisition_sc::general_work(int noutput_items, * 6. Declare positive or negative acquisition using a message port */ - int acquisition_message = -1; //0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL - switch (d_state) { case 0: @@ -303,42 +371,101 @@ int pcps_acquisition_sc::general_work(int noutput_items, d_mag = 0.0; d_input_power = 0.0; d_test_statistics = 0.0; - d_state = 1; } d_sample_counter += d_fft_size * ninput_items[0]; // sample counter consume_each(ninput_items[0]); - //DLOG(INFO) << "Consumed " << ninput_items[0] << " items"; - break; } case 1: { + std::unique_lock lk( d_mutex ); + + int num_items_consumed = 1; + + if( d_worker_active ) + { + if( d_blocking ) + { + // Should never get here: + std::string msg = "pcps_acquisition_sc: Entered general work with worker active in blocking mode, should never happen"; + LOG(WARNING) << msg; + std::cout << msg << std::endl; + d_cond.wait( lk, [&]{ return !this->d_worker_active; } ); + } + else + { + num_items_consumed = ninput_items[0]; + d_sample_counter += d_fft_size * num_items_consumed; + } + } + else + { + // Copy the data to the core and let it know that new data is available + memcpy( d_data_buffer, input_items[0], d_fft_size * sizeof( lv_16sc_t ) ); + d_new_data_available = true; + d_cond.notify_one(); + + if( d_blocking ) + { + d_cond.wait( lk, [&]{ return !this->d_new_data_available; } ); + + } + } + + consume_each(num_items_consumed); + + break; + } // case 1, switch d_state + + } // switch d_state + + return noutput_items; +} + + +void pcps_acquisition_sc::acquisition_core( void ) +{ + d_worker_active = false; + while( 1 ) + { + std::unique_lock lk( d_mutex ); + d_cond.wait( lk, [&]{ return this->d_new_data_available or this->d_done; } ); + d_worker_active = !d_done; + unsigned long int sample_counter = d_sample_counter; // sample counter + lk.unlock(); + + if( d_done ) + { + break; + } + // initialize acquisition algorithm int doppler; uint32_t indext = 0; float magt = 0.0; - const lv_16sc_t *in = reinterpret_cast(input_items[0]); //Get the input samples pointer + const lv_16sc_t *in = d_data_buffer; //Get the input samples pointer + int effective_fft_size = ( d_bit_transition_flag ? d_fft_size/2 : d_fft_size ); //TODO: optimize the signal processing chain to not use gr_complex. This is a temporary solution - volk_gnsssdr_16ic_convert_32fc(d_in_32fc,in,effective_fft_size); + volk_gnsssdr_16ic_convert_32fc(d_in_32fc, in, effective_fft_size); float fft_normalization_factor = static_cast(d_fft_size) * static_cast(d_fft_size); + d_input_power = 0.0; d_mag = 0.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: " + << " , doing acquisition of satellite: " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN + << " ,sample stamp: " << sample_counter << ", threshold: " << d_threshold << ", doppler_max: " << d_doppler_max - << ", doppler_step: " << d_doppler_step; + << ", doppler_step: " << d_doppler_step + << ", use_CFAR_algorithm_flag: " << ( d_use_CFAR_algorithm_flag ? "true" : "false" ); if (d_use_CFAR_algorithm_flag == true) { @@ -351,7 +478,6 @@ int pcps_acquisition_sc::general_work(int noutput_items, for (unsigned int doppler_index = 0; doppler_index < d_num_doppler_bins; doppler_index++) { // doppler search steps - doppler = -static_cast(d_doppler_max) + d_doppler_step * doppler_index; volk_32fc_x2_multiply_32fc(d_fft_if->get_inbuf(), d_in_32fc, @@ -380,7 +506,6 @@ int pcps_acquisition_sc::general_work(int noutput_items, // Normalize the maximum value to correct the scale factor introduced by FFTW magt = d_magnitude[indext] / (fft_normalization_factor * fft_normalization_factor); } - // 4- record the maximum peak and the associated synchronization parameters if (d_mag < magt) { @@ -405,12 +530,11 @@ int pcps_acquisition_sc::general_work(int noutput_items, { d_gnss_synchro->Acq_delay_samples = static_cast(indext % d_samples_per_code); d_gnss_synchro->Acq_doppler_hz = static_cast(doppler); - d_gnss_synchro->Acq_samplestamp_samples = d_sample_counter; + d_gnss_synchro->Acq_samplestamp_samples = 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; - //std::cout<<"d_input_power="<Acq_doppler_hz ="<Acq_doppler_hz <System - <<"_" << d_gnss_synchro->Signal << "_sat_" - << d_gnss_synchro->PRN << "_doppler_" - << doppler - << p.extension().string(); + << boost::filesystem::path::preferred_separator + << p.stem().string() + << "_" << d_gnss_synchro->System + <<"_" << d_gnss_synchro->Signal << "_sat_" + << d_gnss_synchro->PRN << "_doppler_" + << doppler + << p.extension().string(); DLOG(INFO) << "Writing ACQ out to " << filename.str(); @@ -443,11 +567,15 @@ int pcps_acquisition_sc::general_work(int noutput_items, { if (d_test_statistics > d_threshold) { - d_state = 2; // Positive acquisition + d_state = 0; // Positive acquisition + d_active = false; + send_positive_acquisition(); } else if (d_well_count == d_max_dwells) { - d_state = 3; // Negative acquisition + d_state = 0; + d_active = false; + send_negative_acquisition(); } } else @@ -456,71 +584,53 @@ int pcps_acquisition_sc::general_work(int noutput_items, { if (d_test_statistics > d_threshold) { - d_state = 2; // Positive acquisition + d_state = 0; // Positive acquisition + d_active = false; + send_positive_acquisition(); } else { - d_state = 3; // Negative acquisition + d_state = 0; // Negative acquisition + d_active = false; + send_negative_acquisition(); } } } - consume_each(1); - - DLOG(INFO) << "Done. Consumed 1 item."; - - break; + lk.lock(); + d_worker_active = false; + d_new_data_available = false; + lk.unlock(); + d_cond.notify_one(); } - - case 2: - { - // 6.1- Declare positive acquisition using a message port - 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 += d_fft_size * ninput_items[0]; // sample counter - consume_each(ninput_items[0]); - - acquisition_message = 1; - this->message_port_pub(pmt::mp("events"), pmt::from_long(acquisition_message)); - - break; - } - - case 3: - { - // 6.2- Declare negative acquisition using a message port - 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 += d_fft_size * ninput_items[0]; // sample counter - consume_each(ninput_items[0]); - acquisition_message = 2; - this->message_port_pub(pmt::mp("events"), pmt::from_long(acquisition_message)); - - break; - } - } - - return noutput_items; } + + +bool pcps_acquisition_sc::start( void ) +{ + d_worker_active = false; + d_done = false; + + // Start the worker thread and wait for it to acknowledge: + d_worker_thread = std::move( std::thread( &pcps_acquisition_sc::acquisition_core, this ) ); + + return gr::block::start(); +} + + +bool pcps_acquisition_sc::stop( void ) +{ + // Let the worker thread know that we are done and then wait to join + if( d_worker_thread.joinable() ) + { + { + std::lock_guard lk( d_mutex ); + d_done = true; + d_cond.notify_one(); + } + + d_worker_thread.join(); + } + return gr::block::stop(); +} + diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_sc.h b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_sc.h index 093c88dd8..068a9c1c7 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_sc.h +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_sc.h @@ -20,11 +20,12 @@ *
  • Javier Arribas, 2011. jarribas(at)cttc.es *
  • Luis Esteve, 2012. luis(at)epsilon-formacion.com *
  • Marc Molina, 2013. marc.molina.pena@gmail.com + *
  • Cillian O'Driscoll, 2017. cillian(at)ieee.org * * * ------------------------------------------------------------------------- * - * Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors) + * Copyright (C) 2010-2017 (see AUTHORS file for a list of contributors) * * GNSS-SDR is a software defined Global Navigation * Satellite Systems receiver @@ -52,11 +53,16 @@ #include #include +#include +#include +#include #include #include #include +#include #include "gnss_synchro.h" + class pcps_acquisition_sc; typedef boost::shared_ptr pcps_acquisition_sc_sptr; @@ -66,7 +72,7 @@ pcps_make_acquisition_sc(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, bool use_CFAR_algorithm_flag, - bool dump, + bool dump, bool blocking, std::string dump_filename); /*! @@ -83,23 +89,26 @@ private: unsigned int doppler_max, long freq, long fs_in, int samples_per_ms, int samples_per_code, bool bit_transition_flag, bool use_CFAR_algorithm_flag, - bool dump, + bool dump, bool blocking, std::string dump_filename); pcps_acquisition_sc(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, bool use_CFAR_algorithm_flag, - bool dump, + bool dump, bool blocking, std::string dump_filename); - void update_local_carrier(gr_complex* carrier_vector, - int correlator_length_samples, - float freq); + void update_local_carrier(gr_complex* carrier_vector, int correlator_length_samples, float freq); + + void acquisition_core( void ); void update_grid_doppler_wipeoffs(); bool is_fdma(); + void send_negative_acquisition(); + void send_positive_acquisition(); + long d_fs_in; long d_freq; long d_old_freq; @@ -137,6 +146,17 @@ private: unsigned int d_channel; std::string d_dump_filename; + std::thread d_worker_thread; + std::mutex d_mutex; + + std::condition_variable d_cond; + bool d_done; + bool d_new_data_available; + bool d_worker_active; + bool d_blocking; + + lv_16sc_t *d_data_buffer; + public: /*! * \brief Default destructor. @@ -150,6 +170,7 @@ public: */ inline void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) { + gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler d_gnss_synchro = p_gnss_synchro; } @@ -179,6 +200,7 @@ public: */ inline void set_active(bool active) { + gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler d_active = active; } @@ -195,6 +217,7 @@ public: */ inline void set_channel(unsigned int channel) { + gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler d_channel = channel; } @@ -205,6 +228,7 @@ public: */ inline void set_threshold(float threshold) { + gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler d_threshold = threshold; } @@ -214,6 +238,7 @@ public: */ inline void set_doppler_max(unsigned int doppler_max) { + gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler d_doppler_max = doppler_max; } @@ -223,6 +248,7 @@ public: */ inline void set_doppler_step(unsigned int doppler_step) { + gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler d_doppler_step = doppler_step; } @@ -232,6 +258,16 @@ public: int general_work(int noutput_items, gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); + + /*! + * Called by the flowgraph when processing is about to start. + */ + bool start( void ); + + /*! + * Called by the flowgraph when processing is done. + */ + bool stop( void ); }; #endif /* GNSS_SDR_PCPS_ACQUISITION_SC_H_*/ diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_multithread_acquisition_cc.cc b/src/algorithms/acquisition/gnuradio_blocks/pcps_multithread_acquisition_cc.cc deleted file mode 100644 index 0dcbbc070..000000000 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_multithread_acquisition_cc.cc +++ /dev/null @@ -1,478 +0,0 @@ -/*! - * \file pcps_multithread_acquisition_cc.cc - * \brief This class implements a Parallel Code Phase Search Acquisition - * \authors
      - *
    • Javier Arribas, 2011. jarribas(at)cttc.es - *
    • Luis Esteve, 2012. luis(at)epsilon-formacion.com - *
    • Marc Molina, 2013. marc.molina.pena@gmail.com - *
    - * - * ------------------------------------------------------------------------- - * - * Copyright (C) 2010-2015 (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 "pcps_multithread_acquisition_cc.h" -#include -#include -#include -#include -#include -#include -#include -#include "control_message_factory.h" -#include "GPS_L1_CA.h" //GPS_TWO_PI - -using google::LogMessage; - -pcps_multithread_acquisition_cc_sptr pcps_make_multithread_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, - bool dump, - std::string dump_filename) -{ - - return pcps_multithread_acquisition_cc_sptr( - new pcps_multithread_acquisition_cc(sampled_ms, max_dwells, doppler_max, freq, fs_in, samples_per_ms, - samples_per_code, bit_transition_flag, dump, dump_filename)); -} - -pcps_multithread_acquisition_cc::pcps_multithread_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, - bool dump, - std::string dump_filename) : - gr::block("pcps_multithread_acquisition_cc", - gr::io_signature::make(1, 1, sizeof(gr_complex) * sampled_ms * samples_per_ms), - gr::io_signature::make(0, 0, sizeof(gr_complex) * sampled_ms * samples_per_ms)) -{ - this->message_port_register_out(pmt::mp("events")); - d_sample_counter = 0; // SAMPLE COUNTER - d_active = false; - d_state = 0; - d_core_working = false; - d_freq = freq; - d_fs_in = fs_in; - d_samples_per_ms = samples_per_ms; - d_samples_per_code = samples_per_code; - d_sampled_ms = sampled_ms; - d_max_dwells = max_dwells; - d_well_count = 0; - d_doppler_max = doppler_max; - d_fft_size = d_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_in_dwell_count = 0; - - d_in_buffer = new gr_complex*[d_max_dwells]; - - //todo: do something if posix_memalign fails - for (unsigned int i = 0; i < d_max_dwells; i++) - { - d_in_buffer[i] = static_cast(volk_malloc(d_fft_size * sizeof(gr_complex), volk_get_alignment())); - } - d_fft_codes = static_cast(volk_malloc(d_fft_size * sizeof(gr_complex), volk_get_alignment())); - d_magnitude = static_cast(volk_malloc(d_fft_size * sizeof(float), volk_get_alignment())); - - // 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); - - // For dumping samples into a file - d_dump = dump; - d_dump_filename = dump_filename; - - d_doppler_resolution = 0; - d_threshold = 0; - d_doppler_step = 0; - d_grid_doppler_wipeoffs = 0; - d_gnss_synchro = 0; - d_code_phase = 0; - d_doppler_freq = 0; - d_test_statistics = 0; - d_channel = 0; -} - -pcps_multithread_acquisition_cc::~pcps_multithread_acquisition_cc() -{ - if (d_num_doppler_bins > 0) - { - for (unsigned int i = 0; i < d_num_doppler_bins; i++) - { - volk_free(d_grid_doppler_wipeoffs[i]); - } - delete[] d_grid_doppler_wipeoffs; - } - - for (unsigned int i = 0; i < d_max_dwells; i++) - { - volk_free(d_in_buffer[i]); - } - delete[] d_in_buffer; - - volk_free(d_fft_codes); - volk_free(d_magnitude); - - delete d_ifft; - delete d_fft_if; - - if (d_dump) - { - d_dump_file.close(); - } -} - -void pcps_multithread_acquisition_cc::init() -{ - d_gnss_synchro->Flag_valid_acquisition = false; - d_gnss_synchro->Flag_valid_symbol_output = false; - d_gnss_synchro->Flag_valid_pseudorange = false; - d_gnss_synchro->Flag_valid_word = false; - - 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 = static_cast(-d_doppler_max); - doppler <= static_cast(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++) - { - d_grid_doppler_wipeoffs[doppler_index] = static_cast(volk_malloc(d_fft_size * sizeof(gr_complex), volk_get_alignment())); - int doppler = -static_cast(d_doppler_max) + d_doppler_step * doppler_index; - float phase_step_rad = static_cast(GPS_TWO_PI) * (d_freq + doppler) / static_cast(d_fs_in); - float _phase[1]; - _phase[0] = 0; - volk_gnsssdr_s32f_sincos_32fc(d_grid_doppler_wipeoffs[doppler_index], - phase_step_rad, _phase, d_fft_size); - } -} - -void pcps_multithread_acquisition_cc::set_local_code(std::complex * code) -{ - memcpy(d_fft_if->get_inbuf(), code, sizeof(gr_complex)*d_fft_size); - - d_fft_if->execute(); // We need the FFT of local code - - //Conjugate the local code - volk_32fc_conjugate_32fc(d_fft_codes, d_fft_if->get_outbuf(), d_fft_size); -} - -void pcps_multithread_acquisition_cc::acquisition_core() -{ - // initialize acquisition algorithm - int doppler; - uint32_t indext = 0; - float magt = 0.0; - float fft_normalization_factor = static_cast(d_fft_size) * static_cast(d_fft_size); - gr_complex* in = d_in_buffer[d_well_count]; - unsigned long int samplestamp = d_sample_counter_buffer[d_well_count]; - - d_input_power = 0.0; - d_mag = 0.0; - - 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(d_magnitude, in, d_fft_size); - volk_32f_accumulator_s32f(&d_input_power, d_magnitude, d_fft_size); - d_input_power /= static_cast(d_fft_size); - - // 2- Doppler frequency search loop - for (unsigned int doppler_index = 0; doppler_index < d_num_doppler_bins; doppler_index++) - { - // doppler search steps - - doppler = -static_cast(d_doppler_max) + d_doppler_step * doppler_index; - - volk_32fc_x2_multiply_32fc(d_fft_if->get_inbuf(), in, - 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(); - - // 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(d_ifft->get_inbuf(), - d_fft_if->get_outbuf(), d_fft_codes, d_fft_size); - - // compute the inverse FFT - d_ifft->execute(); - - // Search maximum - volk_32fc_magnitude_squared_32f(d_magnitude, d_ifft->get_outbuf(), d_fft_size); - volk_gnsssdr_32f_index_max_32u(&indext, d_magnitude, d_fft_size); - - // Normalize the maximum value to correct the scale factor introduced by FFTW - magt = d_magnitude[indext] / (fft_normalization_factor * fft_normalization_factor); - - // 4- record the maximum peak and the associated synchronization parameters - if (d_mag < magt) - { - d_mag = magt; - - // In case that d_bit_transition_flag = true, we compare the potentially - // new maximum test statistics (d_mag/d_input_power) with the value in - // d_test_statistics. When the second dwell is being processed, the value - // of d_mag/d_input_power could be lower than d_test_statistics (i.e, - // the maximum test statistics in the previous dwell is greater than - // current d_mag/d_input_power). Note that d_test_statistics is not - // restarted between consecutive dwells in multidwell operation. - if (d_test_statistics < (d_mag / d_input_power) || !d_bit_transition_flag) - { - d_gnss_synchro->Acq_delay_samples = static_cast(indext % d_samples_per_code); - d_gnss_synchro->Acq_doppler_hz = static_cast(doppler); - d_gnss_synchro->Acq_samplestamp_samples = samplestamp; - - // 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 = 2 * sizeof(float) * (d_fft_size); // complex 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); - d_dump_file.write(reinterpret_cast(d_ifft->get_outbuf()), n); //write directly |abs(x)|^2 in this Doppler bin? - d_dump_file.close(); - } - } - - if (!d_bit_transition_flag) - { - if (d_test_statistics > d_threshold) - { - d_state = 2; // Positive acquisition - } - else if (d_well_count == d_max_dwells) - { - d_state = 3; // Negative acquisition - } - } - else - { - if (d_well_count == d_max_dwells) // d_max_dwells = 2 - { - if (d_test_statistics > d_threshold) - { - d_state = 2; // Positive acquisition - } - else - { - d_state = 3; // Negative acquisition - } - } - } - - d_core_working = false; -} - - - -void pcps_multithread_acquisition_cc::set_state(int state) -{ - d_state = state; - if (d_state == 1) - { - 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_in_dwell_count = 0; - d_sample_counter_buffer.clear(); - } - else if (d_state == 0) - {} - else - { - LOG(ERROR) << "State can only be set to 0 or 1"; - } -} - - - -int pcps_multithread_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 __attribute__((unused))) -{ - - int acquisition_message = -1; //0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL - - 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_in_dwell_count = 0; - d_sample_counter_buffer.clear(); - - d_state = 1; - } - - d_sample_counter += d_fft_size * ninput_items[0]; // sample counter - - break; - } - - case 1: - { - if (d_in_dwell_count < d_max_dwells) - { - // Fill internal buffer with d_max_dwells signal blocks. This step ensures that - // consecutive signal blocks will be processed in multi-dwell operation. This is - // essential when d_bit_transition_flag = true. - unsigned int num_dwells = std::min(static_cast(d_max_dwells - d_in_dwell_count), ninput_items[0]); - for (unsigned int i = 0; i < num_dwells; i++) - { - memcpy(d_in_buffer[d_in_dwell_count++], reinterpret_cast(input_items[i]), - sizeof(gr_complex)*d_fft_size); - d_sample_counter += d_fft_size; - d_sample_counter_buffer.push_back(d_sample_counter); - } - - if (ninput_items[0] > static_cast(num_dwells)) - { - d_sample_counter += d_fft_size * (ninput_items[0] - num_dwells); - } - } - else - { - // We already have d_max_dwells consecutive blocks in the internal buffer, - // just skip input blocks. - d_sample_counter += d_fft_size * ninput_items[0]; - } - - // We create a new thread to process next block if the following - // conditions are fulfilled: - // 1. There are new blocks in d_in_buffer that have not been processed yet - // (d_well_count < d_in_dwell_count). - // 2. No other acquisition_core thead is working (!d_core_working). - // 3. d_state==1. We need to check again d_state because it can be modified at any - // moment by the external thread (may have changed since checked in the switch()). - // If the external thread has already declared positive (d_state=2) or negative - // (d_state=3) acquisition, we don't have to process next block!! - if ((d_well_count < d_in_dwell_count) && !d_core_working && d_state==1) - { - d_core_working = true; - boost::thread(&pcps_multithread_acquisition_cc::acquisition_core, this); - } - - break; - } - - case 2: - { - // Declare positive acquisition using a message port - 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 += d_fft_size * ninput_items[0]; // sample counter - - acquisition_message = 1; - this->message_port_pub(pmt::mp("events"), pmt::from_long(acquisition_message)); - - break; - } - - case 3: - { - // Declare negative acquisition using a message port - 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 += d_fft_size * ninput_items[0]; // sample counter - - acquisition_message = 2; - this->message_port_pub(pmt::mp("events"), pmt::from_long(acquisition_message)); - - break; - } - } - - consume_each(ninput_items[0]); - - return noutput_items; -} diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_multithread_acquisition_cc.h b/src/algorithms/acquisition/gnuradio_blocks/pcps_multithread_acquisition_cc.h deleted file mode 100644 index d0f5af944..000000000 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_multithread_acquisition_cc.h +++ /dev/null @@ -1,239 +0,0 @@ -/*! - * \file pcps_multithread_acquisition_cc.h - * \brief This class implements a Parallel Code Phase Search Acquisition - * - * 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 port - *
    - * - * Kay Borre book: K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen, - * "A Software-Defined GPS and Galileo Receiver. A Single-Frequency - * Approach", Birkha user, 2007. pp 81-84 - * - * \authors
      - *
    • Javier Arribas, 2011. jarribas(at)cttc.es - *
    • Luis Esteve, 2012. luis(at)epsilon-formacion.com - *
    • Marc Molina, 2013. marc.molina.pena@gmail.com - *
    - * - * ------------------------------------------------------------------------- - * - * Copyright (C) 2010-2015 (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_PCPS_MULTITHREAD_ACQUISITION_CC_H_ -#define GNSS_SDR_PCPS_MULTITHREAD_ACQUISITION_CC_H_ - -#include -#include -#include -#include -#include -#include -#include -#include "gnss_synchro.h" - -class pcps_multithread_acquisition_cc; - -typedef boost::shared_ptr pcps_multithread_acquisition_cc_sptr; - -pcps_multithread_acquisition_cc_sptr -pcps_make_multithread_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, - 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 pcps_multithread_acquisition_cc: public gr::block -{ -private: - friend pcps_multithread_acquisition_cc_sptr - pcps_make_multithread_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, - bool dump, - std::string dump_filename); - - - pcps_multithread_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, - bool dump, - std::string dump_filename); - - void calculate_magnitudes(gr_complex* fft_begin, int doppler_shift, - int doppler_offset); - - 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_sampled_ms; - 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_codes; - 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_magnitude; - float d_input_power; - float d_test_statistics; - bool d_bit_transition_flag; - std::ofstream d_dump_file; - bool d_active; - int d_state; - bool d_core_working; - bool d_dump; - unsigned int d_channel; - std::string d_dump_filename; - gr_complex** d_in_buffer; - std::vector d_sample_counter_buffer; - unsigned int d_in_dwell_count; - -public: - /*! - * \brief Default destructor. - */ - ~pcps_multithread_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. - */ - inline void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) - { - d_gnss_synchro = p_gnss_synchro; - } - - /*! - * \brief Returns the maximum peak of grid search. - */ - inline unsigned int mag() const - { - 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); - - /*! - * \brief Starts acquisition algorithm, turning from standby mode to - * active mode - * \param active - bool that activates/deactivates the block. - */ - inline void set_active(bool active) - { - d_active = active; - } - - /*! - * \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); - - /*! - * \brief Set acquisition channel unique ID - * \param channel - receiver channel. - */ - inline 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]. - */ - inline 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]. - */ - inline void set_doppler_step(unsigned int doppler_step) - { - d_doppler_step = doppler_step; - } - - /*! - * \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 acquisition_core(); -}; - -#endif /* GNSS_SDR_PCPS_MULTITHREAD_ACQUISITION_CC_H_*/ diff --git a/src/core/receiver/gnss_block_factory.cc b/src/core/receiver/gnss_block_factory.cc index 927aaf0fe..0f41c6738 100644 --- a/src/core/receiver/gnss_block_factory.cc +++ b/src/core/receiver/gnss_block_factory.cc @@ -67,7 +67,6 @@ #include "pulse_blanking_filter.h" #include "gps_l1_ca_pcps_acquisition.h" #include "gps_l2_m_pcps_acquisition.h" -#include "gps_l1_ca_pcps_multithread_acquisition.h" #include "gps_l1_ca_pcps_tong_acquisition.h" #include "gps_l1_ca_pcps_assisted_acquisition.h" #include "gps_l1_ca_pcps_acquisition_fine_doppler.h" @@ -1027,12 +1026,6 @@ std::unique_ptr GNSSBlockFactory::GetBlock( out_streams)); block = std::move(block_); } - else if (implementation.compare("GPS_L1_CA_PCPS_Multithread_Acquisition") == 0) - { - std::unique_ptr block_(new GpsL1CaPcpsMultithreadAcquisition(configuration.get(), role, in_streams, - out_streams)); - block = std::move(block_); - } #if OPENCL_BLOCKS else if (implementation.compare("GPS_L1_CA_PCPS_OpenCl_Acquisition") == 0) @@ -1277,12 +1270,6 @@ std::unique_ptr GNSSBlockFactory::GetAcqBlock( out_streams)); block = std::move(block_); } - else if (implementation.compare("GPS_L1_CA_PCPS_Multithread_Acquisition") == 0) - { - std::unique_ptr block_(new GpsL1CaPcpsMultithreadAcquisition(configuration.get(), role, in_streams, - out_streams)); - block = std::move(block_); - } #if OPENCL_BLOCKS else if (implementation.compare("GPS_L1_CA_PCPS_OpenCl_Acquisition") == 0) diff --git a/src/tests/test_main.cc b/src/tests/test_main.cc index d0a8e0c1c..93c968684 100644 --- a/src/tests/test_main.cc +++ b/src/tests/test_main.cc @@ -107,7 +107,7 @@ DECLARE_string(log_dir); #include "unit-tests/signal-processing-blocks/acquisition/galileo_e5a_pcps_acquisition_gsoc2014_gensource_test.cc" #include "unit-tests/signal-processing-blocks/acquisition/glonass_l1_ca_pcps_acquisition_test.cc" #include "unit-tests/signal-processing-blocks/acquisition/glonass_l1_ca_pcps_acquisition_gsoc2017_test.cc" -//#include "unit-tests/signal-processing-blocks/acquisition/gps_l1_ca_pcps_multithread_acquisition_gsoc2013_test.cc" + #if OPENCL_BLOCKS_TEST #include "unit-tests/signal-processing-blocks/acquisition/gps_l1_ca_pcps_opencl_acquisition_gsoc2013_test.cc" #endif diff --git a/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_ca_pcps_multithread_acquisition_gsoc2013_test.cc b/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_ca_pcps_multithread_acquisition_gsoc2013_test.cc deleted file mode 100644 index 6e7098047..000000000 --- a/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_ca_pcps_multithread_acquisition_gsoc2013_test.cc +++ /dev/null @@ -1,566 +0,0 @@ -/*! - * \file gps_l1_ca_pcps_multithread_acquisition_gsoc2013_test.cc - * \brief This class implements an acquisition test for - * GpsL1CaPcpsMultithreadAcquisition class. - * \author Marc Molina, 2013. marc.molina.pena(at)gmail.com - * - * - * ------------------------------------------------------------------------- - * - * Copyright (C) 2010-2015 (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 -#include -#include -#include -#include -#include -#include -#include -#include -#include "gnss_block_interface.h" -#include "in_memory_configuration.h" -#include "configuration_interface.h" -#include "gnss_synchro.h" -#include "gps_l1_ca_pcps_multithread_acquisition.h" -#include "signal_generator.h" -#include "signal_generator_c.h" -#include "fir_filter.h" -#include "gen_signal_source.h" -#include "gnss_sdr_valve.h" -#include "signal_generator.h" -#include "signal_generator.cc" -#include "signal_generator_c.h" -#include "signal_generator_c.cc" - - -class GpsL1CaPcpsMultithreadAcquisitionGSoC2013Test: public ::testing::Test -{ -protected: - GpsL1CaPcpsMultithreadAcquisitionGSoC2013Test() - { - item_size = sizeof(gr_complex); - stop = false; - message = 0; - gnss_synchro = Gnss_Synchro(); - } - - ~GpsL1CaPcpsMultithreadAcquisitionGSoC2013Test() - { - } - - void init(); - void config_1(); - void config_2(); - void start_queue(); - void wait_message(); - void process_message(); - void stop_queue(); - - gr::msg_queue::sptr queue; - gr::top_block_sptr top_block; - std::shared_ptr acquisition; - std::shared_ptr config; - Gnss_Synchro gnss_synchro; - size_t item_size; - bool stop; - int message; - boost::thread ch_thread; - - unsigned int integration_time_ms = 0; - unsigned int fs_in = 0; - - double expected_delay_chips = 0.0; - double expected_doppler_hz = 0.0; - float max_doppler_error_hz = 0.0; - float max_delay_error_chips = 0.0; - - unsigned int num_of_realizations = 0; - unsigned int realization_counter = 0; - unsigned int detection_counter = 0; - unsigned int correct_estimation_counter = 0; - unsigned int acquired_samples = 0; - unsigned int mean_acq_time_us = 0; - - double mse_doppler = 0.0; - double mse_delay = 0.0; - - double Pd = 0.0; - double Pfa_p = 0.0; - double Pfa_a = 0.0; -}; - -void GpsL1CaPcpsMultithreadAcquisitionGSoC2013Test::init() -{ - message = 0; - realization_counter = 0; - detection_counter = 0; - correct_estimation_counter = 0; - acquired_samples = 0; - mse_doppler = 0; - mse_delay = 0; - mean_acq_time_us = 0; - Pd = 0; - Pfa_p = 0; - Pfa_a = 0; -} - -void GpsL1CaPcpsMultithreadAcquisitionGSoC2013Test::config_1() -{ - gnss_synchro.Channel_ID = 0; - gnss_synchro.System = 'G'; - std::string signal = "1C"; - signal.copy(gnss_synchro.Signal,2,0); - - integration_time_ms = 1; - fs_in = 4e6; - - expected_delay_chips = 600; - expected_doppler_hz = 750; - max_doppler_error_hz = 2/(3*integration_time_ms*1e-3); - max_delay_error_chips = 0.50; - - num_of_realizations = 1; - - config = std::make_shared(); - - config->set_property("GNSS-SDR.internal_fs_sps", std::to_string(fs_in)); - - config->set_property("SignalSource.fs_hz", std::to_string(fs_in)); - - config->set_property("SignalSource.item_type", "gr_complex"); - - config->set_property("SignalSource.num_satellites", "1"); - - config->set_property("SignalSource.system_0", "G"); - config->set_property("SignalSource.PRN_0", "10"); - config->set_property("SignalSource.CN0_dB_0", "44"); - 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.noise_flag", "false"); - config->set_property("SignalSource.data_flag", "false"); - config->set_property("SignalSource.BW_BB", "0.97"); - - config->set_property("InputFilter.implementation", "Fir_Filter"); - config->set_property("InputFilter.input_item_type", "gr_complex"); - config->set_property("InputFilter.output_item_type", "gr_complex"); - config->set_property("InputFilter.taps_item_type", "float"); - config->set_property("InputFilter.number_of_taps", "11"); - config->set_property("InputFilter.number_of_bands", "2"); - config->set_property("InputFilter.band1_begin", "0.0"); - config->set_property("InputFilter.band1_end", "0.97"); - config->set_property("InputFilter.band2_begin", "0.98"); - config->set_property("InputFilter.band2_end", "1.0"); - config->set_property("InputFilter.ampl1_begin", "1.0"); - config->set_property("InputFilter.ampl1_end", "1.0"); - config->set_property("InputFilter.ampl2_begin", "0.0"); - config->set_property("InputFilter.ampl2_end", "0.0"); - config->set_property("InputFilter.band1_error", "1.0"); - config->set_property("InputFilter.band2_error", "1.0"); - config->set_property("InputFilter.filter_type", "bandpass"); - config->set_property("InputFilter.grid_density", "16"); - - config->set_property("Acquisition.item_type", "gr_complex"); - config->set_property("Acquisition.if", "0"); - 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", "GPS_L1_CA_PCPS_Multithread_Acquisition"); - config->set_property("Acquisition.threshold", "0.8"); - config->set_property("Acquisition.doppler_max", "10000"); - config->set_property("Acquisition.doppler_step", "250"); - config->set_property("Acquisition.bit_transition_flag", "false"); - config->set_property("Acquisition.dump", "false"); -} - -void GpsL1CaPcpsMultithreadAcquisitionGSoC2013Test::config_2() -{ - gnss_synchro.Channel_ID = 0; - gnss_synchro.System = 'G'; - std::string signal = "1C"; - signal.copy(gnss_synchro.Signal,2,0); - - integration_time_ms = 1; - fs_in = 4e6; - - expected_delay_chips = 600; - expected_doppler_hz = 750; - max_doppler_error_hz = 2/(3*integration_time_ms*1e-3); - max_delay_error_chips = 0.50; - - num_of_realizations = 100; - - config = std::make_shared(); - - config->set_property("GNSS-SDR.internal_fs_sps", std::to_string(fs_in)); - - config->set_property("SignalSource.fs_hz", std::to_string(fs_in)); - - config->set_property("SignalSource.item_type", "gr_complex"); - - config->set_property("SignalSource.num_satellites", "4"); - - config->set_property("SignalSource.system_0", "G"); - config->set_property("SignalSource.PRN_0", "10"); - config->set_property("SignalSource.CN0_dB_0", "44"); - 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.system_1", "G"); - config->set_property("SignalSource.PRN_1", "15"); - config->set_property("SignalSource.CN0_dB_1", "44"); - config->set_property("SignalSource.doppler_Hz_1", "1000"); - config->set_property("SignalSource.delay_chips_1", "100"); - - config->set_property("SignalSource.system_2", "G"); - config->set_property("SignalSource.PRN_2", "21"); - config->set_property("SignalSource.CN0_dB_2", "44"); - config->set_property("SignalSource.doppler_Hz_2", "2000"); - config->set_property("SignalSource.delay_chips_2", "200"); - - config->set_property("SignalSource.system_3", "G"); - config->set_property("SignalSource.PRN_3", "22"); - config->set_property("SignalSource.CN0_dB_3", "44"); - config->set_property("SignalSource.doppler_Hz_3", "3000"); - config->set_property("SignalSource.delay_chips_3", "300"); - - config->set_property("SignalSource.noise_flag", "true"); - config->set_property("SignalSource.data_flag", "true"); - config->set_property("SignalSource.BW_BB", "0.97"); - - config->set_property("InputFilter.implementation", "Fir_Filter"); - config->set_property("InputFilter.input_item_type", "gr_complex"); - config->set_property("InputFilter.output_item_type", "gr_complex"); - config->set_property("InputFilter.taps_item_type", "float"); - config->set_property("InputFilter.number_of_taps", "11"); - config->set_property("InputFilter.number_of_bands", "2"); - config->set_property("InputFilter.band1_begin", "0.0"); - config->set_property("InputFilter.band1_end", "0.97"); - config->set_property("InputFilter.band2_begin", "0.98"); - config->set_property("InputFilter.band2_end", "1.0"); - config->set_property("InputFilter.ampl1_begin", "1.0"); - config->set_property("InputFilter.ampl1_end", "1.0"); - config->set_property("InputFilter.ampl2_begin", "0.0"); - config->set_property("InputFilter.ampl2_end", "0.0"); - config->set_property("InputFilter.band1_error", "1.0"); - config->set_property("InputFilter.band2_error", "1.0"); - config->set_property("InputFilter.filter_type", "bandpass"); - config->set_property("InputFilter.grid_density", "16"); - - config->set_property("Acquisition.item_type", "gr_complex"); - config->set_property("Acquisition.if", "0"); - 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", "GPS_L1_CA_PCPS_Multithread_Acquisition"); - config->set_property("Acquisition.pfa", "0.1"); - config->set_property("Acquisition.doppler_max", "10000"); - config->set_property("Acquisition.doppler_step", "250"); - config->set_property("Acquisition.bit_transition_flag", "false"); - config->set_property("Acquisition.dump", "false"); -} - - -void GpsL1CaPcpsMultithreadAcquisitionGSoC2013Test::start_queue() -{ - stop = false; - ch_thread = boost::thread(&GpsL1CaPcpsMultithreadAcquisitionGSoC2013Test::wait_message, this); -} - - -void GpsL1CaPcpsMultithreadAcquisitionGSoC2013Test::wait_message() -{ - std::chrono::time_point start, end; - std::chrono::duration elapsed_seconds(0); - - while (!stop) - { - acquisition->reset(); - - start = std::chrono::system_clock::now(); - - channel_internal_queue.wait_and_pop(message); - - end = std::chrono::system_clock::now(); - elapsed_seconds = end - start; - - mean_acq_time_us += elapsed_seconds.count() * 1e6; - - process_message(); - } -} - - -void GpsL1CaPcpsMultithreadAcquisitionGSoC2013Test::process_message() -{ - if (message == 1) - { - detection_counter++; - - // The term -5 is here to correct the additional delay introduced by the FIR filter - double delay_error_chips = std::abs(static_cast(expected_delay_chips) - static_cast(gnss_synchro.Acq_delay_samples - 5) * 1023.0 / (static_cast(fs_in) * 1e-3)); - double doppler_error_hz = std::abs(expected_doppler_hz - gnss_synchro.Acq_doppler_hz); - - mse_delay += std::pow(delay_error_chips, 2); - mse_doppler += std::pow(doppler_error_hz, 2); - - if ((delay_error_chips < max_delay_error_chips) && (doppler_error_hz < max_doppler_error_hz)) - { - correct_estimation_counter++; - } - } - - realization_counter++; - - std::cout << "Progress: " << round(static_cast(realization_counter) / static_cast(num_of_realizations) * 100.0) << "% \r" << std::flush; - - if (realization_counter == num_of_realizations) - { - mse_delay /= num_of_realizations; - mse_doppler /= num_of_realizations; - - Pd = static_cast(correct_estimation_counter) / static_cast(num_of_realizations); - Pfa_a = static_cast(detection_counter) / static_cast(num_of_realizations); - Pfa_p = static_cast(detection_counter - correct_estimation_counter) / static_cast(num_of_realizations); - - mean_acq_time_us /= num_of_realizations; - - stop_queue(); - top_block->stop(); - - std::cout << std::endl; - } -} - - -void GpsL1CaPcpsMultithreadAcquisitionGSoC2013Test::stop_queue() -{ - stop = true; -} - - -TEST_F(GpsL1CaPcpsMultithreadAcquisitionGSoC2013Test, Instantiate) -{ - config_1(); - acquisition = std::make_shared(config.get(), "Acquisition", 1, 1); -} - - -TEST_F(GpsL1CaPcpsMultithreadAcquisitionGSoC2013Test, ConnectAndRun) -{ - int nsamples = floor(fs_in*integration_time_ms*1e-3); - std::chrono::time_point start, end; - std::chrono::duration elapsed_seconds(0); - queue = gr::msg_queue::make(0); - top_block = gr::make_top_block("Acquisition test"); - - config_1(); - acquisition = std::make_shared(config.get(), "Acquisition", 1, 1); - - ASSERT_NO_THROW( { - acquisition->connect(top_block); - boost::shared_ptr source = gr::analog::sig_source_c::make(fs_in, gr::analog::GR_SIN_WAVE, 1000, 1, gr_complex(0)); - boost::shared_ptr valve = gnss_sdr_make_valve(sizeof(gr_complex), nsamples, queue); - top_block->connect(source, 0, valve, 0); - top_block->connect(valve, 0, acquisition->get_left_block(), 0); - }) << "Failure connecting the blocks of acquisition test." << std::endl; - - EXPECT_NO_THROW( { - start = std::chrono::system_clock::now(); - top_block->run(); // Start threads and wait - end = std::chrono::system_clock::now(); - elapsed_seconds = end - start; - }) << "Failure running the top_block." << std::endl; - - std::cout << "Processed " << nsamples << " samples in " << elapsed_seconds.count() * 1e6 << " microseconds" << std::endl; -} - - -TEST_F(GpsL1CaPcpsMultithreadAcquisitionGSoC2013Test, ValidationOfResults) -{ - config_1(); - queue = gr::msg_queue::make(0); - top_block = gr::make_top_block("Acquisition test"); - - acquisition = std::make_shared(config.get(), "Acquisition", 1, 1); - - ASSERT_NO_THROW( { - acquisition->set_channel(1); - }) << "Failure setting channel." << std::endl; - - ASSERT_NO_THROW( { - acquisition->set_gnss_synchro(&gnss_synchro); - }) << "Failure setting gnss_synchro." << std::endl; - - ASSERT_NO_THROW( { - acquisition->set_doppler_max(config->property("Acquisition.doppler_max", 10000)); - }) << "Failure setting doppler_max." << std::endl; - - ASSERT_NO_THROW( { - acquisition->set_doppler_step(config->property("Acquisition.doppler_step", 500)); - }) << "Failure setting doppler_step." << std::endl; - - ASSERT_NO_THROW( { - acquisition->set_threshold(config->property("Acquisition.threshold", 0.0)); - }) << "Failure setting threshold." << std::endl; - - ASSERT_NO_THROW( { - acquisition->connect(top_block); - }) << "Failure connecting acquisition to the top_block." << std::endl; - - acquisition->init(); - - ASSERT_NO_THROW( { - boost::shared_ptr signal_source; - SignalGenerator* signal_generator = new SignalGenerator(config.get(), "SignalSource", 0, 1, queue); - FirFilter* filter = new FirFilter(config.get(), "InputFilter", 1, 1); - signal_source.reset(new GenSignalSource(signal_generator, filter, "SignalSource", queue)); - signal_source->connect(top_block); - top_block->connect(signal_source->get_right_block(), 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++) - { - init(); - - if (i == 0) - { - gnss_synchro.PRN = 10; // This satellite is visible - } - else if (i == 1) - { - gnss_synchro.PRN = 20; // This satellite is not visible - } - - acquisition->set_local_code(); - - start_queue(); - - EXPECT_NO_THROW( { - top_block->run(); // Start threads and wait - }) << "Failure running the top_block." << std::endl; - - if (i == 0) - { - EXPECT_EQ(1, message) << "Acquisition failure. Expected message: 1=ACQ SUCCESS."; - if (message == 1) - { - EXPECT_EQ(static_cast(1), correct_estimation_counter) << "Acquisition failure. Incorrect parameters estimation."; - } - - } - else if (i == 1) - { - EXPECT_EQ(2, message) << "Acquisition failure. Expected message: 2=ACQ FAIL."; - } - } -} - - -TEST_F(GpsL1CaPcpsMultithreadAcquisitionGSoC2013Test, ValidationOfResultsProbabilities) -{ - config_2(); - queue = gr::msg_queue::make(0); - top_block = gr::make_top_block("Acquisition test"); - - acquisition = std::make_shared(config.get(), "Acquisition", 1, 1); - - ASSERT_NO_THROW( { - acquisition->set_channel(1); - }) << "Failure setting channel." << std::endl; - - ASSERT_NO_THROW( { - acquisition->set_gnss_synchro(&gnss_synchro); - }) << "Failure setting gnss_synchro." << std::endl; - - ASSERT_NO_THROW( { - acquisition->set_doppler_max(config->property("Acquisition.doppler_max", 10000)); - }) << "Failure setting doppler_max." << std::endl; - - ASSERT_NO_THROW( { - acquisition->set_doppler_step(config->property("Acquisition.doppler_step", 500)); - }) << "Failure setting doppler_step." << std::endl; - - ASSERT_NO_THROW( { - acquisition->set_threshold(config->property("Acquisition.threshold", 0.0)); - }) << "Failure setting threshold." << std::endl; - - ASSERT_NO_THROW( { - acquisition->connect(top_block); - }) << "Failure connecting acquisition to the top_block." << std::endl; - - acquisition->init(); - - ASSERT_NO_THROW( { - boost::shared_ptr signal_source; - SignalGenerator* signal_generator = new SignalGenerator(config.get(), "SignalSource", 0, 1, queue); - FirFilter* filter = new FirFilter(config.get(), "InputFilter", 1, 1); - signal_source.reset(new GenSignalSource(signal_generator, filter, "SignalSource", queue)); - signal_source->connect(top_block); - top_block->connect(signal_source->get_right_block(), 0, acquisition->get_left_block(), 0); - }) << "Failure connecting the blocks of acquisition test." << std::endl; - - std::cout << "Probability of false alarm (target) = " << 0.1 << std::endl; - - // i = 0 --> satellite in acquisition is visible (prob of detection and prob of detection with wrong estimation) - // i = 1 --> satellite in acquisition is not visible (prob of false detection) - for (unsigned int i = 0; i < 2; i++) - { - init(); - - if (i == 0) - { - gnss_synchro.PRN = 10; // This satellite is visible - } - else if (i == 1) - { - gnss_synchro.PRN = 20; // This satellite is not visible - } - - acquisition->set_local_code(); - - start_queue(); - - EXPECT_NO_THROW( { - top_block->run(); // Start threads and wait - }) << "Failure running the top_block." << std::endl; - - if (i == 0) - { - std::cout << "Probability of detection = " << Pd << std::endl; - std::cout << "Probability of false alarm (satellite present) = " << Pfa_p << std::endl; -// std::cout << "Mean acq time = " << mean_acq_time_us << " microseconds." << std::endl; - } - else if (i == 1) - { - std::cout << "Probability of false alarm (satellite absent) = " << Pfa_a << std::endl; -// std::cout << "Mean acq time = " << mean_acq_time_us << " microseconds." << std::endl; - } - } -}