From 8b10549fee82b569633724ed10f0eff6d977d89e Mon Sep 17 00:00:00 2001 From: Luis Esteve Date: Tue, 23 Jul 2013 18:03:07 +0000 Subject: [PATCH] Patch submitted by Marc Molina: Improving PCPS Acquisition with some VOLK instructions. Enabling the secondary spreading code in Galileo acquisition. Adding Signal Generator to GNSS-SDR. git-svn-id: https://svn.code.sf.net/p/gnss-sdr/code/trunk@397 64b25241-fba3-4117-9849-534c7e92360d --- src/algorithms/CMakeLists.txt | 1 + .../galileo_e1_pcps_ambiguous_acquisition.cc | 38 +- .../galileo_e1_pcps_ambiguous_acquisition.h | 6 + .../adapters/gps_l1_ca_pcps_acquisition.cc | 54 +-- .../adapters/gps_l1_ca_pcps_acquisition.h | 8 +- ...gps_l1_ca_pcps_acquisition_fine_doppler.cc | 15 +- .../gps_l1_ca_pcps_acquisition_fine_doppler.h | 2 + .../gps_l1_ca_pcps_assisted_acquisition.cc | 13 +- .../gps_l1_ca_pcps_assisted_acquisition.h | 2 + .../gnuradio_blocks/pcps_acquisition_cc.cc | 154 +++++--- .../gnuradio_blocks/pcps_acquisition_cc.h | 77 ++-- src/algorithms/channel/adapters/channel.cc | 5 +- .../libs/galileo_e1_signal_processing.cc | 106 ++++-- .../libs/galileo_e1_signal_processing.h | 10 +- .../signal_generator/CMakeLists.txt | 20 ++ .../signal_generator/adapters/CMakeLists.txt | 34 ++ .../adapters/signal_generator.cc | 167 +++++++++ .../adapters/signal_generator.h | 96 +++++ .../gnuradio_blocks/CMakeLists.txt | 35 ++ .../gnuradio_blocks/signal_generator_c.cc | 335 ++++++++++++++++++ .../gnuradio_blocks/signal_generator_c.h | 129 +++++++ .../signal_source/adapters/CMakeLists.txt | 2 +- .../adapters/gen_signal_source.cc | 115 ++++++ .../adapters/gen_signal_source.h | 80 +++++ src/core/interfaces/acquisition_interface.h | 1 + src/core/system_parameters/Galileo_E1.h | 6 +- 26 files changed, 1349 insertions(+), 162 deletions(-) create mode 100644 src/algorithms/signal_generator/CMakeLists.txt create mode 100644 src/algorithms/signal_generator/adapters/CMakeLists.txt create mode 100644 src/algorithms/signal_generator/adapters/signal_generator.cc create mode 100644 src/algorithms/signal_generator/adapters/signal_generator.h create mode 100644 src/algorithms/signal_generator/gnuradio_blocks/CMakeLists.txt create mode 100644 src/algorithms/signal_generator/gnuradio_blocks/signal_generator_c.cc create mode 100644 src/algorithms/signal_generator/gnuradio_blocks/signal_generator_c.h create mode 100644 src/algorithms/signal_source/adapters/gen_signal_source.cc create mode 100644 src/algorithms/signal_source/adapters/gen_signal_source.h diff --git a/src/algorithms/CMakeLists.txt b/src/algorithms/CMakeLists.txt index 720fbb9eb..49a7ce162 100644 --- a/src/algorithms/CMakeLists.txt +++ b/src/algorithms/CMakeLists.txt @@ -25,6 +25,7 @@ add_subdirectory(observables) add_subdirectory(telemetry_decoder) add_subdirectory(output_filter) add_subdirectory(resampler) +add_subdirectory(signal_generator) add_subdirectory(signal_source) add_subdirectory(input_filter) add_subdirectory(tracking) diff --git a/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.cc b/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.cc index 7944bca7b..f00287c1a 100644 --- a/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.cc +++ b/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.cc @@ -71,17 +71,20 @@ GalileoE1PcpsAmbiguousAcquisition::GalileoE1PcpsAmbiguousAcquisition( fs_in_ / (Galileo_E1_CODE_CHIP_RATE_HZ / Galileo_E1_B_CODE_LENGTH_CHIPS)); + int samples_per_ms = vector_length_ / 4; - code_ = new gr_complex[vector_length_]; + vector_length_ = samples_per_ms * 4; + + code_ = new gr_complex[samples_per_ms*sampled_ms_]; if (item_type_.compare("gr_complex") == 0) { item_size_ = sizeof(gr_complex); acquisition_cc_ = pcps_make_acquisition_cc(sampled_ms_, - shift_resolution_, if_, fs_in_, samples_per_ms, queue_, - dump_, dump_filename_); - stream_to_vector_ = gr::blocks::stream_to_vector::make(item_size_, vector_length_); + shift_resolution_, if_, fs_in_, samples_per_ms, vector_length_, + queue_, dump_, dump_filename_); + stream_to_vector_ = gr::blocks::stream_to_vector::make(item_size_, samples_per_ms * sampled_ms_); DLOG(INFO) << "stream_to_vector(" << stream_to_vector_->unique_id() << ")"; DLOG(INFO) << "acquisition(" << acquisition_cc_->unique_id() @@ -115,6 +118,7 @@ GalileoE1PcpsAmbiguousAcquisition::set_channel(unsigned int channel) void GalileoE1PcpsAmbiguousAcquisition::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); @@ -124,7 +128,7 @@ GalileoE1PcpsAmbiguousAcquisition::set_threshold(float threshold) threshold_ = threshold; } else - { + { threshold_ = calculate_threshold(pfa); } @@ -202,16 +206,32 @@ GalileoE1PcpsAmbiguousAcquisition::mag() void GalileoE1PcpsAmbiguousAcquisition::init() +{ + acquisition_cc_->init(); + set_local_code(); +} + +void +GalileoE1PcpsAmbiguousAcquisition::set_local_code() { if (item_type_.compare("gr_complex") == 0) { bool cboc = configuration_->property( "Acquisition" + boost::lexical_cast(channel_) + ".cboc", false); - galileo_e1_code_gen_complex_sampled(code_, gnss_synchro_->Signal, - cboc, gnss_synchro_->PRN, fs_in_, 0); + + std::complex * code = new std::complex[vector_length_]; + + galileo_e1_code_gen_complex_sampled(code, gnss_synchro_->Signal, + cboc, gnss_synchro_->PRN, fs_in_, 0, false); + + for (unsigned int i = 0; i < sampled_ms_/4; i++) + { + memcpy(&(code_[i*vector_length_]), code, + sizeof(gr_complex)*vector_length_); + } + acquisition_cc_->set_local_code(code_); - acquisition_cc_->init(); } } @@ -227,8 +247,6 @@ GalileoE1PcpsAmbiguousAcquisition::reset() float GalileoE1PcpsAmbiguousAcquisition::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_) { diff --git a/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.h b/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.h index 3c26a3324..bdd28f28d 100644 --- a/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.h +++ b/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.h @@ -113,6 +113,12 @@ public: */ void init(); + /*! + * \brief Sets local code for Galileo E1 PCPS acquisition algorithm. + */ + + void set_local_code(); + /*! * \brief Returns the maximum peak of grid search */ diff --git a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition.cc b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition.cc index e31e51534..fc59fd4eb 100644 --- a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition.cc +++ b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition.cc @@ -65,7 +65,7 @@ GpsL1CaPcpsAcquisition::GpsL1CaPcpsAcquisition( fs_in_ = configuration_->property("GNSS-SDR.internal_fs_hz", 2048000); if_ = configuration_->property(role + ".ifreq", 0); dump_ = configuration_->property(role + ".dump", false); - shift_resolution_ = configuration_->property(role + ".doppler_max", 15); + shift_resolution_ = configuration_->property(role + ".doppler_max", 10000); sampled_ms_ = configuration_->property(role + ".sampled_ms", 1); dump_filename_ = configuration_->property(role + ".dump_filename", default_dump_filename); @@ -74,16 +74,16 @@ GpsL1CaPcpsAcquisition::GpsL1CaPcpsAcquisition( vector_length_ = round(fs_in_ / (GPS_L1_CA_CODE_RATE_HZ / GPS_L1_CA_CODE_LENGTH_CHIPS)); - code_= new gr_complex[vector_length_]; + code_= new gr_complex[vector_length_ * sampled_ms_]; if (item_type_.compare("gr_complex") == 0) { item_size_ = sizeof(gr_complex); acquisition_cc_ = pcps_make_acquisition_cc(sampled_ms_, - shift_resolution_, if_, fs_in_, vector_length_, queue_, + shift_resolution_, if_, fs_in_, vector_length_, vector_length_, queue_, dump_, dump_filename_); - stream_to_vector_ = gr::blocks::stream_to_vector::make(item_size_, vector_length_); + stream_to_vector_ = gr::blocks::stream_to_vector::make(item_size_, vector_length_*sampled_ms_); DLOG(INFO) << "stream_to_vector(" << stream_to_vector_->unique_id() << ")"; @@ -123,13 +123,13 @@ void GpsL1CaPcpsAcquisition::set_threshold(float threshold) pfa = configuration_->property(role_+".pfa", 0.0); } if(pfa==0.0) - { - threshold_ = threshold; - } + { + threshold_ = threshold; + } else - { - threshold_ = calculate_threshold(pfa); - } + { + threshold_ = calculate_threshold(pfa); + } DLOG(INFO) <<"Channel "<PRN, fs_in_, 0); - acquisition_cc_->set_local_code(code_); - acquisition_cc_->init(); - } +void GpsL1CaPcpsAcquisition::init() +{ + acquisition_cc_->init(); + set_local_code(); } +void GpsL1CaPcpsAcquisition::set_local_code() +{ + if (item_type_.compare("gr_complex") == 0) + { + std::complex* code = new std::complex[vector_length_]; + + gps_l1_ca_code_gen_complex_sampled(code, gnss_synchro_->PRN, fs_in_, 0); + + for (unsigned int i = 0; i < sampled_ms_; i++) + { + memcpy(&(code_[i*vector_length_]), code, + sizeof(gr_complex)*vector_length_); + } + + acquisition_cc_->set_local_code(code_); + } +} void GpsL1CaPcpsAcquisition::reset() { @@ -238,9 +252,9 @@ float GpsL1CaPcpsAcquisition::calculate_threshold(float pfa) void GpsL1CaPcpsAcquisition::connect(gr::top_block_sptr top_block) { if (item_type_.compare("gr_complex") == 0) - { - top_block->connect(stream_to_vector_, 0, acquisition_cc_, 0); - } + { + top_block->connect(stream_to_vector_, 0, acquisition_cc_, 0); + } } diff --git a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition.h b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition.h index 0df019145..93aede7b8 100644 --- a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition.h +++ b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition.h @@ -5,7 +5,7 @@ * \authors
    *
  • Javier Arribas, 2011. jarribas(at)cttc.es *
  • Luis Esteve, 2012. luis(at)epsilon-formacion.com - *
* + * * * ------------------------------------------------------------------------- * @@ -116,6 +116,12 @@ public: */ void init(); + /*! + * \brief Sets local code for GPS L1/CA PCPS acquisition algorithm. + */ + + void set_local_code(); + /*! * \brief Returns the maximum peak of grid search */ diff --git a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fine_doppler.cc b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fine_doppler.cc index 0c0e5885e..c1719c956 100644 --- a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fine_doppler.cc +++ b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fine_doppler.cc @@ -146,10 +146,17 @@ signed int GpsL1CaPcpsAcquisitionFineDoppler::mag() } -void GpsL1CaPcpsAcquisitionFineDoppler::init(){ - gps_l1_ca_code_gen_complex_sampled(code_, gnss_synchro_->PRN, fs_in_, 0); - acquisition_cc_->set_local_code(code_); - acquisition_cc_->init(); +void GpsL1CaPcpsAcquisitionFineDoppler::init() +{ + acquisition_cc_->init(); + set_local_code(); +} + + +void GpsL1CaPcpsAcquisitionFineDoppler::set_local_code() +{ + gps_l1_ca_code_gen_complex_sampled(code_, gnss_synchro_->PRN, fs_in_, 0); + acquisition_cc_->set_local_code(code_); } diff --git a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fine_doppler.h b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fine_doppler.h index cf85f41da..4f6580cb4 100644 --- a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fine_doppler.h +++ b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fine_doppler.h @@ -115,6 +115,8 @@ public: */ void init(); + void set_local_code(); + /*! * \brief Returns the maximum peak of grid search */ diff --git a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_assisted_acquisition.cc b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_assisted_acquisition.cc index 41d054c2a..4bdf80660 100644 --- a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_assisted_acquisition.cc +++ b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_assisted_acquisition.cc @@ -145,12 +145,17 @@ signed int GpsL1CaPcpsAssistedAcquisition::mag() } -void GpsL1CaPcpsAssistedAcquisition::init(){ - gps_l1_ca_code_gen_complex_sampled(code_, gnss_synchro_->PRN, fs_in_, 0); - acquisition_cc_->set_local_code(code_); - acquisition_cc_->init(); +void GpsL1CaPcpsAssistedAcquisition::init() +{ + acquisition_cc_->init(); + set_local_code(); } +void GpsL1CaPcpsAssistedAcquisition::set_local_code() +{ + gps_l1_ca_code_gen_complex_sampled(code_, gnss_synchro_->PRN, fs_in_, 0); + acquisition_cc_->set_local_code(code_); +} void GpsL1CaPcpsAssistedAcquisition::reset() { diff --git a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_assisted_acquisition.h b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_assisted_acquisition.h index a7808ada8..1f8e17e3b 100644 --- a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_assisted_acquisition.h +++ b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_assisted_acquisition.h @@ -115,6 +115,8 @@ public: */ void init(); + void set_local_code(); + /*! * \brief Returns the maximum peak of grid search */ diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.cc b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.cc index 2bed6d37d..5e5f21d3f 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.cc +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.cc @@ -4,6 +4,7 @@ * \authors
    *
  • Javier Arribas, 2011. jarribas(at)cttc.es *
  • Luis Esteve, 2012. luis(at)epsilon-formacion.com + *
  • Marc Molina, 2013. marc.molina.pena@gmail.com *
* * ------------------------------------------------------------------------- @@ -43,25 +44,25 @@ using google::LogMessage; pcps_acquisition_cc_sptr pcps_make_acquisition_cc( - unsigned int sampled_ms, unsigned int doppler_max, long freq, - long fs_in, int samples_per_ms, gr::msg_queue::sptr queue, bool dump, - std::string dump_filename) + unsigned int sampled_ms, unsigned int doppler_max, + long freq, long fs_in, int samples_per_ms, int samples_per_code, + gr::msg_queue::sptr queue, bool dump, std::string dump_filename) { return pcps_acquisition_cc_sptr( - new pcps_acquisition_cc(sampled_ms, doppler_max, freq, - fs_in, samples_per_ms, queue, dump, dump_filename)); + new pcps_acquisition_cc(sampled_ms, doppler_max, freq, fs_in, + samples_per_ms, samples_per_code, queue, dump, dump_filename)); } pcps_acquisition_cc::pcps_acquisition_cc( - unsigned int sampled_ms, unsigned int doppler_max, long freq, - long fs_in, int samples_per_ms, gr::msg_queue::sptr queue, bool dump, - std::string dump_filename) : - gr::block("pcps_acquisition_cc", - gr::io_signature::make(1, 1, sizeof(gr_complex) * sampled_ms * samples_per_ms), - gr::io_signature::make(0, 0, sizeof(gr_complex) * sampled_ms * samples_per_ms)) + unsigned int sampled_ms, unsigned int doppler_max, + long freq, long fs_in, int samples_per_ms, int samples_per_code, + gr::msg_queue::sptr queue, bool dump, std::string dump_filename) : + gr::block("pcps_acquisition_cc", + gr::io_signature::make(1, 1, sizeof(gr_complex) * sampled_ms * samples_per_ms), + gr::io_signature::make(0, 0, sizeof(gr_complex) * sampled_ms * samples_per_ms)) { d_sample_counter = 0; // SAMPLE COUNTER d_active = false; @@ -69,15 +70,17 @@ pcps_acquisition_cc::pcps_acquisition_cc( d_freq = freq; d_fs_in = fs_in; d_samples_per_ms = samples_per_ms; + d_samples_per_code = samples_per_code; d_sampled_ms = sampled_ms; d_doppler_max = doppler_max; d_fft_size = d_sampled_ms * d_samples_per_ms; d_mag = 0; d_input_power = 0.0; + d_num_doppler_bins = 0; //todo: do something if posix_memalign fails - if (posix_memalign((void**)&d_carrier, 16, d_fft_size * sizeof(gr_complex)) == 0){}; if (posix_memalign((void**)&d_fft_codes, 16, d_fft_size * sizeof(gr_complex)) == 0){}; + if (posix_memalign((void**)&d_magnitude, 16, d_fft_size * sizeof(gr_complex)) == 0){}; // Direct FFT d_fft_if = new gr::fft::fft_complex(d_fft_size, true); @@ -94,8 +97,22 @@ pcps_acquisition_cc::pcps_acquisition_cc( pcps_acquisition_cc::~pcps_acquisition_cc() { - free(d_carrier); + + + for (unsigned int doppler_index = 0; doppler_index < d_num_doppler_bins; doppler_index++) + { + free(d_grid_doppler_wipeoffs[doppler_index]); + } + + + if (d_num_doppler_bins > 0) + { + delete[] d_grid_doppler_wipeoffs; + } + free(d_fft_codes); + free(d_magnitude); + delete d_ifft; delete d_fft_if; if (d_dump) @@ -108,7 +125,19 @@ pcps_acquisition_cc::~pcps_acquisition_cc() void pcps_acquisition_cc::set_local_code(std::complex * code) { - memcpy(d_fft_if->get_inbuf(),code, sizeof(gr_complex)*d_fft_size); + 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_codes,d_fft_if->get_outbuf(),d_fft_size); + } + else + { + volk_32fc_conjugate_32fc_a(d_fft_codes,d_fft_if->get_outbuf(),d_fft_size); + } } @@ -121,13 +150,18 @@ void pcps_acquisition_cc::init() d_mag = 0.0; d_input_power = 0.0; - d_fft_if->execute(); // We need the FFT of local code + // Create the carrier Doppler wipeoff signals + d_num_doppler_bins=floor(2*std::abs((int)d_doppler_max)/d_doppler_step); + d_grid_doppler_wipeoffs = new gr_complex*[d_num_doppler_bins]; + for (unsigned int doppler_index=0;doppler_index(conj(d_fft_if->get_outbuf()[i])); - } + 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); + } } @@ -158,7 +192,6 @@ int pcps_acquisition_cc::general_work(int noutput_items, int doppler; unsigned int indext = 0; float magt = 0.0; - float tmp_magt = 0.0; const gr_complex *in = (const gr_complex *)input_items[0]; //Get the input samples pointer bool positive_acquisition = false; int acquisition_message = -1; //0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL @@ -175,35 +208,41 @@ int pcps_acquisition_cc::general_work(int noutput_items, d_input_power = 0.0; 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; + << " , 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 - for (i = 0; i < d_fft_size; i++) + if (is_unaligned()) { - d_input_power += std::norm(in[i]); + volk_32fc_magnitude_squared_32f_u(d_magnitude, in, d_fft_size); + for (i = 0; i < d_fft_size; i++) + d_input_power += d_magnitude[i]; } - d_input_power = d_input_power / (float)d_fft_size; + else + { + 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 (doppler = (int)(-d_doppler_max); doppler <= (int)d_doppler_max; doppler += d_doppler_step) + for (unsigned int doppler_index=0;doppler_indexget_inbuf(), in, d_carrier, d_fft_size); + volk_32fc_x2_multiply_32fc_u(d_fft_if->get_inbuf(), in, + d_grid_doppler_wipeoffs[doppler_index], d_fft_size); } else { - //use directly the input vector - volk_32fc_x2_multiply_32fc_a(d_fft_if->get_inbuf(), in, d_carrier, d_fft_size); + volk_32fc_x2_multiply_32fc_a(d_fft_if->get_inbuf(), in, + d_grid_doppler_wipeoffs[doppler_index], d_fft_size); } // 3- Perform the FFT-based convolution (parallel time search) @@ -212,32 +251,52 @@ int pcps_acquisition_cc::general_work(int noutput_items, // 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_codes, d_fft_size); + if (is_unaligned()) + { + volk_32fc_x2_multiply_32fc_u(d_ifft->get_inbuf(), + d_fft_if->get_outbuf(), d_fft_codes, d_fft_size); + } + else + { + volk_32fc_x2_multiply_32fc_a(d_ifft->get_inbuf(), + d_fft_if->get_outbuf(), d_fft_codes, d_fft_size); + } // compute the inverse FFT d_ifft->execute(); // Search maximum indext = 0; - magt = 0; + magt = 0.0; + fft_normalization_factor = (float)d_fft_size * (float)d_fft_size; - for (i = 0; i < d_fft_size; i++) + + if (is_unaligned()) { - tmp_magt = std::norm(d_ifft->get_outbuf()[i]); - if (tmp_magt > magt) + volk_32fc_magnitude_squared_32f_u(d_magnitude, d_ifft->get_outbuf(), d_fft_size); + for (i = 0; i < d_fft_size; i++) { - magt = tmp_magt; - indext = i; + if(d_magnitude[i] > magt) + { + magt = d_magnitude[i]; + indext = i; + } } } + else + { + volk_32fc_magnitude_squared_32f_a(d_magnitude, d_ifft->get_outbuf(), d_fft_size); + volk_32f_index_max_16u_a(&indext, d_magnitude, d_fft_size); + } + // Normalize the maximum value to correct the scale factor introduced by FFTW - magt = magt / (fft_normalization_factor * fft_normalization_factor); + magt = d_magnitude[indext] / (fft_normalization_factor * fft_normalization_factor); // 4- record the maximum peak and the associated synchronization parameters if (d_mag < magt) { d_mag = magt; - d_gnss_synchro->Acq_delay_samples = (double)indext; + d_gnss_synchro->Acq_delay_samples = (double)(indext % d_samples_per_code); d_gnss_synchro->Acq_doppler_hz = (double)doppler; } @@ -298,6 +357,7 @@ int pcps_acquisition_cc::general_work(int noutput_items, { acquisition_message = 2; } + d_channel_internal_queue->push(acquisition_message); consume_each(1); } diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.h b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.h index 8a35dcf8f..0dc3aed09 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.h +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.h @@ -19,6 +19,7 @@ * \authors
    *
  • Javier Arribas, 2011. jarribas(at)cttc.es *
  • Luis Esteve, 2012. luis(at)epsilon-formacion.com + *
  • Marc Molina, 2013. marc.molina.pena@gmail.com *
* * ------------------------------------------------------------------------- @@ -65,8 +66,8 @@ class pcps_acquisition_cc; typedef boost::shared_ptr pcps_acquisition_cc_sptr; pcps_acquisition_cc_sptr -pcps_make_acquisition_cc(unsigned int sampled_ms, - unsigned int doppler_max, long freq, long fs_in, int samples_per_ms, +pcps_make_acquisition_cc(unsigned int sampled_ms, unsigned int doppler_max, + long freq, long fs_in, int samples_per_ms, int samples_per_code, gr::msg_queue::sptr queue, bool dump, std::string dump_filename); /*! @@ -79,47 +80,49 @@ class pcps_acquisition_cc: public gr::block { private: friend pcps_acquisition_cc_sptr - pcps_make_acquisition_cc(unsigned int sampled_ms, - unsigned int doppler_max, long freq, long fs_in, - int samples_per_ms, gr::msg_queue::sptr queue, bool dump, - std::string dump_filename); + pcps_make_acquisition_cc(unsigned int sampled_ms, unsigned int doppler_max, + long freq, long fs_in, int samples_per_ms, int samples_per_code, + gr::msg_queue::sptr queue, bool dump, std::string dump_filename); - pcps_acquisition_cc(unsigned int sampled_ms, - unsigned int doppler_max, long freq, long fs_in, - int samples_per_ms, gr::msg_queue::sptr d_queue, bool dump, - std::string dump_filename); + pcps_acquisition_cc(unsigned int sampled_ms, unsigned int doppler_max, + long freq, long fs_in, int samples_per_ms, int samples_per_code, + 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; - unsigned int d_doppler_resolution; - float d_threshold; - std::string d_satellite_str; - unsigned int d_doppler_max; - unsigned int d_doppler_step; - unsigned int d_sampled_ms; - unsigned int d_fft_size; - unsigned long int d_sample_counter; - gr_complex* d_carrier; - gr_complex* d_fft_codes; - gr::fft::fft_complex* d_fft_if; - gr::fft::fft_complex* d_ifft; - Gnss_Synchro *d_gnss_synchro; - unsigned int d_code_phase; - float d_doppler_freq; - float d_mag; - float d_input_power; - float d_test_statistics; + + long d_fs_in; + long d_freq; + int d_samples_per_ms; + int d_samples_per_code; + unsigned int d_doppler_resolution; + float d_threshold; + std::string d_satellite_str; + unsigned int d_doppler_max; + unsigned int d_doppler_step; + unsigned int d_sampled_ms; + unsigned int d_fft_size; + unsigned long int d_sample_counter; + gr_complex** d_grid_doppler_wipeoffs; + unsigned int d_num_doppler_bins; + gr_complex* d_fft_codes; + gr::fft::fft_complex* d_fft_if; + gr::fft::fft_complex* d_ifft; + Gnss_Synchro *d_gnss_synchro; + unsigned int d_code_phase; + float d_doppler_freq; + float d_mag; + float* d_magnitude; + float d_input_power; + float d_test_statistics; gr::msg_queue::sptr d_queue; - concurrent_queue *d_channel_internal_queue; - std::ofstream d_dump_file; - bool d_active; - bool d_dump; - unsigned int d_channel; - std::string d_dump_filename; + concurrent_queue *d_channel_internal_queue; + std::ofstream d_dump_file; + bool d_active; + bool d_dump; + unsigned int d_channel; + std::string d_dump_filename; public: /*! diff --git a/src/algorithms/channel/adapters/channel.cc b/src/algorithms/channel/adapters/channel.cc index e277f3b2f..5709fee50 100644 --- a/src/algorithms/channel/adapters/channel.cc +++ b/src/algorithms/channel/adapters/channel.cc @@ -76,7 +76,7 @@ Channel::Channel(ConfigurationInterface *configuration, unsigned int channel, unsigned int doppler_step = configuration->property("Acquisition" + boost::lexical_cast(channel_) + ".doppler_step",0); - if(doppler_step==0) doppler_step = configuration->property("Acquisition.doppler_step",0); + if(doppler_step==0) doppler_step = configuration->property("Acquisition.doppler_step",500); DLOG(INFO) << "Channel "<< channel_<<" Doppler_step = " << doppler_step << std::endl; @@ -88,6 +88,7 @@ Channel::Channel(ConfigurationInterface *configuration, unsigned int channel, acq_->set_threshold(threshold); + acq_->init(); repeat_ = configuration->property("Acquisition" + boost::lexical_cast< std::string>(channel_) + ".repeat_satellite", false); @@ -184,7 +185,7 @@ void Channel::set_signal(Gnss_Signal gnss_signal) gnss_synchro_.Signal[2] = 0; // make sure that string length is only two characters gnss_synchro_.PRN = gnss_signal_.get_satellite().get_PRN(); gnss_synchro_.System = gnss_signal_.get_satellite().get_system_short().c_str()[0]; - acq_->init(); + acq_->set_local_code(); nav_->set_satellite(gnss_signal_.get_satellite()); } diff --git a/src/algorithms/libs/galileo_e1_signal_processing.cc b/src/algorithms/libs/galileo_e1_signal_processing.cc index b8c94b526..9a0c2f895 100644 --- a/src/algorithms/libs/galileo_e1_signal_processing.cc +++ b/src/algorithms/libs/galileo_e1_signal_processing.cc @@ -53,7 +53,7 @@ galileo_e1_code_gen_int(int* _dest, char _Signal[3], signed int _prn, { hex_to_binary_converter(&_dest[index], Galileo_E1_B_PRIMARY_CODE[prn].at(i)); - index = index +4; + index = index + 4; } } @@ -122,8 +122,8 @@ galileo_e1_gen(std::complex* _dest, int* _prn, char _Signal[3]) const float alpha = sqrt(10.0 / 11.0); const float beta = sqrt(1.0 / 11.0); - std::complex sinboc_11[49152]; // 12*4096 (_codeLength not accepted by Clang ) - std::complex sinboc_61[49152]; + std::complex sinboc_11[_codeLength]; // 12*4092 (_codeLength not accepted by Clang ) + std::complex sinboc_61[_codeLength]; galileo_e1_sinboc_11_gen(sinboc_11, _prn, _codeLength); //generate sinboc(1,1) 12 samples per chip galileo_e1_sinboc_61_gen(sinboc_61, _prn, _codeLength); //generate sinboc(6,1) 12 samples per chip @@ -150,48 +150,88 @@ galileo_e1_gen(std::complex* _dest, int* _prn, char _Signal[3]) void galileo_e1_code_gen_complex_sampled(std::complex* _dest, char _Signal[3], - bool _cboc, unsigned int _prn, signed int _fs, unsigned int _chip_shift) + bool _cboc, unsigned int _prn, signed int _fs, unsigned int _chip_shift, + bool _secondary_flag) { - // This function is based on the GNU software GPS for MATLAB in the Kay Borre book + + // This function is based on the GNU software GPS for MATLAB in the Kay Borre bookç + + std::string _galileo_signal = _Signal; unsigned int _samplesPerCode; const unsigned int _codeFreqBasis = Galileo_E1_CODE_CHIP_RATE_HZ; //Hz unsigned int _codeLength = Galileo_E1_B_CODE_LENGTH_CHIPS; - int primary_code_E1_chips[4096]; + int primary_code_E1_chips[(int)Galileo_E1_B_CODE_LENGTH_CHIPS]; _samplesPerCode = round(_fs / (_codeFreqBasis / _codeLength)); + const int _samplesPerChip = (_cboc == true) ? 12 : 2; + + const unsigned int delay = (((int)Galileo_E1_B_CODE_LENGTH_CHIPS - _chip_shift) + % (int)Galileo_E1_B_CODE_LENGTH_CHIPS) + * _samplesPerCode / Galileo_E1_B_CODE_LENGTH_CHIPS; galileo_e1_code_gen_int(primary_code_E1_chips, _Signal, _prn, 0); //generate Galileo E1 code, 1 sample per chip + std::complex* _signal_E1; + + _codeLength = _samplesPerChip * Galileo_E1_B_CODE_LENGTH_CHIPS; + _signal_E1 = new std::complex[_codeLength]; + if (_cboc == true) { - _codeLength = 12 * Galileo_E1_B_CODE_LENGTH_CHIPS; - if (_fs != 12 * _codeFreqBasis) - { - std::complex _signal_E1[4096]; - galileo_e1_gen(_signal_E1, primary_code_E1_chips, _Signal); //generate cboc 12 samples per chip - resampler(_signal_E1, _dest, 12 * _codeFreqBasis, _fs, - _codeLength, _samplesPerCode); //resamples code to fs - } - else - { - galileo_e1_gen(_dest, primary_code_E1_chips, _Signal); //generate cboc 12 samples per chip - } + galileo_e1_gen(_signal_E1, primary_code_E1_chips, _Signal); //generate cboc 12 samples per chip } else { - //--- Find number of samples per spreading code ---------------------------- - _codeLength = 2 * Galileo_E1_B_CODE_LENGTH_CHIPS; - if (_fs != 2 * _codeFreqBasis) - { - std::complex _signal_E1[8192]; - galileo_e1_sinboc_11_gen(_signal_E1, primary_code_E1_chips, - _codeLength); //generate sinboc(1,1) 2 samples per chip - resampler(_signal_E1, _dest, 2 * _codeFreqBasis, _fs, - _codeLength, _samplesPerCode); //resamples code to fs - } - else - { - galileo_e1_sinboc_11_gen(_dest, primary_code_E1_chips, - _codeLength); //generate sinboc(1,1) 2 samples per chip } - } + galileo_e1_sinboc_11_gen(_signal_E1, primary_code_E1_chips, + _codeLength); //generate sinboc(1,1) 2 samples per chip } + + if (_fs != _samplesPerChip * _codeFreqBasis) + { + std::complex* _resampled_signal = new std::complex[_samplesPerCode]; + resampler(_signal_E1, _resampled_signal, _samplesPerChip * _codeFreqBasis, _fs, + _codeLength, _samplesPerCode); //resamples code to fs + + delete[] _signal_E1; + _signal_E1 = _resampled_signal; + } + + + if (_galileo_signal.rfind("1C") != std::string::npos && _galileo_signal.length() >= 2 && _secondary_flag) + { + + std::complex* _signal_E1C_secondary = new std::complex + [(int)Galileo_E1_C_SECONDARY_CODE_LENGTH + * _samplesPerCode]; + + for (unsigned int i = 0; i < (int)Galileo_E1_C_SECONDARY_CODE_LENGTH; i++) + { + for (unsigned k = 0; k < _samplesPerCode; k++) + { + _signal_E1C_secondary[i*_samplesPerCode + k] = _signal_E1[k] + * (Galileo_E1_C_SECONDARY_CODE.at(i) == '0' + ? std::complex(1,0) : std::complex(-1,0)); + } + } + + _samplesPerCode *= (int)Galileo_E1_C_SECONDARY_CODE_LENGTH; + + delete[] _signal_E1; + _signal_E1 = _signal_E1C_secondary; + } + + for (unsigned int i = 0; i < _samplesPerCode; i++) + { + _dest[(i+delay)%_samplesPerCode] = _signal_E1[i]; + } + + delete[] _signal_E1; +} + + +void +galileo_e1_code_gen_complex_sampled(std::complex* _dest, char _Signal[3], + bool _cboc, unsigned int _prn, signed int _fs, unsigned int _chip_shift) +{ + galileo_e1_code_gen_complex_sampled(_dest, _Signal, _cboc, _prn, + _fs, _chip_shift, false); } diff --git a/src/algorithms/libs/galileo_e1_signal_processing.h b/src/algorithms/libs/galileo_e1_signal_processing.h index fe6dd4f33..a06414a71 100644 --- a/src/algorithms/libs/galileo_e1_signal_processing.h +++ b/src/algorithms/libs/galileo_e1_signal_processing.h @@ -69,7 +69,13 @@ void galileo_e1_cboc_gen(std::complex* _dest, int* _prn, char _Signal[3]) * */ void galileo_e1_code_gen_complex_sampled(std::complex* _dest, char _Signal[3], - bool _cboc, unsigned int _prn, signed int _fs, - unsigned int _chip_shift); + bool _cboc, unsigned int _prn, signed int _fs, unsigned int _chip_shift, + bool _secondary_flag); + +/*! + * \brief galileo_e1_code_gen_complex_sampled without _secondary_flag for backward compatibility. + */ +void galileo_e1_code_gen_complex_sampled(std::complex* _dest, char _Signal[3], + bool _cboc, unsigned int _prn, signed int _fs, unsigned int _chip_shift); #endif /* GNSS_SDR_GALILEO_E1_SIGNAL_PROCESSING_H_ */ diff --git a/src/algorithms/signal_generator/CMakeLists.txt b/src/algorithms/signal_generator/CMakeLists.txt new file mode 100644 index 000000000..0796d6d4c --- /dev/null +++ b/src/algorithms/signal_generator/CMakeLists.txt @@ -0,0 +1,20 @@ +# Copyright (C) 2012-2013 (see AUTHORS file for a list of contributors) +# +# 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 . +# + +add_subdirectory(adapters) +add_subdirectory(gnuradio_blocks) diff --git a/src/algorithms/signal_generator/adapters/CMakeLists.txt b/src/algorithms/signal_generator/adapters/CMakeLists.txt new file mode 100644 index 000000000..e8f96f099 --- /dev/null +++ b/src/algorithms/signal_generator/adapters/CMakeLists.txt @@ -0,0 +1,34 @@ +# Copyright (C) 2012-2013 (see AUTHORS file for a list of contributors) +# +# 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 . +# + +set(SIGNAL_GENERATOR_ADAPTER_SOURCES signal_generator.cc) + +include_directories( + $(CMAKE_CURRENT_SOURCE_DIR) + ${CMAKE_SOURCE_DIR}/src/core/system_parameters + ${CMAKE_SOURCE_DIR}/src/core/interfaces + ${CMAKE_SOURCE_DIR}/src/core/receiver + ${CMAKE_SOURCE_DIR}/src/algorithms/signal_generator/gnuradio_blocks + ${CMAKE_SOURCE_DIR}/src/algorithms/libs + ${GLOG_INCLUDE_DIRS} + ${GFlags_INCLUDE_DIRS} + ${GNURADIO_RUNTIME_INCLUDE_DIRS} +) + +add_library(signal_generator_adapters ${SIGNAL_GENERATOR_ADAPTER_SOURCES}) +target_link_libraries(signal_generator_adapters gnss_sp_libs signal_generator_blocks ${GNURADIO_RUNTIME_LIBRARIES} ${GNURADIO_BLOCKS_LIBRARIES} ${GNURADIO_FILTER_LIBRARIES}) diff --git a/src/algorithms/signal_generator/adapters/signal_generator.cc b/src/algorithms/signal_generator/adapters/signal_generator.cc new file mode 100644 index 000000000..c2cb9c922 --- /dev/null +++ b/src/algorithms/signal_generator/adapters/signal_generator.cc @@ -0,0 +1,167 @@ +/*! + * \file signal_generator.cc + * \brief Signal generator. + * \author Marc Molina, 2013. marc.molina.pena@gmail.com + * + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2013 (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 "signal_generator.h" +#include "configuration_interface.h" +#include "Galileo_E1.h" +#include "GPS_L1_CA.h" +#include +#include + +using google::LogMessage; + +SignalGenerator::SignalGenerator(ConfigurationInterface* configuration, + std::string role, unsigned int in_stream, + unsigned int out_stream, boost::shared_ptr queue) : + role_(role), in_stream_(in_stream), out_stream_(out_stream), queue_(queue) +{ + std::string default_item_type = "gr_complex"; + std::string default_dump_file = "./data/gen_source.dat"; + std::string default_system = "G"; + + item_type_ = configuration->property(role + ".item_type", default_item_type); + dump_ = configuration->property(role + ".dump", false); + dump_filename_ = configuration->property(role + ".dump_filename", default_dump_file); + + unsigned int fs_in = configuration->property("SignalSource.fs_hz", 4e6); + bool data_flag = configuration->property("SignalSource.data_flag", false); + bool noise_flag = configuration->property("SignalSource.noise_flag", false); + float BW_BB = configuration->property("SignalSource.BW_BB", 1.0); + unsigned int num_satellites = configuration->property("SignalSource.num_satellites", 1); + + std::vector system; + std::vector PRN; + std::vector CN0_dB; + std::vector doppler_Hz; + std::vector delay_chips; + + for (unsigned int sat_idx = 0; sat_idx < num_satellites; sat_idx++) + { + std::string sat = std::to_string(sat_idx); + system.push_back(configuration->property("SignalSource.system_" + sat, default_system)); + PRN.push_back(configuration->property("SignalSource.PRN_" + sat, 1)); + CN0_dB.push_back(configuration->property("SignalSource.CN0_dB_" + sat, 10)); + doppler_Hz.push_back(configuration->property("SignalSource.doppler_Hz_" + sat, 0)); + delay_chips.push_back(configuration->property("SignalSource.delay_chips_" + sat, 0)); + } + + // If Gallileo signal is present -> vector duration = 100 ms (25 * 4 ms) + // If there is only GPS signal (Gallileo signal not present) -> vector duration = 1 ms + unsigned int vector_length = 0; + if (std::find(system.begin(), system.end(), "E") != system.end()) + { + vector_length = round((float)fs_in / (Galileo_E1_CODE_CHIP_RATE_HZ + / Galileo_E1_B_CODE_LENGTH_CHIPS)) + * Galileo_E1_C_SECONDARY_CODE_LENGTH; + } + else if (std::find(system.begin(), system.end(), "G") != system.end()) + { + vector_length = round((float)fs_in + / (GPS_L1_CA_CODE_RATE_HZ / GPS_L1_CA_CODE_LENGTH_CHIPS)); + } + + if (item_type_.compare("gr_complex") == 0) + { + item_size_ = sizeof(gr_complex); + DLOG(INFO) << "Item size " << item_size_; + gen_source_ = signal_make_generator_c(system, PRN, CN0_dB, doppler_Hz, delay_chips, + data_flag, noise_flag, fs_in, vector_length, BW_BB); + + vector_to_stream_ = gr::blocks::vector_to_stream::make(item_size_, vector_length); + + DLOG(INFO) << "vector_to_stream(" << vector_to_stream_->unique_id() << ")"; + DLOG(INFO) << "gen_source(" << gen_source_->unique_id() << ")"; + } + + else + { + LOG_AT_LEVEL(WARNING) << item_type_ + << " unrecognized item type for resampler"; + item_size_ = sizeof(short); + } + + if (dump_) + { + DLOG(INFO) << "Dumping output into file " << dump_filename_; + file_sink_ = gr::blocks::file_sink::make(item_size_, dump_filename_.c_str()); + } + if (dump_) + { + DLOG(INFO) << "file_sink(" << file_sink_->unique_id() << ")"; + } +} + + +SignalGenerator::~SignalGenerator() +{} + + +void SignalGenerator::connect(gr::top_block_sptr top_block) +{ + if (item_type_.compare("gr_complex") == 0) + { + top_block->connect(gen_source_, 0, vector_to_stream_, 0); + DLOG(INFO) << "connected gen_source to vector_to_stream"; + + if (dump_) + { + top_block->connect(vector_to_stream_, 0, file_sink_, 0); + DLOG(INFO) << "connected vector_to_stream_ to file sink"; + } + + } +} + + +void SignalGenerator::disconnect(gr::top_block_sptr top_block) +{ + if (item_type_.compare("gr_complex") == 0) + { + top_block->disconnect(gen_source_, 0, vector_to_stream_, 0); + if (dump_) + { + top_block->disconnect(vector_to_stream_, 0, file_sink_, 0); + } + } +} + + +gr::basic_block_sptr SignalGenerator::get_left_block() +{ + LOG_AT_LEVEL(WARNING) << "Left block of a signal source should not be retrieved"; + return gr::block_sptr(); +} + + +gr::basic_block_sptr SignalGenerator::get_right_block() +{ + return vector_to_stream_; +} diff --git a/src/algorithms/signal_generator/adapters/signal_generator.h b/src/algorithms/signal_generator/adapters/signal_generator.h new file mode 100644 index 000000000..7d610858e --- /dev/null +++ b/src/algorithms/signal_generator/adapters/signal_generator.h @@ -0,0 +1,96 @@ +/*! + * \file signal_generator.h + * \brief Adapter of a class that generates synthesized GNSS signal. + * \author Marc Molina, 2013. marc.molina.pena@gmail.com + * + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2013 (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_SIGNAL_GENERATOR_H_ +#define GNSS_SDR_SIGNAL_GENERATOR_H_ + +#include +#include +#include +#include + +#include "gnss_block_interface.h" +#include "signal_generator_c.h" + +class ConfigurationInterface; + +/*! + * \brief This class generates synthesized GNSS signal. + * + */ +class SignalGenerator: public GNSSBlockInterface +{ +public: + SignalGenerator(ConfigurationInterface* configuration, + std::string role, unsigned int in_stream, + unsigned int out_stream, boost::shared_ptr queue); + + virtual ~SignalGenerator(); + std::string role() + { + return role_; + } + + /*! + * \brief Returns "SignalGenerator". + */ + std::string implementation() + { + return "GNSSSignalGenerator"; + } + 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(); + + +private: + std::string role_; + unsigned int in_stream_; + unsigned int out_stream_; + std::string item_type_; + size_t item_size_; + bool dump_; + std::string dump_filename_; + boost::shared_ptr gen_source_; + gr::blocks::vector_to_stream::sptr vector_to_stream_; + gr::blocks::file_sink::sptr file_sink_; + boost::shared_ptr queue_; + +}; + +#endif /*GNSS_SDR_SIGNAL_GENERATOR_H_*/ diff --git a/src/algorithms/signal_generator/gnuradio_blocks/CMakeLists.txt b/src/algorithms/signal_generator/gnuradio_blocks/CMakeLists.txt new file mode 100644 index 000000000..71974bc39 --- /dev/null +++ b/src/algorithms/signal_generator/gnuradio_blocks/CMakeLists.txt @@ -0,0 +1,35 @@ +# Copyright (C) 2012-2013 (see AUTHORS file for a list of contributors) +# +# 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 . +# + +set(SIGNAL_GENERATOR_BLOCK_SOURCES signal_generator_c.cc) + +include_directories( + $(CMAKE_CURRENT_SOURCE_DIR) + ${CMAKE_SOURCE_DIR}/src/core/system_parameters + ${CMAKE_SOURCE_DIR}/src/core/interfaces + ${CMAKE_SOURCE_DIR}/src/core/receiver + ${CMAKE_SOURCE_DIR}/src/algorithms/libs + ${GLOG_INCLUDE_DIRS} + ${GFlags_INCLUDE_DIRS} + ${GNURADIO_RUNTIME_INCLUDE_DIRS} +) + +add_library(signal_generator_blocks ${SIGNAL_GENERATOR_BLOCK_SOURCES}) +target_link_libraries(signal_generator_blocks gnss_system_parameters ${GNURADIO_RUNTIME_LIBRARIES} ${GNURADIO_FFT_LIBRARIES} ${VOLK_LIBRARIES}) + + diff --git a/src/algorithms/signal_generator/gnuradio_blocks/signal_generator_c.cc b/src/algorithms/signal_generator/gnuradio_blocks/signal_generator_c.cc new file mode 100644 index 000000000..d31ce6b47 --- /dev/null +++ b/src/algorithms/signal_generator/gnuradio_blocks/signal_generator_c.cc @@ -0,0 +1,335 @@ +/*! + * \file signal_generator_c.h + * \brief GNU Radio source block that generates synthesized GNSS signal. + * \author Marc Molina, 2013. marc.molina.pena@gmail.com + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2012 (see AUTHORS file for a list of contributors) + * + * GNSS-SDR is a software defined Global Navigation + * Satellite Systems receiver + * + * This file is part of GNSS-SDR. + * + * GNSS-SDR is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * at your option) any later version. + * + * GNSS-SDR is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNSS-SDR. If not, see . + * + * ------------------------------------------------------------------------- + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "signal_generator_c.h" +#include +#include "gps_sdr_signal_processing.h" +#include "galileo_e1_signal_processing.h" +#include +#include "nco_lib.h" + + +/* + * Create a new instance of signal_generator_c and return + * a boost shared_ptr. This is effectively the public constructor. + */ +signal_generator_c_sptr +signal_make_generator_c (std::vector system, const std::vector &PRN, + const std::vector &CN0_dB, const std::vector &doppler_Hz, + const std::vector &delay_chips, bool data_flag, bool noise_flag, + unsigned int fs_in, unsigned int vector_length, float BW_BB) +{ + return gnuradio::get_initial_sptr(new signal_generator_c(system, PRN, CN0_dB, doppler_Hz, delay_chips, + data_flag, noise_flag, fs_in, vector_length, BW_BB)); +} + +/* + * The private constructor + */ +signal_generator_c::signal_generator_c (std::vector system, const std::vector &PRN, + const std::vector &CN0_dB, const std::vector &doppler_Hz, + const std::vector &delay_chips, bool data_flag, bool noise_flag, + unsigned int fs_in, unsigned int vector_length, float BW_BB) : + + gr::block ("signal_gen_cc", gr::io_signature::make(0, 0, sizeof(gr_complex)), + gr::io_signature::make(1, 1, sizeof(gr_complex)*vector_length)), + system_(system), + PRN_(PRN), + CN0_dB_(CN0_dB), + doppler_Hz_(doppler_Hz), + delay_chips_(delay_chips), + data_flag_(data_flag), + noise_flag_(noise_flag), + fs_in_(fs_in), + num_sats_(PRN.size()), + vector_length_(vector_length), + BW_BB_(BW_BB*(float)fs_in/2) +{ + init(); + generate_codes(); +} + +void signal_generator_c::init() +{ + if (posix_memalign((void**)&complex_phase_, 16, vector_length_ * sizeof(gr_complex)) == 0){}; + + // True if Gallileo satellites are present + bool gallileo_signal = std::find(system_.begin(), system_.end(), "E") != system_.end(); + + for (unsigned int sat = 0; sat < num_sats_; sat++) + { + start_phase_rad_.push_back(0); + current_data_bits_.push_back(gr_complex(1,0)); + ms_counter_.push_back(0); + + if (system_[sat] == "G") + { + samples_per_code_.push_back(round((float)fs_in_ + / (GPS_L1_CA_CODE_RATE_HZ / GPS_L1_CA_CODE_LENGTH_CHIPS))); + + num_of_codes_per_vector_.push_back(gallileo_signal ? 4*(int)Galileo_E1_C_SECONDARY_CODE_LENGTH : 1); + data_bit_duration_ms_.push_back(1e3/GPS_CA_TELEMETRY_RATE_BITS_SECOND); + } + else if (system_[sat] == "E") + { + samples_per_code_.push_back(round((float)fs_in_ / (Galileo_E1_CODE_CHIP_RATE_HZ + / Galileo_E1_B_CODE_LENGTH_CHIPS))); + + num_of_codes_per_vector_.push_back((int)Galileo_E1_C_SECONDARY_CODE_LENGTH); + data_bit_duration_ms_.push_back(1e3/Galileo_E1_B_SYMBOL_RATE_BPS); + } + } + + random_ = new gr::random(); + +// std::cout << "fs_in: " << fs_in_ << std::endl; +// std::cout << "data_flag: " << data_flag_ << std::endl; +// std::cout << "noise_flag_: " << noise_flag_ << std::endl; +// std::cout << "num_sats_: " << num_sats_ << std::endl; +// std::cout << "vector_length_: " << vector_length_ << std::endl; +// std::cout << "BW_BB_: " << BW_BB_ << std::endl; + +// for (unsigned int i = 0; i < num_sats_; i++) +// { +// std::cout << "Sat " << i << ": " << std::endl; +// std::cout << "System " << system_[i] << ": " << std::endl; +// std::cout << " PRN: " << PRN_[i] << std::endl; +// std::cout << " CN0: " << CN0_dB_[i] << std::endl; +// std::cout << " Doppler: " << doppler_Hz_[i] << std::endl; +// std::cout << " Delay: " << delay_chips_[i] << std::endl; +// std::cout << "Samples per code = " << samples_per_code_[i] << std::endl; +// std::cout << "codes per vector = " << num_of_codes_per_vector_[i] << std::endl; +// std::cout << "data_bit_duration = " << data_bit_duration_ms_[i] << std::endl; +// } +} + +void signal_generator_c::generate_codes() +{ + sampled_code_data_.reset(new gr_complex*[num_sats_]); + sampled_code_pilot_.reset(new gr_complex*[num_sats_]); + + for (unsigned int sat = 0; sat < num_sats_; sat++) + { + if (posix_memalign((void**)&(sampled_code_data_[sat]), 16, + vector_length_ * sizeof(gr_complex)) == 0){}; + + gr_complex code[samples_per_code_[sat]]; + + if (system_[sat] == "G") + { + // Generate one code-period of 1C signal + gps_l1_ca_code_gen_complex_sampled(code, PRN_[sat], fs_in_, + (int)GPS_L1_CA_CODE_LENGTH_CHIPS-delay_chips_[sat]); + + // Obtain the desired CN0 assuming that Pn = 1. + for (unsigned int i = 0; i < samples_per_code_[sat]; i++) + { + code[i] *= sqrt(pow(10,CN0_dB_[sat]/10)/BW_BB_); + } + + // Concatenate "num_of_codes_per_vector_" codes + for (unsigned int i = 0; i < num_of_codes_per_vector_[sat]; i++) + { + memcpy(&(sampled_code_data_[sat][i*samples_per_code_[sat]]), + code, sizeof(gr_complex)*samples_per_code_[sat]); + } + } + else if (system_[sat] == "E") + { + // Generate one code-period of E1B signal + bool cboc = true; + char signal[3]; + strcpy(signal, "1B"); + + galileo_e1_code_gen_complex_sampled(code, signal, cboc, PRN_[sat], fs_in_, + (int)Galileo_E1_B_CODE_LENGTH_CHIPS-delay_chips_[sat]); + + // Obtain the desired CN0 assuming that Pn = 1. + for (unsigned int i = 0; i < samples_per_code_[sat]; i++) + { + code[i] *= sqrt(pow(10,CN0_dB_[sat]/10)/BW_BB_/2); + } + + // Concatenate "num_of_codes_per_vector_" codes + for (unsigned int i = 0; i < num_of_codes_per_vector_[sat]; i++) + { + memcpy(&(sampled_code_data_[sat][i*samples_per_code_[sat]]), + code, sizeof(gr_complex)*samples_per_code_[sat]); + } + + // Generate E1C signal (25 code-periods, with secondary code) + if (posix_memalign((void**)&(sampled_code_pilot_[sat]), 16, + vector_length_ * sizeof(gr_complex)) == 0){}; + + strcpy(signal, "1C"); + + galileo_e1_code_gen_complex_sampled(sampled_code_pilot_[sat], signal, cboc, PRN_[sat], fs_in_, + (int)Galileo_E1_B_CODE_LENGTH_CHIPS-delay_chips_[sat], true); + + // Obtain the desired CN0 assuming that Pn = 1. + for (unsigned int i = 0; i < vector_length_; i++) + { + sampled_code_pilot_[sat][i] *= sqrt(pow(10,CN0_dB_[sat]/10)/BW_BB_/2); + } + } + } +} + + +/* + * Our virtual destructor. + */ +signal_generator_c::~signal_generator_c() +{ + for (unsigned int sat = 0; sat < num_sats_; sat++) + { + free(sampled_code_data_[sat]); + if (system_[sat] == "E") + { + free(sampled_code_pilot_[sat]); + } + } + + delete random_; +} + + +int +signal_generator_c::general_work (int noutput_items, + gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items) +{ + gr_complex *out = (gr_complex *) output_items[0]; + + unsigned int out_idx = 0; + unsigned int i = 0; + unsigned int k = 0; + + for (out_idx = 0; out_idx < vector_length_; out_idx++) + { + out[out_idx] = gr_complex(0.0,0.0); + } + + for (unsigned int sat = 0; sat < num_sats_; sat++) + { + + float phase_step_rad = -(float)GPS_TWO_PI*doppler_Hz_[sat] / (float)fs_in_; + fxp_nco(complex_phase_, vector_length_, start_phase_rad_[sat], phase_step_rad); + start_phase_rad_[sat] += vector_length_ * phase_step_rad; + + out_idx = 0; + + if (system_[sat] == "G") + { + unsigned int delay_samples = (delay_chips_[sat] % (int)GPS_L1_CA_CODE_LENGTH_CHIPS) + * samples_per_code_[sat] / GPS_L1_CA_CODE_LENGTH_CHIPS; + + for (i = 0; i < num_of_codes_per_vector_[sat]; i++) + { + gr_complex prev_data_bit = current_data_bits_[sat]; + if (ms_counter_[sat] == 0 && data_flag_) + { + // New random data bit + current_data_bits_[sat] = gr_complex((rand()%2) == 0 ? 1 : -1, 0); + } + + for (k = 0; k < delay_samples; k++) + { + out[out_idx] += sampled_code_data_[sat][out_idx] + * prev_data_bit + * complex_phase_[out_idx]; + out_idx++; + } + + for (k = delay_samples; k < samples_per_code_[sat]; k++) + { + out[out_idx] += sampled_code_data_[sat][out_idx] + * current_data_bits_[sat] + * complex_phase_[out_idx]; + out_idx++; + } + + ms_counter_[sat] = (ms_counter_[sat] + (int)round(1e3*GPS_L1_CA_CODE_PERIOD)) + % data_bit_duration_ms_[sat]; + } + } + + else if (system_[sat] == "E") + { + unsigned int delay_samples = (delay_chips_[sat] % (int)Galileo_E1_B_CODE_LENGTH_CHIPS) + * samples_per_code_[sat] / Galileo_E1_B_CODE_LENGTH_CHIPS; + + for (i = 0; i < num_of_codes_per_vector_[sat]; i++) + { + gr_complex prev_data_bit = current_data_bits_[sat]; + if (ms_counter_[sat] == 0 && data_flag_) + { + // New random data bit + current_data_bits_[sat] = gr_complex((rand()%2) == 0 ? -1 : 1, 0); + } + + for (k = 0; k < delay_samples; k++) + { + out[out_idx] += (sampled_code_data_[sat][out_idx] * prev_data_bit + - sampled_code_pilot_[sat][out_idx]) + * complex_phase_[out_idx]; + out_idx++; + } + + for (k = delay_samples; k < samples_per_code_[sat]; k++) + { + out[out_idx] += (sampled_code_data_[sat][out_idx] * current_data_bits_[sat] + - sampled_code_pilot_[sat][out_idx]) + * complex_phase_[out_idx]; + out_idx++; + } + + ms_counter_[sat] = (ms_counter_[sat] + (int)round(1e3*Galileo_E1_CODE_PERIOD)) + % data_bit_duration_ms_[sat]; + } + } + } + + if (noise_flag_) + { + for (out_idx = 0; out_idx < vector_length_; out_idx++) + { + out[out_idx] += gr_complex(random_->gasdev(),random_->gasdev()); + } + } + + // Tell runtime system how many output items we produced. + return 1; +} + diff --git a/src/algorithms/signal_generator/gnuradio_blocks/signal_generator_c.h b/src/algorithms/signal_generator/gnuradio_blocks/signal_generator_c.h new file mode 100644 index 000000000..1b8a3174f --- /dev/null +++ b/src/algorithms/signal_generator/gnuradio_blocks/signal_generator_c.h @@ -0,0 +1,129 @@ +/*! + * \file signal_generator_c.h + * \brief GNU Radio source block that generates synthesized GNSS signal. + * \author Marc Molina, 2013. marc.molina.pena@gmail.com + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2013 (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_SIGNAL_GENERATOR_C_H +#define GNSS_SDR_SIGNAL_GENERATOR_C_H + +#include "gnss_signal.h" +#include +#include +#include + + +class signal_generator_c; + +/* + * We use boost::shared_ptr's instead of raw pointers for all access + * to gr_blocks (and many other data structures). The shared_ptr gets + * us transparent reference counting, which greatly simplifies storage + * management issues. This is especially helpful in our hybrid + * C++ / Python system. + * + * See http://www.boost.org/libs/smart_ptr/smart_ptr.htm + * + * As a convention, the _sptr suffix indicates a boost::shared_ptr + */ +typedef boost::shared_ptr signal_generator_c_sptr; + +/*! + * \brief Return a shared_ptr to a new instance of gen_source. + * + * To avoid accidental use of raw pointers, gen_source's + * constructor is private. signal_make_generator_c is the public + * interface for creating new instances. + */ +signal_generator_c_sptr +signal_make_generator_c (std::vector system, const std::vector &PRN, + const std::vector &CN0_dB, const std::vector &doppler_Hz, + const std::vector &delay_chips, bool data_flag, bool noise_flag, + unsigned int fs_in, unsigned int vector_length, float BW_BB); + +/*! + * \brief This class generates synthesized GNSS signal. + * \ingroup block + * + * \sa gen_source for a version that subclasses gr_block. + */ +class signal_generator_c : public gr::block +{ +private: + // The friend declaration allows gen_source to + // access the private constructor. + + /* Create the signal_generator_c object*/ + friend signal_generator_c_sptr + signal_make_generator_c (std::vector system, const std::vector &PRN, + const std::vector &CN0_dB, const std::vector &doppler_Hz, + const std::vector &delay_chips, bool data_flag, bool noise_flag, + unsigned int fs_in, unsigned int vector_length, float BW_BB); + + signal_generator_c (std::vector system, const std::vector &PRN, + const std::vector &CN0_dB, const std::vector &doppler_Hz, + const std::vector &delay_chips, bool data_flag, bool noise_flag, + unsigned int fs_in, unsigned int vector_length, float BW_BB); + + void init(); + void generate_codes(); + + std::vector system_; + std::vector PRN_; + std::vector CN0_dB_; + std::vector doppler_Hz_; + std::vector delay_chips_; + bool data_flag_; + bool noise_flag_; + unsigned int fs_in_; + unsigned int num_sats_; + unsigned int vector_length_; + float BW_BB_; + + std::vector samples_per_code_; + std::vector num_of_codes_per_vector_; + std::vector data_bit_duration_ms_; + std::vector ms_counter_; + std::vector start_phase_rad_; + std::vector current_data_bits_; + + boost::scoped_array sampled_code_data_; + boost::scoped_array sampled_code_pilot_; + gr::random* random_; + gr_complex* complex_phase_; + + public: + ~signal_generator_c (); // public destructor + + // Where all the action really happens + + 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 /* GNSS_SDR_SIGNAL_GENERATOR_C_H */ diff --git a/src/algorithms/signal_source/adapters/CMakeLists.txt b/src/algorithms/signal_source/adapters/CMakeLists.txt index 23e328016..d6e9aa5d9 100644 --- a/src/algorithms/signal_source/adapters/CMakeLists.txt +++ b/src/algorithms/signal_source/adapters/CMakeLists.txt @@ -74,7 +74,7 @@ if(RTLSDR_DRIVER) set(OPT_DRIVER_INCLUDE_DIRS ${OPT_DRIVER_INCLUDE_DIRS} ${RTL_DRIVER_INCLUDE_DIRS}) endif(RTLSDR_DRIVER) -set(SIGNAL_SOURCE_ADAPTER_SOURCES file_signal_source.cc uhd_signal_source.cc ${OPT_DRIVER_SOURCES}) +set(SIGNAL_SOURCE_ADAPTER_SOURCES file_signal_source.cc gen_signal_source.cc uhd_signal_source.cc ${OPT_DRIVER_SOURCES}) include_directories( diff --git a/src/algorithms/signal_source/adapters/gen_signal_source.cc b/src/algorithms/signal_source/adapters/gen_signal_source.cc new file mode 100644 index 000000000..452937031 --- /dev/null +++ b/src/algorithms/signal_source/adapters/gen_signal_source.cc @@ -0,0 +1,115 @@ +/*! + * \file gen_signal_source.cc + * \brief It wraps blocks that generates synthesized GNSS signal and filters + * it. + * \author Marc Molina, 2013. marc.molina.pena@gmail.com + * + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2013 (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 "gen_signal_source.h" +//#include "gnss_flowgraph.h" +#include +#include +#include +#include +#include +#include +#include +#include + +using google::LogMessage; + +// Constructor +GenSignalSource::GenSignalSource(ConfigurationInterface *configuration, + GNSSBlockInterface *signal_generator, GNSSBlockInterface *filter, + std::string role, boost::shared_ptr queue) : + signal_generator_(signal_generator), + filter_(filter), + role_(role), + queue_(queue) +{ + connected_ = false; +} + + +// Destructor +GenSignalSource::~GenSignalSource() +{ + delete signal_generator_; + delete filter_; +} + + +void GenSignalSource::connect(gr::top_block_sptr top_block) +{ + if (connected_) + { + LOG_AT_LEVEL(WARNING) << "Signal conditioner already connected internally"; + return; + } + + signal_generator_->connect(top_block); + filter_->connect(top_block); + + top_block->connect(signal_generator_->get_right_block(), 0, + filter_->get_left_block(), 0); + + DLOG(INFO) << "signal_generator -> filter"; + + connected_ = true; +} + + +void GenSignalSource::disconnect(gr::top_block_sptr top_block) +{ + if (!connected_) + { + LOG_AT_LEVEL(WARNING) << "Signal conditioner already disconnected internally"; + return; + } + + top_block->disconnect(signal_generator_->get_right_block(), 0, + filter_->get_left_block(), 0); + + signal_generator_->disconnect(top_block); + filter_->disconnect(top_block); + + connected_ = false; +} + + +gr::basic_block_sptr GenSignalSource::get_left_block() +{ + return signal_generator_->get_left_block(); +} + + +gr::basic_block_sptr GenSignalSource::get_right_block() +{ + return filter_->get_right_block(); +} + diff --git a/src/algorithms/signal_source/adapters/gen_signal_source.h b/src/algorithms/signal_source/adapters/gen_signal_source.h new file mode 100644 index 000000000..f313ef509 --- /dev/null +++ b/src/algorithms/signal_source/adapters/gen_signal_source.h @@ -0,0 +1,80 @@ +/*! + * \file gen_signal_source.h + * \brief It wraps blocks that generates synthesized GNSS signal and filters + * it. + * \author Marc Molina, 2013. marc.molina.pena@gmail.com + * + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2013 (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_GEN_SIGNAL_SOURCE_H_ +#define GNSS_SDR_GEN_SIGNAL_SOURCE_H_ + +#include +#include "gnss_block_interface.h" + + +class ConfigurationInterface; + +/*! + * \brief This class wraps blocks that generates synthesized GNSS signal and + * filters the signal. + */ +class GenSignalSource: public GNSSBlockInterface +{ +public: + //! Constructor + GenSignalSource(ConfigurationInterface *configuration, + GNSSBlockInterface *signal_generator, GNSSBlockInterface *filter, + std::string role, boost::shared_ptr queue); + + //! Virtual destructor + virtual ~GenSignalSource(); + + 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(); + + std::string role(){ return role_; } + + //! Returns "Signal Source" + std::string implementation(){ return "Signal Source"; } + size_t item_size(){ return 0; } + + GNSSBlockInterface *signal_generator(){ return signal_generator_; } + GNSSBlockInterface *output_filter(){ return filter_; } + +private: + GNSSBlockInterface *signal_generator_; + GNSSBlockInterface *filter_; + std::string role_; + std::string implementation_; + bool connected_; + boost::shared_ptr queue_; +}; + +#endif /*GNSS_SDR_GEN_SIGNAL_SOURCE_H*/ diff --git a/src/core/interfaces/acquisition_interface.h b/src/core/interfaces/acquisition_interface.h index 965d26887..bfb44ff64 100644 --- a/src/core/interfaces/acquisition_interface.h +++ b/src/core/interfaces/acquisition_interface.h @@ -61,6 +61,7 @@ public: virtual void set_doppler_step(unsigned int doppler_step) = 0; virtual void set_channel_queue(concurrent_queue *channel_internal_queue) = 0; virtual void init() = 0; + virtual void set_local_code() = 0; virtual signed int mag() = 0; virtual void reset() = 0; }; diff --git a/src/core/system_parameters/Galileo_E1.h b/src/core/system_parameters/Galileo_E1.h index 8051684b1..0ec661147 100644 --- a/src/core/system_parameters/Galileo_E1.h +++ b/src/core/system_parameters/Galileo_E1.h @@ -48,7 +48,7 @@ const double Galileo_E1_SUB_CARRIER_A_RATE_HZ = 1.023e6; //!< Galileo E1 sub-car const double Galileo_E1_SUB_CARRIER_B_RATE_HZ = 6.138e6; //!< Galileo E1 sub-carrier 'b' rate [Hz] const double Galileo_E1_B_CODE_LENGTH_CHIPS = 4092.0; //!< Galileo E1-B code length [chips] const double Galileo_E1_B_SYMBOL_RATE_BPS = 250.0; //!< Galileo E1-B symbol rate [bits/second] - +const double Galileo_E1_C_SECONDARY_CODE_LENGTH = 25.0; //!< Galileo E1-C secondary code length [chips] const int Galileo_E1_NUMBER_OF_CODES = 50; // Galileo INAV Telemetry structure @@ -188,4 +188,8 @@ const std::string Galileo_E1_C_PRIMARY_CODE[Galileo_E1_NUMBER_OF_CODES] = { "CD7AAC98501F29507EA4E0183E8A40D2E5117E47BB5D18D01A3732DE4C821DFE86521CBEA7DB29BE1148BD544ECC681689BCD1B41EAF755310B7659342F8EE11CB41550CC30E566E192796B66C1A83C0B28BACCFA6C393043A0A2CB89712BC1CCB174DE58E66896AF39C1CEED1E05B0435F8CF6FD920D100F51584FE24879987399481DBF27DDB6286B6353919E552E669290CE02AB4CD5113D7F484229F379C7332767EC69E4336439B05DE1C1E3563DD303A4F580BFF20A40E49CB0822F715ED0221EBCDB5DBAD751124B1715E82F37488265135B6C8BBCF4F801ECC4D3525FF189493AD4EFF0C042B070C4CA8FB1FDF43D79F06A6E4E3D35D7B07D4B728D5DC54EEDACBBBA1EDDCDC07ADF7DFCFEF835E44DF1FF66DAF2A7BAEBE218AC3B15E183044D6A8A89B3C101B40BED97ED5DF93BBC1B84931D56B8C822A6D058AC74CFA4C85D8B456698E82D5B7574C17B041E5F4BEED09F75012355CBC322B822C63F10C18A8F279E9A0E18E1FEF183D23E13894E31F6D046956FE8A647558228F6D4D6910151EC03937876B6ED7A078D33DAEB3F2239353BB8181E62B286BBC41588DE10F478A5CE5B508F205A41820356767B0A0ED4B8DB9EFE348362E9A90D6C30218B295B338B51C09239D02FC8A1E7DAAAB60AC37F5E67CFC88EEF69567B5C81A03B449F4ED38B9D295A36AA3503173F6F6F66D93CE72D753076040FACDE", "ADDCEDB50E907D20E826E6E8A0D30C20C74B2DF204EA784BAE9F618CAE33A3C937729DF9CB10BA2A4C33E0182A37200C0CC509729D828B8A2A20F283AC4F9306596684EA3FB5492A4C9F2DB459E7531C9F9C0950E7D9E93B3EE5912AE7E39AC8F4EC14B18F24E325003F477E347C5AC1B67CDB11AF3BBBBCD0AC3703024B5767AA67A208254F798684BFD1D3EACD757EEC77254950A146620400DB95E694574F739A991EBA771EBBDFF1056BB39A77DBE0636A032E17141332F951C57C6C90F348F165E3ABDD60D429D5D6BEC7E3E3463806F819EB2D212B3528A5EDE51F235AD100A35E890955F8A1DC51FDCB53EABCA2540997DD054C1F5B29462995B876B44D085904E55E1B838BEF600A992EB49CE078DF75AF3D0F137685AC0D07F0BE1EB87B63A41E74DDE869C8A683BDE60AF5D77FF18F7137495BCEFD0ED28F62F9C3E25D332B5F861D999FCDC0B4851A984A4DBB53401FD40351ADA4335C702BCC8D900C737507B990BDDBE91D201E3A0946DC968D43FD10D04B0B76667FF5B4291C2124B0124C6B710A6D1BCFAEB016B9DEEB0F7A4FE044CA4EA0CCD84B7682617C3A545071EC295B0663B3F577D562DE1D9DD80DE6A1EFD6D5991EB5246F1597B86D0E9A90CF6DB0EB2B8E7BAE9431E567F01AA98502C773742246467ABF911A91A51F6C1B9E0C3233DC1A37D17DB91A5F0F661B0EB5886964456C7818601BD0C" }; + +const std::string Galileo_E1_C_SECONDARY_CODE = + "0011100000001010110110010"; + #endif /* GNSS_SDR_GALILEO_E1_H_ */