diff --git a/conf/gnss-sdr_Galileo_E5a.conf b/conf/gnss-sdr_Galileo_E5a.conf index 5ba2daa46..702c15cc7 100644 --- a/conf/gnss-sdr_Galileo_E5a.conf +++ b/conf/gnss-sdr_Galileo_E5a.conf @@ -7,7 +7,7 @@ ;######### GLOBAL OPTIONS ################## ;internal_fs_hz: Internal signal sampling frequency after the signal conditioning stage [Hz]. -GNSS-SDR.internal_fs_hz=12000000 +GNSS-SDR.internal_fs_hz=32000000 ;######### CONTROL_THREAD CONFIG ############ ControlThread.wait_for_flowgraph=false @@ -32,15 +32,15 @@ SignalSource.implementation=File_Signal_Source ;SignalSource.filename=/home/marc/E5a_acquisitions/signal_source_5X_primary.dat ;SignalSource.filename=/home/marc/E5a_acquisitions/galileo_E5_8M_r2_upsampled_12.dat ;SignalSource.filename=/home/marc/E5a_acquisitions/Tiered_sim_4sat_stup4_2s_up.dat -SignalSource.filename=/home/marc/E5a_acquisitions/signal_source_sec21M_long.dat - +;SignalSource.filename=/home/marc/E5a_acquisitions/signal_source_sec21M_long.dat +SignalSource.filename=/home/marc/E5a_acquisitions/32MS_complex.dat; ;#item_type: Type and resolution for each of the signal samples. Use only gr_complex in this version. SignalSource.item_type=gr_complex ;#sampling_frequency: Original Signal sampling frequency in [Hz] -SignalSource.sampling_frequency=12000000 +SignalSource.sampling_frequency=32000000 ;#freq: RF front-end center frequency in [Hz] SignalSource.freq=1176450000 @@ -151,7 +151,7 @@ InputFilter.grid_density=16 ;#The following options are used only in Freq_Xlating_Fir_Filter implementation. ;#InputFilter.IF is the intermediate frequency (in Hz) shifted down to zero Hz -InputFilter.sampling_frequency=12000000 +InputFilter.sampling_frequency=32000000 InputFilter.IF=0 @@ -246,7 +246,7 @@ Channel.system=Galileo ;# "6Q" COMPASS E6 Q ;# "6X" COMPASS E6 IQ ;#if the option is disabled by default is assigned "1C" GPS L1 C/A -Channel.signal=5Q +Channel.signal=5X ;######### SPECIFIC CHANNELS CONFIG ###### ;#The following options are specific to each channel and overwrite the generic options @@ -254,29 +254,29 @@ Channel.signal=5Q ;######### CHANNEL 0 CONFIG ############ Channel0.system=Galileo -Channel0.signal=5Q +Channel0.signal=5X ;#satellite: Satellite PRN ID for this channel. Disable this option to random search -Channel0.satellite=11 +Channel0.satellite=19 ;Channel0.repeat_satellite=true ;######### CHANNEL 1 CONFIG ############ -Channel1.system=Galileo -Channel1.signal=5Q -Channel1.satellite=12 +;Channel1.system=Galileo +;Channel1.signal=5Q +;Channel1.satellite=12 ;######### CHANNEL 2 CONFIG ############ -Channel2.system=Galileo -Channel2.signal=5Q -Channel2.satellite=19 +;Channel2.system=Galileo +;Channel2.signal=5Q +;Channel2.satellite=11 ;######### CHANNEL 3 CONFIG ############ -Channel3.system=Galileo -Channel3.signal=5Q -Channel3.satellite=20 +;Channel3.system=Galileo +;Channel3.signal=5Q +;Channel3.satellite=20 ;######### ACQUISITION GLOBAL CONFIG ############ @@ -289,13 +289,13 @@ Acquisition.item_type=gr_complex ;#if: Signal intermediate frequency in [Hz] Acquisition.if=0 ;#sampled_ms: Signal block duration for the acquisition signal detection [ms] -Acquisition.coherent_integration_time_ms=2 +Acquisition.coherent_integration_time_ms=1 ;#implementation: Acquisition algorithm selection for this channel: [GPS_L1_CA_PCPS_Acquisition] or [Galileo_E1_PCPS_Ambiguous_Acquisition] -Acquisition.implementation=Galileo_E5a_3ms_Noncoherent_IQ_Acquisition +Acquisition.implementation=Galileo_E5a_Noncoherent_IQ_Acquisition_CAF ;#threshold: Acquisition threshold. It will be ignored if pfa is defined. -Acquisition.threshold=0.0005 +Acquisition.threshold=0.001 ;#pfa: Acquisition false alarm probability. This option overrides the threshold option. Only use with implementations: [GPS_L1_CA_PCPS_Acquisition] or [Galileo_E1_PCPS_Ambiguous_Acquisition] -;Acquisition.pfa=0.0001 +Acquisition.pfa=0.0003 ;#doppler_max: Maximum expected Doppler shift [Hz] Acquisition.doppler_max=10000 ;#doppler_max: Doppler step in the grid search [Hz] @@ -304,7 +304,13 @@ Acquisition.doppler_step=250 ;maximum test statistics. Only use with implementation: [GPS_L1_CA_PCPS_Acquisition] (should not be used for Galileo_E1_PCPS_Ambiguous_Acquisition]) Acquisition.bit_transition_flag=false ;#max_dwells: Maximum number of consecutive dwells to be processed. It will be ignored if bit_transition_flag=true -Acquisition.max_dwells=2 +Acquisition.max_dwells=1 + +;#CAF filter: Resolves doppler ambiguity averaging the specified BW in the winner code delay. If set to 0 CAF filter is desactivated. +Acquisition.CAF_window_hz=2000 +;#Zero_padding: Avoids power loss and doppler ambiguity in bit transitions by correlating one code with twice the input data length, ensuring that at least one full code is present without transitions. +;#If set to 1 it is ON, if set to 0 it is OFF. +Acquisition.Zero_padding=0 ;######### ACQUISITION CHANNELS CONFIG ###### ;#The following options are specific to each channel and overwrite the generic options @@ -343,8 +349,15 @@ Tracking.dump=true ;#dump_filename: Log path and filename. Notice that the tracking channel will add "x.dat" where x is the channel number. Tracking.dump_filename=./tracking_ch_ +;#pll_bw_hz_init: PLL loop filter bandwidth during initialization [Hz] +Tracking.pll_bw_hz_init=20.0; +;#dll_bw_hz_init: DLL loop filter bandwidth during initialization [Hz] +Tracking.dll_bw_hz_init=20.0; +;#dll_ti_ms: loop filter integration time after initialization (secondary code delay search)[ms] +Tracking.ti_ms=3; + ;#pll_bw_hz: PLL loop filter bandwidth [Hz] -Tracking.pll_bw_hz=50.0; +Tracking.pll_bw_hz=5.0; ;#dll_bw_hz: DLL loop filter bandwidth [Hz] Tracking.dll_bw_hz=2.0; diff --git a/src/algorithms/acquisition/adapters/CMakeLists.txt b/src/algorithms/acquisition/adapters/CMakeLists.txt index 16dc96583..600ed7f6b 100644 --- a/src/algorithms/acquisition/adapters/CMakeLists.txt +++ b/src/algorithms/acquisition/adapters/CMakeLists.txt @@ -28,10 +28,7 @@ if(OPENCL_FOUND) galileo_e1_pcps_cccwsr_ambiguous_acquisition.cc galileo_e1_pcps_tong_ambiguous_acquisition.cc galileo_e1_pcps_8ms_ambiguous_acquisition.cc - galileo_e5a_pcps_acquisition.cc - galileo_e5a_pilot_3ms_acquisition.cc - galileo_e5ax_2ms_pcps_acquisition.cc - galileo_e5a_3ms_noncoherent_iq_acquisition.cc + galileo_e5a_noncoherent_iq_acquisition_caf.cc ) else(OPENCL_FOUND) set(ACQ_ADAPTER_SOURCES @@ -44,10 +41,7 @@ else(OPENCL_FOUND) galileo_e1_pcps_cccwsr_ambiguous_acquisition.cc galileo_e1_pcps_tong_ambiguous_acquisition.cc galileo_e1_pcps_8ms_ambiguous_acquisition.cc - galileo_e5a_pcps_acquisition.cc - galileo_e5a_pilot_3ms_acquisition.cc - galileo_e5ax_2ms_pcps_acquisition.cc - galileo_e5a_3ms_noncoherent_iq_acquisition.cc + galileo_e5a_noncoherent_iq_acquisition_caf.cc ) endif(OPENCL_FOUND) diff --git a/src/algorithms/acquisition/adapters/galileo_e5a_3ms_noncoherent_iq_acquisition.cc b/src/algorithms/acquisition/adapters/galileo_e5a_noncoherent_iq_acquisition_caf.cc similarity index 63% rename from src/algorithms/acquisition/adapters/galileo_e5a_3ms_noncoherent_iq_acquisition.cc rename to src/algorithms/acquisition/adapters/galileo_e5a_noncoherent_iq_acquisition_caf.cc index 9690e0282..9b1b531a1 100644 --- a/src/algorithms/acquisition/adapters/galileo_e5a_3ms_noncoherent_iq_acquisition.cc +++ b/src/algorithms/acquisition/adapters/galileo_e5a_noncoherent_iq_acquisition_caf.cc @@ -1,8 +1,14 @@ /*! - * \file galileo_e5a_3ms_noncoherent_iq_acquisition.cc + * \file galileo_e5a_noncoherent_iq_acquisition_caf.cc * \brief Adapts a PCPS acquisition block to an AcquisitionInterface for * Galileo E5a data and pilot Signals * \author Marc Sales, 2014. marcsales92(at)gmail.com + * \based on work from: + * * * ------------------------------------------------------------------------- * @@ -29,7 +35,7 @@ * ------------------------------------------------------------------------- */ -#include "galileo_e5a_3ms_noncoherent_iq_acquisition.h" +#include "galileo_e5a_noncoherent_iq_acquisition_caf.h" #include #include #include @@ -39,11 +45,10 @@ #include "galileo_e5_signal_processing.h" #include "Galileo_E5a.h" #include "configuration_interface.h" -//#include using google::LogMessage; -GalileoE5a3msNoncoherentIQAcquisition::GalileoE5a3msNoncoherentIQAcquisition( +GalileoE5aNoncoherentIQAcquisitionCaf::GalileoE5aNoncoherentIQAcquisitionCaf( ConfigurationInterface* configuration, std::string role, unsigned int in_streams, unsigned int out_streams, boost::shared_ptr queue) : @@ -58,24 +63,26 @@ GalileoE5a3msNoncoherentIQAcquisition::GalileoE5a3msNoncoherentIQAcquisition( item_type_ = configuration_->property(role + ".item_type", default_item_type); - fs_in_ = configuration_->property("GNSS-SDR.internal_fs_hz", 21000000); + fs_in_ = configuration_->property("GNSS-SDR.internal_fs_hz", 32000000); if_ = configuration_->property(role + ".ifreq", 0); dump_ = configuration_->property(role + ".dump", false); shift_resolution_ = configuration_->property(role + ".doppler_max", 15); - sampled_ms_ = configuration_->property(role + ".coherent_integration_time_ms", 3); - if (sampled_ms_ < 2) - { - sampled_ms_=2; - DLOG(INFO) << "Coherent integration time should be 2 or 3 ms. Changing to 2ms "; - std::cout<<"Too low coherent integration time. Changing to 2ms" << std::endl; - } - else if (sampled_ms_ > 3) + CAF_window_hz_ = configuration_->property(role + ".CAF_window_hz",0); + Zero_padding = configuration_->property(role + ".Zero_padding",0); + sampled_ms_ = configuration_->property(role + ".coherent_integration_time_ms", 1); + if (sampled_ms_ > 3) { sampled_ms_=3; - DLOG(INFO) << "Coherent integration time should be 2 or 3 ms. Changing to 3ms "; - std::cout<<"Too low coherent integration time. Changing to 3ms" << std::endl; + DLOG(INFO) << "Coherent integration time should be 3 ms or less. Changing to 3ms "; + std::cout<<"Too high coherent integration time. Changing to 3ms" << std::endl; } - //bit_transition_flag_ = configuration_->property(role + ".bit_transition_flag", false); + if (Zero_padding > 0) + { + sampled_ms_ = 2; + DLOG(INFO) << "Zero padding activated. Changing to 1ms code + 1ms zero padding "; + std::cout<<"Zero padding activated. Changing to 1ms code + 1ms zero padding" << std::endl; + } + max_dwells_ = configuration_->property(role + ".max_dwells", 1); dump_filename_ = configuration_->property(role + ".dump_filename", @@ -84,31 +91,23 @@ GalileoE5a3msNoncoherentIQAcquisition::GalileoE5a3msNoncoherentIQAcquisition( //--- Find number of samples per spreading code (1ms)------------------------- code_length_ = round(fs_in_/ Galileo_E5a_CODE_CHIP_RATE_HZ*Galileo_E5a_CODE_LENGTH_CHIPS); - // WARNING: In presence of secondary codes, 2ms must be correlated with 1ms - // of primary code and 1ms of padded zeros. vector_length_=code_length_ * sampled_ms_; -// vector_length_=15*code_length_; - - //std::cout << sampled_ms_ << " sampledms" << code_length_ << " cdelength" << std::endl; - - //if (posix_memalign((void**)&(code_), 16,vector_length_ * sizeof(gr_complex)) == 0){}; codeI_= new gr_complex[vector_length_]; codeQ_= new gr_complex[vector_length_]; + both_signal_components = false; + std::string sig_ = configuration_->property("Channel.signal", std::string("5X")); + if (sig_.at(0) == '5' && sig_.at(1) == 'X') + { + both_signal_components = true; + } if (item_type_.compare("gr_complex") == 0) { item_size_ = sizeof(gr_complex); - acquisition_cc_ = galileo_e5a_3ms_noncoherentIQ_make_acquisition_cc(sampled_ms_, max_dwells_, + acquisition_cc_ = galileo_e5a_noncoherentIQ_make_acquisition_caf_cc(sampled_ms_, max_dwells_, shift_resolution_, if_, fs_in_, code_length_, code_length_, - bit_transition_flag_, queue_, dump_, dump_filename_); - -// stream_to_vector_ = gr::blocks::stream_to_vector::make(item_size_, vector_length_); -// -// DLOG(INFO) << "stream_to_vector(" << stream_to_vector_->unique_id() -// << ")"; -// DLOG(INFO) << "acquisition(" << acquisition_cc_->unique_id() -// << ")"; + bit_transition_flag_, queue_, dump_, dump_filename_, both_signal_components, CAF_window_hz_); } else { @@ -118,13 +117,13 @@ GalileoE5a3msNoncoherentIQAcquisition::GalileoE5a3msNoncoherentIQAcquisition( } -GalileoE5a3msNoncoherentIQAcquisition::~GalileoE5a3msNoncoherentIQAcquisition() +GalileoE5aNoncoherentIQAcquisitionCaf::~GalileoE5aNoncoherentIQAcquisitionCaf() { delete[] codeI_; delete[] codeQ_; } -void GalileoE5a3msNoncoherentIQAcquisition::set_channel(unsigned int channel) +void GalileoE5aNoncoherentIQAcquisitionCaf::set_channel(unsigned int channel) { channel_ = channel; if (item_type_.compare("gr_complex") == 0) @@ -133,7 +132,7 @@ void GalileoE5a3msNoncoherentIQAcquisition::set_channel(unsigned int channel) } } -void GalileoE5a3msNoncoherentIQAcquisition::set_threshold(float threshold) +void GalileoE5aNoncoherentIQAcquisitionCaf::set_threshold(float threshold) { float pfa = configuration_->property(role_+ boost::lexical_cast(channel_) + ".pfa", 0.0); @@ -158,7 +157,7 @@ void GalileoE5a3msNoncoherentIQAcquisition::set_threshold(float threshold) } -void GalileoE5a3msNoncoherentIQAcquisition::set_doppler_max(unsigned int doppler_max) +void GalileoE5aNoncoherentIQAcquisitionCaf::set_doppler_max(unsigned int doppler_max) { doppler_max_ = doppler_max; @@ -168,7 +167,7 @@ void GalileoE5a3msNoncoherentIQAcquisition::set_doppler_max(unsigned int doppler } } -void GalileoE5a3msNoncoherentIQAcquisition::set_doppler_step(unsigned int doppler_step) +void GalileoE5aNoncoherentIQAcquisitionCaf::set_doppler_step(unsigned int doppler_step) { doppler_step_ = doppler_step; if (item_type_.compare("gr_complex") == 0) @@ -177,7 +176,7 @@ void GalileoE5a3msNoncoherentIQAcquisition::set_doppler_step(unsigned int dopple } } -void GalileoE5a3msNoncoherentIQAcquisition::set_channel_queue( +void GalileoE5aNoncoherentIQAcquisitionCaf::set_channel_queue( concurrent_queue *channel_internal_queue) { channel_internal_queue_ = channel_internal_queue; @@ -188,7 +187,7 @@ void GalileoE5a3msNoncoherentIQAcquisition::set_channel_queue( } -void GalileoE5a3msNoncoherentIQAcquisition::set_gnss_synchro( +void GalileoE5aNoncoherentIQAcquisitionCaf::set_gnss_synchro( Gnss_Synchro* gnss_synchro) { gnss_synchro_ = gnss_synchro; @@ -199,7 +198,7 @@ void GalileoE5a3msNoncoherentIQAcquisition::set_gnss_synchro( } -signed int GalileoE5a3msNoncoherentIQAcquisition::mag() +signed int GalileoE5aNoncoherentIQAcquisitionCaf::mag() { if (item_type_.compare("gr_complex") == 0) { @@ -212,13 +211,13 @@ signed int GalileoE5a3msNoncoherentIQAcquisition::mag() } -void GalileoE5a3msNoncoherentIQAcquisition::init() +void GalileoE5aNoncoherentIQAcquisitionCaf::init() { acquisition_cc_->init(); set_local_code(); } -void GalileoE5a3msNoncoherentIQAcquisition::set_local_code() +void GalileoE5aNoncoherentIQAcquisitionCaf::set_local_code() { if (item_type_.compare("gr_complex")==0) { @@ -226,28 +225,48 @@ void GalileoE5a3msNoncoherentIQAcquisition::set_local_code() std::complex* codeI = new std::complex[code_length_]; std::complex* codeQ = new std::complex[code_length_]; - std::cout << "ADAPTER E5a 3ms noncoherentIQ. SIGNAL = " << gnss_synchro_->Signal << " PRN = " << gnss_synchro_->PRN << std::endl; - - char a[3]; - strcpy(a,"5I"); - galileo_e5_a_code_gen_complex_sampled(codeI, a, - gnss_synchro_->PRN, fs_in_, 0, false); - - strcpy(a,"5Q"); - galileo_e5_a_code_gen_complex_sampled(codeQ, a, - gnss_synchro_->PRN, fs_in_, 0, false); + if (gnss_synchro_->Signal[0] == '5' && gnss_synchro_->Signal[1] == 'X') + { + char a[3]; + strcpy(a,"5I"); + galileo_e5_a_code_gen_complex_sampled(codeI, a, + gnss_synchro_->PRN, fs_in_, 0); + strcpy(a,"5Q"); + galileo_e5_a_code_gen_complex_sampled(codeQ, a, + gnss_synchro_->PRN, fs_in_, 0); + } + else + { + galileo_e5_a_code_gen_complex_sampled(codeI, gnss_synchro_->Signal, + gnss_synchro_->PRN, fs_in_, 0); + } // WARNING: 3ms are coherently integrated. Secondary sequence (1,1,1) // is generated, and modulated in the 'block'. - for (unsigned int i = 0; i < sampled_ms_; i++) + if (Zero_padding == 0) // if no zero_padding { - memcpy(&(codeI_[i*code_length_]), codeI, - sizeof(gr_complex)*code_length_); - - memcpy(&(codeQ_[i*code_length_]), codeQ, - sizeof(gr_complex)*code_length_); + for (unsigned int i = 0; i < sampled_ms_; i++) + { + memcpy(&(codeI_[i*code_length_]), codeI, + sizeof(gr_complex)*code_length_); + if (gnss_synchro_->Signal[0] == '5' && gnss_synchro_->Signal[1] == 'X') + { + memcpy(&(codeQ_[i*code_length_]), codeQ, + sizeof(gr_complex)*code_length_); + } + } + } + else + { + // 1ms code + 1ms zero padding + memcpy(&(codeI_[0]), codeI, + sizeof(gr_complex)*code_length_); + if (gnss_synchro_->Signal[0] == '5' && gnss_synchro_->Signal[1] == 'X') + { + memcpy(&(codeQ_[0]), codeQ, + sizeof(gr_complex)*code_length_); + } } - acquisition_cc_->set_local_code(codeI_,codeQ_); delete[] codeI; @@ -257,7 +276,7 @@ void GalileoE5a3msNoncoherentIQAcquisition::set_local_code() } -void GalileoE5a3msNoncoherentIQAcquisition::reset() +void GalileoE5aNoncoherentIQAcquisitionCaf::reset() { if (item_type_.compare("gr_complex") == 0) { @@ -266,7 +285,7 @@ void GalileoE5a3msNoncoherentIQAcquisition::reset() } -float GalileoE5a3msNoncoherentIQAcquisition::calculate_threshold(float pfa) +float GalileoE5aNoncoherentIQAcquisitionCaf::calculate_threshold(float pfa) { //Calculate the threshold unsigned int frequency_bins = 0; @@ -286,31 +305,24 @@ float GalileoE5a3msNoncoherentIQAcquisition::calculate_threshold(float pfa) } -void GalileoE5a3msNoncoherentIQAcquisition::connect(gr::top_block_sptr top_block) +void GalileoE5aNoncoherentIQAcquisitionCaf::connect(gr::top_block_sptr top_block) { -// if (item_type_.compare("gr_complex") == 0) -// { -// top_block->connect(stream_to_vector_, 0, acquisition_cc_, 0); -// } + // Nothing to connect internally } -void GalileoE5a3msNoncoherentIQAcquisition::disconnect(gr::top_block_sptr top_block) +void GalileoE5aNoncoherentIQAcquisitionCaf::disconnect(gr::top_block_sptr top_block) { -// if (item_type_.compare("gr_complex") == 0) -// { -// top_block->disconnect(stream_to_vector_, 0, acquisition_cc_, 0); -// } + // Nothing to disconnect internally } -gr::basic_block_sptr GalileoE5a3msNoncoherentIQAcquisition::get_left_block() -{ - return acquisition_cc_; - //return stream_to_vector_; -} - - -gr::basic_block_sptr GalileoE5a3msNoncoherentIQAcquisition::get_right_block() +gr::basic_block_sptr GalileoE5aNoncoherentIQAcquisitionCaf::get_left_block() +{ + return acquisition_cc_; +} + + +gr::basic_block_sptr GalileoE5aNoncoherentIQAcquisitionCaf::get_right_block() { return acquisition_cc_; } diff --git a/src/algorithms/acquisition/adapters/galileo_e5a_3ms_noncoherent_iq_acquisition.h b/src/algorithms/acquisition/adapters/galileo_e5a_noncoherent_iq_acquisition_caf.h similarity index 78% rename from src/algorithms/acquisition/adapters/galileo_e5a_3ms_noncoherent_iq_acquisition.h rename to src/algorithms/acquisition/adapters/galileo_e5a_noncoherent_iq_acquisition_caf.h index c08361424..6d7f0d13c 100644 --- a/src/algorithms/acquisition/adapters/galileo_e5a_3ms_noncoherent_iq_acquisition.h +++ b/src/algorithms/acquisition/adapters/galileo_e5a_noncoherent_iq_acquisition_caf.h @@ -1,8 +1,14 @@ /*! - * \file galileo_e5a_3ms_noncoherent_iq_acquisition.h + * \file galileo_e5a_noncoherent_iq_acquisition_caf.h * \brief Adapts a PCPS acquisition block to an AcquisitionInterface for * Galileo E5a data and pilot Signals - * \author Marc Sales, 2014. marcsales92(at)gmail.com + * \author Marc Sales, 2014. marcsales92(at)gmail.com + * \based on work from: + *
    + *
  • Javier Arribas, 2011. jarribas(at)cttc.es + *
  • Luis Esteve, 2012. luis(at)epsilon-formacion.com + *
  • Marc Molina, 2013. marc.molina.pena@gmail.com + *
* * ------------------------------------------------------------------------- * @@ -29,37 +35,37 @@ * ------------------------------------------------------------------------- */ -#ifndef GALILEO_E5A_3MS_NONCOHERENT_IQ_ACQUISITION_H_ -#define GALILEO_E5A_3MS_NONCOHERENT_IQ_ACQUISITION_H_ +#ifndef GALILEO_E5A_NONCOHERENT_IQ_ACQUISITION_CAF_H_ +#define GALILEO_E5A_NONCOHERENT_IQ_ACQUISITION_CAF_H_ #include #include #include #include "gnss_synchro.h" #include "acquisition_interface.h" -#include "galileo_e5a_3ms_noncoherent_iq_acquisition_cc.h" +#include "galileo_e5a_noncoherent_iq_acquisition_caf_cc.h" class ConfigurationInterface; -class GalileoE5a3msNoncoherentIQAcquisition: public AcquisitionInterface +class GalileoE5aNoncoherentIQAcquisitionCaf: public AcquisitionInterface { public: - GalileoE5a3msNoncoherentIQAcquisition(ConfigurationInterface* configuration, + GalileoE5aNoncoherentIQAcquisitionCaf(ConfigurationInterface* configuration, std::string role, unsigned int in_streams, unsigned int out_streams, boost::shared_ptr queue); - virtual ~GalileoE5a3msNoncoherentIQAcquisition(); + virtual ~GalileoE5aNoncoherentIQAcquisitionCaf(); std::string role() { return role_; } /*! - * \brief Returns "Galileo_E5a_3ms_Noncoherent_IQ_Acquisition" + * \brief Returns "Galileo_E5a_Noncoherent_IQ_Acquisition_CAF" */ std::string implementation() { - return "Galileo_E5a_3ms_Noncoherent_IQ_Acquisition"; + return "Galileo_E5a_Noncoherent_IQ_Acquisition_CAF"; } size_t item_size() { @@ -71,7 +77,6 @@ public: gr::basic_block_sptr get_left_block(); gr::basic_block_sptr get_right_block(); - /*! * \brief Set acquisition/tracking common Gnss_Synchro object pointer * to efficiently exchange synchronization data between acquisition and @@ -126,7 +131,7 @@ public: private: ConfigurationInterface* configuration_; - galileo_e5a_3ms_noncoherentIQ_acquisition_cc_sptr acquisition_cc_; + galileo_e5a_noncoherentIQ_acquisition_caf_cc_sptr acquisition_cc_; gr::blocks::stream_to_vector::sptr stream_to_vector_; size_t item_size_; std::string item_type_; @@ -144,8 +149,11 @@ private: long if_; bool dump_; std::string dump_filename_; + int Zero_padding; + int CAF_window_hz_; std::complex * codeI_; std::complex * codeQ_; + bool both_signal_components; Gnss_Synchro * gnss_synchro_; std::string role_; unsigned int in_streams_; @@ -154,4 +162,4 @@ private: concurrent_queue *channel_internal_queue_; float calculate_threshold(float pfa); }; -#endif /* GALILEO_E5A_3MS_NONCOHERENT_IQ_ACQUISITION_H_ */ +#endif /* GALILEO_E5A_NONCOHERENT_IQ_ACQUISITION_CAF_H_ */ diff --git a/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition.cc b/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition.cc deleted file mode 100644 index 12476b033..000000000 --- a/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition.cc +++ /dev/null @@ -1,300 +0,0 @@ -/*! - * \file galileo_e5a_pcps_acquisition.cc - * \brief Adapts a PCPS acquisition block to an AcquisitionInterface for - * Galileo E5a data and pilot Signals - * \author Marc Sales, 2014. marcsales92(at)gmail.com - * - * ------------------------------------------------------------------------- - * - * Copyright (C) 2010-2014 (see AUTHORS file for a list of contributors) - * - * GNSS-SDR is a software defined Global Navigation - * Satellite Systems receiver - * - * This file is part of GNSS-SDR. - * - * GNSS-SDR is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * at your option) any later version. - * - * GNSS-SDR is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNSS-SDR. If not, see . - * - * ------------------------------------------------------------------------- - */ - -#include "galileo_e5a_pcps_acquisition.h" -#include -#include -#include -#include -#include -#include -#include "galileo_e5_signal_processing.h" -#include "Galileo_E5a.h" -#include "configuration_interface.h" -//#include - -using google::LogMessage; - -GalileoE5aPcpsAcquisition::GalileoE5aPcpsAcquisition( - ConfigurationInterface* configuration, std::string role, - unsigned int in_streams, unsigned int out_streams, - boost::shared_ptr queue) : - role_(role), in_streams_(in_streams), out_streams_(out_streams), queue_(queue) -{ - configuration_ = configuration; - std::string default_item_type = "gr_complex"; - std::string default_dump_filename = "../data/acquisition.dat"; - - DLOG(INFO) << "role " << role; - - item_type_ = configuration_->property(role + ".item_type", - default_item_type); - - fs_in_ = configuration_->property("GNSS-SDR.internal_fs_hz", 12000000); - if_ = configuration_->property(role + ".ifreq", 0); - dump_ = configuration_->property(role + ".dump", false); - shift_resolution_ = configuration_->property(role + ".doppler_max", 15); - sampled_ms_ = 1; // try luck without zero padding to achieve better gain when bit transition coincides. - bit_transition_flag_ = configuration_->property(role + ".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 (1ms)------------------------- - code_length_ = round(fs_in_/ Galileo_E5a_CODE_CHIP_RATE_HZ*Galileo_E5a_CODE_LENGTH_CHIPS); - - // Several dwells will be needed without zero-padding. Only 1ms in this implementation. - vector_length_=code_length_;// * sampled_ms_; - - //std::cout << sampled_ms_ << " sampledms" << code_length_ << " cdelength" << std::endl; - - //if (posix_memalign((void**)&(code_), 16,vector_length_ * sizeof(gr_complex)) == 0){}; - - code_= new gr_complex[vector_length_]; - - if (item_type_.compare("gr_complex") == 0) - { - item_size_ = sizeof(gr_complex); - acquisition_cc_ = pcps_make_acquisition_cc(sampled_ms_, max_dwells_, - shift_resolution_, if_, fs_in_, code_length_, code_length_, - bit_transition_flag_, queue_, dump_, dump_filename_); - - stream_to_vector_ = gr::blocks::stream_to_vector::make(item_size_, vector_length_); - - DLOG(INFO) << "stream_to_vector(" << stream_to_vector_->unique_id() - << ")"; - DLOG(INFO) << "acquisition(" << acquisition_cc_->unique_id() - << ")"; - } - else - { - LOG(WARNING) << item_type_ - << " unknown acquisition item type"; - } - -} - -GalileoE5aPcpsAcquisition::~GalileoE5aPcpsAcquisition() -{ - delete[] code_; -} - -void GalileoE5aPcpsAcquisition::set_channel(unsigned int channel) -{ - channel_ = channel; - if (item_type_.compare("gr_complex") == 0) - { - acquisition_cc_->set_channel(channel_); - } -} - -void GalileoE5aPcpsAcquisition::set_threshold(float threshold) -{ - - float pfa = configuration_->property(role_+ boost::lexical_cast(channel_) + ".pfa", 0.0); - - if(pfa==0.0) pfa = configuration_->property(role_+".pfa", 0.0); - - if(pfa==0.0) - { - threshold_ = threshold; - } - else - { - threshold_ = calculate_threshold(pfa); - } - - DLOG(INFO) <<"Channel "<set_threshold(threshold_); - } -} - - -void GalileoE5aPcpsAcquisition::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 GalileoE5aPcpsAcquisition::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 GalileoE5aPcpsAcquisition::set_channel_queue( - concurrent_queue *channel_internal_queue) -{ - channel_internal_queue_ = channel_internal_queue; - if (item_type_.compare("gr_complex") == 0) - { - acquisition_cc_->set_channel_queue(channel_internal_queue_); - } -} - - -void GalileoE5aPcpsAcquisition::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 GalileoE5aPcpsAcquisition::mag() -{ - if (item_type_.compare("gr_complex") == 0) - { - return acquisition_cc_->mag(); - } - else - { - return 0; - } -} - - -void GalileoE5aPcpsAcquisition::init() -{ - acquisition_cc_->init(); - set_local_code(); -} - -void GalileoE5aPcpsAcquisition::set_local_code() -{ - if (item_type_.compare("gr_complex")==0) - { - - // WARNING: In presence of secondary codes, 2ms must be correlated with 1ms - // of primary code and 1ms of padded zeros. - //std::complex* code = new std::complex[2*code_length_]; - - std::cout << "ADAPTER E5a. SIGNAL = " << gnss_synchro_->Signal << " PRN = " << gnss_synchro_->PRN << std::endl; - galileo_e5_a_code_gen_complex_sampled(code_, gnss_synchro_->Signal, - gnss_synchro_->PRN, fs_in_, 0, false); - - // WARNING: In presence of secondary codes, 2ms of input signal are required - // which are correlated with 1ms of primary code and 1ms of zero padding -// 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 GalileoE5aPcpsAcquisition::reset() -{ - if (item_type_.compare("gr_complex") == 0) - { - acquisition_cc_->set_active(true); - } -} - - -float GalileoE5aPcpsAcquisition::calculate_threshold(float pfa) -{ - //Calculate the threshold - unsigned int frequency_bins = 0; - for (int doppler = (int)(-doppler_max_); doppler <= (int)doppler_max_; doppler += doppler_step_) - { - frequency_bins++; - } - DLOG(INFO) << "Channel " << channel_<< " Pfa = " << pfa; - unsigned int ncells = vector_length_*frequency_bins; - double exponent = 1/(double)ncells; - double val = pow(1.0 - pfa, exponent); - double lambda = double(vector_length_); - boost::math::exponential_distribution mydist (lambda); - float threshold = (float)quantile(mydist,val); - - return threshold; -} - - -void GalileoE5aPcpsAcquisition::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 GalileoE5aPcpsAcquisition::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 GalileoE5aPcpsAcquisition::get_left_block() -{ - return stream_to_vector_; -} - - -gr::basic_block_sptr GalileoE5aPcpsAcquisition::get_right_block() -{ - return acquisition_cc_; -} - - - diff --git a/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition.h b/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition.h deleted file mode 100644 index 3da5453ad..000000000 --- a/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition.h +++ /dev/null @@ -1,157 +0,0 @@ -/*! - * \file galileo_e5a_pcps_acquisition.cc - * \brief Adapts a PCPS acquisition block to an AcquisitionInterface for - * Galileo E5a data and pilot Signals - * \author Marc Sales, 2014. marcsales92(at)gmail.com - * - * ------------------------------------------------------------------------- - * - * Copyright (C) 2010-2014 (see AUTHORS file for a list of contributors) - * - * GNSS-SDR is a software defined Global Navigation - * Satellite Systems receiver - * - * This file is part of GNSS-SDR. - * - * GNSS-SDR is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * at your option) any later version. - * - * GNSS-SDR is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNSS-SDR. If not, see . - * - * ------------------------------------------------------------------------- - */ - -#ifndef GNSS_SDR_GALILEO_E5A_PCPS_ACQUISITION_H_ -#define GNSS_SDR_GALILEO_E5A_PCPS_ACQUISITION_H_ - -#include -#include -#include -#include "gnss_synchro.h" -#include "acquisition_interface.h" -#include "pcps_acquisition_cc.h" - -class ConfigurationInterface; - -class GalileoE5aPcpsAcquisition: public AcquisitionInterface -{ -public: - GalileoE5aPcpsAcquisition(ConfigurationInterface* configuration, - std::string role, unsigned int in_streams, - unsigned int out_streams, boost::shared_ptr queue); - - virtual ~GalileoE5aPcpsAcquisition(); - - std::string role() - { - return role_; - } - /*! - * \brief Returns "Galileo_E5a_PCPS_Acquisition" - */ - std::string implementation() - { - return "Galileo_E5a_PCPS_Acquisition"; - } - size_t item_size() - { - return item_size_; - } - - void connect(gr::top_block_sptr top_block); - void disconnect(gr::top_block_sptr top_block); - gr::basic_block_sptr get_left_block(); - gr::basic_block_sptr get_right_block(); - - - /*! - * \brief Set acquisition/tracking common Gnss_Synchro object pointer - * to efficiently exchange synchronization data between acquisition and - * tracking blocks - */ - void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro); - - /*! - * \brief Set acquisition channel unique ID - */ - void set_channel(unsigned int channel); - - /*! - * \brief Set statistics threshold of PCPS algorithm - */ - void set_threshold(float threshold); - - /*! - * \brief Set maximum Doppler off grid search - */ - void set_doppler_max(unsigned int doppler_max); - - /*! - * \brief Set Doppler steps for the grid search - */ - void set_doppler_step(unsigned int doppler_step); - - /*! - * \brief Set tracking channel internal queue - */ - void set_channel_queue(concurrent_queue *channel_internal_queue); - - /*! - * \brief Initializes acquisition algorithm. - */ - void init(); - - /*! - * \brief Sets local Galileo E5a (data or pilot) code for PCPS acquisition algorithm. - */ - void set_local_code(); - - /*! - * \brief Returns the maximum peak of grid search - */ - signed int mag(); - - /*! - * \brief Restart acquisition algorithm - */ - void reset(); - -private: - ConfigurationInterface* configuration_; - pcps_acquisition_cc_sptr acquisition_cc_; - gr::blocks::stream_to_vector::sptr stream_to_vector_; - size_t item_size_; - std::string item_type_; - unsigned int vector_length_; - unsigned int code_length_; - bool bit_transition_flag_; - unsigned int channel_; - float threshold_; - unsigned int doppler_max_; - unsigned int doppler_step_; - unsigned int shift_resolution_; - unsigned int sampled_ms_; - unsigned int max_dwells_; - long fs_in_; - long if_; - bool dump_; - std::string dump_filename_; - std::complex * code_; - Gnss_Synchro * gnss_synchro_; - std::string role_; - unsigned int in_streams_; - unsigned int out_streams_; - boost::shared_ptr queue_; - concurrent_queue *channel_internal_queue_; - float calculate_threshold(float pfa); -}; - -#endif /* GNSS_SDR_GALILEO_E5A_PCPS_ACQUISITION_H_ */ diff --git a/src/algorithms/acquisition/adapters/galileo_e5a_pilot_3ms_acquisition.cc b/src/algorithms/acquisition/adapters/galileo_e5a_pilot_3ms_acquisition.cc deleted file mode 100644 index 1910237c0..000000000 --- a/src/algorithms/acquisition/adapters/galileo_e5a_pilot_3ms_acquisition.cc +++ /dev/null @@ -1,296 +0,0 @@ -/*! - * \file galileo_e5a_pcps_acquisition.cc - * \brief Adapts a PCPS acquisition block to an AcquisitionInterface for - * Galileo E5a data and pilot Signals - * \author Marc Sales, 2014. marcsales92(at)gmail.com - * - * ------------------------------------------------------------------------- - * - * Copyright (C) 2010-2014 (see AUTHORS file for a list of contributors) - * - * GNSS-SDR is a software defined Global Navigation - * Satellite Systems receiver - * - * This file is part of GNSS-SDR. - * - * GNSS-SDR is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * at your option) any later version. - * - * GNSS-SDR is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNSS-SDR. If not, see . - * - * ------------------------------------------------------------------------- - */ - -#include "galileo_e5a_pilot_3ms_acquisition.h" -#include -#include -#include -#include -#include -#include -#include "galileo_e5_signal_processing.h" -#include "Galileo_E5a.h" -#include "configuration_interface.h" -//#include - -using google::LogMessage; - -GalileoE5aPilot_3msAcquisition::GalileoE5aPilot_3msAcquisition( - ConfigurationInterface* configuration, std::string role, - unsigned int in_streams, unsigned int out_streams, - boost::shared_ptr queue) : - role_(role), in_streams_(in_streams), out_streams_(out_streams), queue_(queue) -{ - configuration_ = configuration; - std::string default_item_type = "gr_complex"; - std::string default_dump_filename = "../data/acquisition.dat"; - - DLOG(INFO) << "role " << role; - - item_type_ = configuration_->property(role + ".item_type", - default_item_type); - - fs_in_ = configuration_->property("GNSS-SDR.internal_fs_hz", 12000000); - if_ = configuration_->property(role + ".ifreq", 0); - dump_ = configuration_->property(role + ".dump", false); - shift_resolution_ = configuration_->property(role + ".doppler_max", 15); - sampled_ms_ = 3; // needed 3 ms of input in presence of secondary code. -// sampled_ms_ = 15; - //bit_transition_flag_ = configuration_->property(role + ".bit_transition_flag", false); - max_dwells_ = configuration_->property(role + ".max_dwells", 1); - - dump_filename_ = configuration_->property(role + ".dump_filename", - default_dump_filename); - - //--- Find number of samples per spreading code (1ms)------------------------- - code_length_ = round(fs_in_/ Galileo_E5a_CODE_CHIP_RATE_HZ*Galileo_E5a_CODE_LENGTH_CHIPS); - - // WARNING: In presence of secondary codes, 2ms must be correlated with 1ms - // of primary code and 1ms of padded zeros. - vector_length_=3*code_length_;// * sampled_ms_; -// vector_length_=15*code_length_; - - //std::cout << sampled_ms_ << " sampledms" << code_length_ << " cdelength" << std::endl; - - //if (posix_memalign((void**)&(code_), 16,vector_length_ * sizeof(gr_complex)) == 0){}; - - code_= new gr_complex[vector_length_]; - - if (item_type_.compare("gr_complex") == 0) - { - item_size_ = sizeof(gr_complex); - acquisition_cc_ = galileo_e5a_pilot_3ms_make_acquisition_cc(max_dwells_, - shift_resolution_, if_, fs_in_, code_length_, code_length_, - bit_transition_flag_, queue_, dump_, dump_filename_); - - stream_to_vector_ = gr::blocks::stream_to_vector::make(item_size_, vector_length_); - - DLOG(INFO) << "stream_to_vector(" << stream_to_vector_->unique_id() - << ")"; - DLOG(INFO) << "acquisition(" << acquisition_cc_->unique_id() - << ")"; - } - else - { - LOG(WARNING) << item_type_ - << " unknown acquisition item type"; - } - -} - -GalileoE5aPilot_3msAcquisition::~GalileoE5aPilot_3msAcquisition() -{ - delete[] code_; -} - -void GalileoE5aPilot_3msAcquisition::set_channel(unsigned int channel) -{ - channel_ = channel; - if (item_type_.compare("gr_complex") == 0) - { - acquisition_cc_->set_channel(channel_); - } -} - -void GalileoE5aPilot_3msAcquisition::set_threshold(float threshold) -{ - - float pfa = configuration_->property(role_+ boost::lexical_cast(channel_) + ".pfa", 0.0); - - if(pfa==0.0) pfa = configuration_->property(role_+".pfa", 0.0); - - if(pfa==0.0) - { - threshold_ = threshold; - } - else - { - threshold_ = calculate_threshold(pfa); - } - - DLOG(INFO) <<"Channel "<set_threshold(threshold_); - } -} - - -void GalileoE5aPilot_3msAcquisition::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 GalileoE5aPilot_3msAcquisition::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 GalileoE5aPilot_3msAcquisition::set_channel_queue( - concurrent_queue *channel_internal_queue) -{ - channel_internal_queue_ = channel_internal_queue; - if (item_type_.compare("gr_complex") == 0) - { - acquisition_cc_->set_channel_queue(channel_internal_queue_); - } -} - - -void GalileoE5aPilot_3msAcquisition::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 GalileoE5aPilot_3msAcquisition::mag() -{ - if (item_type_.compare("gr_complex") == 0) - { - return acquisition_cc_->mag(); - } - else - { - return 0; - } -} - - -void GalileoE5aPilot_3msAcquisition::init() -{ - acquisition_cc_->init(); - set_local_code(); -} - -void GalileoE5aPilot_3msAcquisition::set_local_code() -{ - if (item_type_.compare("gr_complex")==0) - { - - // WARNING: In presence of secondary codes, 2ms must be correlated with 1ms - // of primary code and 1ms of padded zeros. - std::complex* code = new std::complex[code_length_]; - - std::cout << "ADAPTER E5a 3ms. SIGNAL = " << gnss_synchro_->Signal << " PRN = " << gnss_synchro_->PRN << std::endl; - - char a[3]; - strcpy(a,"5X"); - galileo_e5_a_code_gen_complex_sampled(code, a, - gnss_synchro_->PRN, fs_in_, 0, false); - - // WARNING: 3ms are coherently integrated. Secondary sequence (1,1,1) - // is generated, and modulated in the 'block'. - for (unsigned int i = 0; i < 3; i++) - { - memcpy(&(code_[i*code_length_]), code, - sizeof(gr_complex)*code_length_); - - } - - acquisition_cc_->set_local_code(code_); - - delete[] code; - } - -} - -void GalileoE5aPilot_3msAcquisition::reset() -{ - if (item_type_.compare("gr_complex") == 0) - { - acquisition_cc_->set_active(true); - } -} - - -float GalileoE5aPilot_3msAcquisition::calculate_threshold(float pfa) -{ - //Calculate the threshold - unsigned int frequency_bins = 0; - for (int doppler = (int)(-doppler_max_); doppler <= (int)doppler_max_; doppler += doppler_step_) - { - frequency_bins++; - } - DLOG(INFO) << "Channel " << channel_<< " Pfa = " << pfa; - unsigned int ncells = vector_length_*frequency_bins; - double exponent = 1/(double)ncells; - double val = pow(1.0 - pfa, exponent); - double lambda = double(vector_length_); - boost::math::exponential_distribution mydist (lambda); - float threshold = (float)quantile(mydist,val); - - return threshold; -} - - -void GalileoE5aPilot_3msAcquisition::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 GalileoE5aPilot_3msAcquisition::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 GalileoE5aPilot_3msAcquisition::get_left_block() -{ - return stream_to_vector_; -} - - -gr::basic_block_sptr GalileoE5aPilot_3msAcquisition::get_right_block() -{ - return acquisition_cc_; -} - diff --git a/src/algorithms/acquisition/adapters/galileo_e5a_pilot_3ms_acquisition.h b/src/algorithms/acquisition/adapters/galileo_e5a_pilot_3ms_acquisition.h deleted file mode 100644 index 2474164d1..000000000 --- a/src/algorithms/acquisition/adapters/galileo_e5a_pilot_3ms_acquisition.h +++ /dev/null @@ -1,157 +0,0 @@ -/*! - * \file galileo_e5a_pcps_acquisition.cc - * \brief Adapts a PCPS acquisition block to an AcquisitionInterface for - * Galileo E5a data and pilot Signals - * \author Marc Sales, 2014. marcsales92(at)gmail.com - * - * ------------------------------------------------------------------------- - * - * Copyright (C) 2010-2014 (see AUTHORS file for a list of contributors) - * - * GNSS-SDR is a software defined Global Navigation - * Satellite Systems receiver - * - * This file is part of GNSS-SDR. - * - * GNSS-SDR is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * at your option) any later version. - * - * GNSS-SDR is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNSS-SDR. If not, see . - * - * ------------------------------------------------------------------------- - */ - -#ifndef GALILEO_E5A_PILOT_3MS_ACQUISITION_H_ -#define GALILEO_E5A_PILOT_3MS_ACQUISITION_H_ - -#include -#include -#include -#include "gnss_synchro.h" -#include "acquisition_interface.h" -#include "galileo_e5a_pilot_3ms_acquisition_cc.h" - -class ConfigurationInterface; - -class GalileoE5aPilot_3msAcquisition: public AcquisitionInterface -{ -public: - GalileoE5aPilot_3msAcquisition(ConfigurationInterface* configuration, - std::string role, unsigned int in_streams, - unsigned int out_streams, boost::shared_ptr queue); - - virtual ~GalileoE5aPilot_3msAcquisition(); - - std::string role() - { - return role_; - } - /*! - * \brief Returns "Galileo_E5a_Pilot_3ms_Acquisition" - */ - std::string implementation() - { - return "Galileo_E5a_Pilot_3ms_Acquisition"; - } - size_t item_size() - { - return item_size_; - } - - void connect(gr::top_block_sptr top_block); - void disconnect(gr::top_block_sptr top_block); - gr::basic_block_sptr get_left_block(); - gr::basic_block_sptr get_right_block(); - - - /*! - * \brief Set acquisition/tracking common Gnss_Synchro object pointer - * to efficiently exchange synchronization data between acquisition and - * tracking blocks - */ - void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro); - - /*! - * \brief Set acquisition channel unique ID - */ - void set_channel(unsigned int channel); - - /*! - * \brief Set statistics threshold of PCPS algorithm - */ - void set_threshold(float threshold); - - /*! - * \brief Set maximum Doppler off grid search - */ - void set_doppler_max(unsigned int doppler_max); - - /*! - * \brief Set Doppler steps for the grid search - */ - void set_doppler_step(unsigned int doppler_step); - - /*! - * \brief Set tracking channel internal queue - */ - void set_channel_queue(concurrent_queue *channel_internal_queue); - - /*! - * \brief Initializes acquisition algorithm. - */ - void init(); - - /*! - * \brief Sets local Galileo E5a (pilot) code for PCPS acquisition algorithm. - */ - void set_local_code(); - - /*! - * \brief Returns the maximum peak of grid search - */ - signed int mag(); - - /*! - * \brief Restart acquisition algorithm - */ - void reset(); - -private: - ConfigurationInterface* configuration_; - galileo_e5a_pilot_3ms_acquisition_cc_sptr acquisition_cc_; - gr::blocks::stream_to_vector::sptr stream_to_vector_; - size_t item_size_; - std::string item_type_; - unsigned int vector_length_; - unsigned int code_length_; - bool bit_transition_flag_; - unsigned int channel_; - float threshold_; - unsigned int doppler_max_; - unsigned int doppler_step_; - unsigned int shift_resolution_; - unsigned int sampled_ms_; - unsigned int max_dwells_; - long fs_in_; - long if_; - bool dump_; - std::string dump_filename_; - std::complex * code_; - Gnss_Synchro * gnss_synchro_; - std::string role_; - unsigned int in_streams_; - unsigned int out_streams_; - boost::shared_ptr queue_; - concurrent_queue *channel_internal_queue_; - float calculate_threshold(float pfa); -}; - -#endif /* GALILEO_E5A_PILOT_3MS_ACQUISITION_H_ */ diff --git a/src/algorithms/acquisition/adapters/galileo_e5ax_2ms_pcps_acquisition.cc b/src/algorithms/acquisition/adapters/galileo_e5ax_2ms_pcps_acquisition.cc deleted file mode 100644 index 33cac6aa2..000000000 --- a/src/algorithms/acquisition/adapters/galileo_e5ax_2ms_pcps_acquisition.cc +++ /dev/null @@ -1,297 +0,0 @@ - /*\file galileo_e5a_pcps_acquisition.cc - * \brief Adapts a PCPS acquisition block to an AcquisitionInterface for - * Galileo E5a data and pilot Signals - * \author Marc Sales, 2014. marcsales92(at)gmail.com - * - * ------------------------------------------------------------------------- - * - * Copyright (C) 2010-2014 (see AUTHORS file for a list of contributors) - * - * GNSS-SDR is a software defined Global Navigation - * Satellite Systems receiver - * - * This file is part of GNSS-SDR. - * - * GNSS-SDR is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * at your option) any later version. - * - * GNSS-SDR is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNSS-SDR. If not, see . - * - * ------------------------------------------------------------------------- - */ - -#include "galileo_e5ax_2ms_pcps_acquisition.h" -#include -#include -#include -#include -#include -#include -#include "galileo_e5_signal_processing.h" -#include "Galileo_E5a.h" -#include "configuration_interface.h" -//#include - -using google::LogMessage; - -GalileoE5ax2msPcpsAcquisition::GalileoE5ax2msPcpsAcquisition( - ConfigurationInterface* configuration, std::string role, - unsigned int in_streams, unsigned int out_streams, - boost::shared_ptr queue) : - role_(role), in_streams_(in_streams), out_streams_(out_streams), queue_(queue) -{ - configuration_ = configuration; - std::string default_item_type = "gr_complex"; - std::string default_dump_filename = "../data/acquisition.dat"; - - DLOG(INFO) << "role " << role; - - item_type_ = configuration_->property(role + ".item_type", - default_item_type); - - fs_in_ = configuration_->property("GNSS-SDR.internal_fs_hz", 12000000); - if_ = configuration_->property(role + ".ifreq", 0); - dump_ = configuration_->property(role + ".dump", false); - shift_resolution_ = configuration_->property(role + ".doppler_max", 15); - sampled_ms_ = 2; // needed 2 ms of input in presence of secondary code. - //there is always bit transition in e5 - //bit_transition_flag_ = configuration_->property(role + ".bit_transition_flag", false); - - max_dwells_ = configuration_->property(role + ".max_dwells", 1); - - - dump_filename_ = configuration_->property(role + ".dump_filename", - default_dump_filename); - - //--- Find number of samples per spreading code (1ms)------------------------- - code_length_ = round(fs_in_/ Galileo_E5a_CODE_CHIP_RATE_HZ*Galileo_E5a_CODE_LENGTH_CHIPS); - - // WARNING: In presence of secondary codes, 2ms must be correlated with 1ms - // of primary code and 1ms of padded zeros. - vector_length_=2*code_length_;// * sampled_ms_; - - //std::cout << sampled_ms_ << " sampledms" << code_length_ << " cdelength" << std::endl; - - //if (posix_memalign((void**)&(code_), 16,vector_length_ * sizeof(gr_complex)) == 0){}; - - code_= new gr_complex[vector_length_]; - - if (item_type_.compare("gr_complex") == 0) - { - item_size_ = sizeof(gr_complex); - acquisition_cc_ = galileo_e5ax_2ms_pcps_make_acquisition_cc(max_dwells_, - shift_resolution_, if_, fs_in_, code_length_, code_length_, - bit_transition_flag_, queue_, dump_, dump_filename_); - - stream_to_vector_ = gr::blocks::stream_to_vector::make(item_size_, vector_length_); - - DLOG(INFO) << "stream_to_vector(" << stream_to_vector_->unique_id() - << ")"; - DLOG(INFO) << "acquisition(" << acquisition_cc_->unique_id() - << ")"; - } - else - { - LOG(WARNING) << item_type_ - << " unknown acquisition item type"; - } - -} - -GalileoE5ax2msPcpsAcquisition::~GalileoE5ax2msPcpsAcquisition() -{ - delete[] code_; -} - -void GalileoE5ax2msPcpsAcquisition::set_channel(unsigned int channel) -{ - channel_ = channel; - if (item_type_.compare("gr_complex") == 0) - { - acquisition_cc_->set_channel(channel_); - } -} - -void GalileoE5ax2msPcpsAcquisition::set_threshold(float threshold) -{ - - float pfa = configuration_->property(role_+ boost::lexical_cast(channel_) + ".pfa", 0.0); - - if(pfa==0.0) pfa = configuration_->property(role_+".pfa", 0.0); - - if(pfa==0.0) - { - threshold_ = threshold; - } - else - { - threshold_ = calculate_threshold(pfa); - } - - DLOG(INFO) <<"Channel "<set_threshold(threshold_); - } -} - - -void GalileoE5ax2msPcpsAcquisition::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 GalileoE5ax2msPcpsAcquisition::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 GalileoE5ax2msPcpsAcquisition::set_channel_queue( - concurrent_queue *channel_internal_queue) -{ - channel_internal_queue_ = channel_internal_queue; - if (item_type_.compare("gr_complex") == 0) - { - acquisition_cc_->set_channel_queue(channel_internal_queue_); - } -} - - -void GalileoE5ax2msPcpsAcquisition::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 GalileoE5ax2msPcpsAcquisition::mag() -{ - if (item_type_.compare("gr_complex") == 0) - { - return acquisition_cc_->mag(); - } - else - { - return 0; - } -} - - -void GalileoE5ax2msPcpsAcquisition::init() -{ - acquisition_cc_->init(); - set_local_code(); -} - -void GalileoE5ax2msPcpsAcquisition::set_local_code() -{ - if (item_type_.compare("gr_complex")==0) - { - - // WARNING: In presence of secondary codes, 2ms must be correlated with 1ms - // of primary code and 1ms of padded zeros. - //std::complex* code = new std::complex[2*code_length_]; - - std::cout << "ADAPTER E5a. SIGNAL = " << gnss_synchro_->Signal << " PRN = " << gnss_synchro_->PRN << std::endl; - char a[3]; - strcpy(a,"5X"); - galileo_e5_a_code_gen_complex_sampled(code_, a, - gnss_synchro_->PRN, fs_in_, 0, false); - - // WARNING: In presence of secondary codes, 2ms of input signal are required - // which are correlated with 1ms of primary code and 1ms of zero padding -// 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 GalileoE5ax2msPcpsAcquisition::reset() -{ - if (item_type_.compare("gr_complex") == 0) - { - acquisition_cc_->set_active(true); - } -} - - -float GalileoE5ax2msPcpsAcquisition::calculate_threshold(float pfa) -{ - //Calculate the threshold - unsigned int frequency_bins = 0; - for (int doppler = (int)(-doppler_max_); doppler <= (int)doppler_max_; doppler += doppler_step_) - { - frequency_bins++; - } - DLOG(INFO) << "Channel " << channel_<< " Pfa = " << pfa; - unsigned int ncells = vector_length_*frequency_bins; - double exponent = 1/(double)ncells; - double val = pow(1.0 - pfa, exponent); - double lambda = double(vector_length_); - boost::math::exponential_distribution mydist (lambda); - float threshold = (float)quantile(mydist,val); - - return threshold; -} - - -void GalileoE5ax2msPcpsAcquisition::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 GalileoE5ax2msPcpsAcquisition::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 GalileoE5ax2msPcpsAcquisition::get_left_block() -{ - return stream_to_vector_; -} - - -gr::basic_block_sptr GalileoE5ax2msPcpsAcquisition::get_right_block() -{ - return acquisition_cc_; -} - - - diff --git a/src/algorithms/acquisition/adapters/galileo_e5ax_2ms_pcps_acquisition.h b/src/algorithms/acquisition/adapters/galileo_e5ax_2ms_pcps_acquisition.h deleted file mode 100644 index c89c545b5..000000000 --- a/src/algorithms/acquisition/adapters/galileo_e5ax_2ms_pcps_acquisition.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - * galileo_e5ax_1ms_pcps_acquisition.h - * - * Created on: Jun 23, 2014 - * Author: marc - */ - -#ifndef GALILEO_E5AX_2MS_PCPS_ACQUISITION_H_ -#define GALILEO_E5AX_2MS_PCPS_ACQUISITION_H_ - - -#include -#include -#include -#include "gnss_synchro.h" -#include "acquisition_interface.h" -#include "galileo_e5ax_2ms_pcps_acquisition_cc.h" - -class ConfigurationInterface; - -class GalileoE5ax2msPcpsAcquisition: public AcquisitionInterface -{ -public: - GalileoE5ax2msPcpsAcquisition(ConfigurationInterface* configuration, - std::string role, unsigned int in_streams, - unsigned int out_streams, boost::shared_ptr queue); - - virtual ~GalileoE5ax2msPcpsAcquisition(); - - std::string role() - { - return role_; - } - /*! - * \brief Returns "Galileo_E5ax_2ms_Pcps_Acquisition" - */ - std::string implementation() - { - return "Galileo_E5ax_2ms_Pcps_Acquisition"; - } - size_t item_size() - { - return item_size_; - } - - void connect(gr::top_block_sptr top_block); - void disconnect(gr::top_block_sptr top_block); - gr::basic_block_sptr get_left_block(); - gr::basic_block_sptr get_right_block(); - - - /*! - * \brief Set acquisition/tracking common Gnss_Synchro object pointer - * to efficiently exchange synchronization data between acquisition and - * tracking blocks - */ - void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro); - - /*! - * \brief Set acquisition channel unique ID - */ - void set_channel(unsigned int channel); - - /*! - * \brief Set statistics threshold of PCPS algorithm - */ - void set_threshold(float threshold); - - /*! - * \brief Set maximum Doppler off grid search - */ - void set_doppler_max(unsigned int doppler_max); - - /*! - * \brief Set Doppler steps for the grid search - */ - void set_doppler_step(unsigned int doppler_step); - - /*! - * \brief Set tracking channel internal queue - */ - void set_channel_queue(concurrent_queue *channel_internal_queue); - - /*! - * \brief Initializes acquisition algorithm. - */ - void init(); - - /*! - * \brief Sets local Galileo E5a (pilot) code for PCPS acquisition algorithm. - */ - void set_local_code(); - - /*! - * \brief Returns the maximum peak of grid search - */ - signed int mag(); - - /*! - * \brief Restart acquisition algorithm - */ - void reset(); - -private: - ConfigurationInterface* configuration_; - galileo_e5ax_2ms_pcps_acquisition_cc_sptr acquisition_cc_; - gr::blocks::stream_to_vector::sptr stream_to_vector_; - size_t item_size_; - std::string item_type_; - unsigned int vector_length_; - unsigned int code_length_; - bool bit_transition_flag_; - unsigned int channel_; - float threshold_; - unsigned int doppler_max_; - unsigned int doppler_step_; - unsigned int shift_resolution_; - unsigned int sampled_ms_; - unsigned int max_dwells_; - long fs_in_; - long if_; - bool dump_; - std::string dump_filename_; - std::complex * code_; - Gnss_Synchro * gnss_synchro_; - std::string role_; - unsigned int in_streams_; - unsigned int out_streams_; - boost::shared_ptr queue_; - concurrent_queue *channel_internal_queue_; - float calculate_threshold(float pfa); -}; -#endif /* GALILEO_E5AX_2MS_PCPS_ACQUISITION_H_ */ diff --git a/src/algorithms/acquisition/gnuradio_blocks/CMakeLists.txt b/src/algorithms/acquisition/gnuradio_blocks/CMakeLists.txt index f9dac7a74..466bfe6d4 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/CMakeLists.txt +++ b/src/algorithms/acquisition/gnuradio_blocks/CMakeLists.txt @@ -25,9 +25,7 @@ if(OPENCL_FOUND) pcps_tong_acquisition_cc.cc pcps_cccwsr_acquisition_cc.cc galileo_pcps_8ms_acquisition_cc.cc - galileo_e5a_pilot_3ms_acquisition_cc.cc - galileo_e5ax_2ms_pcps_acquisition_cc.cc - galileo_e5a_3ms_noncoherent_iq_acquisition_cc.cc + galileo_e5a_noncoherent_iq_acquisition_caf_cc.cc pcps_opencl_acquisition_cc.cc # Needs OpenCL ) else(OPENCL_FOUND) @@ -39,9 +37,7 @@ else(OPENCL_FOUND) pcps_tong_acquisition_cc.cc pcps_cccwsr_acquisition_cc.cc galileo_pcps_8ms_acquisition_cc.cc - galileo_e5a_pilot_3ms_acquisition_cc.cc - galileo_e5ax_2ms_pcps_acquisition_cc.cc - galileo_e5a_3ms_noncoherent_iq_acquisition_cc.cc + galileo_e5a_noncoherent_iq_acquisition_caf_cc.cc ) endif(OPENCL_FOUND) diff --git a/src/algorithms/acquisition/gnuradio_blocks/galileo_e5a_3ms_noncoherent_iq_acquisition_cc.cc b/src/algorithms/acquisition/gnuradio_blocks/galileo_e5a_3ms_noncoherent_iq_acquisition_cc.cc deleted file mode 100644 index e28dd7a62..000000000 --- a/src/algorithms/acquisition/gnuradio_blocks/galileo_e5a_3ms_noncoherent_iq_acquisition_cc.cc +++ /dev/null @@ -1,592 +0,0 @@ -/*! - * \file galileo_e5a_3ms_noncoherent_iq_acquisition_cc.cc - * \brief Adapts a PCPS acquisition block to an AcquisitionInterface for - * Galileo E5a data and pilot Signals - * \author Marc Sales, 2014. marcsales92(at)gmail.com - * - * ------------------------------------------------------------------------- - * - * Copyright (C) 2010-2014 (see AUTHORS file for a list of contributors) - * - * GNSS-SDR is a software defined Global Navigation - * Satellite Systems receiver - * - * This file is part of GNSS-SDR. - * - * GNSS-SDR is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * at your option) any later version. - * - * GNSS-SDR is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNSS-SDR. If not, see . - * - * ------------------------------------------------------------------------- - */ - -#include "galileo_e5a_3ms_noncoherent_iq_acquisition_cc.h" -#include -#include -#include -#include -#include -#include "gnss_signal_processing.h" -#include "control_message_factory.h" - -using google::LogMessage; - -galileo_e5a_3ms_noncoherentIQ_acquisition_cc_sptr galileo_e5a_3ms_noncoherentIQ_make_acquisition_cc( - unsigned int sampled_ms, - unsigned int max_dwells, - unsigned int doppler_max, long freq, long fs_in, - int samples_per_ms, int samples_per_code, - bool bit_transition_flag, - gr::msg_queue::sptr queue, bool dump, - std::string dump_filename) -{ - - return galileo_e5a_3ms_noncoherentIQ_acquisition_cc_sptr( - new galileo_e5a_3ms_noncoherentIQ_acquisition_cc(sampled_ms, max_dwells, doppler_max, freq, fs_in, samples_per_ms, - samples_per_code, bit_transition_flag, queue, dump, dump_filename)); -} - -galileo_e5a_3ms_noncoherentIQ_acquisition_cc::galileo_e5a_3ms_noncoherentIQ_acquisition_cc( - unsigned int sampled_ms, - unsigned int max_dwells, - unsigned int doppler_max, long freq, long fs_in, - int samples_per_ms, int samples_per_code, - bool bit_transition_flag, - gr::msg_queue::sptr queue, bool dump, - std::string dump_filename) : - gr::block("galileo_e5a_3ms_noncoherentIQ_acquisition_cc", - gr::io_signature::make(1, 1, sizeof(gr_complex)), - gr::io_signature::make(0, 0, sizeof(gr_complex))) - //gr::io_signature::make(1, 1, sizeof(gr_complex) * 3 * samples_per_ms), - //gr::io_signature::make(0, 0, sizeof(gr_complex) * 3 * samples_per_ms)) -{ - //this->set_relative_rate(1.0/1*samples_per_ms); - d_sample_counter = 0; // SAMPLE COUNTER - d_active = false; - d_state = 0; - d_queue = queue; - d_freq = freq; - d_fs_in = fs_in; - d_samples_per_ms = samples_per_ms; - d_samples_per_code = samples_per_code; - d_max_dwells = max_dwells; - d_well_count = 0; - d_doppler_max = doppler_max; - d_fft_size = sampled_ms * d_samples_per_ms; - d_mag = 0; - d_input_power = 0.0; - d_num_doppler_bins = 0; - d_bit_transition_flag = bit_transition_flag; - d_buffer_count=0; - d_gr_stream_buffer = 7000; // number of samples entering each general work, arbitrary number. Works with all numbers below gnu radio maximum buffer - - //todo: do something if posix_memalign fails - if (posix_memalign((void**)&d_inbuffer, 16, ceil((double)d_fft_size/(double)d_gr_stream_buffer)*d_gr_stream_buffer * sizeof(gr_complex)) == 0){}; - if (posix_memalign((void**)&d_fft_code_I_A, 16, d_fft_size * sizeof(gr_complex)) == 0){}; - if (posix_memalign((void**)&d_fft_code_I_B, 16, d_fft_size * sizeof(gr_complex)) == 0){}; - if (posix_memalign((void**)&d_fft_code_Q_A, 16, d_fft_size * sizeof(gr_complex)) == 0){}; - if (posix_memalign((void**)&d_fft_code_Q_B, 16, d_fft_size * sizeof(gr_complex)) == 0){}; - if (posix_memalign((void**)&d_magnitudeIA, 16, d_fft_size * sizeof(float)) == 0){}; - if (posix_memalign((void**)&d_magnitudeIB, 16, d_fft_size * sizeof(float)) == 0){}; - if (posix_memalign((void**)&d_magnitudeQA, 16, d_fft_size * sizeof(float)) == 0){}; - if (posix_memalign((void**)&d_magnitudeQB, 16, d_fft_size * sizeof(float)) == 0){}; - - // Direct FFT - d_fft_if = new gr::fft::fft_complex(d_fft_size, true); - - // Inverse FFT - d_ifft = new gr::fft::fft_complex(d_fft_size, false); -// d_ifft = new gr::fft::fft_complex(d_fft_size, true); - - // For dumping samples into a file - d_dump = dump; - d_dump_filename = dump_filename; -} - -galileo_e5a_3ms_noncoherentIQ_acquisition_cc::~galileo_e5a_3ms_noncoherentIQ_acquisition_cc() -{ - if (d_num_doppler_bins > 0) - { - for (unsigned int i = 0; i < d_num_doppler_bins; i++) - { - free(d_grid_doppler_wipeoffs[i]); - } - delete[] d_grid_doppler_wipeoffs; - } - - free(d_fft_code_I_A); - free(d_fft_code_I_B); - free(d_fft_code_Q_A); - free(d_fft_code_Q_B); - free(d_magnitudeIA); - free(d_magnitudeIB); - free(d_magnitudeQA); - free(d_magnitudeQB); - - - delete d_fft_if; - delete d_ifft; - - - if (d_dump) - { - d_dump_file.close(); - } -} - -void galileo_e5a_3ms_noncoherentIQ_acquisition_cc::forecast (int noutput_items, - gr_vector_int &ninput_items_required) -{ - ninput_items_required[0] = d_gr_stream_buffer ; //set the required available samples in each call -} - -void galileo_e5a_3ms_noncoherentIQ_acquisition_cc::set_local_code(std::complex * codeI, std::complex * codeQ ) -{ - // DATA SIGNAL - // Three replicas of data primary code. CODE A: (1,1,1) - memcpy(d_fft_if->get_inbuf(), codeI, sizeof(gr_complex)*d_fft_size); - - d_fft_if->execute(); // We need the FFT of local code - - //Conjugate the local code - if (is_unaligned()) - { - volk_32fc_conjugate_32fc_u(d_fft_code_I_A,d_fft_if->get_outbuf(),d_fft_size); - } - else - { - volk_32fc_conjugate_32fc_a(d_fft_code_I_A,d_fft_if->get_outbuf(),d_fft_size); - } - - // CODE B: First replica is inverted (0,1,1) - volk_32fc_s32fc_multiply_32fc_a(&(d_fft_if->get_inbuf())[0], - &codeI[0], gr_complex(-1,0), - d_samples_per_code); - d_fft_if->execute(); // We need the FFT of local code - - //Conjugate the local code - if (is_unaligned()) - { - volk_32fc_conjugate_32fc_u(d_fft_code_I_B,d_fft_if->get_outbuf(),d_fft_size); - } - else - { - volk_32fc_conjugate_32fc_a(d_fft_code_I_B,d_fft_if->get_outbuf(),d_fft_size); - } - - // SAME FOR PILOT SIGNAL - // Three replicas of pilot primary code. CODE A: (1,1,1) - memcpy(d_fft_if->get_inbuf(), codeQ, sizeof(gr_complex)*d_fft_size); - - d_fft_if->execute(); // We need the FFT of local code - - //Conjugate the local code - if (is_unaligned()) - { - volk_32fc_conjugate_32fc_u(d_fft_code_Q_A,d_fft_if->get_outbuf(),d_fft_size); - } - else - { - volk_32fc_conjugate_32fc_a(d_fft_code_Q_A,d_fft_if->get_outbuf(),d_fft_size); - } - - // CODE B: First replica is inverted (0,1,1) - volk_32fc_s32fc_multiply_32fc_a(&(d_fft_if->get_inbuf())[0], - &codeQ[0], gr_complex(-1,0), - d_samples_per_code); - d_fft_if->execute(); // We need the FFT of local code - - //Conjugate the local code - if (is_unaligned()) - { - volk_32fc_conjugate_32fc_u(d_fft_code_Q_B,d_fft_if->get_outbuf(),d_fft_size); - } - else - { - volk_32fc_conjugate_32fc_a(d_fft_code_Q_B,d_fft_if->get_outbuf(),d_fft_size); - } - - -} - -void galileo_e5a_3ms_noncoherentIQ_acquisition_cc::init() -{ - d_gnss_synchro->Acq_delay_samples = 0.0; - d_gnss_synchro->Acq_doppler_hz = 0.0; - d_gnss_synchro->Acq_samplestamp_samples = 0; - d_mag = 0.0; - d_input_power = 0.0; - - // Count the number of bins - d_num_doppler_bins = 0; - for (int doppler = (int)(-d_doppler_max); - doppler <= (int)d_doppler_max; - doppler += d_doppler_step) - { - d_num_doppler_bins++; - } - - // Create the carrier Doppler wipeoff signals - d_grid_doppler_wipeoffs = new gr_complex*[d_num_doppler_bins]; - for (unsigned int doppler_index = 0; doppler_index < d_num_doppler_bins; doppler_index++) - { - if (posix_memalign((void**)&(d_grid_doppler_wipeoffs[doppler_index]), 16, - d_fft_size * sizeof(gr_complex)) == 0){}; - - int doppler = -(int)d_doppler_max + d_doppler_step*doppler_index; - complex_exp_gen_conj(d_grid_doppler_wipeoffs[doppler_index], - d_freq + doppler, d_fs_in, d_fft_size); - } -} - - -int galileo_e5a_3ms_noncoherentIQ_acquisition_cc::general_work(int noutput_items, - gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - /* - * By J.Arribas, L.Esteve, M.Molina and M.Sales - * Acquisition strategy (Kay Borre book + CFAR threshold): - * 1. Compute the input signal power estimation - * 2. Doppler serial search loop - * 3. Perform the FFT-based circular convolution (parallel time search) - * 4. Record the maximum peak and the associated synchronization parameters - * 5. Compute the test statistics and compare to the threshold - * 6. Declare positive or negative acquisition using a message queue - */ - - int acquisition_message = -1; //0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL - /* States: 0 Reset and load first stream - * 1 Load the buffer until it reaches fft_size - * 2 Acquisition algorithm - * 3 Positive acquisition - * 4 Negative acquisition - */ - - d_sample_counter += d_gr_stream_buffer; - std::cout << d_state <<" "<< d_sample_counter << std::endl; - switch (d_state) - { - case 0: - { - if (d_active) - { - //restart acquisition variables - d_gnss_synchro->Acq_delay_samples = 0.0; - d_gnss_synchro->Acq_doppler_hz = 0.0; - d_gnss_synchro->Acq_samplestamp_samples = 0; - d_well_count = 0; - d_mag = 0.0; - d_input_power = 0.0; - d_test_statistics = 0.0; - d_state = 1; - } - const gr_complex *in = (const gr_complex *)input_items[0]; //Get the input samples pointer - memcpy(&d_inbuffer[d_buffer_count*d_gr_stream_buffer], in, sizeof(gr_complex)*d_gr_stream_buffer); - d_buffer_count++; - //d_sample_counter += ninput_items[0]; // sample counter - //consume_each(ninput_items[0]); - break; - } - case 1: - { - const gr_complex *in = (const gr_complex *)input_items[0]; //Get the input samples pointer - memcpy(&d_inbuffer[d_buffer_count*d_gr_stream_buffer], in, sizeof(gr_complex)*d_gr_stream_buffer); - d_buffer_count++; - if (d_buffer_count*d_gr_stream_buffer >= d_fft_size-d_gr_stream_buffer) - { - d_state=2; - } -// volk_32fc_x2_multiply_32fc_a(d_fft_if->get_inbuf(), in, -// d_grid_doppler_wipeoffs[0], d_fft_size); - //consume_each(7000); - break; - } - case 2: - { - // Fill last part of the buffer and reset counter - const gr_complex *in = (const gr_complex *)input_items[0]; //Get the input samples pointer - memcpy(&d_inbuffer[d_buffer_count*d_gr_stream_buffer], in, sizeof(gr_complex)*d_gr_stream_buffer); - d_buffer_count = 0; - // initialize acquisition algorithm - int doppler; - unsigned int indext = 0; - unsigned int indext_IA = 0; - unsigned int indext_IB = 0; - unsigned int indext_QA = 0; - unsigned int indext_QB = 0; - float magt = 0.0; - float magt_IA = 0.0; - float magt_IB = 0.0; - float magt_QA = 0.0; - float magt_QB = 0.0; - //const gr_complex *in = (const gr_complex *)input_items[0]; //Get the input samples pointer - float fft_normalization_factor = (float)d_fft_size * (float)d_fft_size; - d_input_power = 0.0; - d_mag = 0.0; - int comb = 0; - - //d_sample_counter += d_fft_size; // sample counter - - d_well_count++; - - DLOG(INFO) << "Channel: " << d_channel - << " , doing acquisition of satellite: " << d_gnss_synchro->System << " "<< d_gnss_synchro->PRN - << " ,sample stamp: " << d_sample_counter << ", threshold: " - << d_threshold << ", doppler_max: " << d_doppler_max - << ", doppler_step: " << d_doppler_step; - - // 1- Compute the input signal power estimation - volk_32fc_magnitude_squared_32f_a(d_magnitudeIA, d_inbuffer, d_fft_size); - volk_32f_accumulator_s32f_a(&d_input_power, d_magnitudeIA, d_fft_size); - d_input_power /= (float)d_fft_size; - - // 2- Doppler frequency search loop - for (unsigned int doppler_index=0;doppler_indexget_inbuf(), d_inbuffer, - d_grid_doppler_wipeoffs[doppler_index], d_fft_size); - - // 3- Perform the FFT-based convolution (parallel time search) - // Compute the FFT of the carrier wiped--off incoming signal - d_fft_if->execute(); - - // CODE IA - // Multiply carrier wiped--off, Fourier transformed incoming signal - // with the local FFT'd code reference using SIMD operations with VOLK library - volk_32fc_x2_multiply_32fc_a(d_ifft->get_inbuf(), - d_fft_if->get_outbuf(), d_fft_code_I_A, d_fft_size); - - // compute the inverse FFT - d_ifft->execute(); - - // Search maximum - volk_32fc_magnitude_squared_32f_a(d_magnitudeIA, d_ifft->get_outbuf(), d_fft_size); - volk_32f_index_max_16u_a(&indext_IA, d_magnitudeIA, d_fft_size); - - // Normalize the maximum value to correct the scale factor introduced by FFTW - magt_IA = d_magnitudeIA[indext_IA] / (fft_normalization_factor * fft_normalization_factor); - - // only 1 ms - //magt=magt_A; - //indext=indext_A; - - - // REPEAT FOR ALL CODES. CODE_IB - volk_32fc_x2_multiply_32fc_a(d_ifft->get_inbuf(), - d_fft_if->get_outbuf(), d_fft_code_I_B, d_fft_size); - d_ifft->execute(); - volk_32fc_magnitude_squared_32f_a(d_magnitudeIB, d_ifft->get_outbuf(), d_fft_size); - volk_32f_index_max_16u_a(&indext_IB, d_magnitudeIB, d_fft_size); - magt_IB = d_magnitudeIB[indext_IB] / (fft_normalization_factor * fft_normalization_factor); - - // REPEAT FOR ALL CODES. CODE_QA - volk_32fc_x2_multiply_32fc_a(d_ifft->get_inbuf(), - d_fft_if->get_outbuf(), d_fft_code_Q_A, d_fft_size); - d_ifft->execute(); - volk_32fc_magnitude_squared_32f_a(d_magnitudeQA, d_ifft->get_outbuf(), d_fft_size); - volk_32f_index_max_16u_a(&indext_QA, d_magnitudeQA, d_fft_size); - magt_QA = d_magnitudeQA[indext_QA] / (fft_normalization_factor * fft_normalization_factor); - - // REPEAT FOR ALL CODES. CODE_QB - volk_32fc_x2_multiply_32fc_a(d_ifft->get_inbuf(), - d_fft_if->get_outbuf(), d_fft_code_Q_B, d_fft_size); - d_ifft->execute(); - volk_32fc_magnitude_squared_32f_a(d_magnitudeQB, d_ifft->get_outbuf(), d_fft_size); - volk_32f_index_max_16u_a(&indext_QB, d_magnitudeQB, d_fft_size); - magt_QB = d_magnitudeIB[indext_QB] / (fft_normalization_factor * fft_normalization_factor); - - // Integrate noncoherently the two best combinations (I² + Q²) - // and store the result in the I channel. - if (magt_IA >= magt_IB) - { - if (magt_QA >= magt_QB) - { - for (unsigned int i=0; i= magt_QB) - { - for (unsigned int i=0; iAcq_delay_samples = (double)(indext % d_samples_per_code); - d_gnss_synchro->Acq_doppler_hz = (double)doppler; - d_gnss_synchro->Acq_samplestamp_samples = d_sample_counter; - - // 5- Compute the test statistics and compare to the threshold - //d_test_statistics = 2 * d_fft_size * d_mag / d_input_power; - d_test_statistics = d_mag / d_input_power; - } - } - - // Record results to file if required - if (d_dump) - { - std::stringstream filename; - std::streamsize n = sizeof(float) * (d_fft_size); // noncomplex file write - filename.str(""); - filename << "../data/test_statistics_" << d_gnss_synchro->System - <<"_" << d_gnss_synchro->Signal << "_sat_" - << d_gnss_synchro->PRN << "_doppler_" << doppler << ".dat"; - d_dump_file.open(filename.str().c_str(), std::ios::out | std::ios::binary); - if (magt_IA >= magt_IB) - { - d_dump_file.write((char*)d_magnitudeIA, n); - } - else - { - d_dump_file.write((char*)d_magnitudeIB, n); - } - //d_dump_file.write((char*)d_magnitudeIA, n); - d_dump_file.close(); - } - } - - if (!d_bit_transition_flag) - { - if (d_test_statistics > d_threshold) - { - d_state = 3; // Positive acquisition - } - else if (d_well_count == d_max_dwells) - { - d_state = 4; // Negative acquisition - } - else - { - d_state = 2; - } - } - else - { - if (d_well_count == d_max_dwells) // d_max_dwells = 2 - { - if (d_test_statistics > d_threshold) - { - d_state = 3; // Positive acquisition - } - else - { - d_state = 4; // Negative acquisition - } - } - else - { - d_state = 2; - } - } - - //consume_each(1); - //consume_each(d_fft_size); - break; - } - case 3: - { - // 6.1- Declare positive acquisition using a message queue - DLOG(INFO) << "positive acquisition"; - DLOG(INFO) << "satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN; - DLOG(INFO) << "sample_stamp " << d_sample_counter; - DLOG(INFO) << "test statistics value " << d_test_statistics; - DLOG(INFO) << "test statistics threshold " << d_threshold; - DLOG(INFO) << "code phase " << d_gnss_synchro->Acq_delay_samples; - DLOG(INFO) << "doppler " << d_gnss_synchro->Acq_doppler_hz; - DLOG(INFO) << "magnitude " << d_mag; - DLOG(INFO) << "input signal power " << d_input_power; - - d_active = false; - d_state = 0; - - //d_sample_counter += 7000; - //d_sample_counter += d_fft_size * ninput_items[0]; // sample counter - //consume_each(ninput_items[0]); - //consume_each(d_fft_size); - acquisition_message = 1; - d_channel_internal_queue->push(acquisition_message); - break; - } - case 4: - { - // 6.2- Declare negative acquisition using a message queue - DLOG(INFO) << "negative acquisition"; - DLOG(INFO) << "satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN; - DLOG(INFO) << "sample_stamp " << d_sample_counter; - DLOG(INFO) << "test statistics value " << d_test_statistics; - DLOG(INFO) << "test statistics threshold " << d_threshold; - DLOG(INFO) << "code phase " << d_gnss_synchro->Acq_delay_samples; - DLOG(INFO) << "doppler " << d_gnss_synchro->Acq_doppler_hz; - DLOG(INFO) << "magnitude " << d_mag; - DLOG(INFO) << "input signal power " << d_input_power; - - d_active = false; - d_state = 0; - - //d_sample_counter += 7000; - //d_sample_counter += d_fft_size * ninput_items[0]; // sample counter - //consume_each(ninput_items[0]); - //consume_each(d_fft_size); - acquisition_message = 2; - d_channel_internal_queue->push(acquisition_message); - break; - } - } - - consume_each(d_gr_stream_buffer); - return 0; -} - diff --git a/src/algorithms/acquisition/gnuradio_blocks/galileo_e5a_noncoherent_iq_acquisition_caf_cc.cc b/src/algorithms/acquisition/gnuradio_blocks/galileo_e5a_noncoherent_iq_acquisition_caf_cc.cc new file mode 100644 index 000000000..28b334285 --- /dev/null +++ b/src/algorithms/acquisition/gnuradio_blocks/galileo_e5a_noncoherent_iq_acquisition_caf_cc.cc @@ -0,0 +1,771 @@ +/*! + * \file galileo_e5a_noncoherent_iq_acquisition_caf_cc.cc + * \brief Adapts a PCPS acquisition block to an AcquisitionInterface for + * Galileo E5a data and pilot Signals + * \author Marc Sales, 2014. marcsales92(at)gmail.com + * \based on work from: + *
    + *
  • 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-2014 (see AUTHORS file for a list of contributors) + * + * GNSS-SDR is a software defined Global Navigation + * Satellite Systems receiver + * + * This file is part of GNSS-SDR. + * + * GNSS-SDR is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * at your option) any later version. + * + * GNSS-SDR is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNSS-SDR. If not, see . + * + * ------------------------------------------------------------------------- + */ + +#include "galileo_e5a_noncoherent_iq_acquisition_caf_cc.h" +#include +#include +#include +#include +#include +#include "gnss_signal_processing.h" +#include "control_message_factory.h" + +using google::LogMessage; + +galileo_e5a_noncoherentIQ_acquisition_caf_cc_sptr galileo_e5a_noncoherentIQ_make_acquisition_caf_cc( + unsigned int sampled_ms, + unsigned int max_dwells, + unsigned int doppler_max, long freq, long fs_in, + int samples_per_ms, int samples_per_code, + bool bit_transition_flag, + gr::msg_queue::sptr queue, bool dump, + std::string dump_filename, + bool both_signal_components_, + int CAF_window_hz_) +{ + + return galileo_e5a_noncoherentIQ_acquisition_caf_cc_sptr( + new galileo_e5a_noncoherentIQ_acquisition_caf_cc(sampled_ms, max_dwells, doppler_max, freq, fs_in, samples_per_ms, + samples_per_code, bit_transition_flag, queue, dump, dump_filename, both_signal_components_, CAF_window_hz_)); +} + +galileo_e5a_noncoherentIQ_acquisition_caf_cc::galileo_e5a_noncoherentIQ_acquisition_caf_cc( + unsigned int sampled_ms, + unsigned int max_dwells, + unsigned int doppler_max, long freq, long fs_in, + int samples_per_ms, int samples_per_code, + bool bit_transition_flag, + gr::msg_queue::sptr queue, bool dump, + std::string dump_filename, + bool both_signal_components_, + int CAF_window_hz_) : + gr::block("galileo_e5a_noncoherentIQ_acquisition_caf_cc", + gr::io_signature::make(1, 1, sizeof(gr_complex)), + gr::io_signature::make(0, 0, sizeof(gr_complex))) +{ + d_sample_counter = 0; // SAMPLE COUNTER + d_active = false; + d_state = 0; + d_queue = queue; + d_freq = freq; + d_fs_in = fs_in; + d_samples_per_ms = samples_per_ms; + d_samples_per_code = samples_per_code; + d_max_dwells = max_dwells; + d_well_count = 0; + d_doppler_max = doppler_max; + d_fft_size = sampled_ms * d_samples_per_ms; + d_mag = 0; + d_input_power = 0.0; + d_num_doppler_bins = 0; + d_bit_transition_flag = bit_transition_flag; + d_buffer_count=0; + d_both_signal_components = both_signal_components_; +// d_CAF_filter = true; +// d_CAF_window_hz = 6000; + d_CAF_window_hz = CAF_window_hz_; + + //todo: do something if posix_memalign fails + if (posix_memalign((void**)&d_inbuffer, 16, d_fft_size * sizeof(gr_complex)) == 0){}; + if (posix_memalign((void**)&d_fft_code_I_A, 16, d_fft_size * sizeof(gr_complex)) == 0){}; + if (posix_memalign((void**)&d_magnitudeIA, 16, d_fft_size * sizeof(float)) == 0){}; + + if (d_both_signal_components == true) + { + if (posix_memalign((void**)&d_fft_code_Q_A, 16, d_fft_size * sizeof(gr_complex)) == 0){}; + if (posix_memalign((void**)&d_magnitudeQA, 16, d_fft_size * sizeof(float)) == 0){}; + } + // IF INTEGRATION TIME > 1 + if (d_samples_per_ms != d_fft_size) + { + if (posix_memalign((void**)&d_fft_code_I_B, 16, d_fft_size * sizeof(gr_complex)) == 0){}; + if (posix_memalign((void**)&d_magnitudeIB, 16, d_fft_size * sizeof(float)) == 0){}; + if (d_both_signal_components == true) + { + if (posix_memalign((void**)&d_fft_code_Q_B, 16, d_fft_size * sizeof(gr_complex)) == 0){}; + if (posix_memalign((void**)&d_magnitudeQB, 16, d_fft_size * sizeof(float)) == 0){}; + } + } + +// if (posix_memalign((void**)&d_fft_code_Q_A, 16, d_fft_size * sizeof(gr_complex)) == 0){}; +// if (posix_memalign((void**)&d_magnitudeQA, 16, d_fft_size * sizeof(float)) == 0){}; +// if (posix_memalign((void**)&d_fft_code_I_B, 16, d_fft_size * sizeof(gr_complex)) == 0){}; +// if (posix_memalign((void**)&d_magnitudeIB, 16, d_fft_size * sizeof(float)) == 0){}; +// if (posix_memalign((void**)&d_fft_code_Q_B, 16, d_fft_size * sizeof(gr_complex)) == 0){}; +// if (posix_memalign((void**)&d_magnitudeQB, 16, d_fft_size * sizeof(float)) == 0){}; + + // Direct FFT + d_fft_if = new gr::fft::fft_complex(d_fft_size, true); + + // Inverse FFT + d_ifft = new gr::fft::fft_complex(d_fft_size, false); + + // For dumping samples into a file + d_dump = dump; + d_dump_filename = dump_filename; +} + +galileo_e5a_noncoherentIQ_acquisition_caf_cc::~galileo_e5a_noncoherentIQ_acquisition_caf_cc() +{ + if (d_num_doppler_bins > 0) + { + for (unsigned int i = 0; i < d_num_doppler_bins; i++) + { + free(d_grid_doppler_wipeoffs[i]); + } + delete[] d_grid_doppler_wipeoffs; + } + + free(d_fft_code_I_A); + free(d_magnitudeIA); + if (d_both_signal_components == true) + { + free(d_fft_code_Q_A); + free(d_magnitudeQA); + } + // IF INTEGRATION TIME > 1 + if (d_samples_per_ms != d_fft_size) + { + free(d_fft_code_I_B); + free(d_magnitudeIB); + if (d_both_signal_components == true) + { + free(d_fft_code_Q_B); + free(d_magnitudeQB); + } + } + + delete d_fft_if; + delete d_ifft; + + + if (d_dump) + { + d_dump_file.close(); + } +} + + +void galileo_e5a_noncoherentIQ_acquisition_caf_cc::set_local_code(std::complex * codeI, std::complex * codeQ ) +{ + // DATA SIGNAL + // Three replicas of data primary code. CODE A: (1,1,1) + memcpy(d_fft_if->get_inbuf(), codeI, sizeof(gr_complex)*d_fft_size); + + d_fft_if->execute(); // We need the FFT of local code + + //Conjugate the local code + if (is_unaligned()) + { + volk_32fc_conjugate_32fc_u(d_fft_code_I_A,d_fft_if->get_outbuf(),d_fft_size); + } + else + { + volk_32fc_conjugate_32fc_a(d_fft_code_I_A,d_fft_if->get_outbuf(),d_fft_size); + } + // SAME FOR PILOT SIGNAL + if (d_both_signal_components == true) + { + // Three replicas of pilot primary code. CODE A: (1,1,1) + memcpy(d_fft_if->get_inbuf(), codeQ, sizeof(gr_complex)*d_fft_size); + + d_fft_if->execute(); // We need the FFT of local code + + //Conjugate the local code + if (is_unaligned()) + { + volk_32fc_conjugate_32fc_u(d_fft_code_Q_A,d_fft_if->get_outbuf(),d_fft_size); + } + else + { + volk_32fc_conjugate_32fc_a(d_fft_code_Q_A,d_fft_if->get_outbuf(),d_fft_size); + } + } + // IF INTEGRATION TIME > 1 code, we need to evaluate the other possible combination + // Note: max integration time allowed = 3ms (dealt in adapter) + if (d_samples_per_ms != d_fft_size) + { + // DATA CODE B: First replica is inverted (0,1,1) + volk_32fc_s32fc_multiply_32fc_a(&(d_fft_if->get_inbuf())[0], + &codeI[0], gr_complex(-1,0), + d_samples_per_code); + d_fft_if->execute(); // We need the FFT of local code + + //Conjugate the local code + if (is_unaligned()) + { + volk_32fc_conjugate_32fc_u(d_fft_code_I_B,d_fft_if->get_outbuf(),d_fft_size); + } + else + { + volk_32fc_conjugate_32fc_a(d_fft_code_I_B,d_fft_if->get_outbuf(),d_fft_size); + } + if (d_both_signal_components == true) + { + // PILOT CODE B: First replica is inverted (0,1,1) + volk_32fc_s32fc_multiply_32fc_a(&(d_fft_if->get_inbuf())[0], + &codeQ[0], gr_complex(-1,0), + d_samples_per_code); + d_fft_if->execute(); // We need the FFT of local code + + //Conjugate the local code + if (is_unaligned()) + { + volk_32fc_conjugate_32fc_u(d_fft_code_Q_B,d_fft_if->get_outbuf(),d_fft_size); + } + else + { + volk_32fc_conjugate_32fc_a(d_fft_code_Q_B,d_fft_if->get_outbuf(),d_fft_size); + } + } + } +} + +void galileo_e5a_noncoherentIQ_acquisition_caf_cc::init() +{ + d_gnss_synchro->Acq_delay_samples = 0.0; + d_gnss_synchro->Acq_doppler_hz = 0.0; + d_gnss_synchro->Acq_samplestamp_samples = 0; + d_mag = 0.0; + d_input_power = 0.0; + + // Count the number of bins + d_num_doppler_bins = 0; + for (int doppler = (int)(-d_doppler_max); + doppler <= (int)d_doppler_max; + doppler += d_doppler_step) + { + d_num_doppler_bins++; + } + + // Create the carrier Doppler wipeoff signals + d_grid_doppler_wipeoffs = new gr_complex*[d_num_doppler_bins]; + for (unsigned int doppler_index = 0; doppler_index < d_num_doppler_bins; doppler_index++) + { + if (posix_memalign((void**)&(d_grid_doppler_wipeoffs[doppler_index]), 16, + d_fft_size * sizeof(gr_complex)) == 0){}; + + int doppler = -(int)d_doppler_max + d_doppler_step*doppler_index; + complex_exp_gen_conj(d_grid_doppler_wipeoffs[doppler_index], + d_freq + doppler, d_fs_in, d_fft_size); + } + + /* CAF Filtering to resolve doppler ambiguity. Phase and quadrature must be processed + * separately before non-coherent integration */ +// if (d_CAF_filter) + if (d_CAF_window_hz > 0) + { + if (posix_memalign((void**)&d_CAF_vector, 16, d_num_doppler_bins * sizeof(float)) == 0){}; + if (posix_memalign((void**)&d_CAF_vector_I, 16, d_num_doppler_bins * sizeof(float)) == 0){}; + if (d_both_signal_components == true) + { + if (posix_memalign((void**)&d_CAF_vector_Q, 16, d_num_doppler_bins * sizeof(float)) == 0){}; + } + } +} + + +int galileo_e5a_noncoherentIQ_acquisition_caf_cc::general_work(int noutput_items, + gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + /* + * By J.Arribas, L.Esteve, M.Molina and M.Sales + * Acquisition strategy (Kay Borre book + CFAR threshold): + * 1. Compute the input signal power estimation + * 2. Doppler serial search loop + * 3. Perform the FFT-based circular convolution (parallel time search) + * 4. OPTIONAL: CAF filter to avoid doppler ambiguity + * 5. Record the maximum peak and the associated synchronization parameters + * 6. Compute the test statistics and compare to the threshold + * 7. Declare positive or negative acquisition using a message queue + */ + + int acquisition_message = -1; //0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL + /* States: 0 Stop Channel + * 1 Load the buffer until it reaches fft_size + * 2 Acquisition algorithm + * 3 Positive acquisition + * 4 Negative acquisition + */ + switch (d_state) + { + case 0: + { + if (d_active) + { + //restart acquisition variables + d_gnss_synchro->Acq_delay_samples = 0.0; + d_gnss_synchro->Acq_doppler_hz = 0.0; + d_gnss_synchro->Acq_samplestamp_samples = 0; + d_well_count = 0; + d_mag = 0.0; + d_input_power = 0.0; + d_test_statistics = 0.0; + d_state = 1; + } + d_sample_counter += ninput_items[0]; // sample counter + consume_each(ninput_items[0]); + + break; + } + case 1: + { + const gr_complex *in = (const gr_complex *)input_items[0]; //Get the input samples pointer + unsigned int buff_increment; + if (ninput_items[0]+d_buffer_count <= d_fft_size) + { + buff_increment = ninput_items[0]; + } + else + { + buff_increment = (d_fft_size-d_buffer_count); + } + memcpy(&d_inbuffer[d_buffer_count], in, sizeof(gr_complex)*buff_increment); + // If buffer will be full in next iteration + if (d_buffer_count >= d_fft_size-d_gr_stream_buffer) + { + d_state=2; + } + d_buffer_count += buff_increment; + d_sample_counter += buff_increment; // sample counter + consume_each(buff_increment); + break; + } + case 2: + { + // Fill last part of the buffer and reset counter + const gr_complex *in = (const gr_complex *)input_items[0]; //Get the input samples pointer + if (d_buffer_count < d_fft_size) + { + memcpy(&d_inbuffer[d_buffer_count], in, sizeof(gr_complex)*(d_fft_size-d_buffer_count)); + } + d_sample_counter += d_fft_size-d_buffer_count; // sample counter + + // initialize acquisition algorithm + int doppler; + unsigned int indext = 0; + unsigned int indext_IA = 0; + unsigned int indext_IB = 0; + unsigned int indext_QA = 0; + unsigned int indext_QB = 0; + float magt = 0.0; + float magt_IA = 0.0; + float magt_IB = 0.0; + float magt_QA = 0.0; + float magt_QB = 0.0; + float fft_normalization_factor = (float)d_fft_size * (float)d_fft_size; + 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_a(d_magnitudeIA, d_inbuffer, d_fft_size); + volk_32f_accumulator_s32f_a(&d_input_power, d_magnitudeIA, d_fft_size); + d_input_power /= (float)d_fft_size; + + // 2- Doppler frequency search loop + for (unsigned int doppler_index=0;doppler_indexget_inbuf(), d_inbuffer, + d_grid_doppler_wipeoffs[doppler_index], d_fft_size); + + // 3- Perform the FFT-based convolution (parallel time search) + // Compute the FFT of the carrier wiped--off incoming signal + d_fft_if->execute(); + + // CODE IA + // Multiply carrier wiped--off, Fourier transformed incoming signal + // with the local FFT'd code reference using SIMD operations with VOLK library + volk_32fc_x2_multiply_32fc_a(d_ifft->get_inbuf(), + d_fft_if->get_outbuf(), d_fft_code_I_A, d_fft_size); + + // compute the inverse FFT + d_ifft->execute(); + + // Search maximum + volk_32fc_magnitude_squared_32f_a(d_magnitudeIA, d_ifft->get_outbuf(), d_fft_size); + volk_32f_index_max_16u_a(&indext_IA, d_magnitudeIA, d_fft_size); + + // Normalize the maximum value to correct the scale factor introduced by FFTW + magt_IA = d_magnitudeIA[indext_IA] / (fft_normalization_factor * fft_normalization_factor); + + if (d_both_signal_components == true) + { + // REPEAT FOR ALL CODES. CODE_QA + volk_32fc_x2_multiply_32fc_a(d_ifft->get_inbuf(), + d_fft_if->get_outbuf(), d_fft_code_Q_A, d_fft_size); + d_ifft->execute(); + volk_32fc_magnitude_squared_32f_a(d_magnitudeQA, d_ifft->get_outbuf(), d_fft_size); + volk_32f_index_max_16u_a(&indext_QA, d_magnitudeQA, d_fft_size); + magt_QA = d_magnitudeQA[indext_QA] / (fft_normalization_factor * fft_normalization_factor); + } + if (d_samples_per_ms != d_fft_size) // If Integration time > 1 code + { + // REPEAT FOR ALL CODES. CODE_IB + volk_32fc_x2_multiply_32fc_a(d_ifft->get_inbuf(), + d_fft_if->get_outbuf(), d_fft_code_I_B, d_fft_size); + d_ifft->execute(); + volk_32fc_magnitude_squared_32f_a(d_magnitudeIB, d_ifft->get_outbuf(), d_fft_size); + volk_32f_index_max_16u_a(&indext_IB, d_magnitudeIB, d_fft_size); + magt_IB = d_magnitudeIB[indext_IB] / (fft_normalization_factor * fft_normalization_factor); + + if (d_both_signal_components == true) + { + // REPEAT FOR ALL CODES. CODE_QB + volk_32fc_x2_multiply_32fc_a(d_ifft->get_inbuf(), + d_fft_if->get_outbuf(), d_fft_code_Q_B, d_fft_size); + d_ifft->execute(); + volk_32fc_magnitude_squared_32f_a(d_magnitudeQB, d_ifft->get_outbuf(), d_fft_size); + volk_32f_index_max_16u_a(&indext_QB, d_magnitudeQB, d_fft_size); + magt_QB = d_magnitudeIB[indext_QB] / (fft_normalization_factor * fft_normalization_factor); + } + } + + // Integrate noncoherently the two best combinations (I² + Q²) + // and store the result in the I channel. + // If CAF filter to resolve doppler ambiguity is needed, + // peak is stored before non-coherent integration. + if (d_samples_per_ms != d_fft_size) // T_integration > 1 code + { + if (magt_IA >= magt_IB) + { +// if (d_CAF_filter) {d_CAF_vector_I[doppler_index] = magt_IA;} + if (d_CAF_window_hz > 0) {d_CAF_vector_I[doppler_index] = d_magnitudeIA[indext_IA];} + if (d_both_signal_components) + { + // Integrate non-coherently I+Q + if (magt_QA >= magt_QB) + { +// if (d_CAF_filter) {d_CAF_vector_Q[doppler_index] = magt_QA;} + if (d_CAF_window_hz > 0) {d_CAF_vector_Q[doppler_index] = d_magnitudeQA[indext_QA];} + for (unsigned int i=0; i 0) {d_CAF_vector_Q[doppler_index] = d_magnitudeQB[indext_QB];} + for (unsigned int i=0; i 0) {d_CAF_vector_I[doppler_index] = d_magnitudeIB[indext_IB];} + if (d_both_signal_components) + { + // Integrate non-coherently I+Q + if (magt_QA >= magt_QB) + { + //if (d_CAF_filter) {d_CAF_vector_Q[doppler_index] = magt_QA;} + if (d_CAF_window_hz > 0) {d_CAF_vector_Q[doppler_index] = d_magnitudeQA[indext_QA];} + for (unsigned int i=0; i 0) {d_CAF_vector_Q[doppler_index] = d_magnitudeQB[indext_QB];} + for (unsigned int i=0; i 0) {d_CAF_vector_I[doppler_index] = d_magnitudeIA[indext_IA];} + if (d_both_signal_components) + { +// if (d_CAF_filter) {d_CAF_vector_Q[doppler_index] = magt_QA;} + if (d_CAF_window_hz > 0) {d_CAF_vector_Q[doppler_index] = d_magnitudeQA[indext_QA];} + // NON-Coherent integration of only 1 code + for (unsigned int i=0; iAcq_delay_samples = (double)(indext % d_samples_per_code); + d_gnss_synchro->Acq_doppler_hz = (double)doppler; + d_gnss_synchro->Acq_samplestamp_samples = d_sample_counter; + + // 5- Compute the test statistics and compare to the threshold + d_test_statistics = d_mag / d_input_power; + } + } + + // Record results to file if required + if (d_dump) + { + std::stringstream filename; + std::streamsize n = sizeof(float) * (d_fft_size); // noncomplex file write + filename.str(""); + filename << "../data/test_statistics_E5a_sat_" + << d_gnss_synchro->PRN << "_doppler_" << doppler << ".dat"; + d_dump_file.open(filename.str().c_str(), std::ios::out | std::ios::binary); + if (d_samples_per_ms != d_fft_size) // If integration time > 1 code + { + if (magt_IA >= magt_IB) + { + d_dump_file.write((char*)d_magnitudeIA, n); + } + else + { + d_dump_file.write((char*)d_magnitudeIB, n); + } + } + else + { + d_dump_file.write((char*)d_magnitudeIA, n); + } + d_dump_file.close(); + } + } + std::cout << "d_mag " << d_mag << ".d_sample_counter " << d_sample_counter << std::endl; + // 6 OPTIONAL: CAF filter to avoid Doppler ambiguity in bit transition. + if (d_CAF_window_hz > 0) + { + int CAF_bins_half; + float* accum; +// double* accum; + if (posix_memalign((void**)&accum, 16, sizeof(float)) == 0){}; + CAF_bins_half = d_CAF_window_hz/(2*d_doppler_step); + std::cout << "CAF_bins_half " << CAF_bins_half << std::endl; + // Initialize first iterations + for (int doppler_index=0;doppler_indexAcq_doppler_hz = (double)doppler; + // Dump if required, appended at the end of the file + if (d_dump) + { + std::stringstream filename; + std::streamsize n = sizeof(float) * (d_num_doppler_bins); // noncomplex file write + filename.str(""); + filename << "../data/test_statistics_E5a_sat_" + << d_gnss_synchro->PRN << "_CAF.dat"; + d_dump_file.open(filename.str().c_str(), std::ios::out | std::ios::binary); + d_dump_file.write((char*)d_CAF_vector, n); + d_dump_file.close(); + } + } + + if (d_well_count == d_max_dwells) + { + if (d_test_statistics > d_threshold) + { + d_state = 3; // Positive acquisition + } + else + { + d_state = 4; // Negative acquisition + } + } + else + { + d_state = 1; + } + + consume_each(d_fft_size-d_buffer_count); + d_buffer_count = 0; + break; + } + case 3: + { + // 7.1- Declare positive acquisition using a message queue + DLOG(INFO) << "positive acquisition"; + DLOG(INFO) << "satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN; + DLOG(INFO) << "sample_stamp " << d_sample_counter; + DLOG(INFO) << "test statistics value " << d_test_statistics; + DLOG(INFO) << "test statistics threshold " << d_threshold; + DLOG(INFO) << "code phase " << d_gnss_synchro->Acq_delay_samples; + DLOG(INFO) << "doppler " << d_gnss_synchro->Acq_doppler_hz; + DLOG(INFO) << "magnitude " << d_mag; + DLOG(INFO) << "input signal power " << d_input_power; + + d_active = false; + d_state = 0; + + + acquisition_message = 1; + d_channel_internal_queue->push(acquisition_message); + d_sample_counter += ninput_items[0]; // sample counter + consume_each(ninput_items[0]); + break; + } + case 4: + { + // 7.2- Declare negative acquisition using a message queue + DLOG(INFO) << "negative acquisition"; + DLOG(INFO) << "satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN; + DLOG(INFO) << "sample_stamp " << d_sample_counter; + DLOG(INFO) << "test statistics value " << d_test_statistics; + DLOG(INFO) << "test statistics threshold " << d_threshold; + DLOG(INFO) << "code phase " << d_gnss_synchro->Acq_delay_samples; + DLOG(INFO) << "doppler " << d_gnss_synchro->Acq_doppler_hz; + DLOG(INFO) << "magnitude " << d_mag; + DLOG(INFO) << "input signal power " << d_input_power; + + d_active = false; + d_state = 0; + + d_sample_counter += ninput_items[0]; // sample counter + consume_each(ninput_items[0]); + acquisition_message = 2; + d_channel_internal_queue->push(acquisition_message); + break; + } + } + + return 0; +} + diff --git a/src/algorithms/acquisition/gnuradio_blocks/galileo_e5a_3ms_noncoherent_iq_acquisition_cc.h b/src/algorithms/acquisition/gnuradio_blocks/galileo_e5a_noncoherent_iq_acquisition_caf_cc.h similarity index 79% rename from src/algorithms/acquisition/gnuradio_blocks/galileo_e5a_3ms_noncoherent_iq_acquisition_cc.h rename to src/algorithms/acquisition/gnuradio_blocks/galileo_e5a_noncoherent_iq_acquisition_caf_cc.h index 11506f2ea..4b97831d6 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/galileo_e5a_3ms_noncoherent_iq_acquisition_cc.h +++ b/src/algorithms/acquisition/gnuradio_blocks/galileo_e5a_noncoherent_iq_acquisition_caf_cc.h @@ -1,8 +1,14 @@ /*! - * \file galileo_e5a_3ms_noncoherent_iq_acquisition_cc.h + * \file galileo_e5a_noncoherent_iq_acquisition_caf_cc.h * \brief Adapts a PCPS acquisition block to an AcquisitionInterface for * Galileo E5a data and pilot Signals * \author Marc Sales, 2014. marcsales92(at)gmail.com + * \based on work from: + *
    + *
  • Javier Arribas, 2011. jarribas(at)cttc.es + *
  • Luis Esteve, 2012. luis(at)epsilon-formacion.com + *
  • Marc Molina, 2013. marc.molina.pena@gmail.com + *
* * ------------------------------------------------------------------------- * @@ -29,8 +35,8 @@ * ------------------------------------------------------------------------- */ -#ifndef GALILEO_E5A_3MS_NONCOHERENT_IQ_ACQUISITION_CC_H_ -#define GALILEO_E5A_3MS_NONCOHERENT_IQ_ACQUISITION_CC_H_ +#ifndef GALILEO_E5A_NONCOHERENT_IQ_ACQUISITION_CAF_CC_H_ +#define GALILEO_E5A_NONCOHERENT_IQ_ACQUISITION_CAF_CC_H_ #include #include @@ -44,18 +50,20 @@ #include "concurrent_queue.h" #include "gnss_synchro.h" -class galileo_e5a_3ms_noncoherentIQ_acquisition_cc; +class galileo_e5a_noncoherentIQ_acquisition_caf_cc; -typedef boost::shared_ptr galileo_e5a_3ms_noncoherentIQ_acquisition_cc_sptr; +typedef boost::shared_ptr galileo_e5a_noncoherentIQ_acquisition_caf_cc_sptr; -galileo_e5a_3ms_noncoherentIQ_acquisition_cc_sptr -galileo_e5a_3ms_noncoherentIQ_make_acquisition_cc(unsigned int sampled_ms, +galileo_e5a_noncoherentIQ_acquisition_caf_cc_sptr +galileo_e5a_noncoherentIQ_make_acquisition_caf_cc(unsigned int sampled_ms, unsigned int max_dwells, unsigned int doppler_max, long freq, long fs_in, int samples_per_ms, int samples_per_code, bool bit_transition_flag, gr::msg_queue::sptr queue, bool dump, - std::string dump_filename); + std::string dump_filename, + bool both_signal_components_, + int CAF_window_hz_); /*! * \brief This class implements a Parallel Code Phase Search Acquisition. @@ -63,27 +71,31 @@ galileo_e5a_3ms_noncoherentIQ_make_acquisition_cc(unsigned int sampled_ms, * Check \ref Navitec2012 "An Open Source Galileo E1 Software Receiver", * Algorithm 1, for a pseudocode description of this implementation. */ -class galileo_e5a_3ms_noncoherentIQ_acquisition_cc: public gr::block +class galileo_e5a_noncoherentIQ_acquisition_caf_cc: public gr::block { private: - friend galileo_e5a_3ms_noncoherentIQ_acquisition_cc_sptr - galileo_e5a_3ms_noncoherentIQ_make_acquisition_cc( + friend galileo_e5a_noncoherentIQ_acquisition_caf_cc_sptr + galileo_e5a_noncoherentIQ_make_acquisition_caf_cc( unsigned int sampled_ms, unsigned int max_dwells, unsigned int doppler_max, long freq, long fs_in, int samples_per_ms, int samples_per_code, bool bit_transition_flag, gr::msg_queue::sptr queue, bool dump, - std::string dump_filename); + std::string dump_filename, + bool both_signal_components_, + int CAF_window_hz_); - galileo_e5a_3ms_noncoherentIQ_acquisition_cc( + galileo_e5a_noncoherentIQ_acquisition_caf_cc( unsigned int sampled_ms, unsigned int max_dwells, unsigned int doppler_max, long freq, long fs_in, int samples_per_ms, int samples_per_code, bool bit_transition_flag, gr::msg_queue::sptr queue, bool dump, - std::string dump_filename); + std::string dump_filename, + bool both_signal_components_, + int CAF_window_hz_); void calculate_magnitudes(gr_complex* fft_begin, int doppler_shift, int doppler_offset); @@ -128,6 +140,15 @@ private: bool d_active; int d_state; bool d_dump; + bool d_both_signal_components; +// bool d_CAF_filter; + int d_CAF_window_hz; + float* d_CAF_vector; + float* d_CAF_vector_I; + float* d_CAF_vector_Q; +// double* d_CAF_vector; +// double* d_CAF_vector_I; +// double* d_CAF_vector_Q; unsigned int d_channel; std::string d_dump_filename; unsigned int d_buffer_count; @@ -137,7 +158,7 @@ public: /*! * \brief Default destructor. */ - ~galileo_e5a_3ms_noncoherentIQ_acquisition_cc(); + ~galileo_e5a_noncoherentIQ_acquisition_caf_cc(); /*! * \brief Set acquisition/tracking common Gnss_Synchro object pointer @@ -232,6 +253,5 @@ public: gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); - void forecast (int noutput_items, gr_vector_int &ninput_items_required); }; -#endif /* GALILEO_E5A_3MS_NONCOHERENT_IQ_ACQUISITION_CC_H_ */ +#endif /* GALILEO_E5A_NONCOHERENT_IQ_ACQUISITION_CAF_CC_H_ */ diff --git a/src/algorithms/acquisition/gnuradio_blocks/galileo_e5a_pilot_3ms_acquisition_cc.cc b/src/algorithms/acquisition/gnuradio_blocks/galileo_e5a_pilot_3ms_acquisition_cc.cc deleted file mode 100644 index 254d2a7dd..000000000 --- a/src/algorithms/acquisition/gnuradio_blocks/galileo_e5a_pilot_3ms_acquisition_cc.cc +++ /dev/null @@ -1,415 +0,0 @@ -/* - * galileo_e5a_pilot_3ms_acquisition_cc.cc - * - * Created on: Jun 22, 2014 - * Author: marc - */ - -#include "galileo_e5a_pilot_3ms_acquisition_cc.h" -#include -#include -#include -#include -#include -#include "gnss_signal_processing.h" -#include "control_message_factory.h" - -using google::LogMessage; - -galileo_e5a_pilot_3ms_acquisition_cc_sptr galileo_e5a_pilot_3ms_make_acquisition_cc( - unsigned int max_dwells, - unsigned int doppler_max, long freq, long fs_in, - int samples_per_ms, int samples_per_code, - bool bit_transition_flag, - gr::msg_queue::sptr queue, bool dump, - std::string dump_filename) -{ - - return galileo_e5a_pilot_3ms_acquisition_cc_sptr( - new galileo_e5a_pilot_3ms_acquisition_cc(max_dwells, doppler_max, freq, fs_in, samples_per_ms, - samples_per_code, bit_transition_flag, queue, dump, dump_filename)); -} - -galileo_e5a_pilot_3ms_acquisition_cc::galileo_e5a_pilot_3ms_acquisition_cc( - unsigned int max_dwells, - unsigned int doppler_max, long freq, long fs_in, - int samples_per_ms, int samples_per_code, - bool bit_transition_flag, - gr::msg_queue::sptr queue, bool dump, - std::string dump_filename) : - gr::block("galileo_e5a_pilot_3ms_acquisition_cc", - gr::io_signature::make(1, 1, sizeof(gr_complex) * 3 * samples_per_ms), - gr::io_signature::make(0, 0, sizeof(gr_complex) * 3 * samples_per_ms)) -{ - //this->set_relative_rate(1.0/3*samples_per_ms); - d_sample_counter = 0; // SAMPLE COUNTER - d_active = false; - d_state = 0; - d_queue = queue; - d_freq = freq; - d_fs_in = fs_in; - d_samples_per_ms = samples_per_ms; - d_samples_per_code = samples_per_code; - d_max_dwells = max_dwells; - d_well_count = 0; - d_doppler_max = doppler_max; - d_fft_size = 3 * d_samples_per_ms; - d_mag = 0; - d_input_power = 0.0; - d_num_doppler_bins = 0; - d_bit_transition_flag = bit_transition_flag; - - //todo: do something if posix_memalign fails - if (posix_memalign((void**)&d_fft_code_A, 16, d_fft_size * sizeof(gr_complex)) == 0){}; - if (posix_memalign((void**)&d_fft_code_B, 16, d_fft_size * sizeof(gr_complex)) == 0){}; - if (posix_memalign((void**)&d_fft_code_C, 16, d_fft_size * sizeof(gr_complex)) == 0){}; - if (posix_memalign((void**)&d_fft_code_D, 16, d_fft_size * sizeof(gr_complex)) == 0){}; - if (posix_memalign((void**)&d_magnitude, 16, d_fft_size * sizeof(float)) == 0){}; - - // Direct FFT - d_fft_if = new gr::fft::fft_complex(d_fft_size, true); - - // Inverse FFT - d_ifft = new gr::fft::fft_complex(d_fft_size, false); -// d_ifft = new gr::fft::fft_complex(d_fft_size, true); - - // For dumping samples into a file - d_dump = dump; - d_dump_filename = dump_filename; -} - -galileo_e5a_pilot_3ms_acquisition_cc::~galileo_e5a_pilot_3ms_acquisition_cc() -{ - if (d_num_doppler_bins > 0) - { - for (unsigned int i = 0; i < d_num_doppler_bins; i++) - { - free(d_grid_doppler_wipeoffs[i]); - } - delete[] d_grid_doppler_wipeoffs; - } - - free(d_fft_code_A); - free(d_fft_code_B); - free(d_fft_code_C); - free(d_fft_code_D); - free(d_magnitude); - - delete d_ifft; - delete d_fft_if; - - if (d_dump) - { - d_dump_file.close(); - } -} - -void galileo_e5a_pilot_3ms_acquisition_cc::set_local_code(std::complex * code) -{ - // Three replicas of pilot primary code. CODE A: (1,1,1) - 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 - if (is_unaligned()) - { - volk_32fc_conjugate_32fc_u(d_fft_code_A,d_fft_if->get_outbuf(),d_fft_size); - } - else - { - volk_32fc_conjugate_32fc_a(d_fft_code_A,d_fft_if->get_outbuf(),d_fft_size); - } - // CODE B: First replica is inverted (0,1,1) - volk_32fc_s32fc_multiply_32fc_a(&(d_fft_if->get_inbuf())[0], - &code[0], gr_complex(-1,0), - d_samples_per_code); - d_fft_if->execute(); // We need the FFT of local code - - //Conjugate the local code - if (is_unaligned()) - { - volk_32fc_conjugate_32fc_u(d_fft_code_B,d_fft_if->get_outbuf(),d_fft_size); - } - else - { - volk_32fc_conjugate_32fc_a(d_fft_code_B,d_fft_if->get_outbuf(),d_fft_size); - } -} - -void galileo_e5a_pilot_3ms_acquisition_cc::init() -{ - d_gnss_synchro->Acq_delay_samples = 0.0; - d_gnss_synchro->Acq_doppler_hz = 0.0; - d_gnss_synchro->Acq_samplestamp_samples = 0; - d_mag = 0.0; - d_input_power = 0.0; - - // Count the number of bins - d_num_doppler_bins = 0; - for (int doppler = (int)(-d_doppler_max); - doppler <= (int)d_doppler_max; - doppler += d_doppler_step) - { - d_num_doppler_bins++; - } - - // Create the carrier Doppler wipeoff signals - d_grid_doppler_wipeoffs = new gr_complex*[d_num_doppler_bins]; - for (unsigned int doppler_index = 0; doppler_index < d_num_doppler_bins; doppler_index++) - { - if (posix_memalign((void**)&(d_grid_doppler_wipeoffs[doppler_index]), 16, - d_fft_size * sizeof(gr_complex)) == 0){}; - - int doppler = -(int)d_doppler_max + d_doppler_step*doppler_index; - complex_exp_gen_conj(d_grid_doppler_wipeoffs[doppler_index], - d_freq + doppler, d_fs_in, d_fft_size); - } -} - -int galileo_e5a_pilot_3ms_acquisition_cc::general_work(int noutput_items, - gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - /* - * By J.Arribas, L.Esteve and M.Molina - * Acquisition strategy (Kay Borre book + CFAR threshold): - * 1. Compute the input signal power estimation - * 2. Doppler serial search loop - * 3. Perform the FFT-based circular convolution (parallel time search) - * 4. Record the maximum peak and the associated synchronization parameters - * 5. Compute the test statistics and compare to the threshold - * 6. Declare positive or negative acquisition using a message queue - */ - - int acquisition_message = -1; //0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL - - switch (d_state) - { - case 0: - { - if (d_active) - { - //restart acquisition variables - d_gnss_synchro->Acq_delay_samples = 0.0; - d_gnss_synchro->Acq_doppler_hz = 0.0; - d_gnss_synchro->Acq_samplestamp_samples = 0; - d_well_count = 0; - d_mag = 0.0; - d_input_power = 0.0; - d_test_statistics = 0.0; - - d_state = 1; - } - - d_sample_counter += d_fft_size * ninput_items[0]; // sample counter - consume_each(ninput_items[0]); - - break; - } - - case 1: - { - // initialize acquisition algorithm - int doppler; - unsigned int indext = 0; - unsigned int indext_A = 0; - unsigned int indext_B = 0; - float magt = 0.0; - float magt_A = 0.0; - float magt_B = 0.0; - unsigned int sec_comb = 0; // secondary combination 0=(111), 1=(011) - const gr_complex *in = (const gr_complex *)input_items[0]; //Get the input samples pointer - float fft_normalization_factor = (float)d_fft_size * (float)d_fft_size; - d_input_power = 0.0; - d_mag = 0.0; - - d_sample_counter += d_fft_size; // sample counter - - d_well_count++; - - DLOG(INFO) << "Channel: " << d_channel - << " , doing acquisition of satellite: " << d_gnss_synchro->System << " "<< d_gnss_synchro->PRN - << " ,sample stamp: " << d_sample_counter << ", threshold: " - << d_threshold << ", doppler_max: " << d_doppler_max - << ", doppler_step: " << d_doppler_step; - - // 1- Compute the input signal power estimation - volk_32fc_magnitude_squared_32f_a(d_magnitude, in, d_fft_size); - volk_32f_accumulator_s32f_a(&d_input_power, d_magnitude, d_fft_size); - d_input_power /= (float)d_fft_size; - - // 2- Doppler frequency search loop - for (unsigned int doppler_index=0;doppler_indexget_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_a(d_ifft->get_inbuf(), - d_fft_if->get_outbuf(), d_fft_code_A, d_fft_size); - - // compute the inverse FFT - d_ifft->execute(); - - // Search maximum - volk_32fc_magnitude_squared_32f_a(d_magnitude, d_ifft->get_outbuf(), d_fft_size); - volk_32f_index_max_16u_a(&indext_A, d_magnitude, d_fft_size); - - // Normalize the maximum value to correct the scale factor introduced by FFTW - magt_A = d_magnitude[indext_A] / (fft_normalization_factor * fft_normalization_factor); - - // REPEAT FOR ALL CODES. CODE_B - volk_32fc_x2_multiply_32fc_a(d_ifft->get_inbuf(), - d_fft_if->get_outbuf(), d_fft_code_B, d_fft_size); - d_ifft->execute(); - volk_32fc_magnitude_squared_32f_a(d_magnitude, d_ifft->get_outbuf(), d_fft_size); - volk_32f_index_max_16u_a(&indext_B, d_magnitude, d_fft_size); - magt_B = d_magnitude[indext_B] / (fft_normalization_factor * fft_normalization_factor); - - //Choose the best correlation - if (magt_A >= magt_B) - { - magt = magt_A; - indext = indext_A; - sec_comb = 0; - } - else - { - magt = magt_B; - indext = indext_B; - sec_comb = 1; - } - // 4- record the maximum peak and the associated synchronization parameters - if (d_mag < magt) - { - d_mag = magt; - std::cout << "ACQ_block_e5a_3ms secondary combination " << sec_comb << std::endl; - - // 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 = (double)(indext % d_samples_per_code); - d_gnss_synchro->Acq_doppler_hz = (double)doppler; - d_gnss_synchro->Acq_samplestamp_samples = d_sample_counter; - - // 5- Compute the test statistics and compare to the threshold - //d_test_statistics = 2 * d_fft_size * d_mag / d_input_power; - d_test_statistics = d_mag / d_input_power; - } - } - - // Record results to file if required - if (d_dump) - { - std::stringstream filename; - std::streamsize n = 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((char*)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 - } - } - } - - consume_each(1); - - break; - } - - case 2: - { - // 6.1- Declare positive acquisition using a message queue - DLOG(INFO) << "positive acquisition"; - DLOG(INFO) << "satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN; - DLOG(INFO) << "sample_stamp " << d_sample_counter; - DLOG(INFO) << "test statistics value " << d_test_statistics; - DLOG(INFO) << "test statistics threshold " << d_threshold; - DLOG(INFO) << "code phase " << d_gnss_synchro->Acq_delay_samples; - DLOG(INFO) << "doppler " << d_gnss_synchro->Acq_doppler_hz; - DLOG(INFO) << "magnitude " << d_mag; - DLOG(INFO) << "input signal power " << d_input_power; - - d_active = false; - d_state = 0; - - d_sample_counter += d_fft_size * ninput_items[0]; // sample counter - consume_each(ninput_items[0]); - - acquisition_message = 1; - d_channel_internal_queue->push(acquisition_message); - - break; - } - - case 3: - { - // 6.2- Declare negative acquisition using a message queue - DLOG(INFO) << "negative acquisition"; - DLOG(INFO) << "satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN; - DLOG(INFO) << "sample_stamp " << d_sample_counter; - DLOG(INFO) << "test statistics value " << d_test_statistics; - DLOG(INFO) << "test statistics threshold " << d_threshold; - DLOG(INFO) << "code phase " << d_gnss_synchro->Acq_delay_samples; - DLOG(INFO) << "doppler " << d_gnss_synchro->Acq_doppler_hz; - DLOG(INFO) << "magnitude " << d_mag; - DLOG(INFO) << "input signal power " << d_input_power; - - d_active = false; - d_state = 0; - - d_sample_counter += d_fft_size * ninput_items[0]; // sample counter - consume_each(ninput_items[0]); - - acquisition_message = 2; - d_channel_internal_queue->push(acquisition_message); - - break; - } - } - - return 0; -} diff --git a/src/algorithms/acquisition/gnuradio_blocks/galileo_e5a_pilot_3ms_acquisition_cc.h b/src/algorithms/acquisition/gnuradio_blocks/galileo_e5a_pilot_3ms_acquisition_cc.h deleted file mode 100644 index 632a24b08..000000000 --- a/src/algorithms/acquisition/gnuradio_blocks/galileo_e5a_pilot_3ms_acquisition_cc.h +++ /dev/null @@ -1,200 +0,0 @@ -/* - * galileo_e5a_pilot_3ms_acquisition_cc.h - * - * Created on: Jun 22, 2014 - * Author: marc - */ - -#ifndef GALILEO_E5A_PILOT_3MS_ACQUISITION_CC_H_ -#define GALILEO_E5A_PILOT_3MS_ACQUISITION_CC_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "concurrent_queue.h" -#include "gnss_synchro.h" - -class galileo_e5a_pilot_3ms_acquisition_cc; - -typedef boost::shared_ptr galileo_e5a_pilot_3ms_acquisition_cc_sptr; - -galileo_e5a_pilot_3ms_acquisition_cc_sptr -galileo_e5a_pilot_3ms_make_acquisition_cc(unsigned int max_dwells, - unsigned int doppler_max, long freq, long fs_in, - int samples_per_ms, int samples_per_code, - bool bit_transition_flag, - gr::msg_queue::sptr queue, bool dump, - std::string dump_filename); - -/*! - * \brief This class implements a Parallel Code Phase Search Acquisition. - * - * Check \ref Navitec2012 "An Open Source Galileo E1 Software Receiver", - * Algorithm 1, for a pseudocode description of this implementation. - */ -class galileo_e5a_pilot_3ms_acquisition_cc: public gr::block -{ -private: - friend galileo_e5a_pilot_3ms_acquisition_cc_sptr - galileo_e5a_pilot_3ms_make_acquisition_cc(unsigned int max_dwells, - unsigned int doppler_max, long freq, long fs_in, - int samples_per_ms, int samples_per_code, - bool bit_transition_flag, - gr::msg_queue::sptr queue, bool dump, - std::string dump_filename); - - galileo_e5a_pilot_3ms_acquisition_cc(unsigned int max_dwells, - unsigned int doppler_max, long freq, long fs_in, - int samples_per_ms, int samples_per_code, - bool bit_transition_flag, - gr::msg_queue::sptr queue, bool dump, - std::string dump_filename); - - void calculate_magnitudes(gr_complex* fft_begin, int doppler_shift, - int doppler_offset); - - long d_fs_in; - long d_freq; - int d_samples_per_ms; - int d_samples_per_code; - unsigned int d_doppler_resolution; - float d_threshold; - std::string d_satellite_str; - unsigned int d_doppler_max; - unsigned int d_doppler_step; - unsigned int d_max_dwells; - unsigned int d_well_count; - unsigned int d_fft_size; - unsigned long int d_sample_counter; - gr_complex** d_grid_doppler_wipeoffs; - unsigned int d_num_doppler_bins; - gr_complex* d_fft_code_A; - gr_complex* d_fft_code_B; - gr_complex* d_fft_code_C; - gr_complex* d_fft_code_D; - 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; - gr::msg_queue::sptr d_queue; - concurrent_queue *d_channel_internal_queue; - std::ofstream d_dump_file; - bool d_active; - int d_state; - bool d_dump; - unsigned int d_channel; - std::string d_dump_filename; - -public: - /*! - * \brief Default destructor. - */ - ~galileo_e5a_pilot_3ms_acquisition_cc(); - - /*! - * \brief Set acquisition/tracking common Gnss_Synchro object pointer - * to exchange synchronization data between acquisition and tracking blocks. - * \param p_gnss_synchro Satellite information shared by the processing blocks. - */ - void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) - { - d_gnss_synchro = p_gnss_synchro; - } - - /*! - * \brief Returns the maximum peak of grid search. - */ - unsigned int mag() - { - return d_mag; - } - - /*! - * \brief Initializes acquisition algorithm. - */ - void init(); - - /*! - * \brief Sets local code for PCPS acquisition algorithm. - * \param code - Pointer to the PRN code. - */ - void set_local_code(std::complex * code); - - /*! - * \brief Starts acquisition algorithm, turning from standby mode to - * active mode - * \param active - bool that activates/deactivates the block. - */ - void set_active(bool active) - { - d_active = active; - } - - /*! - * \brief Set acquisition channel unique ID - * \param channel - receiver channel. - */ - void set_channel(unsigned int channel) - { - d_channel = channel; - } - - /*! - * \brief Set statistics threshold of PCPS algorithm. - * \param threshold - Threshold for signal detection (check \ref Navitec2012, - * Algorithm 1, for a definition of this threshold). - */ - void set_threshold(float threshold) - { - d_threshold = threshold; - } - - /*! - * \brief Set maximum Doppler grid search - * \param doppler_max - Maximum Doppler shift considered in the grid search [Hz]. - */ - void set_doppler_max(unsigned int doppler_max) - { - d_doppler_max = doppler_max; - } - - /*! - * \brief Set Doppler steps for the grid search - * \param doppler_step - Frequency bin of the search grid [Hz]. - */ - void set_doppler_step(unsigned int doppler_step) - { - d_doppler_step = doppler_step; - } - - - /*! - * \brief Set tracking channel internal queue. - * \param channel_internal_queue - Channel's internal blocks information queue. - */ - void set_channel_queue(concurrent_queue *channel_internal_queue) - { - d_channel_internal_queue = channel_internal_queue; - } - - /*! - * \brief Parallel Code Phase Search Acquisition signal processing. - */ - int general_work(int noutput_items, gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; - -#endif /* GALILEO_E5A_PILOT_3MS_ACQUISITION_CC_H_ */ diff --git a/src/algorithms/acquisition/gnuradio_blocks/galileo_e5ax_2ms_pcps_acquisition_cc.cc b/src/algorithms/acquisition/gnuradio_blocks/galileo_e5ax_2ms_pcps_acquisition_cc.cc deleted file mode 100644 index 30bbb6dac..000000000 --- a/src/algorithms/acquisition/gnuradio_blocks/galileo_e5ax_2ms_pcps_acquisition_cc.cc +++ /dev/null @@ -1,402 +0,0 @@ -/* - * galileo_e5ax_1ms_pcps_acquisition_cc.cc - * - * Created on: Jun 23, 2014 - * Author: marc - */ - -#include "galileo_e5ax_2ms_pcps_acquisition_cc.h" - -#include -#include -#include -#include -#include -#include "gnss_signal_processing.h" -#include "control_message_factory.h" - -using google::LogMessage; - -galileo_e5ax_2ms_pcps_acquisition_cc_sptr galileo_e5ax_2ms_pcps_make_acquisition_cc( - unsigned int max_dwells, - unsigned int doppler_max, long freq, long fs_in, - int samples_per_ms, int samples_per_code, - bool bit_transition_flag, - gr::msg_queue::sptr queue, bool dump, - std::string dump_filename) -{ - - return galileo_e5ax_2ms_pcps_acquisition_cc_sptr( - new galileo_e5ax_2ms_pcps_acquisition_cc(max_dwells, doppler_max, freq, fs_in, samples_per_ms, - samples_per_code, bit_transition_flag, queue, dump, dump_filename)); -} - -galileo_e5ax_2ms_pcps_acquisition_cc::galileo_e5ax_2ms_pcps_acquisition_cc( - unsigned int max_dwells, - unsigned int doppler_max, long freq, long fs_in, - int samples_per_ms, int samples_per_code, - bool bit_transition_flag, - gr::msg_queue::sptr queue, bool dump, - std::string dump_filename) : - gr::block("galileo_e5ax_2ms_pcps_acquisition_cc", - gr::io_signature::make(1, 1, sizeof(gr_complex) * 2 * samples_per_ms), - gr::io_signature::make(0, 0, sizeof(gr_complex) * 2 * samples_per_ms)) -{ - //this->set_relative_rate(1.0/3*samples_per_ms); - d_sample_counter = 0; // SAMPLE COUNTER - d_active = false; - d_state = 0; - d_queue = queue; - d_freq = freq; - d_fs_in = fs_in; - d_samples_per_ms = samples_per_ms; - d_samples_per_code = samples_per_code; - d_max_dwells = max_dwells; - d_well_count = 0; - d_doppler_max = doppler_max; - d_fft_size = 2 * d_samples_per_ms; - d_mag = 0; - d_input_power = 0.0; - d_num_doppler_bins = 0; - //always bit transition in e5 - //d_bit_transition_flag = bit_transition_flag; - - //todo: do something if posix_memalign fails - if (posix_memalign((void**)&d_fft_code_A, 16, d_fft_size * sizeof(gr_complex)) == 0){}; - if (posix_memalign((void**)&d_fft_code_B, 16, d_fft_size * sizeof(gr_complex)) == 0){}; - if (posix_memalign((void**)&d_magnitude, 16, d_fft_size * sizeof(float)) == 0){}; - - // Direct FFT - d_fft_if = new gr::fft::fft_complex(d_fft_size, true); - - // Inverse FFT - d_ifft = new gr::fft::fft_complex(d_fft_size, false); - - // For dumping samples into a file - d_dump = dump; - d_dump_filename = dump_filename; -} - -galileo_e5ax_2ms_pcps_acquisition_cc::~galileo_e5ax_2ms_pcps_acquisition_cc() -{ - if (d_num_doppler_bins > 0) - { - for (unsigned int i = 0; i < d_num_doppler_bins; i++) - { - free(d_grid_doppler_wipeoffs[i]); - } - delete[] d_grid_doppler_wipeoffs; - } - - free(d_fft_code_A); - free(d_fft_code_B); - free(d_magnitude); - - delete d_ifft; - delete d_fft_if; - - if (d_dump) - { - d_dump_file.close(); - } -} - -void galileo_e5ax_2ms_pcps_acquisition_cc::set_local_code(std::complex * code) -{ - // Three replicas of pilot primary code. CODE A: (1,1) - 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 - if (is_unaligned()) - { - volk_32fc_conjugate_32fc_u(d_fft_code_A,d_fft_if->get_outbuf(),d_fft_size); - // CODE B: First replica is inverted (0,1) by conjugating the code (I - Qi) - volk_32fc_conjugate_32fc_u(d_fft_if->get_inbuf(),code,d_fft_size); - d_fft_if->execute(); // We need the FFT of local code - volk_32fc_conjugate_32fc_u(d_fft_code_B,d_fft_if->get_outbuf(),d_fft_size); - } - else - { - volk_32fc_conjugate_32fc_a(d_fft_code_A,d_fft_if->get_outbuf(),d_fft_size); - // CODE B: First replica is inverted (0,1) by conjugating the code (I - Qi) - volk_32fc_conjugate_32fc_a(d_fft_if->get_inbuf(),code,d_fft_size); - d_fft_if->execute(); // We need the FFT of local code - volk_32fc_conjugate_32fc_a(d_fft_code_B,d_fft_if->get_outbuf(),d_fft_size); - } -} - -void galileo_e5ax_2ms_pcps_acquisition_cc::init() -{ - d_gnss_synchro->Acq_delay_samples = 0.0; - d_gnss_synchro->Acq_doppler_hz = 0.0; - d_gnss_synchro->Acq_samplestamp_samples = 0; - d_mag = 0.0; - d_input_power = 0.0; - - // Count the number of bins - d_num_doppler_bins = 0; - for (int doppler = (int)(-d_doppler_max); - doppler <= (int)d_doppler_max; - doppler += d_doppler_step) - { - d_num_doppler_bins++; - } - - // Create the carrier Doppler wipeoff signals - d_grid_doppler_wipeoffs = new gr_complex*[d_num_doppler_bins]; - for (unsigned int doppler_index = 0; doppler_index < d_num_doppler_bins; doppler_index++) - { - if (posix_memalign((void**)&(d_grid_doppler_wipeoffs[doppler_index]), 16, - d_fft_size * sizeof(gr_complex)) == 0){}; - - int doppler = -(int)d_doppler_max + d_doppler_step*doppler_index; - complex_exp_gen_conj(d_grid_doppler_wipeoffs[doppler_index], - d_freq + doppler, d_fs_in, d_fft_size); - } -} - -int galileo_e5ax_2ms_pcps_acquisition_cc::general_work(int noutput_items, - gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items) -{ - /* - * By J.Arribas, L.Esteve and M.Molina - * Acquisition strategy (Kay Borre book + CFAR threshold): - * 1. Compute the input signal power estimation - * 2. Doppler serial search loop - * 3. Perform the FFT-based circular convolution (parallel time search) - * 4. Record the maximum peak and the associated synchronization parameters - * 5. Compute the test statistics and compare to the threshold - * 6. Declare positive or negative acquisition using a message queue - */ - - int acquisition_message = -1; //0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL - - switch (d_state) - { - case 0: - { - if (d_active) - { - //restart acquisition variables - d_gnss_synchro->Acq_delay_samples = 0.0; - d_gnss_synchro->Acq_doppler_hz = 0.0; - d_gnss_synchro->Acq_samplestamp_samples = 0; - d_well_count = 0; - d_mag = 0.0; - d_input_power = 0.0; - d_test_statistics = 0.0; - - d_state = 1; - } - - d_sample_counter += d_fft_size * ninput_items[0]; // sample counter - consume_each(ninput_items[0]); - - break; - } - - case 1: - { - // initialize acquisition algorithm - int doppler; - unsigned int indext = 0; - unsigned int indext_A = 0; - unsigned int indext_B = 0; - float magt = 0.0; - float magt_A = 0.0; - float magt_B = 0.0; - const gr_complex *in = (const gr_complex *)input_items[0]; //Get the input samples pointer - float fft_normalization_factor = (float)d_fft_size * (float)d_fft_size; - d_input_power = 0.0; - d_mag = 0.0; - - d_sample_counter += d_fft_size; // sample counter - - d_well_count++; - - DLOG(INFO) << "Channel: " << d_channel - << " , doing acquisition of satellite: " << d_gnss_synchro->System << " "<< d_gnss_synchro->PRN - << " ,sample stamp: " << d_sample_counter << ", threshold: " - << d_threshold << ", doppler_max: " << d_doppler_max - << ", doppler_step: " << d_doppler_step; - - // 1- Compute the input signal power estimation - volk_32fc_magnitude_squared_32f_a(d_magnitude, in, d_fft_size); - volk_32f_accumulator_s32f_a(&d_input_power, d_magnitude, d_fft_size); - d_input_power /= (float)d_fft_size; - - // 2- Doppler frequency search loop - for (unsigned int doppler_index=0;doppler_indexget_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_a(d_ifft->get_inbuf(), - d_fft_if->get_outbuf(), d_fft_code_A, d_fft_size); - - // compute the inverse FFT - d_ifft->execute(); - - // Search maximum - volk_32fc_magnitude_squared_32f_a(d_magnitude, d_ifft->get_outbuf(), d_fft_size); - volk_32f_index_max_16u_a(&indext_A, d_magnitude, d_fft_size); - - // Normalize the maximum value to correct the scale factor introduced by FFTW - magt_A = d_magnitude[indext_A] / (fft_normalization_factor * fft_normalization_factor); - - // REPEAT FOR CODE_B - volk_32fc_x2_multiply_32fc_a(d_ifft->get_inbuf(), - d_fft_if->get_outbuf(), d_fft_code_B, d_fft_size); - d_ifft->execute(); - volk_32fc_magnitude_squared_32f_a(d_magnitude, d_ifft->get_outbuf(), d_fft_size); - volk_32f_index_max_16u_a(&indext_B, d_magnitude, d_fft_size); - magt_B = d_magnitude[indext_B] / (fft_normalization_factor * fft_normalization_factor); - - //Choose the best correlation - if (magt_A >= magt_B) - { - magt = magt_A; - indext = indext_A; - } - else - { - magt = magt_B; - indext = indext_B; - } - // 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 = (double)(indext % d_samples_per_code); - d_gnss_synchro->Acq_doppler_hz = (double)doppler; - d_gnss_synchro->Acq_samplestamp_samples = d_sample_counter; - - // 5- Compute the test statistics and compare to the threshold - //d_test_statistics = 2 * d_fft_size * d_mag / d_input_power; - d_test_statistics = d_mag / d_input_power; - } - } - - // Record results to file if required - if (d_dump) - { - std::stringstream filename; - std::streamsize n = 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((char*)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 - } - } - } - - consume_each(1); - - break; - } - - case 2: - { - // 6.1- Declare positive acquisition using a message queue - DLOG(INFO) << "positive acquisition"; - DLOG(INFO) << "satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN; - DLOG(INFO) << "sample_stamp " << d_sample_counter; - DLOG(INFO) << "test statistics value " << d_test_statistics; - DLOG(INFO) << "test statistics threshold " << d_threshold; - DLOG(INFO) << "code phase " << d_gnss_synchro->Acq_delay_samples; - DLOG(INFO) << "doppler " << d_gnss_synchro->Acq_doppler_hz; - DLOG(INFO) << "magnitude " << d_mag; - DLOG(INFO) << "input signal power " << d_input_power; - - d_active = false; - d_state = 0; - - d_sample_counter += d_fft_size * ninput_items[0]; // sample counter - consume_each(ninput_items[0]); - - acquisition_message = 1; - d_channel_internal_queue->push(acquisition_message); - - break; - } - - case 3: - { - // 6.2- Declare negative acquisition using a message queue - DLOG(INFO) << "negative acquisition"; - DLOG(INFO) << "satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN; - DLOG(INFO) << "sample_stamp " << d_sample_counter; - DLOG(INFO) << "test statistics value " << d_test_statistics; - DLOG(INFO) << "test statistics threshold " << d_threshold; - DLOG(INFO) << "code phase " << d_gnss_synchro->Acq_delay_samples; - DLOG(INFO) << "doppler " << d_gnss_synchro->Acq_doppler_hz; - DLOG(INFO) << "magnitude " << d_mag; - DLOG(INFO) << "input signal power " << d_input_power; - - d_active = false; - d_state = 0; - - d_sample_counter += d_fft_size * ninput_items[0]; // sample counter - consume_each(ninput_items[0]); - - acquisition_message = 2; - d_channel_internal_queue->push(acquisition_message); - - break; - } - } - - return 0; -} diff --git a/src/algorithms/acquisition/gnuradio_blocks/galileo_e5ax_2ms_pcps_acquisition_cc.h b/src/algorithms/acquisition/gnuradio_blocks/galileo_e5ax_2ms_pcps_acquisition_cc.h deleted file mode 100644 index 715f25804..000000000 --- a/src/algorithms/acquisition/gnuradio_blocks/galileo_e5ax_2ms_pcps_acquisition_cc.h +++ /dev/null @@ -1,197 +0,0 @@ -/* - * galileo_e5ax_1ms_pcps_acquisition_cc.h - * - * Created on: Jun 23, 2014 - * Author: marc - */ - -#ifndef GALILEO_E5AX_2MS_PCPS_ACQUISITION_CC_H_ -#define GALILEO_E5AX_2MS_PCPS_ACQUISITION_CC_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "concurrent_queue.h" -#include "gnss_synchro.h" - -class galileo_e5ax_2ms_pcps_acquisition_cc; - -typedef boost::shared_ptr galileo_e5ax_2ms_pcps_acquisition_cc_sptr; - -galileo_e5ax_2ms_pcps_acquisition_cc_sptr -galileo_e5ax_2ms_pcps_make_acquisition_cc(unsigned int max_dwells, - unsigned int doppler_max, long freq, long fs_in, - int samples_per_ms, int samples_per_code, - bool bit_transition_flag, - gr::msg_queue::sptr queue, bool dump, - std::string dump_filename); - -/*! - * \brief This class implements a Parallel Code Phase Search Acquisition. - * - * Check \ref Navitec2012 "An Open Source Galileo E1 Software Receiver", - * Algorithm 1, for a pseudocode description of this implementation. - */ -class galileo_e5ax_2ms_pcps_acquisition_cc: public gr::block -{ -private: - friend galileo_e5ax_2ms_pcps_acquisition_cc_sptr - galileo_e5ax_2ms_pcps_make_acquisition_cc(unsigned int max_dwells, - unsigned int doppler_max, long freq, long fs_in, - int samples_per_ms, int samples_per_code, - bool bit_transition_flag, - gr::msg_queue::sptr queue, bool dump, - std::string dump_filename); - - galileo_e5ax_2ms_pcps_acquisition_cc(unsigned int max_dwells, - unsigned int doppler_max, long freq, long fs_in, - int samples_per_ms, int samples_per_code, - bool bit_transition_flag, - gr::msg_queue::sptr queue, bool dump, - std::string dump_filename); - - void calculate_magnitudes(gr_complex* fft_begin, int doppler_shift, - int doppler_offset); - - long d_fs_in; - long d_freq; - int d_samples_per_ms; - int d_samples_per_code; - unsigned int d_doppler_resolution; - float d_threshold; - std::string d_satellite_str; - unsigned int d_doppler_max; - unsigned int d_doppler_step; - unsigned int d_max_dwells; - unsigned int d_well_count; - unsigned int d_fft_size; - unsigned long int d_sample_counter; - gr_complex** d_grid_doppler_wipeoffs; - unsigned int d_num_doppler_bins; - gr_complex* d_fft_code_A; - gr_complex* d_fft_code_B; - 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; - gr::msg_queue::sptr d_queue; - concurrent_queue *d_channel_internal_queue; - std::ofstream d_dump_file; - bool d_active; - int d_state; - bool d_dump; - unsigned int d_channel; - std::string d_dump_filename; - -public: - /*! - * \brief Default destructor. - */ - ~galileo_e5ax_2ms_pcps_acquisition_cc(); - - /*! - * \brief Set acquisition/tracking common Gnss_Synchro object pointer - * to exchange synchronization data between acquisition and tracking blocks. - * \param p_gnss_synchro Satellite information shared by the processing blocks. - */ - void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) - { - d_gnss_synchro = p_gnss_synchro; - } - - /*! - * \brief Returns the maximum peak of grid search. - */ - unsigned int mag() - { - return d_mag; - } - - /*! - * \brief Initializes acquisition algorithm. - */ - void init(); - - /*! - * \brief Sets local code for PCPS acquisition algorithm. - * \param code - Pointer to the PRN code. - */ - void set_local_code(std::complex * code); - - /*! - * \brief Starts acquisition algorithm, turning from standby mode to - * active mode - * \param active - bool that activates/deactivates the block. - */ - void set_active(bool active) - { - d_active = active; - } - - /*! - * \brief Set acquisition channel unique ID - * \param channel - receiver channel. - */ - void set_channel(unsigned int channel) - { - d_channel = channel; - } - - /*! - * \brief Set statistics threshold of PCPS algorithm. - * \param threshold - Threshold for signal detection (check \ref Navitec2012, - * Algorithm 1, for a definition of this threshold). - */ - void set_threshold(float threshold) - { - d_threshold = threshold; - } - - /*! - * \brief Set maximum Doppler grid search - * \param doppler_max - Maximum Doppler shift considered in the grid search [Hz]. - */ - void set_doppler_max(unsigned int doppler_max) - { - d_doppler_max = doppler_max; - } - - /*! - * \brief Set Doppler steps for the grid search - * \param doppler_step - Frequency bin of the search grid [Hz]. - */ - void set_doppler_step(unsigned int doppler_step) - { - d_doppler_step = doppler_step; - } - - - /*! - * \brief Set tracking channel internal queue. - * \param channel_internal_queue - Channel's internal blocks information queue. - */ - void set_channel_queue(concurrent_queue *channel_internal_queue) - { - d_channel_internal_queue = channel_internal_queue; - } - - /*! - * \brief Parallel Code Phase Search Acquisition signal processing. - */ - int general_work(int noutput_items, gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); -}; -#endif /* GALILEO_E5AX_2MS_PCPS_ACQUISITION_CC_H_ */ diff --git a/src/algorithms/libs/galileo_e5_signal_processing.cc b/src/algorithms/libs/galileo_e5_signal_processing.cc index e22445a0e..737a9794f 100644 --- a/src/algorithms/libs/galileo_e5_signal_processing.cc +++ b/src/algorithms/libs/galileo_e5_signal_processing.cc @@ -35,7 +35,6 @@ void galileo_e5_a_code_gen_complex_primary(std::complex* _dest, signed int _prn, char _Signal[3]) { - std::string _galileo_signal = _Signal; unsigned int prn=_prn-1; unsigned int index=0; int a[4]; @@ -43,7 +42,7 @@ void galileo_e5_a_code_gen_complex_primary(std::complex* _dest, signed in { return; } - if (_galileo_signal.rfind("5Q") != std::string::npos && _galileo_signal.length() >= 2) + if (_Signal[0]=='5' && _Signal[1]=='Q') { for (size_t i = 0; i < Galileo_E5a_Q_PRIMARY_CODE[prn].length()-1; i++) { @@ -61,7 +60,7 @@ void galileo_e5_a_code_gen_complex_primary(std::complex* _dest, signed in _dest[index]=std::complex(float(0.0),a[0]); _dest[index+1]=std::complex(float(0.0),a[1]); } - else if (_galileo_signal.rfind("5I") != std::string::npos && _galileo_signal.length() >= 2) + else if (_Signal[0]=='5' && _Signal[1]=='I') { for (size_t i = 0; i < Galileo_E5a_I_PRIMARY_CODE[prn].length()-1; i++) { @@ -79,7 +78,7 @@ void galileo_e5_a_code_gen_complex_primary(std::complex* _dest, signed in _dest[index]=std::complex(float(a[0]),0.0); _dest[index+1]=std::complex(float(a[1]),0.0); } - else if (_galileo_signal.rfind("5X") != std::string::npos && _galileo_signal.length() >= 2) + else if (_Signal[0]=='5' && _Signal[1]=='X') { int b[4]; for (size_t i = 0; i < Galileo_E5a_I_PRIMARY_CODE[prn].length()-1; i++) @@ -104,74 +103,11 @@ void galileo_e5_a_code_gen_complex_primary(std::complex* _dest, signed in } } -void galileo_e5_a_code_gen_tiered(std::complex* _dest,std::complex* _primary ,unsigned int _prn, char _Signal[3]) -{ - - std::string _galileo_signal = _Signal; - unsigned int prn=_prn-1; - // Note: always generates 100 ms of tiered code - if (_galileo_signal.rfind("5Q") != std::string::npos && _galileo_signal.length() >= 2) - { - for (size_t i = 0; i < Galileo_E5a_Q_SECONDARY_CODE_LENGTH; i++) - { - for (size_t k=0; k< Galileo_E5a_CODE_LENGTH_CHIPS; k++) - { - //_dest[i*Galileo_E5a_CODE_LENGTH_CHIPS + k] = _primary[k]; - //_dest[i*Galileo_E5a_CODE_LENGTH_CHIPS + k] = new std::complex(0,0); - _dest[i*Galileo_E5a_CODE_LENGTH_CHIPS + k].imag( _primary[k].imag() * - (Galileo_E5a_Q_SECONDARY_CODE[prn].at(i)=='0' ? (float)1 : (float)-1)); - - _dest[i*Galileo_E5a_CODE_LENGTH_CHIPS + k].real((float)0); - } - } - } - else if (_galileo_signal.rfind("5I") != std::string::npos && _galileo_signal.length() >= 2) - { - for (size_t i = 0; i < Galileo_E5a_Q_SECONDARY_CODE_LENGTH; i++) - { - for (size_t k=0; k< Galileo_E5a_CODE_LENGTH_CHIPS; k++) - { - //_dest[i*Galileo_E5a_CODE_LENGTH_CHIPS + k] = _primary[k]; - //_dest[i*Galileo_E5a_CODE_LENGTH_CHIPS + k] = new std::complex(0,0); - // Modulo operator i%20 since i[0,99] and sec code[0,19] - _dest[i*Galileo_E5a_CODE_LENGTH_CHIPS + k].real( _primary[k].real() * - (Galileo_E5a_I_SECONDARY_CODE.at(i%20)=='0' ? (float)1 : (float)-1)); - - _dest[i*Galileo_E5a_CODE_LENGTH_CHIPS + k].imag((float)0); - - } - } - } - else if (_galileo_signal.rfind("5X") != std::string::npos && _galileo_signal.length() >= 2) - { - for (size_t i = 0; i < Galileo_E5a_Q_SECONDARY_CODE_LENGTH; i++) - { - for (size_t k=0; k< Galileo_E5a_CODE_LENGTH_CHIPS; k++) - { - //_dest[i*Galileo_E5a_CODE_LENGTH_CHIPS + k] = _primary[k]; - //_dest[i*Galileo_E5a_CODE_LENGTH_CHIPS + k] = new std::complex(0,0); - - _dest[i*Galileo_E5a_CODE_LENGTH_CHIPS + k].imag( _primary[k].imag() * - (Galileo_E5a_Q_SECONDARY_CODE[prn].at(i)=='0' ? (float)1 : (float)-1)); - - _dest[i*Galileo_E5a_CODE_LENGTH_CHIPS + k].real( _primary[k].real() * - (Galileo_E5a_I_SECONDARY_CODE.at(i%20)=='0' ? (float)1 : (float)-1)); - } - } - } - else - { - std::cout << "Signal doesn't correspond to E5a signal" << std::endl; - } -} - void galileo_e5_a_code_gen_complex_sampled(std::complex* _dest, char _Signal[3], - unsigned int _prn, signed int _fs, unsigned int _chip_shift, - bool _secondary_flag) + unsigned int _prn, signed int _fs, unsigned int _chip_shift) { // This function is based on the GNU software GPS for MATLAB in the Kay Borre book - //std::string _galileo_signal = _Signal; unsigned int _samplesPerCode; unsigned int delay; unsigned int _codeLength = Galileo_E5a_CODE_LENGTH_CHIPS; @@ -179,74 +115,31 @@ void galileo_e5_a_code_gen_complex_sampled(std::complex* _dest, char _Sig std::complex* _code; -// if (posix_memalign((void**)&_code, 16, _codeLength * sizeof(gr_complex)) == 0){}; _code=new std::complex[_codeLength]; - //std::complex primary_code_E5a_chips[(int)Galileo_E5a_CODE_LENGTH_CHIPS]; - galileo_e5_a_code_gen_complex_primary(_code , _prn , _Signal); - if (_secondary_flag) - { - std::complex* _tiered_code = new std::complex - [Galileo_E5a_Q_SECONDARY_CODE_LENGTH * Galileo_E5a_CODE_LENGTH_CHIPS]; - - _codeLength *= Galileo_E5a_Q_SECONDARY_CODE_LENGTH; -// std::complex* _tiered_code; -// if (posix_memalign((void**)&_tiered_code, 16, _codeLength * sizeof(gr_complex)) == 0){}; -// std::complex _tiered_code[Galileo_E5a_Q_SECONDARY_CODE_LENGTH * Galileo_E5a_CODE_LENGTH_CHIPS]; - //malloc(_tiered_code, ) - //std::cout << sizeof (&_tiered_code) << std::endl; - - galileo_e5_a_code_gen_tiered(_tiered_code, _code,_prn, _Signal); - - delete[] _code; - //free(_code); - //if (posix_memalign((void**)&_code, 16, _codeLength * sizeof(gr_complex)) == 0){}; - _code = _tiered_code; -// delete[] _tiered_code; - free(_tiered_code); - - - - } - _samplesPerCode = round(_fs / (_codeFreqBasis / _codeLength)); - // NOTE: if secondary, delay accounts for tiered code delay and samples/codesecondary + delay = ((_codeLength - _chip_shift) % _codeLength) * _samplesPerCode / _codeLength; - //std::cout << "check tiered code delay" << delay << std::endl; - //std::cout << "check codelength" << _codeLength << std::endl; if (_fs != _codeFreqBasis) { - std::complex* _resampled_signal;// = new std::complex[_codeLength]; + std::complex* _resampled_signal; if (posix_memalign((void**)&_resampled_signal, 16, _samplesPerCode * sizeof(gr_complex)) == 0){}; resampler(_code, _resampled_signal, _codeFreqBasis, _fs, _codeLength, _samplesPerCode); //resamples code to fs - -// free(_code); -// if (posix_memalign((void**)&_code, 16, _samplesPerCode * sizeof(gr_complex)) == 0){}; delete[] _code; _code = _resampled_signal; -// delete[] _resampled_signal; - //free(_resampled_signal); } - //std::cout << _fs << "fs" << std::endl; for (unsigned int i = 0; i < _samplesPerCode; i++) { _dest[(i+delay)%_samplesPerCode] = _code[i]; } -// if (_code[0]==gr_complex(0,0)) -// { -// std::cout <<"ERROR: first chip is 0. prn:"<< _prn << std::endl; -// std::cout << _Signal << "signal" << std::endl; -// } - - //std::cout << "no problem gen sampled code" <<_prn << " " << _code[0] <* _dest,std::complex * bool _pilot generates E5aQ code if true and E5aI (data signal) if false. */ void galileo_e5_a_code_gen_complex_sampled(std::complex* _dest, - char _Signal[3], unsigned int _prn, signed int _fs, unsigned int _chip_shift, - bool _secondary_flag); + char _Signal[3], unsigned int _prn, signed int _fs, unsigned int _chip_shift); #endif /* GNSS_SDR_GALILEO_E5_SIGNAL_PROCESSING_H_ */ diff --git a/src/algorithms/signal_generator/gnuradio_blocks/signal_generator_c.cc b/src/algorithms/signal_generator/gnuradio_blocks/signal_generator_c.cc index b703505c7..fb625a572 100644 --- a/src/algorithms/signal_generator/gnuradio_blocks/signal_generator_c.cc +++ b/src/algorithms/signal_generator/gnuradio_blocks/signal_generator_c.cc @@ -199,59 +199,22 @@ void signal_generator_c::generate_codes() if(signal_[sat].at(0)=='5') { char signal[3]; -// strcpy(signal,"5I"); strcpy(signal,"5X"); if (posix_memalign((void**)&(sampled_code_data_[sat]), 16, vector_length_ * sizeof(gr_complex)) == 0){}; -// galileo_e5_a_code_gen_complex_sampled(sampled_code_data_[sat] , signal, PRN_[sat], fs_in_, -// (int)Galileo_E5a_Q_SECONDARY_CODE_LENGTH - delay_chips_[sat], true); galileo_e5_a_code_gen_complex_sampled(sampled_code_data_[sat] , signal, PRN_[sat], fs_in_, - (int)Galileo_E5a_CODE_LENGTH_CHIPS-delay_chips_[sat],false); + (int)Galileo_E5a_CODE_LENGTH_CHIPS-delay_chips_[sat]); - std::cout << "PRN "<< PRN_[sat] << " first two bytes "<< sampled_code_data_[sat][0] << sampled_code_data_[sat][1] << sampled_code_data_[sat][2] << sampled_code_data_[sat][3] << sampled_code_data_[sat][4] << sampled_code_data_[sat][5] << sampled_code_data_[sat][6] << sampled_code_data_[sat][7] << std::endl; - /////////// - /* - std::ofstream d_dump_file; - std::stringstream filename; - std::streamsize n = 2 * sizeof(float) * (Galileo_E5a_CODE_LENGTH_CHIPS); // complex file write - filename.str(""); - filename << "../data/PRN11_Xcode_noiseless" << ".dat"; - d_dump_file.open(filename.str().c_str(), std::ios::out | std::ios::binary); - d_dump_file.write((char*)&sampled_code_data_[sat][0], n); - d_dump_file.close(); - */ - ///////////////////// - //// std::ofstream myfile; -// //myfile.open ("example_sink_gencode.dat"); -// std::ofstream myfile("example_sink_gencode.bin",std::ios_base::binary); -//// for (int k=0; k< vector_length_; k++) -//// { -// myfile.write((char*)&sampled_code_data_[sat],sizeof(gr_complex)*vector_length_); -// //myfile << sampled_code_data_[sat][k]; -//// } -// -// myfile.close(); - //std::cout << "checking tiered code" << sampled_code_data_[sat][0] << sampled_code_data_[sat][1] << sampled_code_data_[sat][2] << sampled_code_data_[sat][3] << sampled_code_data_[sat][4] << sampled_code_data_[sat][1200000] << sampled_code_data_[sat][1200000-1] << std::endl; - - // PILOT -// if (posix_memalign((void**)&(sampled_code_pilot_[sat]), 16, -// vector_length_ * sizeof(gr_complex)) == 0){}; -// -// strcpy(signal, "5Q"); -// -// galileo_e5_a_code_gen_complex_sampled(sampled_code_pilot_[sat] , signal, PRN_[sat], fs_in_, -// (int)Galileo_E5a_CODE_LENGTH_CHIPS - delay_chips_[sat], false); //noise if (noise_flag_) { for (unsigned int i = 0; i < vector_length_; i++) { sampled_code_data_[sat][i] *= sqrt(pow(10, CN0_dB_[sat] / 10) / BW_BB_ / 2); - //sampled_code_pilot_[sat][i] *= sqrt(pow(10, CN0_dB_[sat] / 10) / BW_BB_ / 2); } } @@ -389,7 +352,6 @@ gr_vector_void_star &output_items) if(signal_[sat].at(0)=='5') { // EACH WORK outputs 1 modulated primary code - //int codelen = (int)(Galileo_E5a_CODE_LENGTH_CHIPS * Galileo_E5a_Q_SECONDARY_CODE_LENGTH); int codelen = (int)Galileo_E5a_CODE_LENGTH_CHIPS; unsigned int delay_samples = (delay_chips_[sat] % codelen) * samples_per_code_[sat] / codelen; @@ -409,12 +371,6 @@ gr_vector_void_star &output_items) data_modulation_[sat] = current_data_bit_int_[sat] * (Galileo_E5a_I_SECONDARY_CODE.at((ms_counter_[sat]+delay_sec_[sat])%20)=='0' ? 1 : -1); pilot_modulation_[sat] = (Galileo_E5a_Q_SECONDARY_CODE[PRN_[sat]-1].at((ms_counter_[sat]+delay_sec_[sat])%100)=='0' ? 1 : -1); -// if (work_counter_==1) -// { - //std::cout << "ms " << ms_counter_[sat] << " sat " << sat << " PRN" << PRN_[sat]; - //std::cout << " delay_secI " << (ms_counter_[sat]+delay_sec_[sat])%20 << " delay_secQ " << (ms_counter_[sat]+delay_sec_[sat])%100 << std::endl;//" pilot mod " << pilot_modulation_[sat] << " data bit " << current_data_bit_int_[sat] << " data mod " << data_modulation_[sat] << std::endl; - //std::cout << "code 1st 2 byte " << out[0] << out[1] << out[2] << out[3] << out[4] << out[5] << out[6] << out[7] << std::endl; -// } ms_counter_[sat] = ms_counter_[sat] + (int)round(1e3*GALILEO_E5a_CODE_PERIOD); for (k = delay_samples; k < samples_per_code_[sat]; k++) @@ -425,8 +381,6 @@ gr_vector_void_star &output_items) out_idx++; } - - } else { @@ -473,19 +427,7 @@ gr_vector_void_star &output_items) out[out_idx] += gr_complex(random_->gasdev(),random_->gasdev()); } } -/* -if (work_counter_==1) - { - std::ofstream d_dump_file; - std::stringstream filename; - std::streamsize n = 2 * sizeof(float) * (samples_per_code_[0]); // complex file write - filename.str(""); - filename << "../data/PRN11_Xcode_genwork" << ".dat"; - d_dump_file.open(filename.str().c_str(), std::ios::out | std::ios::binary); - d_dump_file.write((char*)out, n); - d_dump_file.close(); - } -*/ + // Tell runtime system how many output items we produced. return 1; } diff --git a/src/algorithms/telemetry_decoder/gnuradio_blocks/galileo_e5a_telemetry_decoder_cc.cc b/src/algorithms/telemetry_decoder/gnuradio_blocks/galileo_e5a_telemetry_decoder_cc.cc index ec6735865..a85718987 100644 --- a/src/algorithms/telemetry_decoder/gnuradio_blocks/galileo_e5a_telemetry_decoder_cc.cc +++ b/src/algorithms/telemetry_decoder/gnuradio_blocks/galileo_e5a_telemetry_decoder_cc.cc @@ -41,6 +41,7 @@ #include "galileo_fnav_message.h" #include "gnss_synchro.h" #include "convolutional.h" +//#include //#include "galileo_e1b_telemetry_decoder_cc.h" #define CRC_ERROR_LIMIT 6 @@ -58,12 +59,14 @@ galileo_e5a_make_telemetry_decoder_cc(Gnss_Satellite satellite, long if_freq, lo void galileo_e5a_telemetry_decoder_cc::forecast (int noutput_items, gr_vector_int &ninput_items_required) { - ninput_items_required[0] = GALILEO_FNAV_SYMBOLS_PER_PAGE; // set the required sample history + //ninput_items_required[0] = GALILEO_FNAV_SAMPLES_PER_PAGE; // set the required sample history + ninput_items_required[0] = GALILEO_FNAV_CODES_PER_PREAMBLE; } void galileo_e5a_telemetry_decoder_cc::viterbi_decoder(double *page_part_symbols, int *page_part_bits) { - int CodeLength = 240; +// int CodeLength = 240; + int CodeLength = 488; int DataLength; int nn, KK, mm, max_states; int g_encoder[2]; @@ -72,6 +75,8 @@ void galileo_e5a_telemetry_decoder_cc::viterbi_decoder(double *page_part_symbols KK = 7; // Constraint Length g_encoder[0] = 121; // Polynomial G1 g_encoder[1] = 91; // Polynomial G2 +// g_encoder[0] = 171; // Polynomial G1 +// g_encoder[1] = 133; // Polynomial G2 mm = KK - 1; max_states = 1 << mm; // 2^mm @@ -127,15 +132,14 @@ void galileo_e5a_telemetry_decoder_cc::decode_word(double *page_symbols,int fram page_symbols_deint[i] = -page_symbols_deint[i]; } } - int page_part_bits[frame_length]; - - viterbi_decoder(page_symbols_deint, page_part_bits); + int page_bits[frame_length/2]; + galileo_e5a_telemetry_decoder_cc::viterbi_decoder(page_symbols_deint, page_bits); // 3. Call the Galileo page decoder std::string page_String; for(int i = 0; i < frame_length; i++) { - if (page_part_bits[i] > 0) + if (page_bits[i] > 0) { page_String.push_back('1'); } @@ -202,36 +206,49 @@ galileo_e5a_telemetry_decoder_cc::galileo_e5a_telemetry_decoder_cc( d_fs_in = fs_in; // set the preamble - unsigned short int preambles_bits[GALILEO_INAV_PREAMBLE_LENGTH_BITS] = GALILEO_INAV_PREAMBLE; + //unsigned short int preambles_bits[GALILEO_FNAV_PREAMBLE_LENGTH_BITS] = GALILEO_FNAV_PREAMBLE; + for (int i = 0; i < GALILEO_FNAV_PREAMBLE_LENGTH_BITS; i++) + { + if (GALILEO_FNAV_PREAMBLE.at(i) == '0') + { + d_preamble_bits[i] = 1; + } + else + { + d_preamble_bits[i] = -1; + } + } - //d_symbols_per_preamble = GALILEO_INAV_PREAMBLE_LENGTH_BITS * d_samples_per_symbol; +// memcpy((unsigned short int*)this->d_preambles_bits, (unsigned short int*)preambles_bits, GALILEO_FNAV_PREAMBLE_LENGTH_BITS*sizeof(unsigned short int)); - memcpy((unsigned short int*)this->d_preambles_bits, (unsigned short int*)preambles_bits, GALILEO_INAV_PREAMBLE_LENGTH_BITS*sizeof(unsigned short int)); - - // preamble bits to sampled symbols - d_preambles_symbols = (signed int*)malloc(sizeof(signed int) * GALILEO_FNAV_SAMPLES_PER_PREAMBLE); - int n = 0; - for (int i = 0; i < GALILEO_INAV_PREAMBLE_LENGTH_BITS; i++) - { - for (unsigned int j = 0; j < GALILEO_FNAV_SAMPLES_PER_SYMBOL; j++) - { - if (d_preambles_bits[i] == 1) - { - d_preambles_symbols[n] = 1; - } - else - { - d_preambles_symbols[n] = -1; - } - n++; - } - } +// // preamble bits to sampled symbols +// d_preambles_symbols = (signed int*)malloc(sizeof(signed int) * GALILEO_FNAV_SAMPLES_PER_PREAMBLE); +// int n = 0; +// for (int i = 0; i < GALILEO_FNAV_PREAMBLE_LENGTH_BITS; i++) +// { +// for (unsigned int j = 0; j < GALILEO_FNAV_SAMPLES_PER_SYMBOL; j++) +// { +// if (d_preambles_bits[i] == 1) +// { +// d_preambles_symbols[n] = 1; +// } +// else +// { +// d_preambles_symbols[n] = -1; +// } +// n++; +// } +// } +// d_sample_counter = 0; - //d_stat = 0; + d_state = 0; d_preamble_lock=false; d_preamble_index = 0; d_preamble_time_seconds = 0; d_flag_frame_sync = false; + d_current_symbol_float = 0; + d_prompt_counter = 0; + d_symbol_counter = 0; d_TOW_at_Preamble = 0; d_TOW_at_current_symbol = 0; @@ -241,222 +258,300 @@ galileo_e5a_telemetry_decoder_cc::galileo_e5a_telemetry_decoder_cc( galileo_e5a_telemetry_decoder_cc::~galileo_e5a_telemetry_decoder_cc() { - delete d_preambles_symbols; - d_dump_file.close(); + delete d_preamble_bits; + d_dump_file.close(); } int galileo_e5a_telemetry_decoder_cc::general_work (int noutput_items, gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items) { - int preamble_diff = 0; - int corr_sign=0; - bool corr_flag=true; - - Gnss_Synchro **out = (Gnss_Synchro **) &output_items[0]; - d_sample_counter++; //count for the processed samples - - // ########### Output the tracking data to navigation and PVT ########## + // const Gnss_Synchro **in = (const Gnss_Synchro **) &input_items[0]; //Get the input samples pointer + Gnss_Synchro **out = (Gnss_Synchro **) &output_items[0]; - d_flag_preamble = false; - //******* frame sync ****************** - if (d_preamble_lock == false) - { - // d_preamble_lock tells if we have received a valid preamble and we are waiting - // for the next one. Doesn't ensure frame sync yet. - //******* preamble correlation ******** - // check if the preamble starts positive correlated or negative correlated - if (in[0][0].Prompt_I < 0) // symbols clipping - { - corr_sign=d_preambles_symbols[0]; - } - else - { - corr_sign=-d_preambles_symbols[0]; - } - // the preamble is fully correlated only if maintains corr_sign along the whole sequence - for (int i = 1; i < GALILEO_FNAV_SAMPLES_PER_PREAMBLE; i++) - { - if (in[0][i].Prompt_I < 0 && d_preambles_symbols[i]+corr_sign != 0) - { - //exit for - corr_flag=false; - break; - } - if (in[0][i].Prompt_I > 0 && d_preambles_symbols[i]+corr_sign == 0) - { - //exit for - corr_flag=false; - break; - } - } - if (corr_flag==true) - { - d_preamble_index = d_sample_counter;//record the preamble sample stamp - LOG(INFO) << "Preamble detection for Galileo SAT " << this->d_satellite << std::endl; - d_preamble_lock=true; - } - } - // else, preamble_lock == true , we are waiting for the next preamble at a specific time - else if (d_sample_counter == d_preamble_index + GALILEO_FNAV_SAMPLES_PER_PAGE) - { - // only correlate preamble at the right time - //******* preamble correlation ******** - // check if the preamble starts positive correlated or negative correlated - if (in[0][0].Prompt_I < 0) // symbols clipping - { - corr_sign = d_preambles_symbols[0]; - } - else - { - corr_sign = -d_preambles_symbols[0]; - } - // the preamble is fully correlated only if maintains corr_sign along the whole sequence - for (int i = 1; i < GALILEO_FNAV_SAMPLES_PER_PREAMBLE; i++) - { - if (in[0][i].Prompt_I < 0 && d_preambles_symbols[i] + corr_sign != 0) - { - //exit for - corr_flag = false; - break; - } - if (in[0][i].Prompt_I > 0 - && d_preambles_symbols[i] + corr_sign == 0) - { - //exit for - corr_flag = false; - break; - } - } - if (corr_flag == false) // lost preamble sync - { - d_preamble_lock = false; - LOG(INFO)<< "Lost of frame sync SAT " << this->d_satellite << " preamble_diff= " << preamble_diff; - d_flag_frame_sync = false; - flag_TOW_set = false; - } - else // NEW PAGE RECEIVED - { - // 1 - Obtain message symbols averaging samples (20 samples / symbol) - int frame_length_symbols = GALILEO_FNAV_SYMBOLS_PER_PAGE - - GALILEO_FNAV_PREAMBLE_LENGTH_BITS; - //int page_symbols[frame_length_symbols]; - double samples_to_bit_accumulator[frame_length_symbols]; - //int samples_to_bit_accumulator = 0; - for (int i = 0; i < frame_length_symbols; i++) - { - samples_to_bit_accumulator[i]=0.0; - for (int k = 0; k < GALILEO_FNAV_SAMPLES_PER_SYMBOL; k++) - { - samples_to_bit_accumulator[i] += in[0][k + i*GALILEO_FNAV_SAMPLES_PER_SYMBOL + GALILEO_FNAV_SAMPLES_PER_PREAMBLE].Prompt_I; - // Reminder: corr_sign is negative if phase lock is at 180º -// if (in[0][k + i*GALILEO_FNAV_SAMPLES_PER_SYMBOL + GALILEO_FNAV_SAMPLES_PER_PREAMBLE].Prompt_I -// > 0) -// { -// samples_to_bit_accumulator += corr_sign; -// } -// else -// { -// samples_to_bit_accumulator -= corr_sign; -// } + /* Terminology: Prompt: output from tracking Prompt correlator (Prompt samples) + * Symbol: encoded navigation bits. 1 symbol = 20 samples in E5a + * Bit: decoded navigation bits forming words as described in Galileo ICD + * States: 0 Receiving dummy samples. + * 1 Preamble not locked + * 3 Preamble lock + */ + switch (d_state) + { + case 0: + { + if (in[0][0].Prompt_I != 0) + { + d_current_symbol_float += (float)in[0][0].Prompt_I; + if (d_prompt_counter == GALILEO_FNAV_CODES_PER_SYMBOL - 1) + { + if (d_current_symbol_float > 0) + { + d_page_symbols[d_symbol_counter] = 1; + } + else + { + d_page_symbols[d_symbol_counter] = -1; + } + d_current_symbol_float = 0; + d_symbol_counter++; + d_prompt_counter = 0; + if (d_symbol_counter == GALILEO_FNAV_PREAMBLE_LENGTH_BITS-1) + { + d_state = 1; + } + } + else + { + d_prompt_counter++; + } + } + break; + } + case 1: + { + d_current_symbol_float += (float)in[0][0].Prompt_I; + if (d_prompt_counter == GALILEO_FNAV_CODES_PER_SYMBOL - 1) + { + if (d_current_symbol_float > 0) + { + d_page_symbols[d_symbol_counter] = 1; + } + else + { + d_page_symbols[d_symbol_counter] = -1; + } +// d_page_symbols[d_symbol_counter] = d_current_symbol_float/(float)GALILEO_FNAV_CODES_PER_SYMBOL; + d_current_symbol_float = 0; + d_symbol_counter++; + d_prompt_counter = 0; + // **** Attempt Preamble correlation **** + bool corr_flag=true; + int corr_sign = 0; // sequence can be found inverted +// corr_sign = d_preamble_bits[0] * d_page_symbols[d_symbol_counter - GALILEO_FNAV_PREAMBLE_LENGTH_BITS]; +// for (int i = 1; i < GALILEO_FNAV_PREAMBLE_LENGTH_BITS; i++) +// { +// if ((d_preamble_bits[i] * d_page_symbols[i + d_symbol_counter - GALILEO_FNAV_PREAMBLE_LENGTH_BITS]) != corr_sign) +// { +// //exit for if one bit doesn't correlate +// corr_flag=false; +// break; +// } +// } + // check if the preamble starts positive correlated or negative correlated + if (d_page_symbols[d_symbol_counter - GALILEO_FNAV_PREAMBLE_LENGTH_BITS] < 0) // symbols clipping + { + corr_sign=-d_preamble_bits[0]; + } + else + { + corr_sign=d_preamble_bits[0]; + } + // the preamble is fully correlated only if maintains corr_sign along the whole sequence + for (int i = 1; i < GALILEO_FNAV_PREAMBLE_LENGTH_BITS; i++) + { + if (d_page_symbols[d_symbol_counter - GALILEO_FNAV_PREAMBLE_LENGTH_BITS + i] < 0 && d_preamble_bits[i]+corr_sign != 0) + { + //exit for + corr_flag=false; + break; + } + if (d_page_symbols[d_symbol_counter - GALILEO_FNAV_PREAMBLE_LENGTH_BITS + i] > 0 && d_preamble_bits[i]+corr_sign == 0) + { + //exit for + corr_flag=false; + break; + } + } + // + if (corr_flag==true) // preamble fully correlates + { + d_preamble_index = d_sample_counter - GALILEO_FNAV_CODES_PER_PREAMBLE;//record the preamble sample stamp. Remember correlation appears at the end of the preamble in this design + LOG(INFO) << "Preamble detection for Galileo SAT " << this->d_satellite << std::endl; + d_symbol_counter = 0; // d_page_symbols start right after preamble and finish at the end of next preamble. + d_state = 2; // preamble lock + } + if (d_symbol_counter >= GALILEO_FNAV_SYMBOLS_PER_PAGE + GALILEO_FNAV_PREAMBLE_LENGTH_BITS) + { + d_symbol_counter = GALILEO_FNAV_PREAMBLE_LENGTH_BITS; // prevents overflow + } + } + else + { + d_prompt_counter++; + } + break; + } + case 2: + { + d_current_symbol_float += (float)in[0][0].Prompt_I; + if (d_prompt_counter == GALILEO_FNAV_CODES_PER_SYMBOL - 1) + { + if (d_current_symbol_float > 0) + { + d_page_symbols[d_symbol_counter] = 1; + } + else + { + d_page_symbols[d_symbol_counter] = -1; + } +// d_page_symbols[d_symbol_counter] = d_current_symbol_float/(float)GALILEO_FNAV_CODES_PER_SYMBOL; + d_current_symbol_float = 0; + d_symbol_counter++; + d_prompt_counter = 0; + // At the right sample stamp, check preamble synchro + if (d_sample_counter == d_preamble_index + GALILEO_FNAV_CODES_PER_PAGE + GALILEO_FNAV_CODES_PER_PREAMBLE) + { + // **** Attempt Preamble correlation **** + bool corr_flag = true; + int corr_sign = 0; // sequence can be found inverted +// corr_sign = d_preamble_bits[0] * d_page_symbols[d_symbol_counter - GALILEO_FNAV_PREAMBLE_LENGTH_BITS]; +// for (int i = 1; i < GALILEO_FNAV_PREAMBLE_LENGTH_BITS; i++) +// { +// if ((d_preamble_bits[i] * d_page_symbols[i + d_symbol_counter - GALILEO_FNAV_PREAMBLE_LENGTH_BITS]) != corr_sign) +// { +// //exit for if one bit doesn't correlate +// corr_flag=false; +// break; +// } +// } + // check if the preamble starts positive correlated or negative correlated + if (d_page_symbols[d_symbol_counter - GALILEO_FNAV_PREAMBLE_LENGTH_BITS] < 0) // symbols clipping + { + corr_sign=-d_preamble_bits[0]; + } + else + { + corr_sign=d_preamble_bits[0]; + } + // the preamble is fully correlated only if maintains corr_sign along the whole sequence + for (int i = 1; i < GALILEO_FNAV_PREAMBLE_LENGTH_BITS; i++) + { + if (d_page_symbols[d_symbol_counter - GALILEO_FNAV_PREAMBLE_LENGTH_BITS + i] < 0 && d_preamble_bits[i]+corr_sign != 0) + { + //exit for + corr_flag=false; + break; + } + if (d_page_symbols[d_symbol_counter - GALILEO_FNAV_PREAMBLE_LENGTH_BITS + i] > 0 && d_preamble_bits[i]+corr_sign == 0) + { + //exit for + corr_flag=false; + break; + } + } + // + if (corr_flag==true) // NEW PREAMBLE RECEIVED. DECODE PAGE + { + d_preamble_index = d_sample_counter - GALILEO_FNAV_CODES_PER_PREAMBLE;//record the preamble sample stamp + // Change sign if necessary +// if (corr_sign < 0) +// { +// // NOTE: exists volk library for integers ??? +// for (int i = 0; i < d_symbol_counter; i++) +// { +// d_page_symbols[i] = -d_page_symbols[i]; +// } +// } + // DECODE WORD + decode_word(d_page_symbols, GALILEO_FNAV_SYMBOLS_PER_PAGE - GALILEO_FNAV_PREAMBLE_LENGTH_BITS); + // CHECK CRC + if (d_nav.flag_CRC_test == true) + { + d_CRC_error_counter = 0; + d_flag_preamble = true; //valid preamble indicator (initialized to false every work()) + d_preamble_time_seconds = in[0][0].Tracking_timestamp_secs - ((double)(GALILEO_FNAV_CODES_PER_PAGE+GALILEO_FNAV_CODES_PER_PREAMBLE) * GALILEO_E5a_CODE_PERIOD); //record the PRN start sample index associated to the preamble start. + if (!d_flag_frame_sync) + { + d_flag_frame_sync = true; + LOG(INFO) <<" Frame sync SAT " << this->d_satellite << " with preamble start at " << d_preamble_time_seconds << " [s]"; + } + d_symbol_counter = 0; // d_page_symbols start right after preamble and finish at the end of next preamble. + } + else + { + d_CRC_error_counter++; + if (d_CRC_error_counter > CRC_ERROR_LIMIT) + { + LOG(INFO) << "Lost of frame sync SAT " << this->d_satellite; + d_state = 1; + d_symbol_counter = GALILEO_FNAV_PREAMBLE_LENGTH_BITS; // prevents overflow + d_flag_frame_sync = false; + } + else + { + d_symbol_counter = 0; // d_page_symbols start right after preamble and finish at the end of next preamble. + } + } + } + } + } + else + { + d_prompt_counter++; + } + break; + } + } + consume_each(1); - } - samples_to_bit_accumulator[i] /= corr_sign*GALILEO_FNAV_SAMPLES_PER_SYMBOL; -// if (samples_to_bit_accumulator > 0) -// { -// page_symbols[i] = 1; // because last symbol of the preamble is just received now! -// -// } -// else -// { -// page_symbols[i] = -1; // because last symbol of the preamble is just received now! -// } - } - // DECODE WORD - decode_word(samples_to_bit_accumulator, frame_length_symbols); - // CHECK CRC - if (d_nav.flag_CRC_test == true) - { - d_CRC_error_counter = 0; - d_flag_preamble = true; //valid preamble indicator (initialized to false every work()) - d_preamble_index = d_sample_counter; //record the preamble sample stamp (t_P) - d_preamble_time_seconds = in[0][0].Tracking_timestamp_secs; // - d_preamble_duration_seconds; //record the PRN start sample index associated to the preamble - if (!d_flag_frame_sync) - { - d_flag_frame_sync = true; - LOG(INFO) <<" Frame sync SAT " << this->d_satellite << " with preamble start at " << d_preamble_time_seconds << " [s]"; - } - } - else - { - d_CRC_error_counter++; - d_preamble_index = d_sample_counter; //record the preamble sample stamp - if (d_CRC_error_counter > CRC_ERROR_LIMIT) - { - LOG(INFO) << "Lost of frame sync SAT " << this->d_satellite; - d_flag_frame_sync = false; - d_preamble_lock = false; - } - } - } - } - consume_each(1); //one by one // UPDATE GNSS SYNCHRO DATA Gnss_Synchro current_synchro_data; //structure to save the synchronization information and send the output object to the next block //1. Copy the current tracking output current_synchro_data = in[0][0]; //2. Add the telemetry decoder information if (this->d_flag_preamble == true and d_nav.flag_TOW_set == true) - //update TOW at the preamble instant - //We expect a preamble each 10 seconds (FNAV page period) - { - Prn_timestamp_at_preamble_ms = in[0][0].Tracking_timestamp_secs * 1000.0; - if (d_nav.flag_TOW_1 == true) - { - d_TOW_at_Preamble = d_nav.FNAV_TOW_1; - d_TOW_at_current_symbol = d_TOW_at_Preamble; - d_nav.flag_TOW_1 = false; - } - if (d_nav.flag_TOW_2 == true) - { - d_TOW_at_Preamble = d_nav.FNAV_TOW_2; - d_TOW_at_current_symbol = d_TOW_at_Preamble; - d_nav.flag_TOW_2 = false; - } - if (d_nav.flag_TOW_3 == true) - { - d_TOW_at_Preamble = d_nav.FNAV_TOW_3; - d_TOW_at_current_symbol = d_TOW_at_Preamble; - d_nav.flag_TOW_3 = false; - } - if (d_nav.flag_TOW_4 == true) - { - d_TOW_at_Preamble = d_nav.FNAV_TOW_4; - d_TOW_at_current_symbol = d_TOW_at_Preamble; - d_nav.flag_TOW_4 = false; - } - else - { - //this page has no timming information - d_TOW_at_Preamble = d_TOW_at_Preamble + GALILEO_FNAV_SECONDS_PER_PAGE; - d_TOW_at_current_symbol = d_TOW_at_current_symbol + GALILEO_E5a_CODE_PERIOD; - } + //update TOW at the preamble instant + //We expect a preamble each 10 seconds (FNAV page period) + { + Prn_timestamp_at_preamble_ms = d_preamble_time_seconds * 1000; + //Prn_timestamp_at_preamble_ms = in[0][0].Tracking_timestamp_secs * 1000.0; + if (d_nav.flag_TOW_1 == true) + { + d_TOW_at_Preamble = d_nav.FNAV_TOW_1; + d_TOW_at_current_symbol = d_TOW_at_Preamble + ((double)(GALILEO_FNAV_CODES_PER_PAGE+GALILEO_FNAV_CODES_PER_PREAMBLE) * GALILEO_E5a_CODE_PERIOD); + d_nav.flag_TOW_1 = false; + } + if (d_nav.flag_TOW_2 == true) + { + d_TOW_at_Preamble = d_nav.FNAV_TOW_2; + d_TOW_at_current_symbol = d_TOW_at_Preamble + ((double)(GALILEO_FNAV_CODES_PER_PAGE+GALILEO_FNAV_CODES_PER_PREAMBLE) * GALILEO_E5a_CODE_PERIOD); + d_nav.flag_TOW_2 = false; + } + if (d_nav.flag_TOW_3 == true) + { + d_TOW_at_Preamble = d_nav.FNAV_TOW_3; + d_TOW_at_current_symbol = d_TOW_at_Preamble + ((double)(GALILEO_FNAV_CODES_PER_PAGE+GALILEO_FNAV_CODES_PER_PREAMBLE) * GALILEO_E5a_CODE_PERIOD); + d_nav.flag_TOW_3 = false; + } + if (d_nav.flag_TOW_4 == true) + { + d_TOW_at_Preamble = d_nav.FNAV_TOW_4; + d_TOW_at_current_symbol = d_TOW_at_Preamble + ((double)(GALILEO_FNAV_CODES_PER_PAGE+GALILEO_FNAV_CODES_PER_PREAMBLE) * GALILEO_E5a_CODE_PERIOD); + d_nav.flag_TOW_4 = false; + } + else + { + //this page has no timming information + d_TOW_at_Preamble = d_TOW_at_Preamble + GALILEO_FNAV_SECONDS_PER_PAGE; + d_TOW_at_current_symbol = d_TOW_at_current_symbol + GALILEO_E5a_CODE_PERIOD; + } - } + } else //if there is not a new preamble, we define the TOW of the current symbol - { - d_TOW_at_current_symbol = d_TOW_at_current_symbol + GALILEO_E5a_CODE_PERIOD; - } + { + d_TOW_at_current_symbol = d_TOW_at_current_symbol + GALILEO_E5a_CODE_PERIOD; + } //if (d_flag_frame_sync == true and d_nav.flag_TOW_set==true and d_nav.flag_CRC_test == true) if (d_flag_frame_sync == true and d_nav.flag_TOW_set == true) - { - current_synchro_data.Flag_valid_word = true; - } + { + current_synchro_data.Flag_valid_word = true; + } else - { - current_synchro_data.Flag_valid_word = false; - } + { + current_synchro_data.Flag_valid_word = false; + } current_synchro_data.d_TOW = d_TOW_at_Preamble; current_synchro_data.d_TOW_at_current_symbol = d_TOW_at_current_symbol; @@ -465,23 +560,24 @@ int galileo_e5a_telemetry_decoder_cc::general_work (int noutput_items, gr_vector current_synchro_data.Prn_timestamp_at_preamble_ms = Prn_timestamp_at_preamble_ms; if(d_dump == true) - { - // MULTIPLEXED FILE RECORDING - Record results to file - try - { - double tmp_double; - tmp_double = d_TOW_at_current_symbol; - d_dump_file.write((char*)&tmp_double, sizeof(double)); - tmp_double = current_synchro_data.Prn_timestamp_ms; - d_dump_file.write((char*)&tmp_double, sizeof(double)); - tmp_double = d_TOW_at_Preamble; - d_dump_file.write((char*)&tmp_double, sizeof(double)); - } - catch (const std::ifstream::failure& e) - { - LOG(WARNING) << "Exception writing observables dump file " << e.what(); - } - } + { + // MULTIPLEXED FILE RECORDING - Record results to file + try + { + double tmp_double; + tmp_double = d_TOW_at_current_symbol; + d_dump_file.write((char*)&tmp_double, sizeof(double)); + tmp_double = current_synchro_data.Prn_timestamp_ms; + d_dump_file.write((char*)&tmp_double, sizeof(double)); + tmp_double = d_TOW_at_Preamble; + d_dump_file.write((char*)&tmp_double, sizeof(double)); + } + catch (const std::ifstream::failure& e) + { + LOG(WARNING) << "Exception writing observables dump file " << e.what(); + } + } + d_sample_counter++; //count for the processed samples //3. Make the output (copy the object contents to the GNURadio reserved memory) *out[0] = current_synchro_data; return 1; diff --git a/src/algorithms/telemetry_decoder/gnuradio_blocks/galileo_e5a_telemetry_decoder_cc.h b/src/algorithms/telemetry_decoder/gnuradio_blocks/galileo_e5a_telemetry_decoder_cc.h index 773a65d71..5f38cc09a 100644 --- a/src/algorithms/telemetry_decoder/gnuradio_blocks/galileo_e5a_telemetry_decoder_cc.h +++ b/src/algorithms/telemetry_decoder/gnuradio_blocks/galileo_e5a_telemetry_decoder_cc.h @@ -96,15 +96,20 @@ private: void decode_word(double *page_symbols,int frame_length); - unsigned short int d_preambles_bits[GALILEO_FNAV_PREAMBLE_LENGTH_BITS]; - - signed int *d_preambles_symbols; + signed int d_preamble_bits[GALILEO_FNAV_PREAMBLE_LENGTH_BITS]; +// signed int d_page_symbols[GALILEO_FNAV_SYMBOLS_PER_PAGE + GALILEO_FNAV_PREAMBLE_LENGTH_BITS]; + double d_page_symbols[GALILEO_FNAV_SYMBOLS_PER_PAGE + GALILEO_FNAV_PREAMBLE_LENGTH_BITS]; + signed int *d_preamble_symbols; + float d_current_symbol_float; + long unsigned int d_symbol_counter; + int d_prompt_counter; long unsigned int d_sample_counter; long unsigned int d_preamble_index; bool d_preamble_lock; bool d_flag_frame_sync; + int d_state; bool d_flag_preamble; int d_CRC_error_counter; diff --git a/src/algorithms/telemetry_decoder/libs/convolutional.h b/src/algorithms/telemetry_decoder/libs/convolutional.h index a225d2c2c..ed2a952b8 100644 --- a/src/algorithms/telemetry_decoder/libs/convolutional.h +++ b/src/algorithms/telemetry_decoder/libs/convolutional.h @@ -441,7 +441,7 @@ static void Viterbi(int output_u_int[], for (t = 0; t < LL + mm; t++) { for (i = 0; i < nn; i++) - rec_array[i] = (float)input_c[nn*t + i]; + rec_array[i] = (float)input_c[nn*t + i]; /* precompute all possible branch metrics */ for (i = 0; i < number_symbols; i++) diff --git a/src/algorithms/tracking/adapters/CMakeLists.txt b/src/algorithms/tracking/adapters/CMakeLists.txt index 7415e5e1c..4db5df1db 100644 --- a/src/algorithms/tracking/adapters/CMakeLists.txt +++ b/src/algorithms/tracking/adapters/CMakeLists.txt @@ -24,7 +24,6 @@ set(TRACKING_ADAPTER_SOURCES gps_l1_ca_dll_pll_optim_tracking.cc gps_l1_ca_dll_pll_tracking.cc gps_l1_ca_tcp_connector_tracking.cc - galileo_e5a_dll_fll_pll_tracking.cc galileo_e5a_dll_pll_tracking.cc ) diff --git a/src/algorithms/tracking/adapters/galileo_e5a_dll_fll_pll_tracking.cc b/src/algorithms/tracking/adapters/galileo_e5a_dll_fll_pll_tracking.cc deleted file mode 100644 index 2caf9b3c2..000000000 --- a/src/algorithms/tracking/adapters/galileo_e5a_dll_fll_pll_tracking.cc +++ /dev/null @@ -1,149 +0,0 @@ -/*! - * \file galileo_e5a_dll_fll_pll_tracking_cc.h - * \brief Adapts code DLL + carrier PLL aided with FLL - * tracking block to TrackingInterface for Galileo E5a signals - * \author Marc Sales, 2014. marcsales92(at)gmail.com - * - * ------------------------------------------------------------------------- - * - * Copyright (C) 2010-2014 (see AUTHORS file for a list of contributors) - * - * GNSS-SDR is a software defined Global Navigation - * Satellite Systems receiver - * - * This file is part of GNSS-SDR. - * - * GNSS-SDR is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * at your option) any later version. - * - * GNSS-SDR is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNSS-SDR. If not, see . - * - * ------------------------------------------------------------------------- - */ -#include "galileo_e5a_dll_fll_pll_tracking.h" -#include -#include "Galileo_E5a.h" -#include "configuration_interface.h" - -using google::LogMessage; - -GalileoE5aDllFllPllTracking::GalileoE5aDllFllPllTracking( - ConfigurationInterface* configuration, - std::string role, - unsigned int in_streams, unsigned int - out_streams, - boost::shared_ptr queue) : - role_(role), - in_streams_(in_streams), - out_streams_(out_streams), - queue_(queue) -{ - DLOG(INFO) << "role " << role; - //################# CONFIGURATION PARAMETERS ######################## - int fs_in; - int vector_length; - int f_if; - bool dump; - std::string dump_filename; - std::string item_type; - std::string default_item_type = "gr_complex"; - float pll_bw_hz; - float fll_bw_hz; - float dll_bw_hz; - float early_late_space_chips; - int order; - item_type = configuration->property(role + ".item_type",default_item_type); - //vector_length = configuration->property(role + ".vector_length", 2048); - fs_in = configuration->property("GNSS-SDR.internal_fs_hz", 2048000); - f_if = configuration->property(role + ".if", 0); - dump = configuration->property(role + ".dump", false); - order = configuration->property(role + ".order", 2); - pll_bw_hz = configuration->property(role + ".pll_bw_hz", 50.0); - fll_bw_hz = configuration->property(role + ".fll_bw_hz", 100.0); - dll_bw_hz = configuration->property(role + ".dll_bw_hz", 2.0); - early_late_space_chips = configuration->property(role + ".early_late_space_chips", 0.5); - std::string default_dump_filename = "./track_ch"; - dump_filename = configuration->property(role + ".dump_filename", - default_dump_filename); //unused! - vector_length = round(fs_in / (Galileo_E5a_CODE_CHIP_RATE_HZ / Galileo_E5a_CODE_LENGTH_CHIPS)); - - //################# MAKE TRACKING GNURadio object ################### - if (item_type.compare("gr_complex") == 0) - { - item_size_ = sizeof(gr_complex); - tracking_ = galileo_e5a_dll_fll_pll_make_tracking_cc( - f_if, - fs_in, - vector_length, - queue_, - dump, - dump_filename, - order, - fll_bw_hz, - pll_bw_hz, - dll_bw_hz, - early_late_space_chips); - } - else - { - LOG(WARNING) << item_type << " unknown tracking item type."; - } - - DLOG(INFO) << "tracking(" << tracking_->unique_id() << ")"; -} - - -GalileoE5aDllFllPllTracking::~GalileoE5aDllFllPllTracking() -{} - - -void GalileoE5aDllFllPllTracking::start_tracking() -{ - tracking_->start_tracking(); -} - -void GalileoE5aDllFllPllTracking::set_channel(unsigned int channel) -{ - channel_ = channel; - tracking_->set_channel(channel); -} - -void GalileoE5aDllFllPllTracking::set_channel_queue( - concurrent_queue *channel_internal_queue) -{ - channel_internal_queue_ = channel_internal_queue; - tracking_->set_channel_queue(channel_internal_queue_); -} - -void GalileoE5aDllFllPllTracking::set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) -{ - return tracking_->set_gnss_synchro(p_gnss_synchro); -} - -void GalileoE5aDllFllPllTracking::connect(gr::top_block_sptr top_block) -{ - //nothing to connect, now the tracking uses gr_sync_decimator -} - -void GalileoE5aDllFllPllTracking::disconnect(gr::top_block_sptr top_block) -{ - //nothing to disconnect, now the tracking uses gr_sync_decimator -} - -gr::basic_block_sptr GalileoE5aDllFllPllTracking::get_left_block() -{ - return tracking_; -} - -gr::basic_block_sptr GalileoE5aDllFllPllTracking::get_right_block() -{ - return tracking_; -} diff --git a/src/algorithms/tracking/adapters/galileo_e5a_dll_fll_pll_tracking.h b/src/algorithms/tracking/adapters/galileo_e5a_dll_fll_pll_tracking.h deleted file mode 100644 index 176b30779..000000000 --- a/src/algorithms/tracking/adapters/galileo_e5a_dll_fll_pll_tracking.h +++ /dev/null @@ -1,90 +0,0 @@ -/*! - * \file galileo_e5a_dll_fll_pll_tracking_cc.h - * \brief Adapts code DLL + carrier PLL aided with FLL - * tracking block to TrackingInterface for Galileo E5a signals - * \author Marc Sales, 2014. marcsales92(at)gmail.com - * - * ------------------------------------------------------------------------- - * - * Copyright (C) 2010-2014 (see AUTHORS file for a list of contributors) - * - * GNSS-SDR is a software defined Global Navigation - * Satellite Systems receiver - * - * This file is part of GNSS-SDR. - * - * GNSS-SDR is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * at your option) any later version. - * - * GNSS-SDR is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNSS-SDR. If not, see . - * - * ------------------------------------------------------------------------- - */ - -#ifndef GNSS_SDR_GALILEO_E5A_DLL_FLL_PLL_TRACKING_H_ -#define GNSS_SDR_GALILEO_E5A_DLL_FLL_PLL_TRACKING_H_ - -#include -#include -#include "tracking_interface.h" -#include "galileo_e5a_dll_fll_pll_tracking_cc.h" - -class ConfigurationInterface; - -class GalileoE5aDllFllPllTracking: public TrackingInterface -{ -public: - - GalileoE5aDllFllPllTracking(ConfigurationInterface* configuration, - std::string role, - unsigned int in_streams, - unsigned int out_streams, - boost::shared_ptr queue); - - virtual ~GalileoE5aDllFllPllTracking(); - - std::string role() - { - return role_; - } - - //! Returns "Galileo_E5a_DLL_FLL_PLL_Tracking" - std::string implementation() - { - return "Galileo_E5a_DLL_FLL_PLL_Tracking"; - } - size_t item_size() - { - return item_size_; - } - - void connect(gr::top_block_sptr top_block); - void disconnect(gr::top_block_sptr top_block); - gr::basic_block_sptr get_left_block(); - gr::basic_block_sptr get_right_block(); - - void set_channel(unsigned int channel); - void set_channel_queue(concurrent_queue *channel_internal_queue); - void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro); - void start_tracking(); - -private: - galileo_e5a_dll_fll_pll_tracking_cc_sptr tracking_; - size_t item_size_; - unsigned int channel_; - std::string role_; - unsigned int in_streams_; - unsigned int out_streams_; - boost::shared_ptr queue_; - concurrent_queue *channel_internal_queue_; -}; - -#endif /* GNSS_SDR_GALILEO_E5A_DLL_FLL_PLL_TRACKING_H_ */ diff --git a/src/algorithms/tracking/adapters/galileo_e5a_dll_pll_tracking.cc b/src/algorithms/tracking/adapters/galileo_e5a_dll_pll_tracking.cc index 64ba9ba65..2cd33c004 100644 --- a/src/algorithms/tracking/adapters/galileo_e5a_dll_pll_tracking.cc +++ b/src/algorithms/tracking/adapters/galileo_e5a_dll_pll_tracking.cc @@ -31,14 +31,21 @@ GalileoE5aDllPllTracking::GalileoE5aDllPllTracking( std::string default_item_type = "gr_complex"; float pll_bw_hz; float dll_bw_hz; + float pll_bw_init_hz; + float dll_bw_init_hz; + int ti_ms; float early_late_space_chips; item_type = configuration->property(role + ".item_type", default_item_type); //vector_length = configuration->property(role + ".vector_length", 2048); fs_in = configuration->property("GNSS-SDR.internal_fs_hz", 12000000); f_if = configuration->property(role + ".if", 0); dump = configuration->property(role + ".dump", false); - pll_bw_hz = configuration->property(role + ".pll_bw_hz", 50.0); + pll_bw_hz = configuration->property(role + ".pll_bw_hz", 5.0); dll_bw_hz = configuration->property(role + ".dll_bw_hz", 2.0); + pll_bw_init_hz = configuration->property(role + ".pll_bw_init_hz", 20.0); + dll_bw_init_hz = configuration->property(role + ".dll_bw_init_hz", 20.0); + ti_ms = configuration->property(role + ".ti_ms", 3); + early_late_space_chips = configuration->property(role + ".early_late_space_chips", 0.5); std::string default_dump_filename = "./track_ch"; dump_filename = configuration->property(role + ".dump_filename", @@ -58,6 +65,9 @@ GalileoE5aDllPllTracking::GalileoE5aDllPllTracking( dump_filename, pll_bw_hz, dll_bw_hz, + pll_bw_init_hz, + dll_bw_init_hz, + ti_ms, early_late_space_chips); } else diff --git a/src/algorithms/tracking/gnuradio_blocks/CMakeLists.txt b/src/algorithms/tracking/gnuradio_blocks/CMakeLists.txt index 70376a3f3..1a7e4be6e 100644 --- a/src/algorithms/tracking/gnuradio_blocks/CMakeLists.txt +++ b/src/algorithms/tracking/gnuradio_blocks/CMakeLists.txt @@ -23,7 +23,6 @@ set(TRACKING_GR_BLOCKS_SOURCES gps_l1_ca_dll_pll_optim_tracking_cc.cc gps_l1_ca_dll_pll_tracking_cc.cc gps_l1_ca_tcp_connector_tracking_cc.cc - galileo_e5a_dll_fll_pll_tracking_cc.cc galileo_e5a_dll_pll_tracking_cc.cc ) diff --git a/src/algorithms/tracking/gnuradio_blocks/galileo_e5a_dll_fll_pll_tracking_cc.cc b/src/algorithms/tracking/gnuradio_blocks/galileo_e5a_dll_fll_pll_tracking_cc.cc deleted file mode 100644 index 1c1ab9f70..000000000 --- a/src/algorithms/tracking/gnuradio_blocks/galileo_e5a_dll_fll_pll_tracking_cc.cc +++ /dev/null @@ -1,670 +0,0 @@ -/*! - * \file galileo_e5a_dll_fll_pll_tracking_cc.h - * \brief Implementation of a code DLL + carrier PLL aided with FLL - * tracking block for Galileo E5a signals - * \author Marc Sales, 2014. marcsales92(at)gmail.com - * - * ------------------------------------------------------------------------- - * - * Copyright (C) 2010-2014 (see AUTHORS file for a list of contributors) - * - * GNSS-SDR is a software defined Global Navigation - * Satellite Systems receiver - * - * This file is part of GNSS-SDR. - * - * GNSS-SDR is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * at your option) any later version. - * - * GNSS-SDR is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNSS-SDR. If not, see . - * - * ------------------------------------------------------------------------- - */ - -#include "galileo_e5a_dll_fll_pll_tracking_cc.h" -#include -#include -#include -#include -#include -#include -#include "gnss_synchro.h" -#include "galileo_e5_signal_processing.h" -#include "Galileo_E5a.h" -#include "Galileo_E1.h" -#include "tracking_discriminators.h" -#include "lock_detectors.h" -#include "tracking_FLL_PLL_filter.h" -#include "control_message_factory.h" -#include "gnss_flowgraph.h" - -/*! - * \todo Include in definition header file - */ -#define CN0_ESTIMATION_SAMPLES 20 -#define MINIMUM_VALID_CN0 25 -#define MAXIMUM_LOCK_FAIL_COUNTER 50 -#define CARRIER_LOCK_THRESHOLD 0.85 - -using google::LogMessage; - -galileo_e5a_dll_fll_pll_tracking_cc_sptr galileo_e5a_dll_fll_pll_make_tracking_cc( - long if_freq, - long fs_in, - unsigned - int vector_length, - boost::shared_ptr queue, - bool dump, std::string dump_filename, - int order, - float fll_bw_hz, - float pll_bw_hz, - float dll_bw_hz, - float early_late_space_chips) -{ - - return galileo_e5a_dll_fll_pll_tracking_cc_sptr(new galileo_e5a_dll_fll_pll_tracking_cc(if_freq, - fs_in, vector_length, queue, dump, dump_filename, order, fll_bw_hz, pll_bw_hz,dll_bw_hz, - early_late_space_chips)); -} - - - - -void galileo_e5a_dll_fll_pll_tracking_cc::forecast (int noutput_items, gr_vector_int &ninput_items_required) -{ - ninput_items_required[0] = d_vector_length*2; //set the required available samples in each call -} - - -galileo_e5a_dll_fll_pll_tracking_cc::galileo_e5a_dll_fll_pll_tracking_cc( - long if_freq, - long fs_in, - unsigned int vector_length, - boost::shared_ptr queue, - bool dump, - std::string dump_filename, - int order, - float fll_bw_hz, - float pll_bw_hz, - float dll_bw_hz, - float early_late_space_chips) : - gr::block("galileo_e5a_dll_fll_pll_tracking_cc", gr::io_signature::make(1, 1, sizeof(gr_complex)), - gr::io_signature::make(1, 1, sizeof(Gnss_Synchro))) -{ - this->set_relative_rate(1.0/vector_length); - // initialize internal vars - d_queue = queue; - d_dump = dump; - - d_acquisition_gnss_synchro = NULL; - - d_if_freq = (double)if_freq; - d_fs_in = (double)fs_in; - d_vector_length = vector_length; - d_early_late_spc_chips = (double)early_late_space_chips; // Define early-late offset (in chips) - d_dump_filename = dump_filename; - - //d_sampled_codeLength = round(d_fs_in / (Galileo_E5a_CODE_CHIP_RATE_HZ / Galileo_E5a_CODE_LENGTH_CHIPS)); - // Initialize tracking variables ========================================== - d_carrier_loop_filter.set_params(fll_bw_hz, pll_bw_hz,order); - - d_code_loop_filter = Tracking_2nd_DLL_filter(GALILEO_E5a_CODE_PERIOD); - d_code_loop_filter.set_DLL_BW(dll_bw_hz); - - // Get space for a vector with the C/A code replica sampled 1x/chip - d_ca_code = new gr_complex[(int)Galileo_E5a_CODE_LENGTH_CHIPS + 2]; - - /* If an array is partitioned for more than one thread to operate on, - * having the sub-array boundaries unaligned to cache lines could lead - * to performance degradation. Here we allocate memory - * (gr_complex array of size 2*d_vector_length) aligned to cache of 16 bytes - */ - // todo: do something if posix_memalign fails - // Get space for the resampled early / prompt / late local replicas - if (posix_memalign((void**)&d_early_code, 16, d_vector_length * sizeof(gr_complex) * 2) == 0){}; - if (posix_memalign((void**)&d_late_code, 16, d_vector_length * sizeof(gr_complex) * 2) == 0){}; - if (posix_memalign((void**)&d_prompt_code, 16, d_vector_length * sizeof(gr_complex) * 2) == 0){}; - // space for carrier wipeoff and signal baseband vectors - if (posix_memalign((void**)&d_carr_sign, 16, d_vector_length * sizeof(gr_complex) * 2) == 0){}; - if (posix_memalign((void**)&d_Early, 16, sizeof(gr_complex)) == 0){}; - if (posix_memalign((void**)&d_Prompt, 16, sizeof(gr_complex)) == 0){}; - if (posix_memalign((void**)&d_Late, 16, sizeof(gr_complex)) == 0){}; - - // sample synchronization - d_sample_counter = 0; - d_acq_sample_stamp = 0; - d_last_seg = 0;// this is for debug output only - d_code_phase_samples = 0; - d_enable_tracking = false; - d_current_prn_length_samples = (int)d_vector_length; - - // CN0 estimation and lock detector buffers - d_cn0_estimation_counter = 0; - d_Prompt_buffer = new gr_complex[CN0_ESTIMATION_SAMPLES]; - d_carrier_lock_test = 1; - d_CN0_SNV_dB_Hz = 0; - d_carrier_lock_fail_counter = 0; - d_carrier_lock_threshold = CARRIER_LOCK_THRESHOLD; - - systemName["G"] = std::string("GPS"); - systemName["R"] = std::string("GLONASS"); - systemName["S"] = std::string("SBAS"); - systemName["E"] = std::string("Galileo"); - systemName["C"] = std::string("Compass"); -} - - - - -void galileo_e5a_dll_fll_pll_tracking_cc::start_tracking() -{ - /* - * correct the code phase according to the delay between acq and trk - */ - d_acq_code_phase_samples = d_acquisition_gnss_synchro->Acq_delay_samples; - d_acq_carrier_doppler_hz = d_acquisition_gnss_synchro->Acq_doppler_hz; - d_acq_sample_stamp = d_acquisition_gnss_synchro->Acq_samplestamp_samples; - - long int acq_trk_diff_samples; - float acq_trk_diff_seconds; - acq_trk_diff_samples = (long int)d_sample_counter - (long int)d_acq_sample_stamp; - acq_trk_diff_seconds = (double)acq_trk_diff_samples / d_fs_in; - //doppler effect - // Fd=(C/(C+Vr))*F - double radial_velocity; - radial_velocity = (Galileo_E5a_FREQ_HZ + d_acq_carrier_doppler_hz) / Galileo_E5a_FREQ_HZ; - // new chip and prn sequence periods based on acq Doppler - double T_chip_mod_seconds; - double T_prn_mod_seconds; - double T_prn_mod_samples; - d_code_freq_hz = radial_velocity * Galileo_E5a_CODE_CHIP_RATE_HZ; - T_chip_mod_seconds = 1 / d_code_freq_hz; - T_prn_mod_seconds = T_chip_mod_seconds * Galileo_E5a_CODE_LENGTH_CHIPS; - T_prn_mod_samples = T_prn_mod_seconds * d_fs_in; - d_current_prn_length_samples = round(T_prn_mod_samples); - - double T_prn_true_seconds = Galileo_E5a_CODE_LENGTH_CHIPS / Galileo_E5a_CODE_CHIP_RATE_HZ; - double T_prn_true_samples = T_prn_true_seconds * d_fs_in; - double T_prn_diff_seconds; - T_prn_diff_seconds = T_prn_true_seconds - T_prn_mod_seconds; - double N_prn_diff; - N_prn_diff = acq_trk_diff_seconds / T_prn_true_seconds; - double corrected_acq_phase_samples, delay_correction_samples; - corrected_acq_phase_samples = fmod((d_acq_code_phase_samples + T_prn_diff_seconds * N_prn_diff * d_fs_in), T_prn_true_samples); - - if (corrected_acq_phase_samples < 0) - { - corrected_acq_phase_samples = T_prn_mod_samples + corrected_acq_phase_samples; - } - delay_correction_samples = d_acq_code_phase_samples - corrected_acq_phase_samples; - d_acq_code_phase_samples = corrected_acq_phase_samples; - - d_carrier_doppler_hz = d_acq_carrier_doppler_hz; - // DLL/PLL filter initialization - d_carrier_loop_filter.initialize(d_acq_carrier_doppler_hz); - d_FLL_wait = 1; - - // generate local reference ALWAYS starting at chip 1 (1 sample per chip) - galileo_e5_a_code_gen_complex_sampled(&d_ca_code[1], d_acquisition_gnss_synchro->Signal, d_acquisition_gnss_synchro->PRN, d_fs_in,0,false); - - d_ca_code[0] = d_ca_code[(int)Galileo_E5a_CODE_LENGTH_CHIPS]; - d_ca_code[(int)Galileo_E5a_CODE_LENGTH_CHIPS + 1] = d_ca_code[1]; - - d_carrier_lock_fail_counter = 0; - d_Prompt_prev = 0; - d_rem_code_phase_samples = 0; - d_rem_carr_phase = 0; - d_FLL_discriminator_hz = 0; - d_rem_code_phase_samples = 0; - d_acc_carrier_phase_rad = 0; - - std::string sys_ = &d_acquisition_gnss_synchro->System; - sys = sys_.substr(0,1); - - // DEBUG OUTPUT - std::cout << "Tracking start on channel " << d_channel << " for satellite " << Gnss_Satellite(systemName[sys], d_acquisition_gnss_synchro->PRN) << std::endl; - LOG(INFO) << "Starting tracking of satellite " << Gnss_Satellite(systemName[sys], d_acquisition_gnss_synchro->PRN) << " on channel " << d_channel; - - // enable tracking Gnss_Satellite(systemName[&d_acquisition_gnss_synchro->System], d_acquisition_gnss_synchro->PRN) - d_pull_in = true; - d_enable_tracking = true; - - LOG(INFO) << "PULL-IN Doppler [Hz]= " << d_carrier_doppler_hz - << " Code Phase correction [samples]=" << delay_correction_samples - << " PULL-IN Code Phase [samples]= " << d_acq_code_phase_samples << std::endl; -} - - - - - -void galileo_e5a_dll_fll_pll_tracking_cc::update_local_code() -{ - double tcode_chips; - double rem_code_phase_chips; - double code_phase_step_chips; - int early_late_spc_samples; - int epl_loop_length_samples; - - int associated_chip_index; - int code_length_chips = (int)Galileo_E5a_CODE_LENGTH_CHIPS; - code_phase_step_chips = d_code_freq_hz / d_fs_in; - rem_code_phase_chips = d_rem_code_phase_samples * (d_code_freq_hz / d_fs_in); - // unified loop for E, P, L code vectors - tcode_chips = -rem_code_phase_chips; - // Alternative EPL code generation (40% of speed improvement!) - early_late_spc_samples = round(d_early_late_spc_chips/code_phase_step_chips); - epl_loop_length_samples = d_current_prn_length_samples + early_late_spc_samples*2; - for (int i = 0; i < epl_loop_length_samples; i++) - { - associated_chip_index = 1 + round(fmod(tcode_chips - d_early_late_spc_chips, code_length_chips)); - d_early_code[i] = d_ca_code[associated_chip_index]; - tcode_chips = tcode_chips + code_phase_step_chips; - } - - memcpy(d_prompt_code,&d_early_code[early_late_spc_samples],d_current_prn_length_samples* sizeof(gr_complex)); - memcpy(d_late_code,&d_early_code[early_late_spc_samples*2],d_current_prn_length_samples* sizeof(gr_complex)); - - // for (int i=0; itelemetry_decoder - Gnss_Synchro current_synchro_data; - // Fill the acquisition data - current_synchro_data = *d_acquisition_gnss_synchro; - /* - * Receiver signal alignment - */ - if (d_pull_in == true) - { - int samples_offset; - double acq_trk_shif_correction_samples; - int acq_to_trk_delay_samples; - acq_to_trk_delay_samples = d_sample_counter-d_acq_sample_stamp; - acq_trk_shif_correction_samples = d_current_prn_length_samples - fmod((double)acq_to_trk_delay_samples, (double)d_current_prn_length_samples); - samples_offset = round(d_acq_code_phase_samples + acq_trk_shif_correction_samples); - // /todo: Check if the sample counter sent to the next block as a time reference should be incremented AFTER sended or BEFORE - d_sample_counter = d_sample_counter + samples_offset; //count for the processed samples - d_pull_in = false; - consume_each(samples_offset); //shift input to perform alignment with local replica - - // make an output to not stop the rest of the processing blocks - current_synchro_data.Prompt_I = 0.0; - current_synchro_data.Prompt_Q = 0.0; - current_synchro_data.Tracking_timestamp_secs = (double)d_sample_counter/d_fs_in; - current_synchro_data.Carrier_phase_rads = 0.0; - current_synchro_data.Code_phase_secs = 0.0; - current_synchro_data.CN0_dB_hz = 0.0; - current_synchro_data.Flag_valid_tracking = false; - - *out[0] = current_synchro_data; - - return 1; - } - - update_local_code(); - update_local_carrier(); - - // perform Early, Prompt and Late correlation - d_correlator.Carrier_wipeoff_and_EPL_volk(d_current_prn_length_samples, - in, - d_carr_sign, - d_early_code, - d_prompt_code, - d_late_code, - d_Early, - d_Prompt, - d_Late, - is_unaligned()); - // check for samples consistency (this should be done before in the receiver / here only if the source is a file) - if (isnan((*d_Prompt).real()) == true or isnan((*d_Prompt).imag()) == true )// or std::isinf(in[i].real())==true or std::isinf(in[i].imag())==true) - { - const int samples_available = ninput_items[0]; - d_sample_counter = d_sample_counter + samples_available; - LOG(WARNING) << "Detected NaN samples at sample number " << d_sample_counter; - consume_each(samples_available); - - // make an output to not stop the rest of the processing blocks - current_synchro_data.Prompt_I = 0.0; - current_synchro_data.Prompt_Q = 0.0; - current_synchro_data.Tracking_timestamp_secs = (double)d_sample_counter/d_fs_in; - current_synchro_data.Carrier_phase_rads = 0.0; - current_synchro_data.Code_phase_secs = 0.0; - current_synchro_data.CN0_dB_hz = 0.0; - current_synchro_data.Flag_valid_tracking = false; - - *out[0] =current_synchro_data; - - return 1; - } - - /* - * DLL, FLL, and PLL discriminators - */ - // Compute DLL error - code_error_chips = dll_nc_e_minus_l_normalized(*d_Early, *d_Late); - // Compute DLL filtered error - code_error_filt_chips = d_code_loop_filter.get_code_nco(code_error_chips); - - //compute FLL error - correlation_time_s = ((double)d_current_prn_length_samples) / d_fs_in; - if (d_FLL_wait == 1) - { - d_Prompt_prev = *d_Prompt; - d_FLL_wait = 0; - } - else - { - d_FLL_discriminator_hz = fll_four_quadrant_atan(d_Prompt_prev, *d_Prompt, 0, correlation_time_s) / GPS_TWO_PI; - d_Prompt_prev = *d_Prompt; - d_FLL_wait = 1; - } - - // Compute PLL error - PLL_discriminator_hz = pll_cloop_two_quadrant_atan(*d_Prompt) / GPS_TWO_PI; - - /* - * DLL and FLL+PLL filter and get current carrier Doppler and code frequency - */ - carr_nco_hz = d_carrier_loop_filter.get_carrier_error(d_FLL_discriminator_hz, PLL_discriminator_hz, correlation_time_s); - d_carrier_doppler_hz = d_if_freq + carr_nco_hz; - - d_code_freq_hz = Galileo_E5a_CODE_CHIP_RATE_HZ + (((d_carrier_doppler_hz + d_if_freq) * Galileo_E5a_CODE_CHIP_RATE_HZ) / Galileo_E5a_FREQ_HZ); - - /*! - * \todo Improve the lock detection algorithm! - */ - // ####### CN0 ESTIMATION AND LOCK DETECTORS ###### - if (d_cn0_estimation_counter < CN0_ESTIMATION_SAMPLES) - { - // fill buffer with prompt correlator output values - d_Prompt_buffer[d_cn0_estimation_counter] = *d_Prompt; - d_cn0_estimation_counter++; - } - else - { - d_cn0_estimation_counter = 0; - //d_CN0_SNV_dB_Hz = gps_l1_ca_CN0_SNV(d_Prompt_buffer, CN0_ESTIMATION_SAMPLES, d_fs_in); - d_CN0_SNV_dB_Hz = cn0_svn_estimator(d_Prompt_buffer, CN0_ESTIMATION_SAMPLES, d_fs_in, Galileo_E5a_CODE_LENGTH_CHIPS); - - d_carrier_lock_test = carrier_lock_detector(d_Prompt_buffer, CN0_ESTIMATION_SAMPLES); - // ###### TRACKING UNLOCK NOTIFICATION ##### - if (d_carrier_lock_test < d_carrier_lock_threshold or d_CN0_SNV_dB_Hz < MINIMUM_VALID_CN0) - { - d_carrier_lock_fail_counter++; - } - else - { - if (d_carrier_lock_fail_counter > 0) d_carrier_lock_fail_counter--; - } - if (d_carrier_lock_fail_counter > MAXIMUM_LOCK_FAIL_COUNTER) - { - std::cout << "Loss of lock in channel " << d_channel << "!" << std::endl; - LOG(INFO) << "Loss of lock in channel " << d_channel << "!"; - ControlMessageFactory* cmf = new ControlMessageFactory(); - if (d_queue != gr::msg_queue::sptr()) - { - d_queue->handle(cmf->GetQueueMessage(d_channel, 2)); - } - delete cmf; - d_carrier_lock_fail_counter = 0; - d_enable_tracking = false; // TODO: check if disabling tracking is consistent with the channel state machine - } - } - - // ########## DEBUG OUTPUT - /*! - * \todo The stop timer has to be moved to the signal source! - */ - // debug: Second counter in channel 0 - if (d_channel == 0) - { - if (floor(d_sample_counter/d_fs_in) != d_last_seg) - { - d_last_seg = floor(d_sample_counter/d_fs_in); - std::cout << "Current input signal time = " << d_last_seg << " [s]" << std::endl; - LOG(INFO) << "Tracking CH " << d_channel << ": Satellite " << Gnss_Satellite(systemName[sys], d_acquisition_gnss_synchro->PRN) << ", CN0 = " << d_CN0_SNV_dB_Hz << " [dB-Hz]"; - } - } - else - { - if (floor(d_sample_counter/d_fs_in) != d_last_seg) - { - d_last_seg = floor(d_sample_counter/d_fs_in); - LOG(INFO) << "Tracking CH " << d_channel << ": Satellite " << Gnss_Satellite(systemName[sys], d_acquisition_gnss_synchro->PRN) << ", CN0 = " << d_CN0_SNV_dB_Hz << " [dB-Hz]"; - } - } - - //predict the next loop PRN period length prediction - double T_chip_seconds; - double T_prn_seconds; - double T_prn_samples; - double K_blk_samples; - T_chip_seconds = 1/d_code_freq_hz; - T_prn_seconds = T_chip_seconds * Galileo_E5a_CODE_LENGTH_CHIPS; - T_prn_samples = T_prn_seconds * d_fs_in; - - float code_error_filt_samples; - code_error_filt_samples = T_prn_seconds*code_error_filt_chips*T_chip_seconds*(float)d_fs_in; //[seconds] - d_acc_code_phase_samples = d_acc_code_phase_samples + code_error_filt_samples; - - K_blk_samples = T_prn_samples + d_rem_code_phase_samples + code_error_filt_samples; - d_current_prn_length_samples = round(K_blk_samples); //round to a discrete sample - d_rem_code_phase_samples = K_blk_samples - d_current_prn_length_samples; //rounding error - - // ########### Output the tracking data to navigation and PVT ########## - current_synchro_data.Prompt_I = (double)(*d_Prompt).real(); - current_synchro_data.Prompt_Q = (double)(*d_Prompt).imag(); - // Tracking_timestamp_secs is aligned with the PRN start sample - current_synchro_data.Tracking_timestamp_secs = ((double)d_sample_counter + (double)d_current_prn_length_samples + d_rem_code_phase_samples)/d_fs_in; - // This tracking block aligns the Tracking_timestamp_secs with the start sample of the PRN, Code_phase_secs=0 - current_synchro_data.Code_phase_secs = 0; - current_synchro_data.Carrier_phase_rads = d_acc_carrier_phase_rad; - current_synchro_data.Carrier_Doppler_hz = d_carrier_doppler_hz; - current_synchro_data.CN0_dB_hz = d_CN0_SNV_dB_Hz; - current_synchro_data.Flag_valid_tracking = true; - *out[0] = current_synchro_data; - } - else - { - // ########## DEBUG OUTPUT (TIME ONLY for channel 0 when tracking is disabled) - /*! - * \todo The stop timer has to be moved to the signal source! - */ - // stream to collect cout calls to improve thread safety - std::stringstream tmp_str_stream; - if (floor(d_sample_counter / d_fs_in) != d_last_seg) - { - d_last_seg = floor(d_sample_counter / d_fs_in); - - if (d_channel == 0) - { - // debug: Second counter in channel 0 - tmp_str_stream << "Current input signal time = " << d_last_seg << " [s]" << std::endl << std::flush; - std::cout << tmp_str_stream.rdbuf() << std::flush; - } - } - *d_Early = gr_complex(0,0); - *d_Prompt = gr_complex(0,0); - *d_Late = gr_complex(0,0); - Gnss_Synchro **out = (Gnss_Synchro **) &output_items[0]; //block output streams pointer - *out[0] = *d_acquisition_gnss_synchro; - } - - - if(d_dump) - { - // MULTIPLEXED FILE RECORDING - Record results to file - float prompt_I; - float prompt_Q; - float tmp_E, tmp_P, tmp_L; - float tmp_float; - double tmp_double; - prompt_I = (*d_Prompt).real(); - prompt_Q = (*d_Prompt).imag(); - tmp_E = std::abs(*d_Early); - tmp_P = std::abs(*d_Prompt); - tmp_L = std::abs(*d_Late); - try - { - // EPR - d_dump_file.write((char*)&tmp_E, sizeof(float)); - d_dump_file.write((char*)&tmp_P, sizeof(float)); - d_dump_file.write((char*)&tmp_L, sizeof(float)); - // PROMPT I and Q (to analyze navigation symbols) - d_dump_file.write((char*)&prompt_I, sizeof(float)); - d_dump_file.write((char*)&prompt_Q, sizeof(float)); - // PRN start sample stamp - d_dump_file.write((char*)&d_sample_counter, sizeof(unsigned long int)); - // accumulated carrier phase - tmp_float = (float)d_acc_carrier_phase_rad; - d_dump_file.write((char*)&tmp_float, sizeof(float)); - - // carrier and code frequency - tmp_float = (float)d_carrier_doppler_hz; - d_dump_file.write((char*)&tmp_float, sizeof(float)); - tmp_float = (float)d_code_freq_hz; - d_dump_file.write((char*)&tmp_float, sizeof(float)); - - //PLL commands - tmp_float = (float)PLL_discriminator_hz; - d_dump_file.write((char*)&tmp_float, sizeof(float)); - tmp_float = (float)carr_nco_hz; - d_dump_file.write((char*)&tmp_float, sizeof(float)); - - //DLL commands - tmp_float = (float)code_error_chips; - d_dump_file.write((char*)&tmp_float, sizeof(float)); - tmp_float = (float)code_error_filt_chips; - d_dump_file.write((char*)&tmp_float, sizeof(float)); - - // CN0 and carrier lock test - tmp_float = (float)d_CN0_SNV_dB_Hz; - d_dump_file.write((char*)&tmp_float, sizeof(float)); - tmp_float = (float)d_carrier_lock_test; - d_dump_file.write((char*)&tmp_float, sizeof(float)); - - // AUX vars (for debug purposes) - tmp_float = (float)d_rem_code_phase_samples; - d_dump_file.write((char*)&tmp_float, sizeof(float)); - tmp_double = (double)(d_sample_counter + d_current_prn_length_samples); - d_dump_file.write((char*)&tmp_double, sizeof(double)); - } - catch (std::ifstream::failure e) - { - LOG(INFO) << "Exception writing trk dump file "<< e.what() << std::endl; - } - } - consume_each(d_current_prn_length_samples); // this is necessary in gr::block derivates - d_sample_counter += d_current_prn_length_samples; //count for the processed samples - return 1; //output tracking result ALWAYS even in the case of d_enable_tracking==false -} - - -void galileo_e5a_dll_fll_pll_tracking_cc::set_channel(unsigned int channel) -{ - d_channel = channel; - LOG(INFO) << "Tracking Channel set to " << d_channel; - // ############# ENABLE DATA FILE LOG ################# - if (d_dump == true) - { - if (d_dump_file.is_open() == false) - { - try - { - d_dump_filename.append(boost::lexical_cast(d_channel)); - d_dump_filename.append(".dat"); - d_dump_file.exceptions ( std::ifstream::failbit | std::ifstream::badbit ); - d_dump_file.open(d_dump_filename.c_str(), std::ios::out | std::ios::binary); - LOG(INFO) << "Tracking dump enabled on channel " << d_channel << " Log file: " << d_dump_filename.c_str(); - } - catch (std::ifstream::failure e) - { - LOG(WARNING) << "channel " << d_channel << " Exception opening trk dump file " << e.what(); - } - } - } -} - - - -void galileo_e5a_dll_fll_pll_tracking_cc::set_channel_queue(concurrent_queue *channel_internal_queue) -{ - d_channel_internal_queue = channel_internal_queue; -} - -void galileo_e5a_dll_fll_pll_tracking_cc::set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) -{ - d_acquisition_gnss_synchro=p_gnss_synchro; -} diff --git a/src/algorithms/tracking/gnuradio_blocks/galileo_e5a_dll_fll_pll_tracking_cc.h b/src/algorithms/tracking/gnuradio_blocks/galileo_e5a_dll_fll_pll_tracking_cc.h deleted file mode 100644 index 3766bde0e..000000000 --- a/src/algorithms/tracking/gnuradio_blocks/galileo_e5a_dll_fll_pll_tracking_cc.h +++ /dev/null @@ -1,206 +0,0 @@ -/*! - * \file galileo_e5a_dll_fll_pll_tracking_cc.h - * \brief Implementation of a code DLL + carrier PLL aided with FLL - * tracking block for Galileo E5a signals - * \author Marc Sales, 2014. marcsales92(at)gmail.com - * - * ------------------------------------------------------------------------- - * - * Copyright (C) 2010-2014 (see AUTHORS file for a list of contributors) - * - * GNSS-SDR is a software defined Global Navigation - * Satellite Systems receiver - * - * This file is part of GNSS-SDR. - * - * GNSS-SDR is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * at your option) any later version. - * - * GNSS-SDR is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNSS-SDR. If not, see . - * - * ------------------------------------------------------------------------- - */ - -#ifndef GNSS_SDR_GALILEO_E5A_DLL_FLL_PLL_TRACKING_CC_H_ -#define GNSS_SDR_GALILEO_E5A_DLL_FLL_PLL_TRACKING_CC_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "concurrent_queue.h" -#include "galileo_e5_signal_processing.h" -#include "tracking_FLL_PLL_filter.h" -#include "tracking_2nd_DLL_filter.h" -#include "gnss_synchro.h" -#include "correlator.h" - -class galileo_e5a_dll_fll_pll_tracking_cc; - -typedef boost::shared_ptr -galileo_e5a_dll_fll_pll_tracking_cc_sptr; - -galileo_e5a_dll_fll_pll_tracking_cc_sptr -galileo_e5a_dll_fll_pll_make_tracking_cc( - long if_freq, - long fs_in, - unsigned int vector_length, - boost::shared_ptr queue, - bool dump, - std::string dump_filename, - int order, - float fll_bw_hz, - float pll_bw_hz, - float dll_bw_hz, - float early_late_space_chips); - - -/*! - * \brief This class implements a DLL and a FLL assisted PLL tracking loop block - */ -class galileo_e5a_dll_fll_pll_tracking_cc: public gr::block -{ -public: - ~galileo_e5a_dll_fll_pll_tracking_cc(); - - void set_channel(unsigned int channel); - void start_tracking(); - void update_local_code(); - void update_local_carrier(); - void set_FLL_and_PLL_BW(float fll_bw_hz,float pll_bw_hz); - /* - * \brief Satellite signal synchronization parameters uses shared memory between acquisition and tracking - */ - void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro); - void set_channel_queue(concurrent_queue *channel_internal_queue); - - /* - * \brief just like gr_block::general_work, only this arranges to call consume_each for you - * - * The user must override work to define the signal processing code - */ - - int general_work (int noutput_items, gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); - - void forecast (int noutput_items, gr_vector_int &ninput_items_required); -private: - friend galileo_e5a_dll_fll_pll_tracking_cc_sptr - galileo_e5a_dll_fll_pll_make_tracking_cc( - long if_freq, - long fs_in, unsigned - int vector_length, - boost::shared_ptr queue, - bool dump, - std::string dump_filename, - int order, - float fll_bw_hz, - float pll_bw_hz, - float dll_bw_hz, - float early_late_space_chips); - - galileo_e5a_dll_fll_pll_tracking_cc( - long if_freq, - long fs_in, unsigned - int vector_length, - boost::shared_ptr queue, - bool dump, - std::string dump_filename, - int order, - float fll_bw_hz, - float pll_bw_hz, - float dll_bw_hz, - float early_late_space_chips); - - void CN0_estimation_and_lock_detectors(); - - // class private vars - Gnss_Synchro *d_acquisition_gnss_synchro; - boost::shared_ptr d_queue; - concurrent_queue *d_channel_internal_queue; - unsigned int d_vector_length; - bool d_dump; - unsigned int d_channel; - int d_last_seg; - double d_if_freq; - double d_fs_in; - //int d_sampled_codeLength; - - gr_complex* d_ca_code; - - gr_complex* d_early_code; - gr_complex* d_late_code; - gr_complex* d_prompt_code; - - gr_complex* d_carr_sign; - - gr_complex* d_Early; - gr_complex* d_Prompt; - gr_complex* d_Late; - - gr_complex d_Prompt_prev; - - double d_early_late_spc_chips; - - double d_carrier_doppler_hz; - double d_code_freq_hz; - double d_code_phase_samples; - int d_current_prn_length_samples; - //int d_next_prn_length_samples; - int d_FLL_wait; - double d_rem_carr_phase; - double d_rem_code_phase_samples; - //double d_next_rem_code_phase_samples; - bool d_pull_in; - - // acquisition - double d_acq_code_phase_samples; - double d_acq_carrier_doppler_hz; - - // correlator - Correlator d_correlator; - - // FLL + PLL filter - double d_FLL_discriminator_hz; // This is a class variable because FLL needs to have memory - Tracking_FLL_PLL_filter d_carrier_loop_filter; - double d_acc_carrier_phase_rad; - double d_acc_code_phase_samples; - - Tracking_2nd_DLL_filter d_code_loop_filter; - - unsigned long int d_sample_counter; - - unsigned long int d_acq_sample_stamp; - - // CN0 estimation and lock detector - int d_cn0_estimation_counter; - gr_complex* d_Prompt_buffer; - double d_carrier_lock_test; - double d_CN0_SNV_dB_Hz; - - double d_carrier_lock_threshold; - - int d_carrier_lock_fail_counter; - - bool d_enable_tracking; - - std::string d_dump_filename; - std::ofstream d_dump_file; - - std::map systemName; - std::string sys; -}; - -#endif /* GNSS_SDR_GALILEO_E5A_DLL_FLL_PLL_TRACKING_CC_H_ */ diff --git a/src/algorithms/tracking/gnuradio_blocks/galileo_e5a_dll_pll_tracking_cc.cc b/src/algorithms/tracking/gnuradio_blocks/galileo_e5a_dll_pll_tracking_cc.cc index 7a90a5f03..7a8e836f3 100644 --- a/src/algorithms/tracking/gnuradio_blocks/galileo_e5a_dll_pll_tracking_cc.cc +++ b/src/algorithms/tracking/gnuradio_blocks/galileo_e5a_dll_pll_tracking_cc.cc @@ -48,8 +48,7 @@ /*! * \todo Include in definition header file */ -//#define CN0_ESTIMATION_SAMPLES 20 -#define CN0_ESTIMATION_SAMPLES 80 +#define CN0_ESTIMATION_SAMPLES 20 #define MINIMUM_VALID_CN0 25 #define MAXIMUM_LOCK_FAIL_COUNTER 50 #define CARRIER_LOCK_THRESHOLD 0.85 @@ -67,10 +66,13 @@ galileo_e5a_dll_pll_make_tracking_cc( std::string dump_filename, float pll_bw_hz, float dll_bw_hz, + float pll_bw_init_hz, + float dll_bw_init_hz, + int ti_ms, float early_late_space_chips) { return galileo_e5a_dll_pll_tracking_cc_sptr(new Galileo_E5a_Dll_Pll_Tracking_cc(if_freq, - fs_in, vector_length, queue, dump, dump_filename, pll_bw_hz, dll_bw_hz, early_late_space_chips)); + fs_in, vector_length, queue, dump, dump_filename, pll_bw_hz, dll_bw_hz,pll_bw_init_hz, dll_bw_init_hz, ti_ms, early_late_space_chips)); } @@ -90,6 +92,9 @@ Galileo_E5a_Dll_Pll_Tracking_cc::Galileo_E5a_Dll_Pll_Tracking_cc( std::string dump_filename, float pll_bw_hz, float dll_bw_hz, + float pll_bw_init_hz, + float dll_bw_init_hz, + int ti_ms, float early_late_space_chips) : gr::block("Galileo_E5a_Dll_Pll_Tracking_cc", gr::io_signature::make(1, 1, sizeof(gr_complex)), gr::io_signature::make(1, 1, sizeof(Gnss_Synchro))) @@ -104,17 +109,24 @@ Galileo_E5a_Dll_Pll_Tracking_cc::Galileo_E5a_Dll_Pll_Tracking_cc( d_dump_filename = dump_filename; d_code_loop_filter = Tracking_2nd_DLL_filter(GALILEO_E5a_CODE_PERIOD); d_carrier_loop_filter = Tracking_2nd_PLL_filter(GALILEO_E5a_CODE_PERIOD); + d_current_ti_ms = 1; // initializes with 1ms of integration time until secondary code lock + d_ti_ms = ti_ms; + d_dll_bw_hz = dll_bw_hz; + d_pll_bw_hz = pll_bw_hz; + d_dll_bw_init_hz = dll_bw_init_hz; + d_pll_bw_init_hz = pll_bw_init_hz; // Initialize tracking ========================================== - d_code_loop_filter.set_DLL_BW(dll_bw_hz); - d_carrier_loop_filter.set_PLL_BW(pll_bw_hz); + d_code_loop_filter.set_DLL_BW(d_dll_bw_init_hz); + d_carrier_loop_filter.set_PLL_BW(d_pll_bw_init_hz); //--- DLL variables -------------------------------------------------------- d_early_late_spc_chips = early_late_space_chips; // Define early-late offset (in chips) // Initialization of local code replica - // Get space for a vector with the E5a primary complex code replica sampled 1x/chip - d_code = new gr_complex[(int)Galileo_E5a_CODE_LENGTH_CHIPS + 2]; + // Get space for a vector with the E5a primary code replicas sampled 1x/chip + d_codeQ = new gr_complex[(int)Galileo_E5a_CODE_LENGTH_CHIPS + 2]; + d_codeI = new gr_complex[(int)Galileo_E5a_CODE_LENGTH_CHIPS + 2]; /* If an array is partitioned for more than one thread to operate on, * having the sub-array boundaries unaligned to cache lines could lead @@ -126,11 +138,16 @@ Galileo_E5a_Dll_Pll_Tracking_cc::Galileo_E5a_Dll_Pll_Tracking_cc( if (posix_memalign((void**)&d_early_code, 16, d_vector_length * sizeof(gr_complex) * 2) == 0){}; if (posix_memalign((void**)&d_late_code, 16, d_vector_length * sizeof(gr_complex) * 2) == 0){}; if (posix_memalign((void**)&d_prompt_code, 16, d_vector_length * sizeof(gr_complex) * 2) == 0){}; + if (posix_memalign((void**)&d_prompt_data_code, 16, d_vector_length * sizeof(gr_complex) * 2) == 0){}; // space for carrier wipeoff and signal baseband vectors if (posix_memalign((void**)&d_carr_sign, 16, d_vector_length * sizeof(gr_complex) * 2) == 0){}; if (posix_memalign((void**)&d_Early, 16, sizeof(gr_complex)) == 0){}; if (posix_memalign((void**)&d_Prompt, 16, sizeof(gr_complex)) == 0){}; if (posix_memalign((void**)&d_Late, 16, sizeof(gr_complex)) == 0){}; +// if (posix_memalign((void**)&d_Prompt_data, 16, sizeof(gr_complex)*MAX_INTEGRATION_TIME_MS) == 0){}; + if (posix_memalign((void**)&d_Prompt_data, 16, sizeof(gr_complex)) == 0){}; + // space for buffer, notice max Ti+1 to ensure enough space since code samples is doppler dependant. +// if (posix_memalign((void**)&d_inbuffer, 16, (MAX_INTEGRATION_TIME_MS+1)*d_vector_length*sizeof(gr_complex)) == 0){}; //--- Perform initializations ------------------------------ // define initial code frequency basis of NCO @@ -140,17 +157,23 @@ Galileo_E5a_Dll_Pll_Tracking_cc::Galileo_E5a_Dll_Pll_Tracking_cc( // define residual carrier phase d_rem_carr_phase_rad = 0.0; + //Filter error vars + d_code_error_filt_secs = 0.0; + + // sample synchronization d_sample_counter = 0; - //d_sample_counter_seconds = 0; d_acq_sample_stamp = 0; - d_enable_tracking = false; - d_pull_in = false; + //d_enable_tracking = false; + //d_pull_in = false; d_last_seg = 0; + d_first_transition = false; d_secondary_lock=false; d_secondary_delay=0; + d_integration_counter = 0; +// d_buffer_counter = 0; d_current_prn_length_samples = (int)d_vector_length; @@ -178,11 +201,9 @@ Galileo_E5a_Dll_Pll_Tracking_cc::~Galileo_E5a_Dll_Pll_Tracking_cc () free(d_late_code); free(d_early_code); free(d_carr_sign); - free(d_Early); - free(d_Prompt); - free(d_Late); - delete[] d_code; + delete[] d_codeQ; + delete[] d_codeI; delete[] d_Prompt_buffer; } @@ -238,12 +259,16 @@ void Galileo_E5a_Dll_Pll_Tracking_cc::start_tracking() d_code_loop_filter.initialize(); // initialize the code filter // generate local reference ALWAYS starting at chip 1 (1 sample per chip) - char sig_pilot[3]; - strcpy(sig_pilot,"5Q"); - galileo_e5_a_code_gen_complex_primary(&d_code[1], d_acquisition_gnss_synchro->PRN, sig_pilot); + char sig[3]; + strcpy(sig,"5Q"); + galileo_e5_a_code_gen_complex_primary(&d_codeQ[1], d_acquisition_gnss_synchro->PRN, sig); + d_codeQ[0] = d_codeQ[(int)Galileo_E5a_CODE_LENGTH_CHIPS]; + d_codeQ[(int)Galileo_E5a_CODE_LENGTH_CHIPS + 1] = d_codeQ[1]; - d_code[0] = d_code[(int)Galileo_E5a_CODE_LENGTH_CHIPS]; - d_code[(int)Galileo_E5a_CODE_LENGTH_CHIPS + 1] = d_code[1]; + strcpy(sig,"5I"); + galileo_e5_a_code_gen_complex_primary(&d_codeI[1], d_acquisition_gnss_synchro->PRN, sig); + d_codeI[0] = d_codeI[(int)Galileo_E5a_CODE_LENGTH_CHIPS]; + d_codeI[(int)Galileo_E5a_CODE_LENGTH_CHIPS + 1] = d_codeI[1]; d_carrier_lock_fail_counter = 0; d_rem_code_phase_samples = 0; @@ -262,19 +287,15 @@ void Galileo_E5a_Dll_Pll_Tracking_cc::start_tracking() // enable tracking - d_pull_in = true; - d_enable_tracking = true; + d_state = 1; LOG(INFO) << "PULL-IN Doppler [Hz]=" << d_carrier_doppler_hz << " Code Phase correction [samples]=" << delay_correction_samples << " PULL-IN Code Phase [samples]=" << d_acq_code_phase_samples; } + void Galileo_E5a_Dll_Pll_Tracking_cc::acquire_secondary() { - //d_Prompt_buffer - //CN0_ESTIMATION_SAMPLES - //d_secondary_lock - //d_secondary_delay // 1. Transform replica to 1 and -1 int sec_code_signed[Galileo_E5a_Q_SECONDARY_CODE_LENGTH]; for (unsigned int i=0; i0) { in_corr[i]=1; @@ -313,32 +333,25 @@ void Galileo_E5a_Dll_Pll_Tracking_cc::acquire_secondary() //reverse replica sign since i*i=-1 (conjugated complex) out_corr += in_corr[j] * -sec_code_signed[(j+i)%Galileo_E5a_Q_SECONDARY_CODE_LENGTH]; } - // VOLK function uses floats, possibly slower -// if (is_unaligned()) -// { -// volk_32f_x2_dot_prod_32f_u(); -// } -// else -// { -// volk_32f_x2_dot_prod_32f_a(); -// } if (abs(out_corr) > current_best_) { current_best_ = abs(out_corr); d_secondary_delay=i; } } - //if (current_best_ > SECONDARY_THRESHOLD) - if (current_best_ >= 0.8*CN0_ESTIMATION_SAMPLES) + if (current_best_ == CN0_ESTIMATION_SAMPLES) // all bits correlate { d_secondary_lock = true; + d_secondary_delay = (d_secondary_delay+CN0_ESTIMATION_SAMPLES-1)%Galileo_E5a_Q_SECONDARY_CODE_LENGTH; } } + void Galileo_E5a_Dll_Pll_Tracking_cc::update_local_code() { double tcode_chips; double rem_code_phase_chips; int associated_chip_index; + int associated_chip_index_data; int code_length_chips = (int)Galileo_E5a_CODE_LENGTH_CHIPS; double code_phase_step_chips; int early_late_spc_samples; @@ -348,32 +361,24 @@ void Galileo_E5a_Dll_Pll_Tracking_cc::update_local_code() code_phase_step_chips = ((double)d_code_freq_chips) / ((double)d_fs_in); rem_code_phase_chips = d_rem_code_phase_samples * (d_code_freq_chips / d_fs_in); tcode_chips = -rem_code_phase_chips; -// SPACING USING QUADRATURE COMPONENT as 0.5 CHIP - double corr_spc_samples = d_early_late_spc_chips / code_phase_step_chips; -// CONVENTIONAL // Alternative EPL code generation (40% of speed improvement!) early_late_spc_samples = round(d_early_late_spc_chips / code_phase_step_chips); epl_loop_length_samples = d_current_prn_length_samples + early_late_spc_samples*2; + for (int i = 0; i < epl_loop_length_samples; i++) { associated_chip_index = 1 + round(fmod(tcode_chips - d_early_late_spc_chips, code_length_chips)); - d_early_code[i] = d_code[associated_chip_index]; + associated_chip_index_data = 1 + round(fmod(tcode_chips, code_length_chips)); + d_early_code[i] = d_codeQ[associated_chip_index]; + d_prompt_data_code[i] = d_codeI[associated_chip_index_data]; tcode_chips = tcode_chips + code_phase_step_chips; } - memcpy(d_prompt_code,&d_early_code[early_late_spc_samples],d_current_prn_length_samples* sizeof(gr_complex)); memcpy(d_late_code,&d_early_code[early_late_spc_samples*2],d_current_prn_length_samples* sizeof(gr_complex)); -//EXPERIMENTAL - - - } - - - void Galileo_E5a_Dll_Pll_Tracking_cc::update_local_carrier() { float phase_rad, phase_step_rad; @@ -395,243 +400,347 @@ int Galileo_E5a_Dll_Pll_Tracking_cc::general_work (int noutput_items, gr_vector_ float carr_error_filt_hz; float code_error_chips; float code_error_filt_chips; + // GNSS_SYNCHRO OBJECT to interchange data between tracking->telemetry_decoder + Gnss_Synchro **out = (Gnss_Synchro **) &output_items[0]; //block output streams pointer - if (d_enable_tracking == true) - { - if (d_secondary_lock==false) - { - // Receiver signal alignment - if (d_pull_in == true) - { - int samples_offset; - float acq_trk_shif_correction_samples; - int acq_to_trk_delay_samples; - acq_to_trk_delay_samples = d_sample_counter - d_acq_sample_stamp; - acq_trk_shif_correction_samples = d_current_prn_length_samples - fmod((float)acq_to_trk_delay_samples, (float)d_current_prn_length_samples); - samples_offset = round(d_acq_code_phase_samples + acq_trk_shif_correction_samples); - // /todo: Check if the sample counter sent to the next block as a time reference should be incremented AFTER sended or BEFORE - //d_sample_counter_seconds = d_sample_counter_seconds + (((double)samples_offset) / (double)d_fs_in); - d_sample_counter = d_sample_counter + samples_offset; //count for the processed samples - d_pull_in = false; - std::cout<<" samples_offset="<telemetry_decoder + Gnss_Synchro current_synchro_data; + // Fill the acquisition data + current_synchro_data = *d_acquisition_gnss_synchro; - // GNSS_SYNCHRO OBJECT to interchange data between tracking->telemetry_decoder - Gnss_Synchro current_synchro_data; - // Fill the acquisition data - current_synchro_data = *d_acquisition_gnss_synchro; + /* States: 0 Tracking not enabled + * 1 Pull-in of primary code (alignment). + * 3 Tracking algorithm. Correlates EPL each loop and accumulates the result + * until it reaches integration time. + */ + switch (d_state) + { + case 0: + { + // ########## DEBUG OUTPUT (TIME ONLY for channel 0 when tracking is disabled) + /*! + * \todo The stop timer has to be moved to the signal source! + */ + // stream to collect cout calls to improve thread safety + std::stringstream tmp_str_stream; + if (floor(d_sample_counter / d_fs_in) != d_last_seg) + { + d_last_seg = floor(d_sample_counter / d_fs_in); - // Block input data and block output stream pointers - const gr_complex* in = (gr_complex*) input_items[0]; //PRN start block alignment - Gnss_Synchro **out = (Gnss_Synchro **) &output_items[0]; + if (d_channel == 0) + { + // debug: Second counter in channel 0 + tmp_str_stream << "Current input signal time = " << d_last_seg << " [s]" << std::endl << std::flush; + std::cout << tmp_str_stream.rdbuf() << std::flush; + } + } + d_Early = gr_complex(0,0); + d_Prompt = gr_complex(0,0); + d_Late = gr_complex(0,0); + d_Prompt_data = gr_complex(0,0); - // Generate local code and carrier replicas (using \hat{f}_d(k-1)) - update_local_code(); - update_local_carrier(); + *out[0] = *d_acquisition_gnss_synchro; - // perform carrier wipe-off and compute Early, Prompt and Late correlation - d_correlator.Carrier_wipeoff_and_EPL_volk(d_current_prn_length_samples, - in, - d_carr_sign, - d_early_code, - d_prompt_code, - d_late_code, - d_Early, - d_Prompt, - d_Late, - is_unaligned()); + break; + } + case 1: + { + int samples_offset; + float acq_trk_shif_correction_samples; + int acq_to_trk_delay_samples; + acq_to_trk_delay_samples = d_sample_counter - d_acq_sample_stamp; + acq_trk_shif_correction_samples = d_current_prn_length_samples - fmod((float)acq_to_trk_delay_samples, (float)d_current_prn_length_samples); + samples_offset = round(d_acq_code_phase_samples + acq_trk_shif_correction_samples); + // /todo: Check if the sample counter sent to the next block as a time reference should be incremented AFTER sended or BEFORE + d_sample_counter = d_sample_counter + samples_offset; //count for the processed samples + std::cout<<" samples_offset="<PRN-1].at(d_secondary_delay)=='0' ? 1 : -1),0); + sec_sign_I = gr_complex((Galileo_E5a_I_SECONDARY_CODE.at(d_secondary_delay%Galileo_E5a_I_SECONDARY_CODE_LENGTH))=='0' ? 1 : -1,0); + } + else + { + sec_sign_Q = gr_complex(1.0,0.0); + sec_sign_I = gr_complex(1.0,0.0); + } + // Reset integration counter + if (d_integration_counter == d_current_ti_ms) + { + d_integration_counter = 0; + } + //Generate local code and carrier replicas (using \hat{f}_d(k-1)) + if (d_integration_counter == 0) + { + update_local_code(); + update_local_carrier(); + // Reset accumulated values + d_Early = gr_complex(0,0); + d_Prompt = gr_complex(0,0); + d_Late = gr_complex(0,0); + } + gr_complex single_early; + gr_complex single_prompt; + gr_complex single_late; - *out[0] = current_synchro_data; + // perform carrier wipe-off and compute Early, Prompt and Late + // correlation of 1 primary code + d_correlator.Carrier_wipeoff_and_EPL_volk_IQ(d_current_prn_length_samples, + in, + d_carr_sign, + d_early_code, + d_prompt_code, + d_late_code, + d_prompt_data_code, + &single_early, + &single_prompt, + &single_late, + &d_Prompt_data, + is_unaligned()); - return 1; - } + // Accumulate results (coherent integration) + d_Early += single_early * sec_sign_Q; + d_Prompt += single_prompt * sec_sign_Q; + d_Late += single_late * sec_sign_Q; + d_Prompt_data *= sec_sign_I; + d_integration_counter++; - // ################## PLL ########################################################## - // PLL discriminator - carr_error_hz = pll_cloop_two_quadrant_atan(*d_Prompt) / (float)GALILEO_PI*2; - // Carrier discriminator filter - carr_error_filt_hz = d_carrier_loop_filter.get_carrier_nco(carr_error_hz); - // New carrier Doppler frequency estimation - d_carrier_doppler_hz = d_acq_carrier_doppler_hz + carr_error_filt_hz; - // New code Doppler frequency estimation - d_code_freq_chips = Galileo_E5a_CODE_CHIP_RATE_HZ + ((d_carrier_doppler_hz * Galileo_E5a_CODE_CHIP_RATE_HZ) / Galileo_E5a_FREQ_HZ); - //carrier phase accumulator for (K) doppler estimation - d_acc_carrier_phase_rad = d_acc_carrier_phase_rad + 2*GALILEO_PI*d_carrier_doppler_hz*GALILEO_E5a_CODE_PERIOD; - //remanent carrier phase to prevent overflow in the code NCO - d_rem_carr_phase_rad = d_rem_carr_phase_rad+2*GALILEO_PI*d_carrier_doppler_hz*GALILEO_E5a_CODE_PERIOD; - d_rem_carr_phase_rad = fmod(d_rem_carr_phase_rad, 2*GALILEO_PI); + // check for samples consistency (this should be done before in the receiver / here only if the source is a file) + if (std::isnan((d_Prompt).real()) == true or std::isnan((d_Prompt).imag()) == true ) // or std::isinf(in[i].real())==true or std::isinf(in[i].imag())==true) + { + const int samples_available = ninput_items[0]; + d_sample_counter = d_sample_counter + samples_available; + LOG(WARNING) << "Detected NaN samples at sample number " << d_sample_counter; + consume_each(samples_available); - // ################## DLL ########################################################## - // DLL discriminator - code_error_chips = dll_nc_e_minus_l_normalized(*d_Early, *d_Late); //[chips/Ti] - // Code discriminator filter - code_error_filt_chips = d_code_loop_filter.get_code_nco(code_error_chips); //[chips/second] - //Code phase accumulator - float code_error_filt_secs; - code_error_filt_secs = (GALILEO_E5a_CODE_PERIOD*code_error_filt_chips)/Galileo_E5a_CODE_CHIP_RATE_HZ; //[seconds] - d_acc_code_phase_secs = d_acc_code_phase_secs + code_error_filt_secs; + // make an output to not stop the rest of the processing blocks + current_synchro_data.Prompt_I = 0.0; + current_synchro_data.Prompt_Q = 0.0; + current_synchro_data.Tracking_timestamp_secs = (double)d_sample_counter/(double)d_fs_in; + current_synchro_data.Carrier_phase_rads = 0.0; + current_synchro_data.Code_phase_secs = 0.0; + current_synchro_data.CN0_dB_hz = 0.0; + current_synchro_data.Flag_valid_tracking = false; - std::cout<< "Early " << *d_Early << std::endl; - std::cout<< "Prompt " << *d_Prompt << std::endl; - std::cout<< "Late " << *d_Late << std::endl; - // ################## CARRIER AND CODE NCO BUFFER ALIGNEMENT ####################### - // keep alignment parameters for the next input buffer - float T_chip_seconds; - float T_prn_seconds; - float T_prn_samples; - float K_blk_samples; - // Compute the next buffer length based in the new period of the PRN sequence and the code phase error estimation - T_chip_seconds = 1 / d_code_freq_chips; - T_prn_seconds = T_chip_seconds * Galileo_E5a_CODE_LENGTH_CHIPS; - T_prn_samples = T_prn_seconds * (float)d_fs_in; - K_blk_samples = T_prn_samples + d_rem_code_phase_samples + code_error_filt_secs*(float)d_fs_in; - d_current_prn_length_samples = round(K_blk_samples); //round to a discrete samples - d_rem_code_phase_samples = K_blk_samples - d_current_prn_length_samples; //rounding error < 1 sample + *out[0] = current_synchro_data; - // ####### CN0 ESTIMATION AND LOCK DETECTORS ###### - if (d_cn0_estimation_counter < CN0_ESTIMATION_SAMPLES) - { - // fill buffer with prompt correlator output values - d_Prompt_buffer[d_cn0_estimation_counter] = *d_Prompt; - d_cn0_estimation_counter++; - } - else - { - // ATTEMPT SECONDARY CODE ACQUISITION - acquire_secondary(); // changes d_secondary_lock and d_secondary_delay - // - d_cn0_estimation_counter = 0; - // Code lock indicator - d_CN0_SNV_dB_Hz = cn0_svn_estimator(d_Prompt_buffer, CN0_ESTIMATION_SAMPLES, d_fs_in, Galileo_E5a_CODE_LENGTH_CHIPS); - // Carrier lock indicator - d_carrier_lock_test = carrier_lock_detector(d_Prompt_buffer, CN0_ESTIMATION_SAMPLES); - // Loss of lock detection - if (d_carrier_lock_test < d_carrier_lock_threshold or d_CN0_SNV_dB_Hz < MINIMUM_VALID_CN0) - { - d_carrier_lock_fail_counter++; - } - else - { - if (d_carrier_lock_fail_counter > 0) d_carrier_lock_fail_counter--; - } - if (d_carrier_lock_fail_counter > MAXIMUM_LOCK_FAIL_COUNTER) - { - std::cout << "Loss of lock in channel " << d_channel << "!" << std::endl; - LOG(INFO) << "Loss of lock in channel " << d_channel << "!"; - ControlMessageFactory* cmf = new ControlMessageFactory(); - if (d_queue != gr::msg_queue::sptr()) - { - d_queue->handle(cmf->GetQueueMessage(d_channel, 2)); - } - delete cmf; - d_carrier_lock_fail_counter = 0; - d_enable_tracking = false; // TODO: check if disabling tracking is consistent with the channel state machine - } - } + return 1; + } + // ################## PLL ########################################################## + // PLL discriminator + if (d_integration_counter == d_current_ti_ms) + { + if (d_secondary_lock == true) + { + carr_error_hz = pll_four_quadrant_atan(d_Prompt) / (float)GALILEO_PI*2; + } + else + { + carr_error_hz = pll_cloop_two_quadrant_atan(d_Prompt) / (float)GALILEO_PI*2; + } - // make an output to not stop the rest of the processing blocks - current_synchro_data.Prompt_I = 0.0; - current_synchro_data.Prompt_Q = 0.0; - current_synchro_data.Tracking_timestamp_secs = (double)d_sample_counter/(double)d_fs_in; - current_synchro_data.Carrier_phase_rads = 0.0; - current_synchro_data.Code_phase_secs = 0.0; - current_synchro_data.CN0_dB_hz = 0.0; - current_synchro_data.Flag_valid_tracking = false; + // Carrier discriminator filter + carr_error_filt_hz = d_carrier_loop_filter.get_carrier_nco(carr_error_hz); + // TEST +// carr_error_filt_hz = 0; + // + // New carrier Doppler frequency estimation + d_carrier_doppler_hz = d_acq_carrier_doppler_hz + carr_error_filt_hz; + // New code Doppler frequency estimation + d_code_freq_chips = Galileo_E5a_CODE_CHIP_RATE_HZ + ((d_carrier_doppler_hz * Galileo_E5a_CODE_CHIP_RATE_HZ) / Galileo_E5a_FREQ_HZ); + } + //carrier phase accumulator for (K) doppler estimation + d_acc_carrier_phase_rad = d_acc_carrier_phase_rad + 2*GALILEO_PI*d_carrier_doppler_hz*GALILEO_E5a_CODE_PERIOD; + //remanent carrier phase to prevent overflow in the code NCO + d_rem_carr_phase_rad = d_rem_carr_phase_rad+2*GALILEO_PI*d_carrier_doppler_hz*GALILEO_E5a_CODE_PERIOD; + d_rem_carr_phase_rad = fmod(d_rem_carr_phase_rad, 2*GALILEO_PI); - *out[0] = current_synchro_data; + // ################## DLL ########################################################## + if (d_integration_counter == d_current_ti_ms) + { + // DLL discriminator + code_error_chips = dll_nc_e_minus_l_normalized(d_Early, d_Late); //[chips/Ti] + // Code discriminator filter + code_error_filt_chips = d_code_loop_filter.get_code_nco(code_error_chips); //[chips/second] + // TEST +// code_error_filt_chips = 0; + // + //Code phase accumulator + d_code_error_filt_secs = (GALILEO_E5a_CODE_PERIOD*code_error_filt_chips)/Galileo_E5a_CODE_CHIP_RATE_HZ; //[seconds] + } + d_acc_code_phase_secs = d_acc_code_phase_secs + d_code_error_filt_secs; +// std::cout<< "Early " << d_Early << std::endl; +// std::cout<< "Prompt " << d_Prompt << std::endl; +// std::cout<< "Late " << d_Late << std::endl; +// std::cout<< "Prompt data " << d_Prompt_data << std::endl; - } - else - { - // code with known secondary chip delay - // ########### Output the tracking data to navigation and PVT ########## - /* - current_synchro_data.Prompt_I = (double)(*d_Prompt).real(); - current_synchro_data.Prompt_Q = (double)(*d_Prompt).imag(); - // Tracking_timestamp_secs is aligned with the PRN start sample - current_synchro_data.Tracking_timestamp_secs = ((double)d_sample_counter + (double)d_current_prn_length_samples + (double)d_rem_code_phase_samples)/(double)d_fs_in; - // This tracking block aligns the Tracking_timestamp_secs with the start sample of the PRN, thus, Code_phase_secs=0 - current_synchro_data.Code_phase_secs = 0; - current_synchro_data.Carrier_phase_rads = (double)d_acc_carrier_phase_rad; - current_synchro_data.Carrier_Doppler_hz = (double)d_carrier_doppler_hz; - current_synchro_data.CN0_dB_hz = (double)d_CN0_SNV_dB_Hz; - *out[0] = current_synchro_data; - */ - } - // ########## DEBUG OUTPUT - /*! - * \todo The stop timer has to be moved to the signal source! - */ - // debug: Second counter in channel 0 - if (d_channel == 0) - { - if (floor(d_sample_counter / d_fs_in) != d_last_seg) - { - d_last_seg = floor(d_sample_counter / d_fs_in); - std::cout << "Current input signal time = " << d_last_seg << " [s]" << std::endl; - LOG(INFO) << "Tracking CH " << d_channel << ": Satellite " << Gnss_Satellite(systemName[sys], d_acquisition_gnss_synchro->PRN) - << ", CN0 = " << d_CN0_SNV_dB_Hz << " [dB-Hz]"; - //if (d_last_seg==5) d_carrier_lock_fail_counter=500; //DEBUG: force unlock! - } - } - else - { - if (floor(d_sample_counter / d_fs_in) != d_last_seg) - { - d_last_seg = floor(d_sample_counter / d_fs_in); - LOG(INFO) << "Tracking CH " << d_channel << ": Satellite " << Gnss_Satellite(systemName[sys], d_acquisition_gnss_synchro->PRN) - << ", CN0 = " << d_CN0_SNV_dB_Hz << " [dB-Hz]"; - //std::cout<<"TRK CH "<telemetry_decoder - *out[0] = *d_acquisition_gnss_synchro; - } + // ####### CN0 ESTIMATION AND LOCK DETECTORS ###### + if (d_cn0_estimation_counter < CN0_ESTIMATION_SAMPLES-1) + { + // fill buffer with prompt correlator output values + d_Prompt_buffer[d_cn0_estimation_counter] = d_Prompt; + d_cn0_estimation_counter++; + // d_cn0_estimation_counter += d_integration_t_ms; + } + else + { + d_Prompt_buffer[d_cn0_estimation_counter] = d_Prompt; + // ATTEMPT SECONDARY CODE ACQUISITION + if (d_secondary_lock == false) + { + acquire_secondary(); // changes d_secondary_lock and d_secondary_delay + if (d_secondary_lock == true) + { +// std::cout << "first prompt=" << d_Prompt_buffer[0] << std::endl; + std::cout << "Secondary code locked." << std::endl; + d_current_ti_ms = d_ti_ms; + d_integration_counter = 0; + // Change loop parameters ========================================== + + d_code_loop_filter.set_pdi(d_current_ti_ms * GALILEO_E5a_CODE_PERIOD); + d_carrier_loop_filter.set_pdi(d_current_ti_ms * GALILEO_E5a_CODE_PERIOD); + d_code_loop_filter.initialize(); + d_carrier_loop_filter.initialize(); + d_code_loop_filter.set_DLL_BW(d_dll_bw_hz); + d_carrier_loop_filter.set_PLL_BW(d_pll_bw_hz); + + consume_each(d_current_prn_length_samples); // this is necessary in gr::block derivates + d_secondary_delay = (d_secondary_delay + 1)%Galileo_E5a_Q_SECONDARY_CODE_LENGTH; + d_sample_counter += d_current_prn_length_samples; //count for the processed samples + return 1; + } + else + { +// std::cout << "first prompt=" << d_Prompt_buffer[0] << std::endl; + std::cout << "Secondary code delay couldn't be resolved." << std::endl; + d_carrier_lock_fail_counter++; + if (d_carrier_lock_fail_counter > MAXIMUM_LOCK_FAIL_COUNTER) + { + std::cout << "Loss of lock in channel " << d_channel << "!" << std::endl; + LOG(INFO) << "Loss of lock in channel " << d_channel << "!"; + ControlMessageFactory* cmf = new ControlMessageFactory(); + if (d_queue != gr::msg_queue::sptr()) + { + d_queue->handle(cmf->GetQueueMessage(d_channel, 2)); + } + delete cmf; + d_carrier_lock_fail_counter = 0; + d_state = 0; // TODO: check if disabling tracking is consistent with the channel state machine + } + } + } + else // Secondary lock achieved, monitor carrier lock. + { + // Code lock indicator + d_CN0_SNV_dB_Hz = cn0_svn_estimator(d_Prompt_buffer, CN0_ESTIMATION_SAMPLES, d_fs_in, Galileo_E5a_CODE_LENGTH_CHIPS); + // Carrier lock indicator + d_carrier_lock_test = carrier_lock_detector(d_Prompt_buffer, CN0_ESTIMATION_SAMPLES); + + // TODO: tune Time integration period and filter parameters according to CN0 levels + + // Loss of lock detection + if (d_carrier_lock_test < d_carrier_lock_threshold or d_CN0_SNV_dB_Hz < MINIMUM_VALID_CN0) + { + d_carrier_lock_fail_counter++; + } + else + { + if (d_carrier_lock_fail_counter > 0) d_carrier_lock_fail_counter--; + + if (d_carrier_lock_fail_counter > MAXIMUM_LOCK_FAIL_COUNTER) + { + std::cout << "Loss of lock in channel " << d_channel << "!" << std::endl; + LOG(INFO) << "Loss of lock in channel " << d_channel << "!"; + ControlMessageFactory* cmf = new ControlMessageFactory(); + if (d_queue != gr::msg_queue::sptr()) + { + d_queue->handle(cmf->GetQueueMessage(d_channel, 2)); + } + delete cmf; + d_carrier_lock_fail_counter = 0; + d_state = 0; + } + } + } + d_cn0_estimation_counter = 0; + } + if (d_secondary_lock && (d_secondary_delay%Galileo_E5a_I_SECONDARY_CODE_LENGTH)==0) + { + d_first_transition = true; + } + // ########### Output the tracking data to navigation and PVT ########## + // The first Prompt output not equal to 0 is synchronized with the transition of a navigation data bit. + if (d_secondary_lock && d_first_transition) + { + current_synchro_data.Prompt_I = (double)(d_Prompt_data.real()); + current_synchro_data.Prompt_Q = (double)(d_Prompt_data.imag()); + // Tracking_timestamp_secs is aligned with the PRN start sample + current_synchro_data.Tracking_timestamp_secs = ((double)d_sample_counter + (double)d_current_prn_length_samples + (double)d_rem_code_phase_samples)/(double)d_fs_in; + // This tracking block aligns the Tracking_timestamp_secs with the start sample of the PRN, thus, Code_phase_secs=0 + current_synchro_data.Code_phase_secs = 0; + current_synchro_data.Carrier_phase_rads = (double)d_acc_carrier_phase_rad; + current_synchro_data.Carrier_Doppler_hz = (double)d_carrier_doppler_hz; + current_synchro_data.CN0_dB_hz = (double)d_CN0_SNV_dB_Hz; + } + else + { + + // make an output to not stop the rest of the processing blocks + current_synchro_data.Prompt_I = 0.0; + current_synchro_data.Prompt_Q = 0.0; + current_synchro_data.Tracking_timestamp_secs = (double)d_sample_counter/d_fs_in; + current_synchro_data.Carrier_phase_rads = 0.0; + current_synchro_data.Code_phase_secs = 0.0; + current_synchro_data.CN0_dB_hz = 0.0; + current_synchro_data.Flag_valid_tracking = false; + } + *out[0] = current_synchro_data; + } + } if(d_dump) { @@ -641,55 +750,59 @@ int Galileo_E5a_Dll_Pll_Tracking_cc::general_work (int noutput_items, gr_vector_ float tmp_E, tmp_P, tmp_L; float tmp_float; double tmp_double; - prompt_I = (*d_Prompt).real(); - prompt_Q = (*d_Prompt).imag(); - tmp_E = std::abs(*d_Early); - tmp_P = std::abs(*d_Prompt); - tmp_L = std::abs(*d_Late); + prompt_I = d_Prompt_data.real(); + prompt_Q = d_Prompt_data.imag(); + if (d_integration_counter == d_current_ti_ms) + { + tmp_E = std::abs(d_Early); + tmp_P = std::abs(d_Prompt); + tmp_L = std::abs(d_Late); + } try { - // EPR - d_dump_file.write((char*)&tmp_E, sizeof(float)); - d_dump_file.write((char*)&tmp_P, sizeof(float)); - d_dump_file.write((char*)&tmp_L, sizeof(float)); - // PROMPT I and Q (to analyze navigation symbols) - d_dump_file.write((char*)&prompt_I, sizeof(float)); - d_dump_file.write((char*)&prompt_Q, sizeof(float)); - // PRN start sample stamp - //tmp_float=(float)d_sample_counter; - d_dump_file.write((char*)&d_sample_counter, sizeof(unsigned long int)); - // accumulated carrier phase - d_dump_file.write((char*)&d_acc_carrier_phase_rad, sizeof(float)); + // EPR + d_dump_file.write((char*)&tmp_E, sizeof(float)); + d_dump_file.write((char*)&tmp_P, sizeof(float)); + d_dump_file.write((char*)&tmp_L, sizeof(float)); + // PROMPT I and Q (to analyze navigation symbols) + //TODO: save all nav symbols, not only the first of the integration time. + d_dump_file.write((char*)&prompt_I, sizeof(float)); + d_dump_file.write((char*)&prompt_Q, sizeof(float)); + // PRN start sample stamp + d_dump_file.write((char*)&d_sample_counter, sizeof(unsigned long int)); + // accumulated carrier phase + d_dump_file.write((char*)&d_acc_carrier_phase_rad, sizeof(float)); - // carrier and code frequency - d_dump_file.write((char*)&d_carrier_doppler_hz, sizeof(float)); - d_dump_file.write((char*)&d_code_freq_chips, sizeof(float)); + // carrier and code frequency + d_dump_file.write((char*)&d_carrier_doppler_hz, sizeof(float)); + d_dump_file.write((char*)&d_code_freq_chips, sizeof(float)); - //PLL commands - d_dump_file.write((char*)&carr_error_hz, sizeof(float)); - d_dump_file.write((char*)&carr_error_filt_hz, sizeof(float)); + //PLL commands + d_dump_file.write((char*)&carr_error_hz, sizeof(float)); + d_dump_file.write((char*)&carr_error_filt_hz, sizeof(float)); - //DLL commands - d_dump_file.write((char*)&code_error_chips, sizeof(float)); - d_dump_file.write((char*)&code_error_filt_chips, sizeof(float)); + //DLL commands + d_dump_file.write((char*)&code_error_chips, sizeof(float)); + d_dump_file.write((char*)&code_error_filt_chips, sizeof(float)); - // CN0 and carrier lock test - d_dump_file.write((char*)&d_CN0_SNV_dB_Hz, sizeof(float)); - d_dump_file.write((char*)&d_carrier_lock_test, sizeof(float)); + // CN0 and carrier lock test + d_dump_file.write((char*)&d_CN0_SNV_dB_Hz, sizeof(float)); + d_dump_file.write((char*)&d_carrier_lock_test, sizeof(float)); - // AUX vars (for debug purposes) - tmp_float = d_rem_code_phase_samples; - d_dump_file.write((char*)&tmp_float, sizeof(float)); - tmp_double=(double)(d_sample_counter+d_current_prn_length_samples); - d_dump_file.write((char*)&tmp_double, sizeof(double)); + // AUX vars (for debug purposes) + tmp_float = d_rem_code_phase_samples; + d_dump_file.write((char*)&tmp_float, sizeof(float)); + tmp_double=(double)(d_sample_counter+d_current_prn_length_samples); + d_dump_file.write((char*)&tmp_double, sizeof(double)); } catch (std::ifstream::failure e) { - LOG(WARNING) << "Exception writing trk dump file " << e.what(); + LOG(WARNING) << "Exception writing trk dump file " << e.what(); } } consume_each(d_current_prn_length_samples); // this is necessary in gr::block derivates + d_secondary_delay = (d_secondary_delay + 1)%Galileo_E5a_Q_SECONDARY_CODE_LENGTH; d_sample_counter += d_current_prn_length_samples; //count for the processed samples return 1; //output tracking result ALWAYS even in the case of d_enable_tracking==false } diff --git a/src/algorithms/tracking/gnuradio_blocks/galileo_e5a_dll_pll_tracking_cc.h b/src/algorithms/tracking/gnuradio_blocks/galileo_e5a_dll_pll_tracking_cc.h index cb2d17bf4..4b489b4db 100644 --- a/src/algorithms/tracking/gnuradio_blocks/galileo_e5a_dll_pll_tracking_cc.h +++ b/src/algorithms/tracking/gnuradio_blocks/galileo_e5a_dll_pll_tracking_cc.h @@ -61,6 +61,9 @@ galileo_e5a_dll_pll_make_tracking_cc(long if_freq, std::string dump_filename, float pll_bw_hz, float dll_bw_hz, + float pll_bw_init_hz, + float dll_bw_init_hz, + int ti_ms, float early_late_space_chips); @@ -93,6 +96,9 @@ private: std::string dump_filename, float pll_bw_hz, float dll_bw_hz, + float pll_bw_init_hz, + float dll_bw_init_hz, + int ti_ms, float early_late_space_chips); Galileo_E5a_Dll_Pll_Tracking_cc(long if_freq, @@ -103,6 +109,9 @@ private: std::string dump_filename, float pll_bw_hz, float dll_bw_hz, + float pll_bw_init_hz, + float dll_bw_init_hz, + int ti_ms, float early_late_space_chips); void update_local_code(); void update_local_carrier(); @@ -111,8 +120,11 @@ private: boost::shared_ptr d_queue; concurrent_queue *d_channel_internal_queue; unsigned int d_vector_length; + int d_current_ti_ms; + int d_ti_ms; bool d_dump; + Gnss_Synchro* d_acquisition_gnss_synchro; unsigned int d_channel; int d_last_seg; @@ -120,17 +132,25 @@ private: long d_fs_in; double d_early_late_spc_chips; + float d_dll_bw_hz; + float d_pll_bw_hz; + float d_dll_bw_init_hz; + float d_pll_bw_init_hz; - gr_complex* d_code; + gr_complex* d_codeQ; + gr_complex* d_codeI; gr_complex* d_early_code; gr_complex* d_late_code; gr_complex* d_prompt_code; + gr_complex* d_prompt_data_code; gr_complex* d_carr_sign; - gr_complex *d_Early; - gr_complex *d_Prompt; - gr_complex *d_Late; + gr_complex d_Early; + gr_complex d_Prompt; + gr_complex d_Late; + gr_complex d_Prompt_data; + // remaining code phase and carrier phase between tracking loops float d_rem_code_phase_samples; @@ -152,6 +172,7 @@ private: float d_acc_carrier_phase_rad; float d_code_phase_samples; float d_acc_code_phase_secs; + float d_code_error_filt_secs; //PRN period in samples int d_current_prn_length_samples; @@ -169,12 +190,13 @@ private: int d_carrier_lock_fail_counter; // control vars - bool d_enable_tracking; - bool d_pull_in; + int d_state; + bool d_first_transition; // Secondary code acquisition bool d_secondary_lock; int d_secondary_delay; + unsigned int d_integration_counter; // file dump std::string d_dump_filename; diff --git a/src/algorithms/tracking/libs/correlator.cc b/src/algorithms/tracking/libs/correlator.cc index 75982cb9d..9b978c932 100644 --- a/src/algorithms/tracking/libs/correlator.cc +++ b/src/algorithms/tracking/libs/correlator.cc @@ -113,6 +113,80 @@ void Correlator::Carrier_wipeoff_and_EPL_volk(int signal_length_samples, const g //} } +//void Correlator::Carrier_wipeoff_and_EPL_volk_IQ(int prn_length_samples,int integration_time ,const gr_complex* input, gr_complex* carrier, gr_complex* E_code, gr_complex* P_code, gr_complex* L_code, gr_complex* P_data_code, gr_complex* E_out, gr_complex* P_out, gr_complex* L_out, gr_complex* P_data_out, bool input_vector_unaligned) +//{ +// gr_complex* bb_signal; +// //gr_complex* input_aligned; +// +// //todo: do something if posix_memalign fails +// if (posix_memalign((void**)&bb_signal, 16, integration_time * prn_length_samples * sizeof(gr_complex)) == 0) {}; +// +// if (input_vector_unaligned == true) +// { +// //todo: do something if posix_memalign fails +// //if (posix_memalign((void**)&input_aligned, 16, signal_length_samples * sizeof(gr_complex)) == 0){}; +// //memcpy(input_aligned,input,signal_length_samples * sizeof(gr_complex)); +// +// volk_32fc_x2_multiply_32fc_u(bb_signal, input, carrier, integration_time * prn_length_samples); +// } +// else +// { +// /* +// * todo: There is a problem with the aligned version of volk_32fc_x2_multiply_32fc_a. +// * It crashes even if the is_aligned() work function returns true. Im keeping the unaligned version in both cases.. +// */ +// //use directly the input vector +// volk_32fc_x2_multiply_32fc_u(bb_signal, input, carrier, integration_time * prn_length_samples); +// } +// +// volk_32fc_x2_dot_prod_32fc_a(E_out, bb_signal, E_code, integration_time * prn_length_samples); +// volk_32fc_x2_dot_prod_32fc_a(P_out, bb_signal, P_code, integration_time * prn_length_samples); +// volk_32fc_x2_dot_prod_32fc_a(L_out, bb_signal, L_code, integration_time * prn_length_samples); +// // Vector of Prompts of I code +// for (int i = 0; i < integration_time; i++) +// { +// volk_32fc_x2_dot_prod_32fc_a(&P_data_out[i], &bb_signal[i*prn_length_samples], P_data_code, prn_length_samples); +// } +// +// free(bb_signal); +// +//} +void Correlator::Carrier_wipeoff_and_EPL_volk_IQ(int signal_length_samples ,const gr_complex* input, gr_complex* carrier, gr_complex* E_code, gr_complex* P_code, gr_complex* L_code, gr_complex* P_data_code, gr_complex* E_out, gr_complex* P_out, gr_complex* L_out, gr_complex* P_data_out, bool input_vector_unaligned) +{ + gr_complex* bb_signal; + //gr_complex* input_aligned; + + //todo: do something if posix_memalign fails + if (posix_memalign((void**)&bb_signal, 16, signal_length_samples * sizeof(gr_complex)) == 0) {}; + + if (input_vector_unaligned == true) + { + //todo: do something if posix_memalign fails + //if (posix_memalign((void**)&input_aligned, 16, signal_length_samples * sizeof(gr_complex)) == 0){}; + //memcpy(input_aligned,input,signal_length_samples * sizeof(gr_complex)); + + volk_32fc_x2_multiply_32fc_u(bb_signal, input, carrier, signal_length_samples); + } + else + { + /* + * todo: There is a problem with the aligned version of volk_32fc_x2_multiply_32fc_a. + * It crashes even if the is_aligned() work function returns true. Im keeping the unaligned version in both cases.. + */ + //use directly the input vector + volk_32fc_x2_multiply_32fc_u(bb_signal, input, carrier, signal_length_samples); + } + + volk_32fc_x2_dot_prod_32fc_a(E_out, bb_signal, E_code, signal_length_samples); + volk_32fc_x2_dot_prod_32fc_a(P_out, bb_signal, P_code, signal_length_samples); + volk_32fc_x2_dot_prod_32fc_a(L_out, bb_signal, L_code, signal_length_samples); + volk_32fc_x2_dot_prod_32fc_a(P_data_out, bb_signal, P_data_code, signal_length_samples); + + + free(bb_signal); + +} + void Correlator::Carrier_wipeoff_and_EPL_volk_custom(int signal_length_samples, const gr_complex* input, gr_complex* carrier,gr_complex* E_code, gr_complex* P_code, gr_complex* L_code, gr_complex* E_out, gr_complex* P_out, gr_complex* L_out, bool input_vector_unaligned) { volk_cw_epl_corr_u(input, carrier, E_code, P_code, L_code, E_out, P_out, L_out, signal_length_samples); diff --git a/src/algorithms/tracking/libs/correlator.h b/src/algorithms/tracking/libs/correlator.h index d0e8bb110..246367429 100644 --- a/src/algorithms/tracking/libs/correlator.h +++ b/src/algorithms/tracking/libs/correlator.h @@ -57,6 +57,8 @@ public: void Carrier_wipeoff_and_EPL_volk(int signal_length_samples, const gr_complex* input, gr_complex* carrier, gr_complex* E_code, gr_complex* P_code, gr_complex* L_code, gr_complex* E_out, gr_complex* P_out, gr_complex* L_out, bool input_vector_unaligned); void Carrier_wipeoff_and_EPL_volk_custom(int signal_length_samples, const gr_complex* input, gr_complex* carrier, gr_complex* E_code, gr_complex* P_code, gr_complex* L_code, gr_complex* E_out, gr_complex* P_out, gr_complex* L_out, bool input_vector_unaligned); void Carrier_wipeoff_and_VEPL_volk(int signal_length_samples, const gr_complex* input, gr_complex* carrier, gr_complex* VE_code, gr_complex* E_code, gr_complex* P_code, gr_complex* L_code, gr_complex* VL_code, gr_complex* VE_out, gr_complex* E_out, gr_complex* P_out, gr_complex* L_out, gr_complex* VL_out, bool input_vector_unaligned); +// void Carrier_wipeoff_and_EPL_volk_IQ(int prn_length_samples,int integration_time ,const gr_complex* input, gr_complex* carrier, gr_complex* E_code, gr_complex* P_code, gr_complex* L_code, gr_complex* P_data_code, gr_complex* E_out, gr_complex* P_out, gr_complex* L_out, gr_complex* P_data_out, bool input_vector_unaligned); + void Carrier_wipeoff_and_EPL_volk_IQ(int signal_length_samples, const gr_complex* input, gr_complex* carrier, gr_complex* E_code, gr_complex* P_code, gr_complex* L_code, gr_complex* P_data_code, gr_complex* E_out, gr_complex* P_out, gr_complex* L_out, gr_complex* P_data_out, bool input_vector_unaligned); Correlator(); ~Correlator(); private: diff --git a/src/algorithms/tracking/libs/tracking_2nd_DLL_filter.cc b/src/algorithms/tracking/libs/tracking_2nd_DLL_filter.cc index b41b34807..79bee1f86 100644 --- a/src/algorithms/tracking/libs/tracking_2nd_DLL_filter.cc +++ b/src/algorithms/tracking/libs/tracking_2nd_DLL_filter.cc @@ -71,7 +71,8 @@ void Tracking_2nd_DLL_filter::initialize() float Tracking_2nd_DLL_filter::get_code_nco(float DLL_discriminator) { float code_nco; - code_nco = d_old_code_nco + (d_tau2_code/d_tau1_code)*(DLL_discriminator - d_old_code_error) + DLL_discriminator * (d_pdi_code/d_tau1_code); + code_nco = d_old_code_nco + (d_tau2_code/d_tau1_code)*(DLL_discriminator - d_old_code_error) + (DLL_discriminator+d_old_code_error) * (d_pdi_code/(2*d_tau1_code)); + //code_nco = d_old_code_nco + (d_tau2_code/d_tau1_code)*(DLL_discriminator - d_old_code_error) + DLL_discriminator * (d_pdi_code/d_tau1_code); d_old_code_nco = code_nco; d_old_code_error = DLL_discriminator; //[chips] return code_nco; @@ -92,3 +93,7 @@ Tracking_2nd_DLL_filter::Tracking_2nd_DLL_filter () Tracking_2nd_DLL_filter::~Tracking_2nd_DLL_filter () {} +void Tracking_2nd_DLL_filter::set_pdi(float pdi_code) +{ + d_pdi_code = pdi_code; // Summation interval for code +} diff --git a/src/algorithms/tracking/libs/tracking_2nd_DLL_filter.h b/src/algorithms/tracking/libs/tracking_2nd_DLL_filter.h index 14a5d9e8f..4ef37c538 100644 --- a/src/algorithms/tracking/libs/tracking_2nd_DLL_filter.h +++ b/src/algorithms/tracking/libs/tracking_2nd_DLL_filter.h @@ -60,6 +60,7 @@ private: public: void set_DLL_BW(float dll_bw_hz); //! Set DLL filter bandwidth [Hz] + void set_pdi(float pdi_code); //! Set Summation interval for code [s] void initialize(); //! Start tracking with acquisition information float get_code_nco(float DLL_discriminator); //! Numerically controlled oscillator Tracking_2nd_DLL_filter(float pdi_code); diff --git a/src/algorithms/tracking/libs/tracking_2nd_PLL_filter.cc b/src/algorithms/tracking/libs/tracking_2nd_PLL_filter.cc index 3882efd21..a98811c09 100644 --- a/src/algorithms/tracking/libs/tracking_2nd_PLL_filter.cc +++ b/src/algorithms/tracking/libs/tracking_2nd_PLL_filter.cc @@ -74,7 +74,8 @@ void Tracking_2nd_PLL_filter::initialize() float Tracking_2nd_PLL_filter::get_carrier_nco(float PLL_discriminator) { float carr_nco; - carr_nco = d_old_carr_nco + (d_tau2_carr/d_tau1_carr)*(PLL_discriminator - d_old_carr_error) + PLL_discriminator * (d_pdi_carr/d_tau1_carr); + carr_nco = d_old_carr_nco + (d_tau2_carr/d_tau1_carr)*(PLL_discriminator - d_old_carr_error) + (PLL_discriminator + d_old_carr_error) * (d_pdi_carr/(2*d_tau1_carr)); + //carr_nco = d_old_carr_nco + (d_tau2_carr/d_tau1_carr)*(PLL_discriminator - d_old_carr_error) + PLL_discriminator * (d_pdi_carr/d_tau1_carr); d_old_carr_nco = carr_nco; d_old_carr_error = PLL_discriminator; return carr_nco; @@ -84,7 +85,8 @@ Tracking_2nd_PLL_filter::Tracking_2nd_PLL_filter (float pdi_carr) { //--- PLL variables -------------------------------------------------------- d_pdi_carr = pdi_carr;// Summation interval for carrier - d_plldampingratio = 0.65; + //d_plldampingratio = 0.65; + d_plldampingratio = 0.7; } @@ -100,3 +102,8 @@ Tracking_2nd_PLL_filter::Tracking_2nd_PLL_filter () Tracking_2nd_PLL_filter::~Tracking_2nd_PLL_filter () {} + +void Tracking_2nd_PLL_filter::set_pdi(float pdi_carr) +{ + d_pdi_carr = pdi_carr; // Summation interval for code +} diff --git a/src/algorithms/tracking/libs/tracking_2nd_PLL_filter.h b/src/algorithms/tracking/libs/tracking_2nd_PLL_filter.h index 265200d5d..dc95bd830 100644 --- a/src/algorithms/tracking/libs/tracking_2nd_PLL_filter.h +++ b/src/algorithms/tracking/libs/tracking_2nd_PLL_filter.h @@ -62,6 +62,7 @@ private: public: void set_PLL_BW(float pll_bw_hz); //! Set PLL loop bandwidth [Hz] + void set_pdi(float pdi_carr); //! Set Summation interval for code [s] void initialize(); float get_carrier_nco(float PLL_discriminator); Tracking_2nd_PLL_filter(float pdi_carr); diff --git a/src/core/receiver/gnss_block_factory.cc b/src/core/receiver/gnss_block_factory.cc index d74290fda..a2a8f3d23 100644 --- a/src/core/receiver/gnss_block_factory.cc +++ b/src/core/receiver/gnss_block_factory.cc @@ -65,21 +65,17 @@ #include "galileo_e1_pcps_8ms_ambiguous_acquisition.h" #include "galileo_e1_pcps_tong_ambiguous_acquisition.h" #include "galileo_e1_pcps_cccwsr_ambiguous_acquisition.h" -#include "galileo_e5a_pcps_acquisition.h" // -#include "galileo_e5a_pilot_3ms_acquisition.h" -#include "galileo_e5ax_2ms_pcps_acquisition.h" -#include "galileo_e5a_3ms_noncoherent_iq_acquisition.h" +#include "galileo_e5a_noncoherent_iq_acquisition_caf.h" #include "gps_l1_ca_dll_pll_tracking.h" #include "gps_l1_ca_dll_pll_optim_tracking.h" #include "gps_l1_ca_dll_fll_pll_tracking.h" #include "gps_l1_ca_tcp_connector_tracking.h" #include "galileo_e1_dll_pll_veml_tracking.h" #include "galileo_e1_tcp_connector_tracking.h" -#include "galileo_e5a_dll_fll_pll_tracking.h" // #include "galileo_e5a_dll_pll_tracking.h" #include "gps_l1_ca_telemetry_decoder.h" #include "galileo_e1b_telemetry_decoder.h" -#include "galileo_e5a_telemetry_decoder.h" // problematic +#include "galileo_e5a_telemetry_decoder.h" #include "sbas_l1_telemetry_decoder.h" #include "gps_l1_ca_observables.h" #include "galileo_e1_observables.h" @@ -460,27 +456,9 @@ std::unique_ptr GNSSBlockFactory::GetBlock( out_streams, queue)); block = std::move(block_); } - else if (implementation.compare("Galileo_E5a_PCPS_Acquisition") == 0) + else if (implementation.compare("Galileo_E5a_Noncoherent_IQ_Acquisition_CAF") == 0) { - std::unique_ptr block_(new GalileoE5aPcpsAcquisition(configuration.get(), role, in_streams, - out_streams, queue)); - block = std::move(block_); - } - else if (implementation.compare("Galileo_E5a_Pilot_3ms_Acquisition") == 0) - { - std::unique_ptr block_(new GalileoE5aPilot_3msAcquisition(configuration.get(), role, in_streams, - out_streams, queue)); - block = std::move(block_); - } - else if (implementation.compare("Galileo_E5ax_2ms_Pcps_Acquisition") == 0) - { - std::unique_ptr block_(new GalileoE5ax2msPcpsAcquisition(configuration.get(), role, in_streams, - out_streams, queue)); - block = std::move(block_); - } - else if (implementation.compare("Galileo_E5a_3ms_Noncoherent_IQ_Acquisition") == 0) - { - std::unique_ptr block_(new GalileoE5a3msNoncoherentIQAcquisition(configuration.get(), role, in_streams, + std::unique_ptr block_(new GalileoE5aNoncoherentIQAcquisitionCaf(configuration.get(), role, in_streams, out_streams, queue)); block = std::move(block_); } @@ -523,12 +501,6 @@ std::unique_ptr GNSSBlockFactory::GetBlock( out_streams, queue)); block = std::move(block_); } - else if (implementation.compare("Galileo_E5a_DLL_FLL_PLL_Tracking") == 0) - { - std::unique_ptr block_(new GalileoE5aDllFllPllTracking(configuration.get(), role, in_streams, - out_streams, queue)); - block = std::move(block_); - } else if (implementation.compare("Galileo_E5a_DLL_PLL_Tracking") == 0) { std::unique_ptr block_(new GalileoE5aDllPllTracking(configuration.get(), role, in_streams, @@ -692,27 +664,9 @@ std::unique_ptr GNSSBlockFactory::GetAcqBlock( out_streams, queue)); block = std::move(block_); } - else if (implementation.compare("Galileo_E5a_PCPS_Acquisition") == 0) + else if (implementation.compare("Galileo_E5a_Noncoherent_IQ_Acquisition_CAF") == 0) { - std::unique_ptr block_(new GalileoE5aPcpsAcquisition(configuration.get(), role, in_streams, - out_streams, queue)); - block = std::move(block_); - } - else if (implementation.compare("Galileo_E5a_Pilot_3ms_Acquisition") == 0) - { - std::unique_ptr block_(new GalileoE5aPilot_3msAcquisition(configuration.get(), role, in_streams, - out_streams, queue)); - block = std::move(block_); - } - else if (implementation.compare("Galileo_E5ax_2ms_Pcps_Acquisition") == 0) - { - std::unique_ptr block_(new GalileoE5ax2msPcpsAcquisition(configuration.get(), role, in_streams, - out_streams, queue)); - block = std::move(block_); - } - else if (implementation.compare("Galileo_E5a_3ms_Noncoherent_IQ_Acquisition") == 0) - { - std::unique_ptr block_(new GalileoE5a3msNoncoherentIQAcquisition(configuration.get(), role, in_streams, + std::unique_ptr block_(new GalileoE5aNoncoherentIQAcquisitionCaf(configuration.get(), role, in_streams, out_streams, queue)); block = std::move(block_); } @@ -770,12 +724,6 @@ std::unique_ptr GNSSBlockFactory::GetTrkBlock( out_streams, queue)); block = std::move(block_); } - else if (implementation.compare("Galileo_E5a_DLL_FLL_PLL_Tracking") == 0) - { - std::unique_ptr block_(new GalileoE5aDllFllPllTracking(configuration.get(), role, in_streams, - out_streams, queue)); - block = std::move(block_); - } else if (implementation.compare("Galileo_E5a_DLL_PLL_Tracking") == 0) { std::unique_ptr block_(new GalileoE5aDllPllTracking(configuration.get(), role, in_streams, diff --git a/src/core/system_parameters/Galileo_E5a.h b/src/core/system_parameters/Galileo_E5a.h index 04397f160..236564d98 100644 --- a/src/core/system_parameters/Galileo_E5a.h +++ b/src/core/system_parameters/Galileo_E5a.h @@ -54,15 +54,13 @@ const int Galileo_E5a_NUMBER_OF_CODES = 50; // F/NAV message structure -#define GALILEO_FNAV_PREAMBLE {1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0} - const int GALILEO_FNAV_PREAMBLE_LENGTH_BITS = 12; -const int GALILEO_FNAV_SAMPLES_PER_SYMBOL = 20; // (chip rate/ code length)/telemetry bps -//const int GALILEO_FNAV_SYMBOLS_PER_PREAMBLE=240; -const int GALILEO_FNAV_SAMPLES_PER_PREAMBLE = 240; // bits preamble * samples/symbol +const std::string GALILEO_FNAV_PREAMBLE = {"101101110000"}; +const int GALILEO_FNAV_CODES_PER_SYMBOL = 20; // (chip rate/ code length)/telemetry bps +const int GALILEO_FNAV_CODES_PER_PREAMBLE = 240; // bits preamble * codes/symbol const int GALILEO_FNAV_SYMBOLS_PER_PAGE = 500; //Total symbols per page including preamble. See Galileo ICD 4.2.2 const int GALILEO_FNAV_SECONDS_PER_PAGE = 10; -const int GALILEO_FNAV_SAMPLES_PER_PAGE = 10000; // symbols * samples/symbol, where each 'sample' is a primary code +const int GALILEO_FNAV_CODES_PER_PAGE = 10000; // symbols * codes/symbol, where code stands for primary code const int GALILEO_FNAV_INTERLEAVER_ROWS = 8; const int GALILEO_FNAV_INTERLEAVER_COLS = 61; diff --git a/src/tests/gnss_block/galileo_e5a_pcps_acquisition_gsoc2014_gensource_test.cc b/src/tests/gnss_block/galileo_e5a_pcps_acquisition_gsoc2014_gensource_test.cc index b856a95dc..8437bdca2 100644 --- a/src/tests/gnss_block/galileo_e5a_pcps_acquisition_gsoc2014_gensource_test.cc +++ b/src/tests/gnss_block/galileo_e5a_pcps_acquisition_gsoc2014_gensource_test.cc @@ -42,10 +42,7 @@ #include "in_memory_configuration.h" #include "configuration_interface.h" #include "gnss_synchro.h" -#include "galileo_e5a_pcps_acquisition.h" -#include "galileo_e5a_pilot_3ms_acquisition.h" -#include "galileo_e5ax_2ms_pcps_acquisition.h" -#include "galileo_e5a_3ms_noncoherent_iq_acquisition.h" +#include "galileo_e5a_noncoherent_iq_acquisition_caf.h" #include "signal_generator.h" #include "signal_generator_c.h" #include "fir_filter.h" @@ -86,10 +83,8 @@ protected: gr::msg_queue::sptr queue; gr::top_block_sptr top_block; //std::shared_ptr factory = std::make_shared(); -// GalileoE5aPcpsAcquisition *acquisition; - //GalileoE5aPilot_3msAcquisition *acquisition; - //GalileoE5ax2msPcpsAcquisition *acquisition; - GalileoE5a3msNoncoherentIQAcquisition *acquisition; + GalileoE5aNoncoherentIQAcquisitionCaf *acquisition; + std::shared_ptr config; Gnss_Synchro gnss_synchro; size_t item_size; @@ -115,6 +110,8 @@ protected: double expected_doppler_hz3; float max_doppler_error_hz; float max_delay_error_chips; + int CAF_window_hz; + int Zero_padding; unsigned int num_of_realizations; unsigned int realization_counter; @@ -152,22 +149,28 @@ void GalileoE5aPcpsAcquisitionGSoC2014GensourceTest::config_1() { gnss_synchro.Channel_ID = 0; gnss_synchro.System = 'E'; - std::string signal = "5I"; - //std::string signal = "5Q"; - //std::string signal = "5X"; +// std::string signal = "5I"; +// std::string signal = "5Q"; + std::string signal = "5X"; signal.copy(gnss_synchro.Signal,2,0); - integration_time_ms = 3; - //fs_in = 10.24e6; + integration_time_ms = 1; + //fs_in = 11e6; //fs_in = 18e6; fs_in = 32e6; + //fs_in = 30.69e6; + //fs_in = 20.47e6; // unsigned int delay_samples = (delay_chips_[sat] % codelen) // * samples_per_code_[sat] / codelen; expected_delay_chips = round(14000*((double)10230000/(double)fs_in)); expected_doppler_hz = 2800; + //expected_doppler_hz = 0; expected_delay_sec = 94; + CAF_window_hz = 2000; +// CAF_window_hz = 0; + Zero_padding = 0; //expected_delay_chips = 1000; //expected_doppler_hz = 250; @@ -181,7 +184,12 @@ void GalileoE5aPcpsAcquisitionGSoC2014GensourceTest::config_1() config = std::make_shared(); + + config->set_property("Channel.signal",signal); + config->set_property("GNSS-SDR.internal_fs_hz", std::to_string(fs_in)); + int a = config->property("GNSS-SDR.internal_fs_hz",10); + std::cout << "fs "<< a <set_property("SignalSource.fs_hz", std::to_string(fs_in)); @@ -228,11 +236,12 @@ void GalileoE5aPcpsAcquisitionGSoC2014GensourceTest::config_1() config->set_property("Acquisition.coherent_integration_time_ms", std::to_string(integration_time_ms)); config->set_property("Acquisition.max_dwells", "1"); -// config->set_property("Acquisition.implementation", "Galileo_E5a_PCPS_Acquisition"); - //config->set_property("Acquisition.implementation", "Galileo_E5a_Pilot_3ms_Acquisition"); + config->set_property("Acquisition.CAF_window_hz",std::to_string(CAF_window_hz)); + config->set_property("Acquisition.Zero_padding",std::to_string(Zero_padding)); - config->set_property("Acquisition.implementation", "Galileo_E5a_3ms_Noncoherent_IQ_Acquisition"); - config->set_property("Acquisition.threshold", "0.1"); + config->set_property("Acquisition.implementation", "Galileo_E5a_Noncoherent_IQ_Acquisition_CAF"); + config->set_property("Acquisition.pfa","0.003"); +// config->set_property("Acquisition.threshold", "0.01"); config->set_property("Acquisition.doppler_max", "10000"); config->set_property("Acquisition.doppler_step", "250"); config->set_property("Acquisition.bit_transition_flag", "false"); @@ -602,9 +611,10 @@ TEST_F(GalileoE5aPcpsAcquisitionGSoC2014GensourceTest, ValidationOfSIM) config_1(); //int nsamples = floor(fs_in*integration_time_ms*1e-3); -// acquisition = new GalileoE5aPcpsAcquisition(config.get(), "Acquisition", 1, 1, queue); - acquisition = new GalileoE5a3msNoncoherentIQAcquisition(config.get(), "Acquisition", 1, 1, queue); - unsigned int skiphead_sps = 0; // 32 Msps + acquisition = new GalileoE5aNoncoherentIQAcquisitionCaf(config.get(), "Acquisition", 1, 1, queue); + unsigned int skiphead_sps = 28000; // 32 Msps +// unsigned int skiphead_sps = 0; + //unsigned int skiphead_sps = 84000; ASSERT_NO_THROW( { acquisition->set_channel(1); @@ -662,23 +672,19 @@ TEST_F(GalileoE5aPcpsAcquisitionGSoC2014GensourceTest, ValidationOfSIM) */ ASSERT_NO_THROW( { - //std::string path = std::string(TEST_PATH); - //std::string file = "/home/marc/E5a_acquisitions/signal_source_21MPrimary.dat"; - //noiseless - std::string file = "/home/marc/E5a_acquisitions/sim_32M_sec94_PRN11.dat"; - //std::string file = "/home/marc/E5a_acquisitions/signal_source_21MSecondary.dat"; + //noiseless sim + std::string file = "/home/marc/E5a_acquisitions/sim_32M_sec94_PRN11_long.dat"; + // real //std::string file = "/home/marc/E5a_acquisitions/32MS_complex.dat"; - //std::string file = "/home/marc/E5a_acquisitions/galileo_E5_8M_r2_upsampled_12.dat"; - //CN040 const char * file_name = file.c_str(); gr::blocks::file_source::sptr file_source = gr::blocks::file_source::make(sizeof(gr_complex), file_name, false); -// gr::blocks::skiphead::sptr skip_head = gr::blocks::skiphead::make(sizeof(gr_complex), skiphead_sps); -// top_block->connect(file_source, 0, skip_head, 0); -// top_block->connect(skip_head, 0, acquisition->get_left_block(), 0); + gr::blocks::skiphead::sptr skip_head = gr::blocks::skiphead::make(sizeof(gr_complex), skiphead_sps); + top_block->connect(file_source, 0, skip_head, 0); + top_block->connect(skip_head, 0, acquisition->get_left_block(), 0); - top_block->connect(file_source, 0, acquisition->get_left_block(), 0); +// top_block->connect(file_source, 0, acquisition->get_left_block(), 0); }) << "Failure connecting the blocks of acquisition test." << std::endl; // i = 0 --> satellite in acquisition is visible diff --git a/src/tests/gnss_block/galileo_e5a_tracking_test.cc b/src/tests/gnss_block/galileo_e5a_tracking_test.cc index 5a1c73169..f9e7a2f2f 100644 --- a/src/tests/gnss_block/galileo_e5a_tracking_test.cc +++ b/src/tests/gnss_block/galileo_e5a_tracking_test.cc @@ -84,10 +84,9 @@ void GalileoE5aTrackingTest::init() { gnss_synchro.Channel_ID = 0; gnss_synchro.System = 'E'; - std::string signal = "5X"; + std::string signal = "5Q"; signal.copy(gnss_synchro.Signal, 2, 0); - //gnss_synchro.PRN = 19;//real - gnss_synchro.PRN = 11;//sim + config->set_property("GNSS-SDR.internal_fs_hz", "32000000"); config->set_property("Tracking.item_type", "gr_complex"); @@ -97,10 +96,11 @@ void GalileoE5aTrackingTest::init() config->set_property("Tracking.early_late_space_chips", "0.5"); config->set_property("Tracking.pll_bw_hz", "5.0"); config->set_property("Tracking.dll_bw_hz", "2.0"); - //config->set_property("Tracking.fll_bw_hz", "10.0"); -// config->set_property("Tracking.pll_bw_hz", "20.0"); -// config->set_property("Tracking.dll_bw_hz", "1.0"); + config->set_property("Tracking.pll_bw_hz_init","20.0"); + config->set_property("Tracking.dll_bw_hz_init","20.0"); + config->set_property("Tracking.ti_ms","3"); + //config->set_property("Tracking.fll_bw_hz", "10.0"); } /* TEST_F(GalileoE5aTrackingTest, InstantiateTrack) @@ -169,9 +169,10 @@ TEST_F(GalileoE5aTrackingTest, ValidationOfResults) struct timeval tv; long long int begin = 0; long long int end = 0; - int num_samples = 3200000000; // 32 Msps + int num_samples = 32000000000; // 32 Msps //unsigned int skiphead_sps = 98000; // 1 Msample - unsigned int skiphead_sps = 0; // 1 Msample + unsigned int skiphead_sps = 0; // 1 Msampl +// unsigned int skiphead_sps = 104191; // 1 Msampl init(); // Example using smart pointers and the block factory @@ -179,16 +180,22 @@ TEST_F(GalileoE5aTrackingTest, ValidationOfResults) std::shared_ptr tracking = std::dynamic_pointer_cast(trk_); //REAL -// gnss_synchro.Acq_delay_samples = 15579; // 32 Msps -// gnss_synchro.Acq_doppler_hz = 3500; // 32 Msps -//// gnss_synchro.Acq_samplestamp_samples = 98000; -// gnss_synchro.Acq_samplestamp_samples = 0; -//SIM - gnss_synchro.Acq_delay_samples = 14001; // 32 Msps - gnss_synchro.Acq_doppler_hz = 2750; // 32 Msps (real 2800) + gnss_synchro.Acq_delay_samples = 15579+1; // 32 Msps + gnss_synchro.Acq_doppler_hz = 3500; // 32 Msps // gnss_synchro.Acq_samplestamp_samples = 98000; gnss_synchro.Acq_samplestamp_samples = 0; +//SIM +// gnss_synchro.Acq_delay_samples = 14001+1; // 32 Msps +// //gnss_synchro.Acq_doppler_hz = 2750; // 32 Msps (real 2800) +// gnss_synchro.Acq_doppler_hz = 2800; // 32 Msps (real 2800) +// //gnss_synchro.Acq_doppler_hz = 0; // 32 Msps (real 2800) +//// gnss_synchro.Acq_samplestamp_samples = 98000; +// gnss_synchro.Acq_samplestamp_samples = 0; +//SIM2 +// gnss_synchro.Acq_delay_samples = 5810; // 32 Msps +// gnss_synchro.Acq_doppler_hz = 2750; +// gnss_synchro.Acq_samplestamp_samples = 0; ASSERT_NO_THROW( { tracking->set_channel(gnss_synchro.Channel_ID); @@ -207,9 +214,11 @@ TEST_F(GalileoE5aTrackingTest, ValidationOfResults) }) << "Failure connecting tracking to the top_block." << std::endl; ASSERT_NO_THROW( { - //std::string file = "/home/marc/E5a_acquisitions/Tiered_sink_4sat.dat"; - //std::string file = "/home/marc/E5a_acquisitions/32MS_complex.dat"; - std::string file = "/home/marc/E5a_acquisitions/sim_32M_sec94_PRN11.dat"; + std::string file = "/home/marc/E5a_acquisitions/32MS_complex.dat"; + //std::string file = "/home/marc/E5a_acquisitions/sim_32M_sec94_PRN11_long.dat"; + //std::string file = "/home/marc/E5a_acquisitions/sim_32M_sec94_PRN11_long_0dopp.dat"; + gnss_synchro.PRN = 19;//real + //gnss_synchro.PRN = 11;//sim const char * file_name = file.c_str(); gr::blocks::file_source::sptr file_source = gr::blocks::file_source::make(sizeof(gr_complex),file_name,false); diff --git a/src/utils/matlab/galileo_e5a_dll_pll_plot_sample_64bits.m b/src/utils/matlab/galileo_e5a_dll_pll_plot_sample_64bits.m new file mode 100644 index 000000000..52942c30f --- /dev/null +++ b/src/utils/matlab/galileo_e5a_dll_pll_plot_sample_64bits.m @@ -0,0 +1,88 @@ +% /*! +% * \file galileo_e5a_dll_pll_plot_sample_64bits.m +% * \brief Read GNSS-SDR Tracking dump binary file using the provided +% function and plot some internal variables +% * \author Javier Arribas, Marc Sales 2014. jarribas(at)cttc.es +% marcsales92@gmail.com +% * ------------------------------------------------------------------------- +% * +% * Copyright (C) 2010-2014 (see AUTHORS file for a list of contributors) +% * +% * GNSS-SDR is a software defined Global Navigation +% * Satellite Systems receiver +% * +% * This file is part of GNSS-SDR. +% * +% * GNSS-SDR is free software: you can redistribute it and/or modify +% * it under the terms of the GNU General Public License as published by +% * the Free Software Foundation, either version 3 of the License, or +% * at your option) any later version. +% * +% * GNSS-SDR is distributed in the hope that it will be useful, +% * but WITHOUT ANY WARRANTY; without even the implied warranty of +% * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% * GNU General Public License for more details. +% * +% * You should have received a copy of the GNU General Public License +% * along with GNSS-SDR. If not, see . +% * +% * ------------------------------------------------------------------------- +% */ +close all; +clear all; +samplingFreq = 64e6/32; %[Hz] +channels=1; +%path='/home/javier/workspace/gnss-sdr/trunk/install/'; +path='/home/marc/git/gnss-sdr/data/'; +clear PRN_absolute_sample_start; +for N=1:1:channels + tracking_log_path=[path 'e5a_tracking_ch_' num2str(N-1) '.dat']; + GNSS_tracking(N)= gps_l1_ca_dll_pll_read_tracking_dump_64bits(tracking_log_path); +end + +% GNSS-SDR format conversion to MATLAB GPS receiver + +for N=1:1:channels + trackResults(N).status='T'; %fake track + trackResults(N).codeFreq=GNSS_tracking(N).code_freq_hz.'; + trackResults(N).carrFreq=GNSS_tracking(N).carrier_doppler_hz.'; + trackResults(N).dllDiscr = GNSS_tracking(N).code_error.'; + trackResults(N).dllDiscrFilt = GNSS_tracking(N).code_nco.'; + trackResults(N).pllDiscr = GNSS_tracking(N).carr_error.'; + trackResults(N).pllDiscrFilt = GNSS_tracking(N).carr_nco.'; + + trackResults(N).I_P=GNSS_tracking(N).prompt_I.'; + trackResults(N).Q_P=GNSS_tracking(N).prompt_Q.'; + + trackResults(N).I_E= GNSS_tracking(N).E.'; + trackResults(N).I_L = GNSS_tracking(N).L.'; + trackResults(N).Q_E = zeros(1,length(GNSS_tracking(N).E)); + trackResults(N).Q_L =zeros(1,length(GNSS_tracking(N).E)); + trackResults(N).PRN=N; %fake PRN + + % Use original MATLAB tracking plot function + settings.numberOfChannels=channels; + settings.msToProcess=length(GNSS_tracking(N).E); + plotTracking(N,trackResults,settings) +end + +for N=1:1:channels +% figure; +% plot([GNSS_tracking(N).E,GNSS_tracking(N).P,GNSS_tracking(N).L],'-*'); +% title(['Early, Prompt, and Late correlator absolute value output for channel ' num2str(N)']); +% figure; +% plot(GNSS_tracking(N).prompt_I,GNSS_tracking(N).prompt_Q,'+'); +% title(['Navigation constellation plot for channel ' num2str(N)]); +% figure; +% +% plot(GNSS_tracking(N).prompt_Q,'r'); +% hold on; +% plot(GNSS_tracking(N).prompt_I); +% title(['Navigation symbols I(red) Q(blue) for channel ' num2str(N)]); +% + figure; + t=0:length(GNSS_tracking(N).carrier_doppler_hz)-1; + t=t/1000; + plot(t,GNSS_tracking(N).carrier_doppler_hz/1000); + xlabel('Time(s)');ylabel('Doppler(KHz)');title(['Doppler frequency channel ' num2str(N)]); +end \ No newline at end of file diff --git a/plot_acq_grid_gsoc_e5.m b/src/utils/matlab/plot_acq_grid_gsoc_e5.m similarity index 51% rename from plot_acq_grid_gsoc_e5.m rename to src/utils/matlab/plot_acq_grid_gsoc_e5.m index ff1a15d12..133ab54a4 100644 --- a/plot_acq_grid_gsoc_e5.m +++ b/src/utils/matlab/plot_acq_grid_gsoc_e5.m @@ -1,16 +1,18 @@ % /*! -% * \file plot_acq_grid_gsoc.m +% * \file plot_acq_grid_gsoc_e5.m % * \brief Read GNSS-SDR Acquisition dump binary file using the provided -% function and plot acquisition grid of acquisition statistic of PRN sat +% function and plot acquisition grid of acquisition statistic of PRN sat. +% CAF input must be 0 or 1 depending if the user desires to read the file +% that resolves doppler ambiguity or not. % -% This function analyzes a experiment performed by Luis Esteve in the framework -% of the Google Summer of Code (GSoC) 2012, with the collaboration of Javier Arribas +% This function analyzes a experiment performed by Marc Sales in the framework +% of the Google Summer of Code (GSoC) 2014, with the collaboration of Luis Esteve, Javier Arribas % and Carles Fernández, related to the extension of GNSS-SDR to Galileo. % -% * \author Luis Esteve, 2012. luis(at)epsilon-formacion.com +% * \author Marc Sales marcsales92(at)gmail.com, Luis Esteve, 2014. luis(at)epsilon-formacion.com % * ------------------------------------------------------------------------- % * -% * Copyright (C) 2010-2011 (see AUTHORS file for a list of contributors) +% * Copyright (C) 2010-2014 (see AUTHORS file for a list of contributors) % * % * GNSS-SDR is a software defined Global Navigation % * Satellite Systems receiver @@ -33,22 +35,30 @@ % * ------------------------------------------------------------------------- % */ -function plot_acq_grid_gsoc_e5(sat) +function plot_acq_grid_gsoc_e5(sat,CAF) -file=['test_statistics_E_5I_sat_' num2str(sat) '_doppler_0.dat']; +path='/home/marc/git/gnss-sdr/data/'; +file=[path 'test_statistics_E5a_sat_' num2str(sat) '_doppler_0.dat']; -sampling_freq_Hz=12E6 -Doppler_max_Hz = 9875 +sampling_freq_Hz=32E6 +%Doppler_max_Hz = 14875 +%Doppler_min_Hz = -15000 +%Doppler_step_Hz = 125 +Doppler_max_Hz = 10000 Doppler_min_Hz = -10000 -Doppler_step_Hz = 125 +Doppler_step_Hz = 250 + % read files %x=read_complex_binary (file); -x=load_complex_data(file); +%x=load_complex_data(file); % complex +%l_y=length(x); +myFile = java.io.File(file); +flen = length(myFile); +l_y=flen/4;% float -l_y=length(x); Doppler_axes=Doppler_min_Hz:Doppler_step_Hz:Doppler_max_Hz; @@ -60,20 +70,33 @@ index=0; for k=Doppler_min_Hz:Doppler_step_Hz:Doppler_max_Hz index=index+1; - filename=['test_statistics_E_5I_sat_' num2str(sat) '_doppler_' num2str(k) '.dat']; - acq_grid(index,:)=abs(read_complex_binary (filename)); - end - -maximum_correlation_peak = max(max(acq_grid)) + filename=[path 'test_statistics_E5a_sat_' num2str(sat) '_doppler_' num2str(k) '.dat']; + fid=fopen(filename,'r'); + xx=fread(fid,'float');%floats from squared correlation + %xx=load_complex_data (filename); %complex + acq_grid(index,:)=abs(xx); +end [fila,col]=find(acq_grid==max(max(acq_grid))); +if (CAF > 0) + filename=[path 'test_statistics_E5a_sat_' num2str(sat) '_CAF.dat']; + fid=fopen(filename,'r'); + xx=fread(fid,'float');%floats from squared correlation + acq_grid(:,col)=abs(xx); + Doppler_error_Hz = Doppler_axes(xx==max(xx)) + maximum_correlation_peak = max(xx) +else + Doppler_error_Hz = Doppler_axes(fila) + maximum_correlation_peak = max(max(acq_grid)) +end + delay_error_sps = col -1 -Doppler_error_Hz = Doppler_axes(fila) + noise_grid=acq_grid; -delay_span=floor(3*sampling_freq_Hz/(1.023e6)); +delay_span=floor(3*sampling_freq_Hz/(1.023e7)); Doppler_span=floor(500/Doppler_step_Hz); noise_grid(fila-Doppler_span:fila+Doppler_span,col-delay_span:col+delay_span)=0; @@ -91,25 +114,24 @@ Gain_dbs = 10*log10(maximum_correlation_peak/noise_floor) figure; surf(X,Y,acq_grid'); -xlabel('Doppler(Hz)');ylabel('Code Delay(samples)');title(['GLRT statistic of Galileo Parallel Code Phase Search Acquisition. Local replica: E5a-I PRN ' num2str(sat)]); +xlabel('Doppler(Hz)');ylabel('Code Delay(samples)');title(['GLRT statistic of Galileo Parallel Code Phase Search Acquisition. PRN ' num2str(sat)]); end function x=load_complex_data(file) -%fid = fopen(file,'r'); -fid = fopen('signal_source.dat','r'); -k=1; -tline=fgetl(fid); -%while (~feof(fid)) -while (ischar(tline)) - %x(k,1:2) = fread(fid, 2, 'float'); - a=strplit(tline); - disp(a); - tline=fgetl(fid); +fid = fopen(file,'r'); +%fid = fopen('signal_source.dat','r'); + +myFile = java.io.File(file); +flen = length(myFile); +num_samples=flen/8; % 8 bytes (2 single floats) per complex sample + +for k=1:num_samples + a(1:2) = fread(fid, 2, 'float'); + x(k) = a(1) + a(2)*1i; k=k+1; - if k==12000 - end end -end \ No newline at end of file +end +