From ba3d7bfcd8f44b186ebbbceff7693d9c73cb359c Mon Sep 17 00:00:00 2001 From: Cillian O'Driscoll Date: Thu, 24 Aug 2017 12:32:37 +0100 Subject: [PATCH 1/7] Added 'blocking' option to pcps_acquisition_cc Using C++ 11 threading routines to create a worker thread that can perform the FFT for acquisition in a non-blocking manner. By default 'blocking' is set to true, which is identical to the previous behaviour (with the added overhead of an extra thread). When 'blocking' is set to false, then the main thread does not wait for the worker, thereby letting the receiver continue even when the FFT thread is working. This is very useful for using FFT acquisition at higher sampling rates, where the FFT cannot be performed in real-time. The aim is to replace the separate pcps_multithread_acquisition_cc. TODO: implement the same thing for the pcps_acquisition_sc --- .../galileo_e1_pcps_ambiguous_acquisition.cc | 7 +- .../galileo_e1_pcps_ambiguous_acquisition.h | 1 + .../adapters/gps_l1_ca_pcps_acquisition.cc | 3 +- .../adapters/gps_l1_ca_pcps_acquisition.h | 1 + .../adapters/gps_l2_m_pcps_acquisition.cc | 4 +- .../adapters/gps_l2_m_pcps_acquisition.h | 1 + .../gnuradio_blocks/pcps_acquisition_cc.cc | 365 +++++++++++------- .../gnuradio_blocks/pcps_acquisition_cc.h | 22 +- 8 files changed, 247 insertions(+), 157 deletions(-) diff --git a/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.cc b/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.cc index a322def0e..44b8ef444 100644 --- a/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.cc +++ b/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.cc @@ -56,6 +56,7 @@ GalileoE1PcpsAmbiguousAcquisition::GalileoE1PcpsAmbiguousAcquisition( fs_in_ = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated); if_ = configuration_->property(role + ".if", 0); dump_ = configuration_->property(role + ".dump", false); + blocking_ = configuration_->property(role + ".blocking", true); doppler_max_ = configuration_->property(role + ".doppler_max", 5000); sampled_ms_ = configuration_->property(role + ".coherent_integration_time_ms", 4); @@ -91,7 +92,8 @@ GalileoE1PcpsAmbiguousAcquisition::GalileoE1PcpsAmbiguousAcquisition( item_size_ = sizeof(lv_16sc_t); acquisition_sc_ = pcps_make_acquisition_sc(sampled_ms_, max_dwells_, doppler_max_, if_, fs_in_, samples_per_ms, code_length_, - bit_transition_flag_, use_CFAR_algorithm_flag_, dump_, dump_filename_); + bit_transition_flag_, use_CFAR_algorithm_flag_, dump_, + dump_filename_); DLOG(INFO) << "acquisition(" << acquisition_sc_->unique_id() << ")"; } @@ -100,7 +102,8 @@ GalileoE1PcpsAmbiguousAcquisition::GalileoE1PcpsAmbiguousAcquisition( item_size_ = sizeof(gr_complex); acquisition_cc_ = pcps_make_acquisition_cc(sampled_ms_, max_dwells_, doppler_max_, if_, fs_in_, samples_per_ms, code_length_, - bit_transition_flag_, use_CFAR_algorithm_flag_, dump_, dump_filename_); + bit_transition_flag_, use_CFAR_algorithm_flag_, dump_, blocking_, + dump_filename_); DLOG(INFO) << "acquisition(" << acquisition_cc_->unique_id() << ")"; } diff --git a/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.h b/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.h index 3874e4df9..da8d2e742 100644 --- a/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.h +++ b/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.h @@ -155,6 +155,7 @@ private: long fs_in_; long if_; bool dump_; + bool blocking_; std::string dump_filename_; std::complex * code_; Gnss_Synchro * gnss_synchro_; diff --git a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition.cc b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition.cc index f0cded2ba..97ee64c50 100644 --- a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition.cc +++ b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition.cc @@ -59,6 +59,7 @@ GpsL1CaPcpsAcquisition::GpsL1CaPcpsAcquisition( fs_in_ = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated); if_ = configuration_->property(role + ".if", 0); dump_ = configuration_->property(role + ".dump", false); + blocking_ = configuration_->property(role + ".blocking", true); doppler_max_ = configuration_->property(role + ".doppler_max", 5000); sampled_ms_ = configuration_->property(role + ".coherent_integration_time_ms", 1); @@ -94,7 +95,7 @@ GpsL1CaPcpsAcquisition::GpsL1CaPcpsAcquisition( item_size_ = sizeof(gr_complex); acquisition_cc_ = pcps_make_acquisition_cc(sampled_ms_, max_dwells_, doppler_max_, if_, fs_in_, code_length_, code_length_, - bit_transition_flag_, use_CFAR_algorithm_flag_, dump_, dump_filename_); + bit_transition_flag_, use_CFAR_algorithm_flag_, dump_, blocking_, dump_filename_); DLOG(INFO) << "acquisition(" << acquisition_cc_->unique_id() << ")"; } diff --git a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition.h b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition.h index 0ff27c87f..183a9212c 100644 --- a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition.h +++ b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition.h @@ -160,6 +160,7 @@ private: long fs_in_; long if_; bool dump_; + bool blocking_; std::string dump_filename_; std::complex * code_; Gnss_Synchro * gnss_synchro_; diff --git a/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition.cc b/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition.cc index e0ff10757..4ab6d2b01 100644 --- a/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition.cc +++ b/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition.cc @@ -59,6 +59,7 @@ GpsL2MPcpsAcquisition::GpsL2MPcpsAcquisition( fs_in_ = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated); if_ = configuration_->property(role + ".if", 0); dump_ = configuration_->property(role + ".dump", false); + blocking_ = configuration_->property(role + ".blocking", true); doppler_max_ = configuration->property(role + ".doppler_max", 5000); bit_transition_flag_ = configuration_->property(role + ".bit_transition_flag", false); @@ -95,7 +96,8 @@ GpsL2MPcpsAcquisition::GpsL2MPcpsAcquisition( item_size_ = sizeof(gr_complex); acquisition_cc_ = pcps_make_acquisition_cc(1, max_dwells_, doppler_max_, if_, fs_in_, code_length_, code_length_, - bit_transition_flag_, use_CFAR_algorithm_flag_, dump_, dump_filename_); + bit_transition_flag_, use_CFAR_algorithm_flag_, dump_, blocking_, + dump_filename_); DLOG(INFO) << "acquisition(" << acquisition_cc_->unique_id() << ")"; } diff --git a/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition.h b/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition.h index cbe2a09a1..544737e79 100644 --- a/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition.h +++ b/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition.h @@ -157,6 +157,7 @@ private: long fs_in_; long if_; bool dump_; + bool blocking_; std::string dump_filename_; std::complex * code_; Gnss_Synchro * gnss_synchro_; diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.cc b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.cc index 399f443b6..b1dda44e0 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.cc +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.cc @@ -50,12 +50,12 @@ pcps_acquisition_cc_sptr pcps_make_acquisition_cc( unsigned int doppler_max, long freq, long fs_in, int samples_per_ms, int samples_per_code, bool bit_transition_flag, bool use_CFAR_algorithm_flag, - bool dump, + bool dump, bool blocking, std::string dump_filename) { return pcps_acquisition_cc_sptr( new pcps_acquisition_cc(sampled_ms, max_dwells, doppler_max, freq, fs_in, samples_per_ms, - samples_per_code, bit_transition_flag, use_CFAR_algorithm_flag, dump, dump_filename)); + samples_per_code, bit_transition_flag, use_CFAR_algorithm_flag, dump, blocking, dump_filename)); } @@ -64,7 +64,7 @@ pcps_acquisition_cc::pcps_acquisition_cc( unsigned int doppler_max, long freq, long fs_in, int samples_per_ms, int samples_per_code, bool bit_transition_flag, bool use_CFAR_algorithm_flag, - bool dump, + bool dump, bool blocking, std::string dump_filename) : gr::block("pcps_acquisition_cc", gr::io_signature::make(1, 1, sizeof(gr_complex) * sampled_ms * samples_per_ms * ( bit_transition_flag ? 2 : 1 )), @@ -129,6 +129,16 @@ pcps_acquisition_cc::pcps_acquisition_cc( d_gnss_synchro = 0; d_grid_doppler_wipeoffs = 0; + + d_done = false; + d_blocking = blocking; + d_new_data_available = false; + d_worker_active = false; + d_data_buffer = static_cast(volk_gnsssdr_malloc(d_fft_size * sizeof(gr_complex), volk_gnsssdr_get_alignment())); + + // Start the worker thread and wait for it to acknowledge: + std::thread t1( &pcps_acquisition_cc::acquisition_core, this ); + std::swap( d_worker_thread, t1 ); } @@ -153,6 +163,16 @@ pcps_acquisition_cc::~pcps_acquisition_cc() { d_dump_file.close(); } + + // Let the worker thread know that we are done and then wait to join + { + std::lock_guard lk( d_mutex ); + d_done = true; + d_cond.notify_one(); + } + + d_worker_thread.join(); + volk_gnsssdr_free( d_data_buffer ); } @@ -212,6 +232,10 @@ void pcps_acquisition_cc::init() int doppler = -static_cast(d_doppler_max) + d_doppler_step * doppler_index; update_local_carrier(d_grid_doppler_wipeoffs[doppler_index], d_fft_size, d_freq + doppler); } + + d_new_data_available = false; + d_done = false; + d_worker_active = false; } @@ -316,176 +340,217 @@ int pcps_acquisition_cc::general_work(int noutput_items, case 1: { - // initialize acquisition algorithm - int doppler; - uint32_t indext = 0; - float magt = 0.0; - const gr_complex *in = reinterpret_cast(input_items[0]); + std::unique_lock lk( d_mutex ); - int effective_fft_size = ( d_bit_transition_flag ? d_fft_size/2 : d_fft_size ); - - float fft_normalization_factor = static_cast(d_fft_size) * static_cast(d_fft_size); - - d_input_power = 0.0; - d_mag = 0.0; - d_sample_counter += d_fft_size; // sample counter - d_well_count++; - - DLOG(INFO)<< "Channel: " << d_channel - << " , doing acquisition of satellite: " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN - << " ,sample stamp: " << d_sample_counter << ", threshold: " - << d_threshold << ", doppler_max: " << d_doppler_max - << ", doppler_step: " << d_doppler_step<(d_fft_size); - } - // 2- Doppler frequency search loop - for (unsigned int doppler_index = 0; doppler_index < d_num_doppler_bins; doppler_index++) - { - // doppler search steps - doppler = -static_cast(d_doppler_max) + d_doppler_step * doppler_index; - - volk_32fc_x2_multiply_32fc(d_fft_if->get_inbuf(), in, - d_grid_doppler_wipeoffs[doppler_index], d_fft_size); - - // 3- Perform the FFT-based convolution (parallel time search) - // Compute the FFT of the carrier wiped--off incoming signal - d_fft_if->execute(); - - // Multiply carrier wiped--off, Fourier transformed incoming signal - // with the local FFT'd code reference using SIMD operations with VOLK library - volk_32fc_x2_multiply_32fc(d_ifft->get_inbuf(), - d_fft_if->get_outbuf(), d_fft_codes, d_fft_size); - - // compute the inverse FFT - d_ifft->execute(); - - // Search maximum - size_t offset = ( d_bit_transition_flag ? effective_fft_size : 0 ); - volk_32fc_magnitude_squared_32f(d_magnitude, d_ifft->get_outbuf() + offset, effective_fft_size); - volk_gnsssdr_32f_index_max_32u(&indext, d_magnitude, effective_fft_size); - magt = d_magnitude[indext]; - - if (d_use_CFAR_algorithm_flag == true) - { - // Normalize the maximum value to correct the scale factor introduced by FFTW - magt = d_magnitude[indext] / (fft_normalization_factor * fft_normalization_factor); - } - // 4- record the maximum peak and the associated synchronization parameters - if (d_mag < magt) - { - d_mag = magt; - - if (d_use_CFAR_algorithm_flag == false) - { - // Search grid noise floor approximation for this doppler line - volk_32f_accumulator_s32f(&d_input_power, d_magnitude, effective_fft_size); - d_input_power = (d_input_power - d_mag) / (effective_fft_size - 1); - } - - // In case that d_bit_transition_flag = true, we compare the potentially - // new maximum test statistics (d_mag/d_input_power) with the value in - // d_test_statistics. When the second dwell is being processed, the value - // of d_mag/d_input_power could be lower than d_test_statistics (i.e, - // the maximum test statistics in the previous dwell is greater than - // current d_mag/d_input_power). Note that d_test_statistics is not - // restarted between consecutive dwells in multidwell operation. - - if (d_test_statistics < (d_mag / d_input_power) || !d_bit_transition_flag) - { - d_gnss_synchro->Acq_delay_samples = static_cast(indext % d_samples_per_code); - d_gnss_synchro->Acq_doppler_hz = static_cast(doppler); - d_gnss_synchro->Acq_samplestamp_samples = 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(""); - - boost::filesystem::path p = d_dump_filename; - filename << p.parent_path().string() - << boost::filesystem::path::preferred_separator - << p.stem().string() - << "_" << d_gnss_synchro->System - <<"_" << d_gnss_synchro->Signal << "_sat_" - << d_gnss_synchro->PRN << "_doppler_" - << doppler - << p.extension().string(); - - DLOG(INFO) << "Writing ACQ out to " << filename.str(); - - d_dump_file.open(filename.str().c_str(), std::ios::out | std::ios::binary); - d_dump_file.write(reinterpret_cast(d_ifft->get_outbuf()), n); //write directly |abs(x)|^2 in this Doppler bin? - d_dump_file.close(); - } + d_cond.wait( lk, [&]{ return !this->d_worker_active; } ); } - if (!d_bit_transition_flag) + d_sample_counter += d_fft_size; + + + if( d_well_count > 0 ) { - if (d_test_statistics > d_threshold) + + if (!d_bit_transition_flag) + { + if (d_test_statistics > d_threshold) { d_state = 0; // Positive acquisition d_active = false; send_positive_acquisition(); } - else if (d_well_count == d_max_dwells) + else if (d_well_count == d_max_dwells) { d_state = 0; d_active = false; send_negative_acquisition(); } - } - else - { - if (d_well_count == d_max_dwells) // d_max_dwells = 2 + } + else + { + if (d_well_count == d_max_dwells) // d_max_dwells = 2 { if (d_test_statistics > d_threshold) - { - d_state = 0; // Positive acquisition - d_active = false; - send_positive_acquisition(); - } + { + d_state = 0; // Positive acquisition + d_active = false; + send_positive_acquisition(); + } else - { - d_state = 0; // Negative acquisition - d_active = false; - send_negative_acquisition(); - } + { + d_state = 0; // Negative acquisition + d_active = false; + send_negative_acquisition(); + } } + } } - consume_each(1); - break; - } - } + if( d_active ) + { + memcpy( d_data_buffer, input_items[0], d_fft_size * sizeof( gr_complex ) ); + d_new_data_available = true; + d_cond.notify_one(); + } + + consume_each(1); + } // if worker_active (else) + + } // case 1, switch d_state + + } // switch d_state return noutput_items; } +void pcps_acquisition_cc::acquisition_core( void ) +{ + d_worker_active = false; + while( 1 ) + { + std::unique_lock lk( d_mutex ); + d_cond.wait( lk, [&]{ return this->d_new_data_available or this->d_done; } ); + d_worker_active = !d_done; + lk.unlock(); -//void pcps_acquisition_cc::forecast (int noutput_items, gr_vector_int &ninput_items_required) -//{ - //// COD: - //// For zero-padded case we need one extra code period - //if( d_bit_transition_flag ) - //{ - //ninput_items_required[0] = noutput_items*(d_samples_per_code * d_max_dwells + d_samples_per_code); - //} - //else - //{ - //ninput_items_required[0] = noutput_items*d_fft_size*d_max_dwells; - //} -//} + if( d_done ) + { + break; + } + + // initialize acquisition algorithm + int doppler; + uint32_t indext = 0; + float magt = 0.0; + const gr_complex *in = d_data_buffer; //Get the input samples pointer + + int effective_fft_size = ( d_bit_transition_flag ? d_fft_size/2 : d_fft_size ); + + float fft_normalization_factor = static_cast(d_fft_size) * static_cast(d_fft_size); + + d_input_power = 0.0; + d_mag = 0.0; + unsigned long int sample_counter = d_sample_counter; // sample counter + d_well_count++; + + DLOG(INFO)<< "Channel: " << d_channel + << " , doing acquisition of satellite: " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN + << " ,sample stamp: " << sample_counter << ", threshold: " + << d_threshold << ", doppler_max: " << d_doppler_max + << ", doppler_step: " << d_doppler_step + << ", use_CFAR_algorithm_flag: " << ( d_use_CFAR_algorithm_flag ? "true" : "false" ) + <(d_fft_size); + } + // 2- Doppler frequency search loop + for (unsigned int doppler_index = 0; doppler_index < d_num_doppler_bins; doppler_index++) + { + // doppler search steps + doppler = -static_cast(d_doppler_max) + d_doppler_step * doppler_index; + + volk_32fc_x2_multiply_32fc(d_fft_if->get_inbuf(), in, + d_grid_doppler_wipeoffs[doppler_index], d_fft_size); + + // 3- Perform the FFT-based convolution (parallel time search) + // Compute the FFT of the carrier wiped--off incoming signal + d_fft_if->execute(); + + // Multiply carrier wiped--off, Fourier transformed incoming signal + // with the local FFT'd code reference using SIMD operations with VOLK library + volk_32fc_x2_multiply_32fc(d_ifft->get_inbuf(), + d_fft_if->get_outbuf(), d_fft_codes, d_fft_size); + + // compute the inverse FFT + d_ifft->execute(); + + // Search maximum + size_t offset = ( d_bit_transition_flag ? effective_fft_size : 0 ); + volk_32fc_magnitude_squared_32f(d_magnitude, d_ifft->get_outbuf() + offset, effective_fft_size); + volk_gnsssdr_32f_index_max_32u(&indext, d_magnitude, effective_fft_size); + magt = d_magnitude[indext]; + + if (d_use_CFAR_algorithm_flag == true) + { + // Normalize the maximum value to correct the scale factor introduced by FFTW + magt = d_magnitude[indext] / (fft_normalization_factor * fft_normalization_factor); + } + // 4- record the maximum peak and the associated synchronization parameters + if (d_mag < magt) + { + d_mag = magt; + + if (d_use_CFAR_algorithm_flag == false) + { + // Search grid noise floor approximation for this doppler line + volk_32f_accumulator_s32f(&d_input_power, d_magnitude, effective_fft_size); + d_input_power = (d_input_power - d_mag) / (effective_fft_size - 1); + } + + // In case that d_bit_transition_flag = true, we compare the potentially + // new maximum test statistics (d_mag/d_input_power) with the value in + // d_test_statistics. When the second dwell is being processed, the value + // of d_mag/d_input_power could be lower than d_test_statistics (i.e, + // the maximum test statistics in the previous dwell is greater than + // current d_mag/d_input_power). Note that d_test_statistics is not + // restarted between consecutive dwells in multidwell operation. + + if (d_test_statistics < (d_mag / d_input_power) || !d_bit_transition_flag) + { + d_gnss_synchro->Acq_delay_samples = static_cast(indext % d_samples_per_code); + d_gnss_synchro->Acq_doppler_hz = static_cast(doppler); + d_gnss_synchro->Acq_samplestamp_samples = 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(""); + + boost::filesystem::path p = d_dump_filename; + filename << p.parent_path().string() + << boost::filesystem::path::preferred_separator + << p.stem().string() + << "_" << d_gnss_synchro->System + <<"_" << d_gnss_synchro->Signal << "_sat_" + << d_gnss_synchro->PRN << "_doppler_" + << doppler + << p.extension().string(); + + DLOG(INFO) << "Writing ACQ out to " << filename.str(); + + 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(); + } + } + + lk.lock(); + d_worker_active = false; + d_new_data_available = false; + lk.unlock(); + d_cond.notify_one(); + + } +} diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.h b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.h index 07fcb32a9..e28888680 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.h +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.h @@ -52,6 +52,9 @@ #include #include +#include +#include +#include #include #include #include @@ -66,7 +69,7 @@ pcps_make_acquisition_cc(unsigned int sampled_ms, unsigned int max_dwells, unsigned int doppler_max, long freq, long fs_in, int samples_per_ms, int samples_per_code, bool bit_transition_flag, bool use_CFAR_algorithm_flag, - bool dump, + bool dump, bool blocking, std::string dump_filename); /*! @@ -83,18 +86,20 @@ private: unsigned int doppler_max, long freq, long fs_in, int samples_per_ms, int samples_per_code, bool bit_transition_flag, bool use_CFAR_algorithm_flag, - bool dump, + bool dump, bool blocking, std::string dump_filename); pcps_acquisition_cc(unsigned int sampled_ms, unsigned int max_dwells, unsigned int doppler_max, long freq, long fs_in, int samples_per_ms, int samples_per_code, bool bit_transition_flag, bool use_CFAR_algorithm_flag, - bool dump, + bool dump, bool blocking, std::string dump_filename); void update_local_carrier(gr_complex* carrier_vector, int correlator_length_samples, float freq); + void acquisition_core( void ); + void send_negative_acquisition(); void send_positive_acquisition(); long d_fs_in; @@ -132,6 +137,17 @@ private: unsigned int d_channel; std::string d_dump_filename; + std::thread d_worker_thread; + std::mutex d_mutex; + + std::condition_variable d_cond; + bool d_done; + bool d_new_data_available; + bool d_worker_active; + bool d_blocking; + + gr_complex *d_data_buffer; + public: /*! * \brief Default destructor. From ba1a143094e11954c83cf08915bf68ad23b887d1 Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Fri, 15 Sep 2017 16:09:02 +0200 Subject: [PATCH 2/7] Minor fixes Avoid C-syle casts Always terminate case with break Consume ninput_items[0] if case=1 --- .../gnuradio_blocks/pcps_acquisition_cc.cc | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.cc b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.cc index b1dda44e0..814953973 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.cc +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.cc @@ -401,10 +401,9 @@ int pcps_acquisition_cc::general_work(int noutput_items, d_new_data_available = true; d_cond.notify_one(); } - - consume_each(1); + consume_each(ninput_items[0]); } // if worker_active (else) - + break; } // case 1, switch d_state } // switch d_state @@ -442,13 +441,12 @@ void pcps_acquisition_cc::acquisition_core( void ) unsigned long int sample_counter = d_sample_counter; // sample counter d_well_count++; - DLOG(INFO)<< "Channel: " << d_channel + DLOG(INFO) << "Channel: " << d_channel << " , doing acquisition of satellite: " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN << " ,sample stamp: " << sample_counter << ", threshold: " << d_threshold << ", doppler_max: " << d_doppler_max << ", doppler_step: " << d_doppler_step - << ", use_CFAR_algorithm_flag: " << ( d_use_CFAR_algorithm_flag ? "true" : "false" ) - <get_outbuf(), n); //write directly |abs(x)|^2 in this Doppler bin? + d_dump_file.write(reinterpret_cast(d_ifft->get_outbuf()), n); //write directly |abs(x)|^2 in this Doppler bin? d_dump_file.close(); } } From 3cf1fdfd92c30232bfcf9fb288ceeffa182f5edd Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Fri, 15 Sep 2017 16:12:52 +0200 Subject: [PATCH 3/7] Test waits for the block message to emit a message --- .../gps_l1_ca_pcps_acquisition_test.cc | 91 +++++++++++++++---- 1 file changed, 73 insertions(+), 18 deletions(-) diff --git a/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_ca_pcps_acquisition_test.cc b/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_ca_pcps_acquisition_test.cc index 76aedce64..ff897256f 100644 --- a/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_ca_pcps_acquisition_test.cc +++ b/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_ca_pcps_acquisition_test.cc @@ -40,9 +40,7 @@ #include #include #include -#include #include -#include "gnss_block_factory.h" #include "gnss_block_interface.h" #include "in_memory_configuration.h" #include "gnss_sdr_valve.h" @@ -55,23 +53,24 @@ class GpsL1CaPcpsAcquisitionTest_msg_rx; typedef boost::shared_ptr GpsL1CaPcpsAcquisitionTest_msg_rx_sptr; -GpsL1CaPcpsAcquisitionTest_msg_rx_sptr GpsL1CaPcpsAcquisitionTest_msg_rx_make(); +GpsL1CaPcpsAcquisitionTest_msg_rx_sptr GpsL1CaPcpsAcquisitionTest_msg_rx_make(concurrent_queue& queue); class GpsL1CaPcpsAcquisitionTest_msg_rx : public gr::block { private: - friend GpsL1CaPcpsAcquisitionTest_msg_rx_sptr GpsL1CaPcpsAcquisitionTest_msg_rx_make(); + friend GpsL1CaPcpsAcquisitionTest_msg_rx_sptr GpsL1CaPcpsAcquisitionTest_msg_rx_make(concurrent_queue& queue); void msg_handler_events(pmt::pmt_t msg); - GpsL1CaPcpsAcquisitionTest_msg_rx(); + GpsL1CaPcpsAcquisitionTest_msg_rx(concurrent_queue& queue); + concurrent_queue& channel_internal_queue; public: int rx_message; ~GpsL1CaPcpsAcquisitionTest_msg_rx(); //!< Default destructor }; -GpsL1CaPcpsAcquisitionTest_msg_rx_sptr GpsL1CaPcpsAcquisitionTest_msg_rx_make() +GpsL1CaPcpsAcquisitionTest_msg_rx_sptr GpsL1CaPcpsAcquisitionTest_msg_rx_make(concurrent_queue& queue) { - return GpsL1CaPcpsAcquisitionTest_msg_rx_sptr(new GpsL1CaPcpsAcquisitionTest_msg_rx()); + return GpsL1CaPcpsAcquisitionTest_msg_rx_sptr(new GpsL1CaPcpsAcquisitionTest_msg_rx(queue)); } @@ -81,6 +80,7 @@ void GpsL1CaPcpsAcquisitionTest_msg_rx::msg_handler_events(pmt::pmt_t msg) { long int message = pmt::to_long(msg); rx_message = message; + channel_internal_queue.push(rx_message); } catch(boost::bad_any_cast& e) { @@ -90,8 +90,8 @@ void GpsL1CaPcpsAcquisitionTest_msg_rx::msg_handler_events(pmt::pmt_t msg) } -GpsL1CaPcpsAcquisitionTest_msg_rx::GpsL1CaPcpsAcquisitionTest_msg_rx() : - gr::block("GpsL1CaPcpsAcquisitionTest_msg_rx", gr::io_signature::make(0, 0, 0), gr::io_signature::make(0, 0, 0)) +GpsL1CaPcpsAcquisitionTest_msg_rx::GpsL1CaPcpsAcquisitionTest_msg_rx(concurrent_queue& queue) : + gr::block("GpsL1CaPcpsAcquisitionTest_msg_rx", gr::io_signature::make(0, 0, 0), gr::io_signature::make(0, 0, 0)), channel_internal_queue(queue) { this->message_port_register_in(pmt::mp("events")); this->set_msg_handler(pmt::mp("events"), boost::bind(&GpsL1CaPcpsAcquisitionTest_msg_rx::msg_handler_events, this, _1)); @@ -110,25 +110,68 @@ class GpsL1CaPcpsAcquisitionTest: public ::testing::Test protected: GpsL1CaPcpsAcquisitionTest() { - factory = std::make_shared(); config = std::make_shared(); item_size = sizeof(gr_complex); gnss_synchro = Gnss_Synchro(); + stop = false; + message = 0; + acquisition = 0; } ~GpsL1CaPcpsAcquisitionTest() {} void init(); + void start_queue(); + void wait_message(); + void process_message(); + void stop_queue(); + concurrent_queue channel_internal_queue; gr::top_block_sptr top_block; - std::shared_ptr factory; + std::shared_ptr acquisition; std::shared_ptr config; Gnss_Synchro gnss_synchro; size_t item_size; + bool stop; + int message; + boost::thread ch_thread; }; +void GpsL1CaPcpsAcquisitionTest::start_queue() +{ + stop = false; + ch_thread = boost::thread(&GpsL1CaPcpsAcquisitionTest::wait_message, this); +} + + +void GpsL1CaPcpsAcquisitionTest::wait_message() +{ + while (!stop) + { + acquisition->reset(); + + channel_internal_queue.wait_and_pop(message); + + process_message(); + } +} + + +void GpsL1CaPcpsAcquisitionTest::process_message() +{ + stop_queue(); + top_block->stop(); +} + + +void GpsL1CaPcpsAcquisitionTest::stop_queue() +{ + stop = true; +} + + void GpsL1CaPcpsAcquisitionTest::init() { gnss_synchro.Channel_ID = 0; @@ -167,8 +210,8 @@ TEST_F(GpsL1CaPcpsAcquisitionTest, ConnectAndRun) top_block = gr::make_top_block("Acquisition test"); init(); - boost::shared_ptr acquisition = boost::make_shared(config.get(), "Acquisition", 1, 1); - boost::shared_ptr msg_rx = GpsL1CaPcpsAcquisitionTest_msg_rx_make(); + acquisition = std::make_shared(config.get(), "Acquisition", 1, 1); + boost::shared_ptr msg_rx = GpsL1CaPcpsAcquisitionTest_msg_rx_make(channel_internal_queue); ASSERT_NO_THROW( { acquisition->connect(top_block); @@ -202,8 +245,8 @@ TEST_F(GpsL1CaPcpsAcquisitionTest, ValidationOfResults) init(); - std::shared_ptr acquisition = std::make_shared(config.get(), "Acquisition", 1, 1); - boost::shared_ptr msg_rx = GpsL1CaPcpsAcquisitionTest_msg_rx_make(); + acquisition = std::make_shared(config.get(), "Acquisition", 1, 1); + boost::shared_ptr msg_rx = GpsL1CaPcpsAcquisitionTest_msg_rx_make(channel_internal_queue); ASSERT_NO_THROW( { acquisition->set_channel(1); @@ -214,7 +257,7 @@ TEST_F(GpsL1CaPcpsAcquisitionTest, ValidationOfResults) }) << "Failure setting gnss_synchro." << std::endl; ASSERT_NO_THROW( { - acquisition->set_threshold(0.001); + acquisition->set_threshold(0.0); }) << "Failure setting threshold." << std::endl; ASSERT_NO_THROW( { @@ -233,14 +276,16 @@ TEST_F(GpsL1CaPcpsAcquisitionTest, ValidationOfResults) std::string path = std::string(TEST_PATH); std::string file = path + "signal_samples/GPS_L1_CA_ID_1_Fs_4Msps_2ms.dat"; const char * file_name = file.c_str(); - gr::blocks::file_source::sptr file_source = gr::blocks::file_source::make(sizeof(gr_complex), file_name, false); + gr::blocks::file_source::sptr file_source = gr::blocks::file_source::make(sizeof(gr_complex), file_name, true); top_block->connect(file_source, 0, acquisition->get_left_block(), 0); top_block->msg_connect(acquisition->get_right_block(), pmt::mp("events"), msg_rx, pmt::mp("events")); }) << "Failure connecting the blocks of acquisition test." << std::endl; acquisition->set_local_code(); - acquisition->set_state(1); // Ensure that acquisition starts at the first sample acquisition->init(); + acquisition->set_state(1); // Ensure that acquisition starts at the first sample + + start_queue(); EXPECT_NO_THROW( { start = std::chrono::system_clock::now(); @@ -259,4 +304,14 @@ TEST_F(GpsL1CaPcpsAcquisitionTest, ValidationOfResults) EXPECT_LE(doppler_error_hz, 666) << "Doppler error exceeds the expected value: 666 Hz = 2/(3*integration period)"; EXPECT_LT(delay_error_chips, 0.5) << "Delay error exceeds the expected value: 0.5 chips"; +#ifdef OLD_BOOST + ASSERT_NO_THROW( { + ch_thread.timed_join(boost::posix_time::seconds(1)); + }) << "Failure while waiting the queue to stop" << std::endl; +#endif +#ifndef OLD_BOOST + ASSERT_NO_THROW( { + ch_thread.try_join_until(boost::chrono::steady_clock::now() + boost::chrono::milliseconds(50)); + }) << "Failure while waiting the queue to stop" << std::endl; +#endif } From 94f0df8ebe75f8c1001338792808dd1b74574a25 Mon Sep 17 00:00:00 2001 From: Cillian O'Driscoll Date: Sat, 16 Sep 2017 14:55:56 +0100 Subject: [PATCH 4/7] Make use of start() and stop() in pcps_acquisition_cc This is a more natural place to start and stop threads in gnuradio blocks --- .../gnuradio_blocks/pcps_acquisition_cc.cc | 45 +++++++++++++++---- .../gnuradio_blocks/pcps_acquisition_cc.h | 10 +++++ 2 files changed, 47 insertions(+), 8 deletions(-) diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.cc b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.cc index b1dda44e0..0d05fbad3 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.cc +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.cc @@ -136,9 +136,6 @@ pcps_acquisition_cc::pcps_acquisition_cc( d_worker_active = false; d_data_buffer = static_cast(volk_gnsssdr_malloc(d_fft_size * sizeof(gr_complex), volk_gnsssdr_get_alignment())); - // Start the worker thread and wait for it to acknowledge: - std::thread t1( &pcps_acquisition_cc::acquisition_core, this ); - std::swap( d_worker_thread, t1 ); } @@ -165,13 +162,17 @@ pcps_acquisition_cc::~pcps_acquisition_cc() } // Let the worker thread know that we are done and then wait to join + if( d_worker_thread.joinable() ) { - std::lock_guard lk( d_mutex ); - d_done = true; - d_cond.notify_one(); + { + std::lock_guard lk( d_mutex ); + d_done = true; + d_cond.notify_one(); + } + + d_worker_thread.join(); } - - d_worker_thread.join(); + volk_gnsssdr_free( d_data_buffer ); } @@ -554,3 +555,31 @@ void pcps_acquisition_cc::acquisition_core( void ) } } + +bool pcps_acquisition_cc::start( void ) +{ + d_worker_active = false; + d_done = false; + + // Start the worker thread and wait for it to acknowledge: + d_worker_thread = std::move( std::thread( &pcps_acquisition_cc::acquisition_core, this ) ); + + return gr::block::start(); +} + +bool pcps_acquisition_cc::stop( void ) +{ + // Let the worker thread know that we are done and then wait to join + if( d_worker_thread.joinable() ) + { + { + std::lock_guard lk( d_mutex ); + d_done = true; + d_cond.notify_one(); + } + + d_worker_thread.join(); + } + return gr::block::stop(); +} + diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.h b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.h index e28888680..a3b56b3b9 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.h +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.h @@ -249,6 +249,16 @@ public: int general_work(int noutput_items, gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); + + /*! + * Called by the flowgraph when processing is about to start. + */ + bool start( void ); + + /*! + * Called by the flowgraph when processing is done. + */ + bool stop( void ); }; #endif /* GNSS_SDR_PCPS_ACQUISITION_CC_H_*/ From aaf4ca94e8abb52dbca099c81ea550c07085078a Mon Sep 17 00:00:00 2001 From: Cillian O'Driscoll Date: Sat, 16 Sep 2017 14:57:50 +0100 Subject: [PATCH 5/7] Fixed logic in pcps_acquisition_cc Previously didn't actually check for positive or negative acquisition until the call to general_work *after* the one in which the detection statistics were generated --- .../gnuradio_blocks/pcps_acquisition_cc.cc | 149 +++++++++--------- 1 file changed, 77 insertions(+), 72 deletions(-) diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.cc b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.cc index 0d05fbad3..3e519b15f 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.cc +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.cc @@ -268,14 +268,14 @@ void pcps_acquisition_cc::send_positive_acquisition() // 6.1- Declare positive acquisition using a message port //0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL DLOG(INFO) << "positive acquisition" - << "satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN - << "sample_stamp " << d_sample_counter - << "test statistics value " << d_test_statistics - << "test statistics threshold " << d_threshold - << "code phase " << d_gnss_synchro->Acq_delay_samples - << "doppler " << d_gnss_synchro->Acq_doppler_hz - << "magnitude " << d_mag - << "input signal power " << d_input_power; + << ", satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN + << ", sample_stamp " << d_sample_counter + << ", test statistics value " << d_test_statistics + << ", test statistics threshold " << d_threshold + << ", code phase " << d_gnss_synchro->Acq_delay_samples + << ", doppler " << d_gnss_synchro->Acq_doppler_hz + << ", magnitude " << d_mag + << ", input signal power " << d_input_power; this->message_port_pub(pmt::mp("events"), pmt::from_long(1)); @@ -287,14 +287,14 @@ void pcps_acquisition_cc::send_negative_acquisition() // 6.2- Declare negative acquisition using a message port //0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL DLOG(INFO) << "negative acquisition" - << "satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN - << "sample_stamp " << d_sample_counter - << "test statistics value " << d_test_statistics - << "test statistics threshold " << d_threshold - << "code phase " << d_gnss_synchro->Acq_delay_samples - << "doppler " << d_gnss_synchro->Acq_doppler_hz - << "magnitude " << d_mag - << "input signal power " << d_input_power; + << ", satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN + << ", sample_stamp " << d_sample_counter + << ", test statistics value " << d_test_statistics + << ", test statistics threshold " << d_threshold + << ", code phase " << d_gnss_synchro->Acq_delay_samples + << ", doppler " << d_gnss_synchro->Acq_doppler_hz + << ", magnitude " << d_mag + << ", input signal power " << d_input_power; this->message_port_pub(pmt::mp("events"), pmt::from_long(2)); @@ -343,68 +343,39 @@ int pcps_acquisition_cc::general_work(int noutput_items, { std::unique_lock lk( d_mutex ); - if( d_worker_active && !d_blocking ) + int num_items_consumed = 1; + + if( d_worker_active ) { - d_sample_counter += d_fft_size * ninput_items[0]; - consume_each( ninput_items[0] ); + if( d_blocking ) + { + // Should never get here: + std::string msg = "pcps_acquisition_cc: Entered general work with worker active in blocking mode, should never happen"; + LOG(WARNING) << msg; + std::cout << msg << std::endl; + d_cond.wait( lk, [&]{ return !this->d_worker_active; } ); + } + else + { + num_items_consumed = ninput_items[0]; + d_sample_counter += d_fft_size * num_items_consumed; + } } else { - if( d_worker_active && d_blocking ) + // Copy the data to the core and let it know that new data is available + memcpy( d_data_buffer, input_items[0], d_fft_size * sizeof( gr_complex ) ); + d_new_data_available = true; + d_cond.notify_one(); + + if( d_blocking ) { - d_cond.wait( lk, [&]{ return !this->d_worker_active; } ); + d_cond.wait( lk, [&]{ return !this->d_new_data_available; } ); + } + } - d_sample_counter += d_fft_size; - - - if( d_well_count > 0 ) - { - - if (!d_bit_transition_flag) - { - if (d_test_statistics > d_threshold) - { - d_state = 0; // Positive acquisition - d_active = false; - send_positive_acquisition(); - } - else if (d_well_count == d_max_dwells) - { - d_state = 0; - d_active = false; - send_negative_acquisition(); - } - } - else - { - if (d_well_count == d_max_dwells) // d_max_dwells = 2 - { - if (d_test_statistics > d_threshold) - { - d_state = 0; // Positive acquisition - d_active = false; - send_positive_acquisition(); - } - else - { - d_state = 0; // Negative acquisition - d_active = false; - send_negative_acquisition(); - } - } - } - } - - if( d_active ) - { - memcpy( d_data_buffer, input_items[0], d_fft_size * sizeof( gr_complex ) ); - d_new_data_available = true; - d_cond.notify_one(); - } - - consume_each(1); - } // if worker_active (else) + consume_each(num_items_consumed); } // case 1, switch d_state @@ -421,6 +392,7 @@ void pcps_acquisition_cc::acquisition_core( void ) std::unique_lock lk( d_mutex ); d_cond.wait( lk, [&]{ return this->d_new_data_available or this->d_done; } ); d_worker_active = !d_done; + unsigned long int sample_counter = d_sample_counter; // sample counter lk.unlock(); if( d_done ) @@ -440,7 +412,6 @@ void pcps_acquisition_cc::acquisition_core( void ) d_input_power = 0.0; d_mag = 0.0; - unsigned long int sample_counter = d_sample_counter; // sample counter d_well_count++; DLOG(INFO)<< "Channel: " << d_channel @@ -547,6 +518,40 @@ void pcps_acquisition_cc::acquisition_core( void ) } } + if (!d_bit_transition_flag) + { + if (d_test_statistics > d_threshold) + { + d_state = 0; // Positive acquisition + d_active = false; + send_positive_acquisition(); + } + else if (d_well_count == d_max_dwells) + { + d_state = 0; + d_active = false; + send_negative_acquisition(); + } + } + else + { + if (d_well_count == d_max_dwells) // d_max_dwells = 2 + { + if (d_test_statistics > d_threshold) + { + d_state = 0; // Positive acquisition + d_active = false; + send_positive_acquisition(); + } + else + { + d_state = 0; // Negative acquisition + d_active = false; + send_negative_acquisition(); + } + } + } + lk.lock(); d_worker_active = false; d_new_data_available = false; From e352978777f88f3dd7ff9539d6a872277799d92f Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Tue, 3 Oct 2017 13:47:55 +0200 Subject: [PATCH 6/7] Implement the non-blocking option for complex shorts Apply GNU-style indentation Add Cillian to files copyright Delete multithread_acquisition block --- .../acquisition/adapters/CMakeLists.txt | 1 - .../galileo_e1_pcps_ambiguous_acquisition.cc | 2 +- .../adapters/gps_l1_ca_pcps_acquisition.cc | 2 +- .../gps_l1_ca_pcps_multithread_acquisition.cc | 287 --------- .../gps_l1_ca_pcps_multithread_acquisition.h | 156 ----- .../adapters/gps_l2_m_pcps_acquisition.cc | 2 +- .../gnuradio_blocks/CMakeLists.txt | 1 - .../gnuradio_blocks/pcps_acquisition_cc.cc | 424 ++++++------- .../gnuradio_blocks/pcps_acquisition_cc.h | 3 +- .../gnuradio_blocks/pcps_acquisition_sc.cc | 308 +++++++--- .../gnuradio_blocks/pcps_acquisition_sc.h | 49 +- .../pcps_multithread_acquisition_cc.cc | 478 --------------- .../pcps_multithread_acquisition_cc.h | 239 -------- src/core/receiver/gnss_block_factory.cc | 13 - src/tests/test_main.cc | 2 +- .../gps_l1_ca_pcps_acquisition_test.cc | 91 +-- ...s_multithread_acquisition_gsoc2013_test.cc | 566 ------------------ 17 files changed, 487 insertions(+), 2137 deletions(-) delete mode 100644 src/algorithms/acquisition/adapters/gps_l1_ca_pcps_multithread_acquisition.cc delete mode 100644 src/algorithms/acquisition/adapters/gps_l1_ca_pcps_multithread_acquisition.h delete mode 100644 src/algorithms/acquisition/gnuradio_blocks/pcps_multithread_acquisition_cc.cc delete mode 100644 src/algorithms/acquisition/gnuradio_blocks/pcps_multithread_acquisition_cc.h delete mode 100644 src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_ca_pcps_multithread_acquisition_gsoc2013_test.cc diff --git a/src/algorithms/acquisition/adapters/CMakeLists.txt b/src/algorithms/acquisition/adapters/CMakeLists.txt index c0900d4ff..57d2bd298 100644 --- a/src/algorithms/acquisition/adapters/CMakeLists.txt +++ b/src/algorithms/acquisition/adapters/CMakeLists.txt @@ -19,7 +19,6 @@ set(ACQ_ADAPTER_SOURCES gps_l1_ca_pcps_acquisition.cc - gps_l1_ca_pcps_multithread_acquisition.cc gps_l1_ca_pcps_assisted_acquisition.cc gps_l1_ca_pcps_acquisition_fine_doppler.cc gps_l1_ca_pcps_tong_acquisition.cc diff --git a/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.cc b/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.cc index 44b8ef444..f2060aebb 100644 --- a/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.cc +++ b/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition.cc @@ -92,7 +92,7 @@ GalileoE1PcpsAmbiguousAcquisition::GalileoE1PcpsAmbiguousAcquisition( item_size_ = sizeof(lv_16sc_t); acquisition_sc_ = pcps_make_acquisition_sc(sampled_ms_, max_dwells_, doppler_max_, if_, fs_in_, samples_per_ms, code_length_, - bit_transition_flag_, use_CFAR_algorithm_flag_, dump_, + bit_transition_flag_, use_CFAR_algorithm_flag_, dump_, blocking_, dump_filename_); DLOG(INFO) << "acquisition(" << acquisition_sc_->unique_id() << ")"; 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 97ee64c50..2cacaae60 100644 --- a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition.cc +++ b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition.cc @@ -87,7 +87,7 @@ GpsL1CaPcpsAcquisition::GpsL1CaPcpsAcquisition( item_size_ = sizeof(lv_16sc_t); acquisition_sc_ = pcps_make_acquisition_sc(sampled_ms_, max_dwells_, doppler_max_, if_, fs_in_, code_length_, code_length_, - bit_transition_flag_, use_CFAR_algorithm_flag_, dump_, dump_filename_); + bit_transition_flag_, use_CFAR_algorithm_flag_, dump_, blocking_, dump_filename_); DLOG(INFO) << "acquisition(" << acquisition_sc_->unique_id() << ")"; } else diff --git a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_multithread_acquisition.cc b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_multithread_acquisition.cc deleted file mode 100644 index e2216bb60..000000000 --- a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_multithread_acquisition.cc +++ /dev/null @@ -1,287 +0,0 @@ -/*! - * \file gps_l1_ca_pcps_multithread_acquisition.cc - * \brief Adapts a multithread PCPS acquisition block to an - * AcquisitionInterface for GPS L1 C/A signals - * \author Marc Molina, 2013. marc.molina.pena(at)gmail.com - * - * ------------------------------------------------------------------------- - * - * Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors) - * - * GNSS-SDR is a software defined Global Navigation - * Satellite Systems receiver - * - * This file is part of GNSS-SDR. - * - * GNSS-SDR is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GNSS-SDR is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNSS-SDR. If not, see . - * - * ------------------------------------------------------------------------- - */ - -#include "gps_l1_ca_pcps_multithread_acquisition.h" -#include -#include -#include "gps_sdr_signal_processing.h" -#include "GPS_L1_CA.h" -#include "configuration_interface.h" - - -using google::LogMessage; - -GpsL1CaPcpsMultithreadAcquisition::GpsL1CaPcpsMultithreadAcquisition( - ConfigurationInterface* configuration, std::string role, - unsigned int in_streams, unsigned int out_streams) : - role_(role), in_streams_(in_streams), out_streams_(out_streams) -{ - configuration_ = configuration; - std::string default_item_type = "gr_complex"; - std::string default_dump_filename = "./data/acquisition.dat"; - - DLOG(INFO) << "role " << role; - - item_type_ = configuration_->property(role + ".item_type", - default_item_type); - - long fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 2048000); - fs_in_ = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated); - if_ = configuration_->property(role + ".if", 0); - dump_ = configuration_->property(role + ".dump", false); - doppler_max_ = configuration->property(role + ".doppler_max", 5000); - sampled_ms_ = configuration_->property(role + ".coherent_integration_time_ms", 1); - - bit_transition_flag_ = configuration_->property("Acquisition.bit_transition_flag", false); - - if (!bit_transition_flag_) - { - max_dwells_ = configuration_->property(role + ".max_dwells", 1); - } - else - { - max_dwells_ = 2; - } - - dump_filename_ = configuration_->property(role + ".dump_filename", - default_dump_filename); - - //--- Find number of samples per spreading code ------------------------- - code_length_ = round(fs_in_ - / (GPS_L1_CA_CODE_RATE_HZ / GPS_L1_CA_CODE_LENGTH_CHIPS)); - - vector_length_ = code_length_ * sampled_ms_; - - code_ = new gr_complex[vector_length_]; - - if (item_type_.compare("gr_complex") == 0) - { - item_size_ = sizeof(gr_complex); - acquisition_cc_ = pcps_make_multithread_acquisition_cc(sampled_ms_, max_dwells_, - doppler_max_, if_, fs_in_, code_length_, code_length_, - bit_transition_flag_, dump_, dump_filename_); - - stream_to_vector_ = gr::blocks::stream_to_vector::make(item_size_, vector_length_); - - DLOG(INFO) << "stream_to_vector(" << stream_to_vector_->unique_id() - << ")"; - DLOG(INFO) << "acquisition(" << acquisition_cc_->unique_id() - << ")"; - } - else - { - item_size_ = sizeof(gr_complex); - LOG(WARNING) << item_type_ << " unknown acquisition item type"; - } - - channel_ = 0; - threshold_ = 0.0; - doppler_step_ = 0; - gnss_synchro_ = 0; -} - - -GpsL1CaPcpsMultithreadAcquisition::~GpsL1CaPcpsMultithreadAcquisition() -{ - delete[] code_; -} - - -void GpsL1CaPcpsMultithreadAcquisition::set_channel(unsigned int channel) -{ - channel_ = channel; - if (item_type_.compare("gr_complex") == 0) - { - acquisition_cc_->set_channel(channel_); - } -} - - -void GpsL1CaPcpsMultithreadAcquisition::set_threshold(float threshold) -{ - float pfa = configuration_->property(role_ + boost::lexical_cast(channel_) + ".pfa", 0.0); - - if(pfa == 0.0) - { - pfa = configuration_->property(role_+".pfa", 0.0); - } - if(pfa == 0.0) - { - threshold_ = threshold; - } - else - { - threshold_ = calculate_threshold(pfa); - } - - DLOG(INFO) << "Channel " << channel_ << " Threshold = " << threshold_; - - if (item_type_.compare("gr_complex") == 0) - { - acquisition_cc_->set_threshold(threshold_); - } -} - - -void GpsL1CaPcpsMultithreadAcquisition::set_doppler_max(unsigned int doppler_max) -{ - doppler_max_ = doppler_max; - if (item_type_.compare("gr_complex") == 0) - { - acquisition_cc_->set_doppler_max(doppler_max_); - } -} - - -void GpsL1CaPcpsMultithreadAcquisition::set_doppler_step(unsigned int doppler_step) -{ - doppler_step_ = doppler_step; - if (item_type_.compare("gr_complex") == 0) - { - acquisition_cc_->set_doppler_step(doppler_step_); - } - -} - - -void GpsL1CaPcpsMultithreadAcquisition::set_gnss_synchro(Gnss_Synchro* gnss_synchro) -{ - gnss_synchro_ = gnss_synchro; - if (item_type_.compare("gr_complex") == 0) - { - acquisition_cc_->set_gnss_synchro(gnss_synchro_); - } -} - - -signed int GpsL1CaPcpsMultithreadAcquisition::mag() -{ - if (item_type_.compare("gr_complex") == 0) - { - return acquisition_cc_->mag(); - } - else - { - return 0; - } -} - - -void GpsL1CaPcpsMultithreadAcquisition::init() -{ - acquisition_cc_->init(); - //set_local_code(); -} - - -void GpsL1CaPcpsMultithreadAcquisition::set_local_code() -{ - if (item_type_.compare("gr_complex") == 0) - { - std::complex* code = new std::complex[code_length_]; - - gps_l1_ca_code_gen_complex_sampled(code, gnss_synchro_->PRN, fs_in_, 0); - - for (unsigned int i = 0; i < sampled_ms_; i++) - { - memcpy(&(code_[i*code_length_]), code, - sizeof(gr_complex)*code_length_); - } - - acquisition_cc_->set_local_code(code_); - - delete[] code; - } -} - - -void GpsL1CaPcpsMultithreadAcquisition::reset() -{ - if (item_type_.compare("gr_complex") == 0) - { - acquisition_cc_->set_active(true); - } -} - - -float GpsL1CaPcpsMultithreadAcquisition::calculate_threshold(float pfa) -{ - //Calculate the threshold - - unsigned int frequency_bins = 0; - for (int doppler = static_cast(-doppler_max_); doppler <= static_cast(doppler_max_); doppler += doppler_step_) - { - frequency_bins++; - } - - DLOG(INFO) << "Channel "<< channel_ << " Pfa = " << pfa; - - unsigned int ncells = vector_length_ * frequency_bins; - double exponent = 1 / static_cast(ncells); - double val = pow(1.0 - pfa, exponent); - double lambda = double(vector_length_); - boost::math::exponential_distribution mydist (lambda); - float threshold = static_cast(quantile(mydist,val)); - - return threshold; -} - - -void GpsL1CaPcpsMultithreadAcquisition::connect(gr::top_block_sptr top_block) -{ - if (item_type_.compare("gr_complex") == 0) - { - top_block->connect(stream_to_vector_, 0, acquisition_cc_, 0); - } - -} - - -void GpsL1CaPcpsMultithreadAcquisition::disconnect(gr::top_block_sptr top_block) -{ - if (item_type_.compare("gr_complex") == 0) - { - top_block->disconnect(stream_to_vector_, 0, acquisition_cc_, 0); - } -} - - -gr::basic_block_sptr GpsL1CaPcpsMultithreadAcquisition::get_left_block() -{ - return stream_to_vector_; -} - - -gr::basic_block_sptr GpsL1CaPcpsMultithreadAcquisition::get_right_block() -{ - return acquisition_cc_; -} - diff --git a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_multithread_acquisition.h b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_multithread_acquisition.h deleted file mode 100644 index 210fe0749..000000000 --- a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_multithread_acquisition.h +++ /dev/null @@ -1,156 +0,0 @@ -/*! - * \file gps_l1_ca_pcps_multithread_acquisition.h - * \brief Adapts a multithread PCPS acquisition block to an - * AcquisitionInterface for GPS L1 C/A signals - * \author Marc Molina, 2013. marc.molina.pena(at)gmail.com - * - * ------------------------------------------------------------------------- - * - * Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors) - * - * GNSS-SDR is a software defined Global Navigation - * Satellite Systems receiver - * - * This file is part of GNSS-SDR. - * - * GNSS-SDR is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GNSS-SDR is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNSS-SDR. If not, see . - * - * ------------------------------------------------------------------------- - */ - -#ifndef GNSS_SDR_GPS_L1_CA_PCPS_MULTITHREAD_ACQUISITION_H_ -#define GNSS_SDR_GPS_L1_CA_PCPS_MULTITHREAD_ACQUISITION_H_ - -#include -#include -#include "gnss_synchro.h" -#include "acquisition_interface.h" -#include "pcps_multithread_acquisition_cc.h" - - - -class ConfigurationInterface; - -/*! - * \brief This class adapts a multithread PCPS acquisition block to an - * AcquisitionInterface for GPS L1 C/A signals - */ -class GpsL1CaPcpsMultithreadAcquisition: public AcquisitionInterface -{ -public: - GpsL1CaPcpsMultithreadAcquisition(ConfigurationInterface* configuration, - std::string role, unsigned int in_streams, - unsigned int out_streams); - - virtual ~GpsL1CaPcpsMultithreadAcquisition(); - - inline std::string role() override - { - return role_; - } - - /*! - * \brief Returns "GPS_L1_CA_PCPS_Multithread_Acquisition" - */ - inline std::string implementation() override - { - return "GPS_L1_CA_PCPS_Multithread_Acquisition"; - } - - inline size_t item_size() override - { - return item_size_; - } - - void connect(gr::top_block_sptr top_block) override; - void disconnect(gr::top_block_sptr top_block) override; - gr::basic_block_sptr get_left_block() override; - gr::basic_block_sptr get_right_block() override; - - /*! - * \brief Set acquisition/tracking common Gnss_Synchro object pointer - * to efficiently exchange synchronization data between acquisition and - * tracking blocks - */ - void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) override; - - /*! - * \brief Set acquisition channel unique ID - */ - void set_channel(unsigned int channel) override; - - /*! - * \brief Set statistics threshold of PCPS algorithm - */ - void set_threshold(float threshold) override; - - /*! - * \brief Set maximum Doppler off grid search - */ - void set_doppler_max(unsigned int doppler_max) override; - - /*! - * \brief Set Doppler steps for the grid search - */ - void set_doppler_step(unsigned int doppler_step) override; - - /*! - * \brief Initializes acquisition algorithm. - */ - void init() override; - - /*! - * \brief Sets local code for GPS L1/CA PCPS acquisition algorithm. - */ - void set_local_code() override; - - /*! - * \brief Returns the maximum peak of grid search - */ - signed int mag() override; - - /*! - * \brief Restart acquisition algorithm - */ - void reset() override; - -private: - ConfigurationInterface* configuration_; - pcps_multithread_acquisition_cc_sptr acquisition_cc_; - gr::blocks::stream_to_vector::sptr stream_to_vector_; - size_t item_size_; - std::string item_type_; - unsigned int vector_length_; - unsigned int code_length_; - bool bit_transition_flag_; - unsigned int channel_; - float threshold_; - unsigned int doppler_max_; - unsigned int doppler_step_; - unsigned int sampled_ms_; - unsigned int max_dwells_; - long fs_in_; - long if_; - bool dump_; - std::string dump_filename_; - std::complex * code_; - Gnss_Synchro * gnss_synchro_; - std::string role_; - unsigned int in_streams_; - unsigned int out_streams_; - - float calculate_threshold(float pfa); -}; - -#endif /* GNSS_SDR_GPS_L1_CA_PCPS_MULTITHREAD_ACQUISITION_H_ */ diff --git a/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition.cc b/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition.cc index 4ab6d2b01..b9443a4e8 100644 --- a/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition.cc +++ b/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition.cc @@ -87,7 +87,7 @@ GpsL2MPcpsAcquisition::GpsL2MPcpsAcquisition( item_size_ = sizeof(lv_16sc_t); acquisition_sc_ = pcps_make_acquisition_sc(1, max_dwells_, doppler_max_, if_, fs_in_, code_length_, code_length_, - bit_transition_flag_, use_CFAR_algorithm_flag_, dump_, dump_filename_); + bit_transition_flag_, use_CFAR_algorithm_flag_, dump_, blocking_, dump_filename_); DLOG(INFO) << "acquisition(" << acquisition_sc_->unique_id() << ")"; } diff --git a/src/algorithms/acquisition/gnuradio_blocks/CMakeLists.txt b/src/algorithms/acquisition/gnuradio_blocks/CMakeLists.txt index c67c6106d..8a22651c4 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/CMakeLists.txt +++ b/src/algorithms/acquisition/gnuradio_blocks/CMakeLists.txt @@ -20,7 +20,6 @@ set(ACQ_GR_BLOCKS_SOURCES pcps_acquisition_cc.cc pcps_acquisition_sc.cc - pcps_multithread_acquisition_cc.cc pcps_assisted_acquisition_cc.cc pcps_acquisition_fine_doppler_cc.cc pcps_tong_acquisition_cc.cc diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.cc b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.cc index 0f2c6d6cd..a0461f9c5 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.cc +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.cc @@ -5,11 +5,12 @@ *
  • Javier Arribas, 2011. jarribas(at)cttc.es *
  • Luis Esteve, 2012. luis(at)epsilon-formacion.com *
  • Marc Molina, 2013. marc.molina.pena@gmail.com + *
  • Cillian O'Driscoll, 2017. cillian(at)ieee.org * * * ------------------------------------------------------------------------- * - * Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors) + * Copyright (C) 2010-2017 (see AUTHORS file for a list of contributors) * * GNSS-SDR is a software defined Global Navigation * Satellite Systems receiver @@ -135,7 +136,6 @@ pcps_acquisition_cc::pcps_acquisition_cc( d_new_data_available = false; d_worker_active = false; d_data_buffer = static_cast(volk_gnsssdr_malloc(d_fft_size * sizeof(gr_complex), volk_gnsssdr_get_alignment())); - } @@ -163,15 +163,15 @@ pcps_acquisition_cc::~pcps_acquisition_cc() // Let the worker thread know that we are done and then wait to join if( d_worker_thread.joinable() ) - { { - std::lock_guard lk( d_mutex ); - d_done = true; - d_cond.notify_one(); + { + std::lock_guard lk( d_mutex ); + d_done = true; + d_cond.notify_one(); + } + + d_worker_thread.join(); } - - d_worker_thread.join(); - } volk_gnsssdr_free( d_data_buffer ); } @@ -186,7 +186,7 @@ void pcps_acquisition_cc::set_local_code(std::complex * code) gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler if( d_bit_transition_flag ) { - int offset = d_fft_size/2; + int offset = d_fft_size / 2; std::fill_n( d_fft_if->get_inbuf(), offset, gr_complex( 0.0, 0.0 ) ); memcpy(d_fft_if->get_inbuf() + offset, code, sizeof(gr_complex) * offset); } @@ -194,7 +194,7 @@ void pcps_acquisition_cc::set_local_code(std::complex * code) { memcpy(d_fft_if->get_inbuf(), code, sizeof(gr_complex) * d_fft_size); } - + d_fft_if->execute(); // We need the FFT of local code volk_32fc_conjugate_32fc(d_fft_codes, d_fft_if->get_outbuf(), d_fft_size); } @@ -268,17 +268,16 @@ void pcps_acquisition_cc::send_positive_acquisition() // 6.1- Declare positive acquisition using a message port //0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL DLOG(INFO) << "positive acquisition" - << ", satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN - << ", sample_stamp " << d_sample_counter - << ", test statistics value " << d_test_statistics - << ", test statistics threshold " << d_threshold - << ", code phase " << d_gnss_synchro->Acq_delay_samples - << ", doppler " << d_gnss_synchro->Acq_doppler_hz - << ", magnitude " << d_mag - << ", input signal power " << d_input_power; + << ", satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN + << ", sample_stamp " << d_sample_counter + << ", test statistics value " << d_test_statistics + << ", test statistics threshold " << d_threshold + << ", code phase " << d_gnss_synchro->Acq_delay_samples + << ", doppler " << d_gnss_synchro->Acq_doppler_hz + << ", magnitude " << d_mag + << ", input signal power " << d_input_power; this->message_port_pub(pmt::mp("events"), pmt::from_long(1)); - } @@ -287,17 +286,16 @@ void pcps_acquisition_cc::send_negative_acquisition() // 6.2- Declare negative acquisition using a message port //0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL DLOG(INFO) << "negative acquisition" - << ", satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN - << ", sample_stamp " << d_sample_counter - << ", test statistics value " << d_test_statistics - << ", test statistics threshold " << d_threshold - << ", code phase " << d_gnss_synchro->Acq_delay_samples - << ", doppler " << d_gnss_synchro->Acq_doppler_hz - << ", magnitude " << d_mag - << ", input signal power " << d_input_power; + << ", satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN + << ", sample_stamp " << d_sample_counter + << ", test statistics value " << d_test_statistics + << ", test statistics threshold " << d_threshold + << ", code phase " << d_gnss_synchro->Acq_delay_samples + << ", doppler " << d_gnss_synchro->Acq_doppler_hz + << ", magnitude " << d_mag + << ", input signal power " << d_input_power; this->message_port_pub(pmt::mp("events"), pmt::from_long(2)); - } @@ -346,34 +344,34 @@ int pcps_acquisition_cc::general_work(int noutput_items, int num_items_consumed = 1; if( d_worker_active ) - { - if( d_blocking ) { - // Should never get here: - std::string msg = "pcps_acquisition_cc: Entered general work with worker active in blocking mode, should never happen"; - LOG(WARNING) << msg; - std::cout << msg << std::endl; - d_cond.wait( lk, [&]{ return !this->d_worker_active; } ); + if( d_blocking ) + { + // Should never get here: + std::string msg = "pcps_acquisition_cc: Entered general work with worker active in blocking mode, should never happen"; + LOG(WARNING) << msg; + std::cout << msg << std::endl; + d_cond.wait( lk, [&]{ return !this->d_worker_active; } ); + } + else + { + num_items_consumed = ninput_items[0]; + d_sample_counter += d_fft_size * num_items_consumed; + } } - else - { - num_items_consumed = ninput_items[0]; - d_sample_counter += d_fft_size * num_items_consumed; - } - } else - { - // Copy the data to the core and let it know that new data is available - memcpy( d_data_buffer, input_items[0], d_fft_size * sizeof( gr_complex ) ); - d_new_data_available = true; - d_cond.notify_one(); - - if( d_blocking ) { - d_cond.wait( lk, [&]{ return !this->d_new_data_available; } ); + // Copy the data to the core and let it know that new data is available + memcpy( d_data_buffer, input_items[0], d_fft_size * sizeof( gr_complex ) ); + d_new_data_available = true; + d_cond.notify_one(); + if( d_blocking ) + { + d_cond.wait( lk, [&]{ return !this->d_new_data_available; } ); + + } } - } consume_each(num_items_consumed); @@ -385,182 +383,183 @@ int pcps_acquisition_cc::general_work(int noutput_items, return noutput_items; } + void pcps_acquisition_cc::acquisition_core( void ) { d_worker_active = false; while( 1 ) - { - std::unique_lock lk( d_mutex ); - d_cond.wait( lk, [&]{ return this->d_new_data_available or this->d_done; } ); - d_worker_active = !d_done; - unsigned long int sample_counter = d_sample_counter; // sample counter - lk.unlock(); - - if( d_done ) { - break; - } + std::unique_lock lk( d_mutex ); + d_cond.wait( lk, [&]{ return this->d_new_data_available or this->d_done; } ); + d_worker_active = !d_done; + unsigned long int sample_counter = d_sample_counter; // sample counter + lk.unlock(); - // initialize acquisition algorithm - int doppler; - uint32_t indext = 0; - float magt = 0.0; - const gr_complex *in = d_data_buffer; //Get the input samples pointer + if( d_done ) + { + break; + } - int effective_fft_size = ( d_bit_transition_flag ? d_fft_size/2 : d_fft_size ); + // initialize acquisition algorithm + int doppler; + uint32_t indext = 0; + float magt = 0.0; + const gr_complex *in = d_data_buffer; //Get the input samples pointer - float fft_normalization_factor = static_cast(d_fft_size) * static_cast(d_fft_size); + int effective_fft_size = ( d_bit_transition_flag ? d_fft_size/2 : d_fft_size ); - d_input_power = 0.0; - d_mag = 0.0; - d_well_count++; + float fft_normalization_factor = static_cast(d_fft_size) * static_cast(d_fft_size); - DLOG(INFO) << "Channel: " << d_channel - << " , doing acquisition of satellite: " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN - << " ,sample stamp: " << sample_counter << ", threshold: " - << d_threshold << ", doppler_max: " << d_doppler_max - << ", doppler_step: " << d_doppler_step - << ", use_CFAR_algorithm_flag: " << ( d_use_CFAR_algorithm_flag ? "true" : "false" ); + d_input_power = 0.0; + d_mag = 0.0; + d_well_count++; - if (d_use_CFAR_algorithm_flag == true) - { - // 1- (optional) Compute the input signal power estimation - volk_32fc_magnitude_squared_32f(d_magnitude, in, d_fft_size); - volk_32f_accumulator_s32f(&d_input_power, d_magnitude, d_fft_size); - d_input_power /= static_cast(d_fft_size); - } - // 2- Doppler frequency search loop - for (unsigned int doppler_index = 0; doppler_index < d_num_doppler_bins; doppler_index++) - { - // doppler search steps - doppler = -static_cast(d_doppler_max) + d_doppler_step * doppler_index; - - volk_32fc_x2_multiply_32fc(d_fft_if->get_inbuf(), in, - d_grid_doppler_wipeoffs[doppler_index], d_fft_size); - - // 3- Perform the FFT-based convolution (parallel time search) - // Compute the FFT of the carrier wiped--off incoming signal - d_fft_if->execute(); - - // Multiply carrier wiped--off, Fourier transformed incoming signal - // with the local FFT'd code reference using SIMD operations with VOLK library - volk_32fc_x2_multiply_32fc(d_ifft->get_inbuf(), - d_fft_if->get_outbuf(), d_fft_codes, d_fft_size); - - // compute the inverse FFT - d_ifft->execute(); - - // Search maximum - size_t offset = ( d_bit_transition_flag ? effective_fft_size : 0 ); - volk_32fc_magnitude_squared_32f(d_magnitude, d_ifft->get_outbuf() + offset, effective_fft_size); - volk_gnsssdr_32f_index_max_32u(&indext, d_magnitude, effective_fft_size); - magt = d_magnitude[indext]; + DLOG(INFO) << "Channel: " << d_channel + << " , doing acquisition of satellite: " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN + << " ,sample stamp: " << sample_counter << ", threshold: " + << d_threshold << ", doppler_max: " << d_doppler_max + << ", doppler_step: " << d_doppler_step + << ", use_CFAR_algorithm_flag: " << ( d_use_CFAR_algorithm_flag ? "true" : "false" ); if (d_use_CFAR_algorithm_flag == true) - { - // Normalize the maximum value to correct the scale factor introduced by FFTW - magt = d_magnitude[indext] / (fft_normalization_factor * fft_normalization_factor); - } - // 4- record the maximum peak and the associated synchronization parameters - if (d_mag < magt) - { - d_mag = magt; - - if (d_use_CFAR_algorithm_flag == false) { - // Search grid noise floor approximation for this doppler line - volk_32f_accumulator_s32f(&d_input_power, d_magnitude, effective_fft_size); - d_input_power = (d_input_power - d_mag) / (effective_fft_size - 1); + // 1- (optional) Compute the input signal power estimation + volk_32fc_magnitude_squared_32f(d_magnitude, in, d_fft_size); + volk_32f_accumulator_s32f(&d_input_power, d_magnitude, d_fft_size); + d_input_power /= static_cast(d_fft_size); + } + // 2- Doppler frequency search loop + for (unsigned int doppler_index = 0; doppler_index < d_num_doppler_bins; doppler_index++) + { + // doppler search steps + doppler = -static_cast(d_doppler_max) + d_doppler_step * doppler_index; + + volk_32fc_x2_multiply_32fc(d_fft_if->get_inbuf(), in, + d_grid_doppler_wipeoffs[doppler_index], d_fft_size); + + // 3- Perform the FFT-based convolution (parallel time search) + // Compute the FFT of the carrier wiped--off incoming signal + d_fft_if->execute(); + + // Multiply carrier wiped--off, Fourier transformed incoming signal + // with the local FFT'd code reference using SIMD operations with VOLK library + volk_32fc_x2_multiply_32fc(d_ifft->get_inbuf(), + d_fft_if->get_outbuf(), d_fft_codes, d_fft_size); + + // compute the inverse FFT + d_ifft->execute(); + + // Search maximum + size_t offset = ( d_bit_transition_flag ? effective_fft_size : 0 ); + volk_32fc_magnitude_squared_32f(d_magnitude, d_ifft->get_outbuf() + offset, effective_fft_size); + volk_gnsssdr_32f_index_max_32u(&indext, d_magnitude, effective_fft_size); + magt = d_magnitude[indext]; + + if (d_use_CFAR_algorithm_flag == true) + { + // Normalize the maximum value to correct the scale factor introduced by FFTW + magt = d_magnitude[indext] / (fft_normalization_factor * fft_normalization_factor); + } + // 4- record the maximum peak and the associated synchronization parameters + if (d_mag < magt) + { + d_mag = magt; + + if (d_use_CFAR_algorithm_flag == false) + { + // Search grid noise floor approximation for this doppler line + volk_32f_accumulator_s32f(&d_input_power, d_magnitude, effective_fft_size); + d_input_power = (d_input_power - d_mag) / (effective_fft_size - 1); + } + + // In case that d_bit_transition_flag = true, we compare the potentially + // new maximum test statistics (d_mag/d_input_power) with the value in + // d_test_statistics. When the second dwell is being processed, the value + // of d_mag/d_input_power could be lower than d_test_statistics (i.e, + // the maximum test statistics in the previous dwell is greater than + // current d_mag/d_input_power). Note that d_test_statistics is not + // restarted between consecutive dwells in multidwell operation. + + if (d_test_statistics < (d_mag / d_input_power) || !d_bit_transition_flag) + { + d_gnss_synchro->Acq_delay_samples = static_cast(indext % d_samples_per_code); + d_gnss_synchro->Acq_doppler_hz = static_cast(doppler); + d_gnss_synchro->Acq_samplestamp_samples = 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(""); + + boost::filesystem::path p = d_dump_filename; + filename << p.parent_path().string() + << boost::filesystem::path::preferred_separator + << p.stem().string() + << "_" << d_gnss_synchro->System + <<"_" << d_gnss_synchro->Signal << "_sat_" + << d_gnss_synchro->PRN << "_doppler_" + << doppler + << p.extension().string(); + + DLOG(INFO) << "Writing ACQ out to " << filename.str(); + + d_dump_file.open(filename.str().c_str(), std::ios::out | std::ios::binary); + d_dump_file.write(reinterpret_cast(d_ifft->get_outbuf()), n); //write directly |abs(x)|^2 in this Doppler bin? + d_dump_file.close(); + } } - // 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) + if (!d_bit_transition_flag) { - d_gnss_synchro->Acq_delay_samples = static_cast(indext % d_samples_per_code); - d_gnss_synchro->Acq_doppler_hz = static_cast(doppler); - d_gnss_synchro->Acq_samplestamp_samples = 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; + if (d_test_statistics > d_threshold) + { + d_state = 0; // Positive acquisition + d_active = false; + send_positive_acquisition(); + } + else if (d_well_count == d_max_dwells) + { + d_state = 0; + d_active = false; + send_negative_acquisition(); + } + } + else + { + if (d_well_count == d_max_dwells) // d_max_dwells = 2 + { + if (d_test_statistics > d_threshold) + { + d_state = 0; // Positive acquisition + d_active = false; + send_positive_acquisition(); + } + else + { + d_state = 0; // Negative acquisition + d_active = false; + send_negative_acquisition(); + } + } } - } - // 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(""); - - boost::filesystem::path p = d_dump_filename; - filename << p.parent_path().string() - << boost::filesystem::path::preferred_separator - << p.stem().string() - << "_" << d_gnss_synchro->System - <<"_" << d_gnss_synchro->Signal << "_sat_" - << d_gnss_synchro->PRN << "_doppler_" - << doppler - << p.extension().string(); - - DLOG(INFO) << "Writing ACQ out to " << filename.str(); - - d_dump_file.open(filename.str().c_str(), std::ios::out | std::ios::binary); - d_dump_file.write(reinterpret_cast(d_ifft->get_outbuf()), n); //write directly |abs(x)|^2 in this Doppler bin? - d_dump_file.close(); - } + lk.lock(); + d_worker_active = false; + d_new_data_available = false; + lk.unlock(); + d_cond.notify_one(); } - - if (!d_bit_transition_flag) - { - if (d_test_statistics > d_threshold) - { - d_state = 0; // Positive acquisition - d_active = false; - send_positive_acquisition(); - } - else if (d_well_count == d_max_dwells) - { - d_state = 0; - d_active = false; - send_negative_acquisition(); - } - } - else - { - if (d_well_count == d_max_dwells) // d_max_dwells = 2 - { - if (d_test_statistics > d_threshold) - { - d_state = 0; // Positive acquisition - d_active = false; - send_positive_acquisition(); - } - else - { - d_state = 0; // Negative acquisition - d_active = false; - send_negative_acquisition(); - } - } - } - - lk.lock(); - d_worker_active = false; - d_new_data_available = false; - lk.unlock(); - d_cond.notify_one(); - - } } + bool pcps_acquisition_cc::start( void ) { d_worker_active = false; @@ -572,19 +571,20 @@ bool pcps_acquisition_cc::start( void ) return gr::block::start(); } + bool pcps_acquisition_cc::stop( void ) { // Let the worker thread know that we are done and then wait to join if( d_worker_thread.joinable() ) - { { - std::lock_guard lk( d_mutex ); - d_done = true; - d_cond.notify_one(); + { + std::lock_guard lk( d_mutex ); + d_done = true; + d_cond.notify_one(); + } + + d_worker_thread.join(); } - - d_worker_thread.join(); - } return gr::block::stop(); } diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.h b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.h index a3b56b3b9..486468379 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.h +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_cc.h @@ -20,11 +20,12 @@ *
  • Javier Arribas, 2011. jarribas(at)cttc.es *
  • Luis Esteve, 2012. luis(at)epsilon-formacion.com *
  • Marc Molina, 2013. marc.molina.pena@gmail.com + *
  • Cillian O'Driscoll, 2017. cillian(at)ieee.org * * * ------------------------------------------------------------------------- * - * Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors) + * Copyright (C) 2010-2017 (see AUTHORS file for a list of contributors) * * GNSS-SDR is a software defined Global Navigation * Satellite Systems receiver diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_sc.cc b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_sc.cc index c265dee17..3946493ff 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_sc.cc +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_sc.cc @@ -5,11 +5,12 @@ *
  • Javier Arribas, 2011. jarribas(at)cttc.es *
  • Luis Esteve, 2012. luis(at)epsilon-formacion.com *
  • Marc Molina, 2013. marc.molina.pena@gmail.com + *
  • Cillian O'Driscoll, 2017. cillian(at)ieee.org * * * ------------------------------------------------------------------------- * - * Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors) + * Copyright (C) 2010-2017 (see AUTHORS file for a list of contributors) * * GNSS-SDR is a software defined Global Navigation * Satellite Systems receiver @@ -32,16 +33,17 @@ * ------------------------------------------------------------------------- */ + #include "pcps_acquisition_sc.h" #include #include #include #include #include -#include #include "control_message_factory.h" #include "GPS_L1_CA.h" //GPS_TWO_PI + using google::LogMessage; pcps_acquisition_sc_sptr pcps_make_acquisition_sc( @@ -49,27 +51,28 @@ pcps_acquisition_sc_sptr pcps_make_acquisition_sc( unsigned int doppler_max, long freq, long fs_in, int samples_per_ms, int samples_per_code, bool bit_transition_flag, bool use_CFAR_algorithm_flag, - bool dump, + bool dump, bool blocking, std::string dump_filename) { - return pcps_acquisition_sc_sptr( new pcps_acquisition_sc(sampled_ms, max_dwells, doppler_max, freq, fs_in, samples_per_ms, - samples_per_code, bit_transition_flag, use_CFAR_algorithm_flag, dump, dump_filename)); + samples_per_code, bit_transition_flag, use_CFAR_algorithm_flag, dump, blocking, dump_filename)); } + pcps_acquisition_sc::pcps_acquisition_sc( unsigned int sampled_ms, unsigned int max_dwells, unsigned int doppler_max, long freq, long fs_in, int samples_per_ms, int samples_per_code, bool bit_transition_flag, bool use_CFAR_algorithm_flag, - bool dump, + bool dump, bool blocking, std::string dump_filename) : gr::block("pcps_acquisition_sc", gr::io_signature::make(1, 1, sizeof(lv_16sc_t) * sampled_ms * samples_per_ms * ( bit_transition_flag ? 2 : 1 )), - gr::io_signature::make(0, 0, 0)) + gr::io_signature::make(0, 0, sizeof(lv_16sc_t) * sampled_ms * samples_per_ms * ( bit_transition_flag ? 2 : 1 )) ) { this->message_port_register_out(pmt::mp("events")); + d_sample_counter = 0; // SAMPLE COUNTER d_active = false; d_state = 0; @@ -88,7 +91,7 @@ pcps_acquisition_sc::pcps_acquisition_sc( d_bit_transition_flag = bit_transition_flag; d_use_CFAR_algorithm_flag = use_CFAR_algorithm_flag; d_threshold = 0.0; - d_doppler_step = 250; + d_doppler_step = 0; d_code_phase = 0; d_test_statistics = 0.0; d_channel = 0; @@ -109,11 +112,12 @@ pcps_acquisition_sc::pcps_acquisition_sc( if( d_bit_transition_flag ) { d_fft_size *= 2; - d_max_dwells = 1; + d_max_dwells = 1; //Activation of d_bit_transition_flag invalidates the value of d_max_dwells } d_fft_codes = static_cast(volk_gnsssdr_malloc(d_fft_size * sizeof(gr_complex), volk_gnsssdr_get_alignment())); d_magnitude = static_cast(volk_gnsssdr_malloc(d_fft_size * sizeof(float), volk_gnsssdr_get_alignment())); + //temporary storage for the input conversion from 16sc to float 32fc d_in_32fc = static_cast(volk_gnsssdr_malloc(d_fft_size * sizeof(gr_complex), volk_gnsssdr_get_alignment())); @@ -129,6 +133,12 @@ pcps_acquisition_sc::pcps_acquisition_sc( d_gnss_synchro = 0; d_grid_doppler_wipeoffs = 0; + + d_done = false; + d_blocking = blocking; + d_new_data_available = false; + d_worker_active = false; + d_data_buffer = static_cast(volk_gnsssdr_malloc(d_fft_size * sizeof(lv_16sc_t), volk_gnsssdr_get_alignment())); } @@ -154,6 +164,20 @@ pcps_acquisition_sc::~pcps_acquisition_sc() { d_dump_file.close(); } + + // Let the worker thread know that we are done and then wait to join + if( d_worker_thread.joinable() ) + { + { + std::lock_guard lk( d_mutex ); + d_done = true; + d_cond.notify_one(); + } + + d_worker_thread.join(); + } + + volk_gnsssdr_free( d_data_buffer ); } @@ -163,13 +187,18 @@ void pcps_acquisition_sc::set_local_code(std::complex * code) // Here we want to create a buffer that looks like this: // [ 0 0 0 ... 0 c_0 c_1 ... c_L] // where c_i is the local code and there are L zeros and L chips - int offset = 0; + gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler if( d_bit_transition_flag ) { - std::fill_n( d_fft_if->get_inbuf(), d_samples_per_code, gr_complex( 0.0, 0.0 ) ); - offset = d_samples_per_code; + int offset = d_fft_size / 2; + std::fill_n( d_fft_if->get_inbuf(), offset, gr_complex( 0.0, 0.0 ) ); + memcpy(d_fft_if->get_inbuf() + offset, code, sizeof(gr_complex) * offset); } - memcpy(d_fft_if->get_inbuf() + offset, code, sizeof(gr_complex) * d_samples_per_code); + else + { + memcpy(d_fft_if->get_inbuf(), code, sizeof(gr_complex) * d_fft_size); + } + d_fft_if->execute(); // We need the FFT of local code volk_32fc_conjugate_32fc(d_fft_codes, d_fft_if->get_outbuf(), d_fft_size); } @@ -208,12 +237,16 @@ void pcps_acquisition_sc::init() int doppler = -static_cast(d_doppler_max) + d_doppler_step * doppler_index; update_local_carrier(d_grid_doppler_wipeoffs[doppler_index], d_fft_size, d_freq + doppler); } -} + d_new_data_available = false; + d_done = false; + d_worker_active = false; +} void pcps_acquisition_sc::set_state(int state) { + gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler d_state = state; if (d_state == 1) { @@ -233,6 +266,43 @@ void pcps_acquisition_sc::set_state(int state) } } + +void pcps_acquisition_sc::send_positive_acquisition() +{ + // 6.1- Declare positive acquisition using a message port + //0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL + DLOG(INFO) << "positive acquisition" + << ", satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN + << ", sample_stamp " << d_sample_counter + << ", test statistics value " << d_test_statistics + << ", test statistics threshold " << d_threshold + << ", code phase " << d_gnss_synchro->Acq_delay_samples + << ", doppler " << d_gnss_synchro->Acq_doppler_hz + << ", magnitude " << d_mag + << ", input signal power " << d_input_power; + + this->message_port_pub(pmt::mp("events"), pmt::from_long(1)); +} + + +void pcps_acquisition_sc::send_negative_acquisition() +{ + // 6.2- Declare negative acquisition using a message port + //0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL + DLOG(INFO) << "negative acquisition" + << ", satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN + << ", sample_stamp " << d_sample_counter + << ", test statistics value " << d_test_statistics + << ", test statistics threshold " << d_threshold + << ", code phase " << d_gnss_synchro->Acq_delay_samples + << ", doppler " << d_gnss_synchro->Acq_doppler_hz + << ", magnitude " << d_mag + << ", input signal power " << d_input_power; + + this->message_port_pub(pmt::mp("events"), pmt::from_long(2)); +} + + int pcps_acquisition_sc::general_work(int noutput_items, gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items __attribute__((unused))) @@ -248,8 +318,6 @@ int pcps_acquisition_sc::general_work(int noutput_items, * 6. Declare positive or negative acquisition using a message port */ - int acquisition_message = -1; //0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL - switch (d_state) { case 0: @@ -264,42 +332,101 @@ int pcps_acquisition_sc::general_work(int noutput_items, d_mag = 0.0; d_input_power = 0.0; d_test_statistics = 0.0; - d_state = 1; } d_sample_counter += d_fft_size * ninput_items[0]; // sample counter consume_each(ninput_items[0]); - //DLOG(INFO) << "Consumed " << ninput_items[0] << " items"; - break; } case 1: { + std::unique_lock lk( d_mutex ); + + int num_items_consumed = 1; + + if( d_worker_active ) + { + if( d_blocking ) + { + // Should never get here: + std::string msg = "pcps_acquisition_sc: Entered general work with worker active in blocking mode, should never happen"; + LOG(WARNING) << msg; + std::cout << msg << std::endl; + d_cond.wait( lk, [&]{ return !this->d_worker_active; } ); + } + else + { + num_items_consumed = ninput_items[0]; + d_sample_counter += d_fft_size * num_items_consumed; + } + } + else + { + // Copy the data to the core and let it know that new data is available + memcpy( d_data_buffer, input_items[0], d_fft_size * sizeof( lv_16sc_t ) ); + d_new_data_available = true; + d_cond.notify_one(); + + if( d_blocking ) + { + d_cond.wait( lk, [&]{ return !this->d_new_data_available; } ); + + } + } + + consume_each(num_items_consumed); + + break; + } // case 1, switch d_state + + } // switch d_state + + return noutput_items; +} + + +void pcps_acquisition_sc::acquisition_core( void ) +{ + d_worker_active = false; + while( 1 ) + { + std::unique_lock lk( d_mutex ); + d_cond.wait( lk, [&]{ return this->d_new_data_available or this->d_done; } ); + d_worker_active = !d_done; + unsigned long int sample_counter = d_sample_counter; // sample counter + lk.unlock(); + + if( d_done ) + { + break; + } + // initialize acquisition algorithm int doppler; uint32_t indext = 0; float magt = 0.0; - const lv_16sc_t *in = reinterpret_cast(input_items[0]); //Get the input samples pointer + const lv_16sc_t *in = d_data_buffer; //Get the input samples pointer + int effective_fft_size = ( d_bit_transition_flag ? d_fft_size/2 : d_fft_size ); //TODO: optimize the signal processing chain to not use gr_complex. This is a temporary solution - volk_gnsssdr_16ic_convert_32fc(d_in_32fc,in,effective_fft_size); + volk_gnsssdr_16ic_convert_32fc(d_in_32fc, in, effective_fft_size); float fft_normalization_factor = static_cast(d_fft_size) * static_cast(d_fft_size); + d_input_power = 0.0; d_mag = 0.0; - - d_sample_counter += d_fft_size; // sample counter d_well_count++; DLOG(INFO) << "Channel: " << d_channel - << " , doing acquisition of satellite: " << d_gnss_synchro->System << " "<< d_gnss_synchro->PRN - << " ,sample stamp: " << d_sample_counter << ", threshold: " + << " , doing acquisition of satellite: " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN + << " ,sample stamp: " << sample_counter << ", threshold: " << d_threshold << ", doppler_max: " << d_doppler_max - << ", doppler_step: " << d_doppler_step; + << ", doppler_step: " << d_doppler_step + << ", use_CFAR_algorithm_flag: " << ( d_use_CFAR_algorithm_flag ? "true" : "false" ); if (d_use_CFAR_algorithm_flag == true) { @@ -312,7 +439,6 @@ int pcps_acquisition_sc::general_work(int noutput_items, for (unsigned int doppler_index = 0; doppler_index < d_num_doppler_bins; doppler_index++) { // doppler search steps - doppler = -static_cast(d_doppler_max) + d_doppler_step * doppler_index; volk_32fc_x2_multiply_32fc(d_fft_if->get_inbuf(), d_in_32fc, @@ -341,7 +467,6 @@ int pcps_acquisition_sc::general_work(int noutput_items, // Normalize the maximum value to correct the scale factor introduced by FFTW magt = d_magnitude[indext] / (fft_normalization_factor * fft_normalization_factor); } - // 4- record the maximum peak and the associated synchronization parameters if (d_mag < magt) { @@ -366,12 +491,11 @@ int pcps_acquisition_sc::general_work(int noutput_items, { d_gnss_synchro->Acq_delay_samples = static_cast(indext % d_samples_per_code); d_gnss_synchro->Acq_doppler_hz = static_cast(doppler); - d_gnss_synchro->Acq_samplestamp_samples = d_sample_counter; + d_gnss_synchro->Acq_samplestamp_samples = sample_counter; // 5- Compute the test statistics and compare to the threshold + //d_test_statistics = 2 * d_fft_size * d_mag / d_input_power; d_test_statistics = d_mag / d_input_power; - //std::cout<<"d_input_power="<Acq_doppler_hz ="<Acq_doppler_hz <System - <<"_" << d_gnss_synchro->Signal << "_sat_" - << d_gnss_synchro->PRN << "_doppler_" - << doppler - << p.extension().string(); + << boost::filesystem::path::preferred_separator + << p.stem().string() + << "_" << d_gnss_synchro->System + <<"_" << d_gnss_synchro->Signal << "_sat_" + << d_gnss_synchro->PRN << "_doppler_" + << doppler + << p.extension().string(); DLOG(INFO) << "Writing ACQ out to " << filename.str(); @@ -404,11 +528,15 @@ int pcps_acquisition_sc::general_work(int noutput_items, { if (d_test_statistics > d_threshold) { - d_state = 2; // Positive acquisition + d_state = 0; // Positive acquisition + d_active = false; + send_positive_acquisition(); } else if (d_well_count == d_max_dwells) { - d_state = 3; // Negative acquisition + d_state = 0; + d_active = false; + send_negative_acquisition(); } } else @@ -417,71 +545,53 @@ int pcps_acquisition_sc::general_work(int noutput_items, { if (d_test_statistics > d_threshold) { - d_state = 2; // Positive acquisition + d_state = 0; // Positive acquisition + d_active = false; + send_positive_acquisition(); } else { - d_state = 3; // Negative acquisition + d_state = 0; // Negative acquisition + d_active = false; + send_negative_acquisition(); } } } - consume_each(1); - - DLOG(INFO) << "Done. Consumed 1 item."; - - break; + lk.lock(); + d_worker_active = false; + d_new_data_available = false; + lk.unlock(); + d_cond.notify_one(); } - - case 2: - { - // 6.1- Declare positive acquisition using a message port - DLOG(INFO) << "positive acquisition"; - DLOG(INFO) << "satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN; - DLOG(INFO) << "sample_stamp " << d_sample_counter; - DLOG(INFO) << "test statistics value " << d_test_statistics; - DLOG(INFO) << "test statistics threshold " << d_threshold; - DLOG(INFO) << "code phase " << d_gnss_synchro->Acq_delay_samples; - DLOG(INFO) << "doppler " << d_gnss_synchro->Acq_doppler_hz; - DLOG(INFO) << "magnitude " << d_mag; - DLOG(INFO) << "input signal power " << d_input_power; - - d_active = false; - d_state = 0; - - d_sample_counter += d_fft_size * ninput_items[0]; // sample counter - consume_each(ninput_items[0]); - - acquisition_message = 1; - this->message_port_pub(pmt::mp("events"), pmt::from_long(acquisition_message)); - - break; - } - - case 3: - { - // 6.2- Declare negative acquisition using a message port - DLOG(INFO) << "negative acquisition"; - DLOG(INFO) << "satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN; - DLOG(INFO) << "sample_stamp " << d_sample_counter; - DLOG(INFO) << "test statistics value " << d_test_statistics; - DLOG(INFO) << "test statistics threshold " << d_threshold; - DLOG(INFO) << "code phase " << d_gnss_synchro->Acq_delay_samples; - DLOG(INFO) << "doppler " << d_gnss_synchro->Acq_doppler_hz; - DLOG(INFO) << "magnitude " << d_mag; - DLOG(INFO) << "input signal power " << d_input_power; - - d_active = false; - d_state = 0; - - d_sample_counter += d_fft_size * ninput_items[0]; // sample counter - consume_each(ninput_items[0]); - acquisition_message = 2; - this->message_port_pub(pmt::mp("events"), pmt::from_long(acquisition_message)); - - break; - } - } - - return noutput_items; } + + +bool pcps_acquisition_sc::start( void ) +{ + d_worker_active = false; + d_done = false; + + // Start the worker thread and wait for it to acknowledge: + d_worker_thread = std::move( std::thread( &pcps_acquisition_sc::acquisition_core, this ) ); + + return gr::block::start(); +} + + +bool pcps_acquisition_sc::stop( void ) +{ + // Let the worker thread know that we are done and then wait to join + if( d_worker_thread.joinable() ) + { + { + std::lock_guard lk( d_mutex ); + d_done = true; + d_cond.notify_one(); + } + + d_worker_thread.join(); + } + return gr::block::stop(); +} + diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_sc.h b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_sc.h index 1b3ab7bf6..7474b910b 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_sc.h +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_sc.h @@ -20,11 +20,12 @@ *
  • Javier Arribas, 2011. jarribas(at)cttc.es *
  • Luis Esteve, 2012. luis(at)epsilon-formacion.com *
  • Marc Molina, 2013. marc.molina.pena@gmail.com + *
  • Cillian O'Driscoll, 2017. cillian(at)ieee.org * * * ------------------------------------------------------------------------- * - * Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors) + * Copyright (C) 2010-2017 (see AUTHORS file for a list of contributors) * * GNSS-SDR is a software defined Global Navigation * Satellite Systems receiver @@ -52,11 +53,16 @@ #include #include +#include +#include +#include #include #include #include +#include #include "gnss_synchro.h" + class pcps_acquisition_sc; typedef boost::shared_ptr pcps_acquisition_sc_sptr; @@ -66,7 +72,7 @@ pcps_make_acquisition_sc(unsigned int sampled_ms, unsigned int max_dwells, unsigned int doppler_max, long freq, long fs_in, int samples_per_ms, int samples_per_code, bool bit_transition_flag, bool use_CFAR_algorithm_flag, - bool dump, + bool dump, bool blocking, std::string dump_filename); /*! @@ -83,20 +89,22 @@ private: unsigned int doppler_max, long freq, long fs_in, int samples_per_ms, int samples_per_code, bool bit_transition_flag, bool use_CFAR_algorithm_flag, - bool dump, + bool dump, bool blocking, std::string dump_filename); pcps_acquisition_sc(unsigned int sampled_ms, unsigned int max_dwells, unsigned int doppler_max, long freq, long fs_in, int samples_per_ms, int samples_per_code, bool bit_transition_flag, bool use_CFAR_algorithm_flag, - bool dump, + bool dump, bool blocking, std::string dump_filename); - void update_local_carrier(gr_complex* carrier_vector, - int correlator_length_samples, - float freq); + void update_local_carrier(gr_complex* carrier_vector, int correlator_length_samples, float freq); + void acquisition_core( void ); + + void send_negative_acquisition(); + void send_positive_acquisition(); long d_fs_in; long d_freq; int d_samples_per_ms; @@ -133,6 +141,17 @@ private: unsigned int d_channel; std::string d_dump_filename; + std::thread d_worker_thread; + std::mutex d_mutex; + + std::condition_variable d_cond; + bool d_done; + bool d_new_data_available; + bool d_worker_active; + bool d_blocking; + + lv_16sc_t *d_data_buffer; + public: /*! * \brief Default destructor. @@ -146,6 +165,7 @@ public: */ inline void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) { + gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler d_gnss_synchro = p_gnss_synchro; } @@ -175,6 +195,7 @@ public: */ inline void set_active(bool active) { + gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler d_active = active; } @@ -191,6 +212,7 @@ public: */ inline void set_channel(unsigned int channel) { + gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler d_channel = channel; } @@ -201,6 +223,7 @@ public: */ inline void set_threshold(float threshold) { + gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler d_threshold = threshold; } @@ -210,6 +233,7 @@ public: */ inline void set_doppler_max(unsigned int doppler_max) { + gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler d_doppler_max = doppler_max; } @@ -219,6 +243,7 @@ public: */ inline void set_doppler_step(unsigned int doppler_step) { + gr::thread::scoped_lock lock(d_setlock); // require mutex with work function called by the scheduler d_doppler_step = doppler_step; } @@ -228,6 +253,16 @@ public: int general_work(int noutput_items, gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items); + + /*! + * Called by the flowgraph when processing is about to start. + */ + bool start( void ); + + /*! + * Called by the flowgraph when processing is done. + */ + bool stop( void ); }; #endif /* GNSS_SDR_PCPS_ACQUISITION_SC_H_*/ diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_multithread_acquisition_cc.cc b/src/algorithms/acquisition/gnuradio_blocks/pcps_multithread_acquisition_cc.cc deleted file mode 100644 index 0dcbbc070..000000000 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_multithread_acquisition_cc.cc +++ /dev/null @@ -1,478 +0,0 @@ -/*! - * \file pcps_multithread_acquisition_cc.cc - * \brief This class implements a Parallel Code Phase Search Acquisition - * \authors
      - *
    • Javier Arribas, 2011. jarribas(at)cttc.es - *
    • Luis Esteve, 2012. luis(at)epsilon-formacion.com - *
    • Marc Molina, 2013. marc.molina.pena@gmail.com - *
    - * - * ------------------------------------------------------------------------- - * - * Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors) - * - * GNSS-SDR is a software defined Global Navigation - * Satellite Systems receiver - * - * This file is part of GNSS-SDR. - * - * GNSS-SDR is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GNSS-SDR is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNSS-SDR. If not, see . - * - * ------------------------------------------------------------------------- - */ - -#include "pcps_multithread_acquisition_cc.h" -#include -#include -#include -#include -#include -#include -#include -#include "control_message_factory.h" -#include "GPS_L1_CA.h" //GPS_TWO_PI - -using google::LogMessage; - -pcps_multithread_acquisition_cc_sptr pcps_make_multithread_acquisition_cc( - unsigned int sampled_ms, unsigned int max_dwells, - unsigned int doppler_max, long freq, long fs_in, - int samples_per_ms, int samples_per_code, - bool bit_transition_flag, - bool dump, - std::string dump_filename) -{ - - return pcps_multithread_acquisition_cc_sptr( - new pcps_multithread_acquisition_cc(sampled_ms, max_dwells, doppler_max, freq, fs_in, samples_per_ms, - samples_per_code, bit_transition_flag, dump, dump_filename)); -} - -pcps_multithread_acquisition_cc::pcps_multithread_acquisition_cc( - unsigned int sampled_ms, unsigned int max_dwells, - unsigned int doppler_max, long freq, long fs_in, - int samples_per_ms, int samples_per_code, - bool bit_transition_flag, - bool dump, - std::string dump_filename) : - gr::block("pcps_multithread_acquisition_cc", - gr::io_signature::make(1, 1, sizeof(gr_complex) * sampled_ms * samples_per_ms), - gr::io_signature::make(0, 0, sizeof(gr_complex) * sampled_ms * samples_per_ms)) -{ - this->message_port_register_out(pmt::mp("events")); - d_sample_counter = 0; // SAMPLE COUNTER - d_active = false; - d_state = 0; - d_core_working = false; - d_freq = freq; - d_fs_in = fs_in; - d_samples_per_ms = samples_per_ms; - d_samples_per_code = samples_per_code; - d_sampled_ms = sampled_ms; - d_max_dwells = max_dwells; - d_well_count = 0; - d_doppler_max = doppler_max; - d_fft_size = d_sampled_ms * d_samples_per_ms; - d_mag = 0; - d_input_power = 0.0; - d_num_doppler_bins = 0; - d_bit_transition_flag = bit_transition_flag; - d_in_dwell_count = 0; - - d_in_buffer = new gr_complex*[d_max_dwells]; - - //todo: do something if posix_memalign fails - for (unsigned int i = 0; i < d_max_dwells; i++) - { - d_in_buffer[i] = static_cast(volk_malloc(d_fft_size * sizeof(gr_complex), volk_get_alignment())); - } - d_fft_codes = static_cast(volk_malloc(d_fft_size * sizeof(gr_complex), volk_get_alignment())); - d_magnitude = static_cast(volk_malloc(d_fft_size * sizeof(float), volk_get_alignment())); - - // Direct FFT - d_fft_if = new gr::fft::fft_complex(d_fft_size, true); - - // Inverse FFT - d_ifft = new gr::fft::fft_complex(d_fft_size, false); - - // For dumping samples into a file - d_dump = dump; - d_dump_filename = dump_filename; - - d_doppler_resolution = 0; - d_threshold = 0; - d_doppler_step = 0; - d_grid_doppler_wipeoffs = 0; - d_gnss_synchro = 0; - d_code_phase = 0; - d_doppler_freq = 0; - d_test_statistics = 0; - d_channel = 0; -} - -pcps_multithread_acquisition_cc::~pcps_multithread_acquisition_cc() -{ - if (d_num_doppler_bins > 0) - { - for (unsigned int i = 0; i < d_num_doppler_bins; i++) - { - volk_free(d_grid_doppler_wipeoffs[i]); - } - delete[] d_grid_doppler_wipeoffs; - } - - for (unsigned int i = 0; i < d_max_dwells; i++) - { - volk_free(d_in_buffer[i]); - } - delete[] d_in_buffer; - - volk_free(d_fft_codes); - volk_free(d_magnitude); - - delete d_ifft; - delete d_fft_if; - - if (d_dump) - { - d_dump_file.close(); - } -} - -void pcps_multithread_acquisition_cc::init() -{ - d_gnss_synchro->Flag_valid_acquisition = false; - d_gnss_synchro->Flag_valid_symbol_output = false; - d_gnss_synchro->Flag_valid_pseudorange = false; - d_gnss_synchro->Flag_valid_word = false; - - d_gnss_synchro->Acq_delay_samples = 0.0; - d_gnss_synchro->Acq_doppler_hz = 0.0; - d_gnss_synchro->Acq_samplestamp_samples = 0; - d_mag = 0.0; - d_input_power = 0.0; - - // Count the number of bins - d_num_doppler_bins = 0; - for (int doppler = static_cast(-d_doppler_max); - doppler <= static_cast(d_doppler_max); - doppler += d_doppler_step) - { - d_num_doppler_bins++; - } - - // Create the carrier Doppler wipeoff signals - d_grid_doppler_wipeoffs = new gr_complex*[d_num_doppler_bins]; - for (unsigned int doppler_index = 0; doppler_index < d_num_doppler_bins; doppler_index++) - { - d_grid_doppler_wipeoffs[doppler_index] = static_cast(volk_malloc(d_fft_size * sizeof(gr_complex), volk_get_alignment())); - int doppler = -static_cast(d_doppler_max) + d_doppler_step * doppler_index; - float phase_step_rad = static_cast(GPS_TWO_PI) * (d_freq + doppler) / static_cast(d_fs_in); - float _phase[1]; - _phase[0] = 0; - volk_gnsssdr_s32f_sincos_32fc(d_grid_doppler_wipeoffs[doppler_index], - phase_step_rad, _phase, d_fft_size); - } -} - -void pcps_multithread_acquisition_cc::set_local_code(std::complex * code) -{ - memcpy(d_fft_if->get_inbuf(), code, sizeof(gr_complex)*d_fft_size); - - d_fft_if->execute(); // We need the FFT of local code - - //Conjugate the local code - volk_32fc_conjugate_32fc(d_fft_codes, d_fft_if->get_outbuf(), d_fft_size); -} - -void pcps_multithread_acquisition_cc::acquisition_core() -{ - // initialize acquisition algorithm - int doppler; - uint32_t indext = 0; - float magt = 0.0; - float fft_normalization_factor = static_cast(d_fft_size) * static_cast(d_fft_size); - gr_complex* in = d_in_buffer[d_well_count]; - unsigned long int samplestamp = d_sample_counter_buffer[d_well_count]; - - d_input_power = 0.0; - d_mag = 0.0; - - d_well_count++; - - DLOG(INFO) << "Channel: " << d_channel - << " , doing acquisition of satellite: " << d_gnss_synchro->System << " "<< d_gnss_synchro->PRN - << " ,sample stamp: " << d_sample_counter << ", threshold: " - << d_threshold << ", doppler_max: " << d_doppler_max - << ", doppler_step: " << d_doppler_step; - - // 1- Compute the input signal power estimation - volk_32fc_magnitude_squared_32f(d_magnitude, in, d_fft_size); - volk_32f_accumulator_s32f(&d_input_power, d_magnitude, d_fft_size); - d_input_power /= static_cast(d_fft_size); - - // 2- Doppler frequency search loop - for (unsigned int doppler_index = 0; doppler_index < d_num_doppler_bins; doppler_index++) - { - // doppler search steps - - doppler = -static_cast(d_doppler_max) + d_doppler_step * doppler_index; - - volk_32fc_x2_multiply_32fc(d_fft_if->get_inbuf(), in, - d_grid_doppler_wipeoffs[doppler_index], d_fft_size); - - // 3- Perform the FFT-based convolution (parallel time search) - // Compute the FFT of the carrier wiped--off incoming signal - d_fft_if->execute(); - - // Multiply carrier wiped--off, Fourier transformed incoming signal - // with the local FFT'd code reference using SIMD operations with VOLK library - volk_32fc_x2_multiply_32fc(d_ifft->get_inbuf(), - d_fft_if->get_outbuf(), d_fft_codes, d_fft_size); - - // compute the inverse FFT - d_ifft->execute(); - - // Search maximum - volk_32fc_magnitude_squared_32f(d_magnitude, d_ifft->get_outbuf(), d_fft_size); - volk_gnsssdr_32f_index_max_32u(&indext, d_magnitude, d_fft_size); - - // Normalize the maximum value to correct the scale factor introduced by FFTW - magt = d_magnitude[indext] / (fft_normalization_factor * fft_normalization_factor); - - // 4- record the maximum peak and the associated synchronization parameters - if (d_mag < magt) - { - d_mag = magt; - - // In case that d_bit_transition_flag = true, we compare the potentially - // new maximum test statistics (d_mag/d_input_power) with the value in - // d_test_statistics. When the second dwell is being processed, the value - // of d_mag/d_input_power could be lower than d_test_statistics (i.e, - // the maximum test statistics in the previous dwell is greater than - // current d_mag/d_input_power). Note that d_test_statistics is not - // restarted between consecutive dwells in multidwell operation. - if (d_test_statistics < (d_mag / d_input_power) || !d_bit_transition_flag) - { - d_gnss_synchro->Acq_delay_samples = static_cast(indext % d_samples_per_code); - d_gnss_synchro->Acq_doppler_hz = static_cast(doppler); - d_gnss_synchro->Acq_samplestamp_samples = samplestamp; - - // 5- Compute the test statistics and compare to the threshold - //d_test_statistics = 2 * d_fft_size * d_mag / d_input_power; - d_test_statistics = d_mag / d_input_power; - } - } - - // Record results to file if required - if (d_dump) - { - std::stringstream filename; - std::streamsize n = 2 * sizeof(float) * (d_fft_size); // complex file write - filename.str(""); - filename << "../data/test_statistics_" << d_gnss_synchro->System - <<"_" << d_gnss_synchro->Signal << "_sat_" - << d_gnss_synchro->PRN << "_doppler_" << doppler << ".dat"; - d_dump_file.open(filename.str().c_str(), std::ios::out | std::ios::binary); - d_dump_file.write(reinterpret_cast(d_ifft->get_outbuf()), n); //write directly |abs(x)|^2 in this Doppler bin? - d_dump_file.close(); - } - } - - if (!d_bit_transition_flag) - { - if (d_test_statistics > d_threshold) - { - d_state = 2; // Positive acquisition - } - else if (d_well_count == d_max_dwells) - { - d_state = 3; // Negative acquisition - } - } - else - { - if (d_well_count == d_max_dwells) // d_max_dwells = 2 - { - if (d_test_statistics > d_threshold) - { - d_state = 2; // Positive acquisition - } - else - { - d_state = 3; // Negative acquisition - } - } - } - - d_core_working = false; -} - - - -void pcps_multithread_acquisition_cc::set_state(int state) -{ - d_state = state; - if (d_state == 1) - { - d_gnss_synchro->Acq_delay_samples = 0.0; - d_gnss_synchro->Acq_doppler_hz = 0.0; - d_gnss_synchro->Acq_samplestamp_samples = 0; - d_well_count = 0; - d_mag = 0.0; - d_input_power = 0.0; - d_test_statistics = 0.0; - d_in_dwell_count = 0; - d_sample_counter_buffer.clear(); - } - else if (d_state == 0) - {} - else - { - LOG(ERROR) << "State can only be set to 0 or 1"; - } -} - - - -int pcps_multithread_acquisition_cc::general_work(int noutput_items, - gr_vector_int &ninput_items, gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items __attribute__((unused))) -{ - - int acquisition_message = -1; //0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL - - switch (d_state) - { - case 0: - { - if (d_active) - { - //restart acquisition variables - d_gnss_synchro->Acq_delay_samples = 0.0; - d_gnss_synchro->Acq_doppler_hz = 0.0; - d_gnss_synchro->Acq_samplestamp_samples = 0; - d_well_count = 0; - d_mag = 0.0; - d_input_power = 0.0; - d_test_statistics = 0.0; - d_in_dwell_count = 0; - d_sample_counter_buffer.clear(); - - d_state = 1; - } - - d_sample_counter += d_fft_size * ninput_items[0]; // sample counter - - break; - } - - case 1: - { - if (d_in_dwell_count < d_max_dwells) - { - // Fill internal buffer with d_max_dwells signal blocks. This step ensures that - // consecutive signal blocks will be processed in multi-dwell operation. This is - // essential when d_bit_transition_flag = true. - unsigned int num_dwells = std::min(static_cast(d_max_dwells - d_in_dwell_count), ninput_items[0]); - for (unsigned int i = 0; i < num_dwells; i++) - { - memcpy(d_in_buffer[d_in_dwell_count++], reinterpret_cast(input_items[i]), - sizeof(gr_complex)*d_fft_size); - d_sample_counter += d_fft_size; - d_sample_counter_buffer.push_back(d_sample_counter); - } - - if (ninput_items[0] > static_cast(num_dwells)) - { - d_sample_counter += d_fft_size * (ninput_items[0] - num_dwells); - } - } - else - { - // We already have d_max_dwells consecutive blocks in the internal buffer, - // just skip input blocks. - d_sample_counter += d_fft_size * ninput_items[0]; - } - - // We create a new thread to process next block if the following - // conditions are fulfilled: - // 1. There are new blocks in d_in_buffer that have not been processed yet - // (d_well_count < d_in_dwell_count). - // 2. No other acquisition_core thead is working (!d_core_working). - // 3. d_state==1. We need to check again d_state because it can be modified at any - // moment by the external thread (may have changed since checked in the switch()). - // If the external thread has already declared positive (d_state=2) or negative - // (d_state=3) acquisition, we don't have to process next block!! - if ((d_well_count < d_in_dwell_count) && !d_core_working && d_state==1) - { - d_core_working = true; - boost::thread(&pcps_multithread_acquisition_cc::acquisition_core, this); - } - - break; - } - - case 2: - { - // Declare positive acquisition using a message port - DLOG(INFO) << "positive acquisition"; - DLOG(INFO) << "satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN; - DLOG(INFO) << "sample_stamp " << d_sample_counter; - DLOG(INFO) << "test statistics value " << d_test_statistics; - DLOG(INFO) << "test statistics threshold " << d_threshold; - DLOG(INFO) << "code phase " << d_gnss_synchro->Acq_delay_samples; - DLOG(INFO) << "doppler " << d_gnss_synchro->Acq_doppler_hz; - DLOG(INFO) << "magnitude " << d_mag; - DLOG(INFO) << "input signal power " << d_input_power; - - d_active = false; - d_state = 0; - - d_sample_counter += d_fft_size * ninput_items[0]; // sample counter - - acquisition_message = 1; - this->message_port_pub(pmt::mp("events"), pmt::from_long(acquisition_message)); - - break; - } - - case 3: - { - // Declare negative acquisition using a message port - DLOG(INFO) << "negative acquisition"; - DLOG(INFO) << "satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN; - DLOG(INFO) << "sample_stamp " << d_sample_counter; - DLOG(INFO) << "test statistics value " << d_test_statistics; - DLOG(INFO) << "test statistics threshold " << d_threshold; - DLOG(INFO) << "code phase " << d_gnss_synchro->Acq_delay_samples; - DLOG(INFO) << "doppler " << d_gnss_synchro->Acq_doppler_hz; - DLOG(INFO) << "magnitude " << d_mag; - DLOG(INFO) << "input signal power " << d_input_power; - - d_active = false; - d_state = 0; - - d_sample_counter += d_fft_size * ninput_items[0]; // sample counter - - acquisition_message = 2; - this->message_port_pub(pmt::mp("events"), pmt::from_long(acquisition_message)); - - break; - } - } - - consume_each(ninput_items[0]); - - return noutput_items; -} diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_multithread_acquisition_cc.h b/src/algorithms/acquisition/gnuradio_blocks/pcps_multithread_acquisition_cc.h deleted file mode 100644 index d0f5af944..000000000 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_multithread_acquisition_cc.h +++ /dev/null @@ -1,239 +0,0 @@ -/*! - * \file pcps_multithread_acquisition_cc.h - * \brief This class implements a Parallel Code Phase Search Acquisition - * - * Acquisition strategy (Kay Borre book + CFAR threshold). - *
      - *
    1. Compute the input signal power estimation - *
    2. Doppler serial search loop - *
    3. Perform the FFT-based circular convolution (parallel time search) - *
    4. Record the maximum peak and the associated synchronization parameters - *
    5. Compute the test statistics and compare to the threshold - *
    6. Declare positive or negative acquisition using a message port - *
    - * - * Kay Borre book: K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen, - * "A Software-Defined GPS and Galileo Receiver. A Single-Frequency - * Approach", Birkha user, 2007. pp 81-84 - * - * \authors
      - *
    • Javier Arribas, 2011. jarribas(at)cttc.es - *
    • Luis Esteve, 2012. luis(at)epsilon-formacion.com - *
    • Marc Molina, 2013. marc.molina.pena@gmail.com - *
    - * - * ------------------------------------------------------------------------- - * - * Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors) - * - * GNSS-SDR is a software defined Global Navigation - * Satellite Systems receiver - * - * This file is part of GNSS-SDR. - * - * GNSS-SDR is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GNSS-SDR is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNSS-SDR. If not, see . - * - * ------------------------------------------------------------------------- - */ - -#ifndef GNSS_SDR_PCPS_MULTITHREAD_ACQUISITION_CC_H_ -#define GNSS_SDR_PCPS_MULTITHREAD_ACQUISITION_CC_H_ - -#include -#include -#include -#include -#include -#include -#include -#include "gnss_synchro.h" - -class pcps_multithread_acquisition_cc; - -typedef boost::shared_ptr pcps_multithread_acquisition_cc_sptr; - -pcps_multithread_acquisition_cc_sptr -pcps_make_multithread_acquisition_cc(unsigned int sampled_ms, unsigned int max_dwells, - unsigned int doppler_max, long freq, long fs_in, - int samples_per_ms, int samples_per_code, - bool bit_transition_flag, - bool dump, - std::string dump_filename); - -/*! - * \brief This class implements a Parallel Code Phase Search Acquisition. - * - * Check \ref Navitec2012 "An Open Source Galileo E1 Software Receiver", - * Algorithm 1, for a pseudocode description of this implementation. - */ -class pcps_multithread_acquisition_cc: public gr::block -{ -private: - friend pcps_multithread_acquisition_cc_sptr - pcps_make_multithread_acquisition_cc(unsigned int sampled_ms, unsigned int max_dwells, - unsigned int doppler_max, long freq, long fs_in, - int samples_per_ms, int samples_per_code, - bool bit_transition_flag, - bool dump, - std::string dump_filename); - - - pcps_multithread_acquisition_cc(unsigned int sampled_ms, unsigned int max_dwells, - unsigned int doppler_max, long freq, long fs_in, - int samples_per_ms, int samples_per_code, - bool bit_transition_flag, - bool dump, - std::string dump_filename); - - void calculate_magnitudes(gr_complex* fft_begin, int doppler_shift, - int doppler_offset); - - long d_fs_in; - long d_freq; - int d_samples_per_ms; - int d_samples_per_code; - unsigned int d_doppler_resolution; - float d_threshold; - std::string d_satellite_str; - unsigned int d_doppler_max; - unsigned int d_doppler_step; - unsigned int d_sampled_ms; - unsigned int d_max_dwells; - unsigned int d_well_count; - unsigned int d_fft_size; - unsigned long int d_sample_counter; - gr_complex** d_grid_doppler_wipeoffs; - unsigned int d_num_doppler_bins; - gr_complex* d_fft_codes; - gr::fft::fft_complex* d_fft_if; - gr::fft::fft_complex* d_ifft; - Gnss_Synchro *d_gnss_synchro; - unsigned int d_code_phase; - float d_doppler_freq; - float d_mag; - float* d_magnitude; - float d_input_power; - float d_test_statistics; - bool d_bit_transition_flag; - std::ofstream d_dump_file; - bool d_active; - int d_state; - bool d_core_working; - bool d_dump; - unsigned int d_channel; - std::string d_dump_filename; - gr_complex** d_in_buffer; - std::vector d_sample_counter_buffer; - unsigned int d_in_dwell_count; - -public: - /*! - * \brief Default destructor. - */ - ~pcps_multithread_acquisition_cc(); - - /*! - * \brief Set acquisition/tracking common Gnss_Synchro object pointer - * to exchange synchronization data between acquisition and tracking blocks. - * \param p_gnss_synchro Satellite information shared by the processing blocks. - */ - inline void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) - { - d_gnss_synchro = p_gnss_synchro; - } - - /*! - * \brief Returns the maximum peak of grid search. - */ - inline unsigned int mag() const - { - return d_mag; - } - - /*! - * \brief Initializes acquisition algorithm. - */ - void init(); - - /*! - * \brief Sets local code for PCPS acquisition algorithm. - * \param code - Pointer to the PRN code. - */ - void set_local_code(std::complex * code); - - /*! - * \brief Starts acquisition algorithm, turning from standby mode to - * active mode - * \param active - bool that activates/deactivates the block. - */ - inline void set_active(bool active) - { - d_active = active; - } - - /*! - * \brief If set to 1, ensures that acquisition starts at the - * first available sample. - * \param state - int=1 forces start of acquisition - */ - void set_state(int state); - - /*! - * \brief Set acquisition channel unique ID - * \param channel - receiver channel. - */ - inline void set_channel(unsigned int channel) - { - d_channel = channel; - } - - /*! - * \brief Set statistics threshold of PCPS algorithm. - * \param threshold - Threshold for signal detection (check \ref Navitec2012, - * Algorithm 1, for a definition of this threshold). - */ - void set_threshold(float threshold) - { - d_threshold = threshold; - } - - /*! - * \brief Set maximum Doppler grid search - * \param doppler_max - Maximum Doppler shift considered in the grid search [Hz]. - */ - inline void set_doppler_max(unsigned int doppler_max) - { - d_doppler_max = doppler_max; - } - - /*! - * \brief Set Doppler steps for the grid search - * \param doppler_step - Frequency bin of the search grid [Hz]. - */ - inline void set_doppler_step(unsigned int doppler_step) - { - d_doppler_step = doppler_step; - } - - /*! - * \brief Parallel Code Phase Search Acquisition signal processing. - */ - int general_work(int noutput_items, gr_vector_int &ninput_items, - gr_vector_const_void_star &input_items, - gr_vector_void_star &output_items); - - void acquisition_core(); -}; - -#endif /* GNSS_SDR_PCPS_MULTITHREAD_ACQUISITION_CC_H_*/ diff --git a/src/core/receiver/gnss_block_factory.cc b/src/core/receiver/gnss_block_factory.cc index 0e85d4f2d..0bac3cbee 100644 --- a/src/core/receiver/gnss_block_factory.cc +++ b/src/core/receiver/gnss_block_factory.cc @@ -67,7 +67,6 @@ #include "pulse_blanking_filter.h" #include "gps_l1_ca_pcps_acquisition.h" #include "gps_l2_m_pcps_acquisition.h" -#include "gps_l1_ca_pcps_multithread_acquisition.h" #include "gps_l1_ca_pcps_tong_acquisition.h" #include "gps_l1_ca_pcps_assisted_acquisition.h" #include "gps_l1_ca_pcps_acquisition_fine_doppler.h" @@ -920,12 +919,6 @@ std::unique_ptr GNSSBlockFactory::GetBlock( out_streams)); block = std::move(block_); } - else if (implementation.compare("GPS_L1_CA_PCPS_Multithread_Acquisition") == 0) - { - std::unique_ptr block_(new GpsL1CaPcpsMultithreadAcquisition(configuration.get(), role, in_streams, - out_streams)); - block = std::move(block_); - } #if OPENCL_BLOCKS else if (implementation.compare("GPS_L1_CA_PCPS_OpenCl_Acquisition") == 0) @@ -1146,12 +1139,6 @@ std::unique_ptr GNSSBlockFactory::GetAcqBlock( out_streams)); block = std::move(block_); } - else if (implementation.compare("GPS_L1_CA_PCPS_Multithread_Acquisition") == 0) - { - std::unique_ptr block_(new GpsL1CaPcpsMultithreadAcquisition(configuration.get(), role, in_streams, - out_streams)); - block = std::move(block_); - } #if OPENCL_BLOCKS else if (implementation.compare("GPS_L1_CA_PCPS_OpenCl_Acquisition") == 0) diff --git a/src/tests/test_main.cc b/src/tests/test_main.cc index bae669086..36662fb67 100644 --- a/src/tests/test_main.cc +++ b/src/tests/test_main.cc @@ -101,7 +101,7 @@ DECLARE_string(log_dir); #include "unit-tests/signal-processing-blocks/acquisition/galileo_e1_pcps_cccwsr_ambiguous_acquisition_gsoc2013_test.cc" #include "unit-tests/signal-processing-blocks/acquisition/galileo_e1_pcps_quicksync_ambiguous_acquisition_gsoc2014_test.cc" #include "unit-tests/signal-processing-blocks/acquisition/galileo_e5a_pcps_acquisition_gsoc2014_gensource_test.cc" -//#include "unit-tests/signal-processing-blocks/acquisition/gps_l1_ca_pcps_multithread_acquisition_gsoc2013_test.cc" + #if OPENCL_BLOCKS_TEST #include "unit-tests/signal-processing-blocks/acquisition/gps_l1_ca_pcps_opencl_acquisition_gsoc2013_test.cc" #endif diff --git a/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_ca_pcps_acquisition_test.cc b/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_ca_pcps_acquisition_test.cc index ff897256f..76aedce64 100644 --- a/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_ca_pcps_acquisition_test.cc +++ b/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_ca_pcps_acquisition_test.cc @@ -40,7 +40,9 @@ #include #include #include +#include #include +#include "gnss_block_factory.h" #include "gnss_block_interface.h" #include "in_memory_configuration.h" #include "gnss_sdr_valve.h" @@ -53,24 +55,23 @@ class GpsL1CaPcpsAcquisitionTest_msg_rx; typedef boost::shared_ptr GpsL1CaPcpsAcquisitionTest_msg_rx_sptr; -GpsL1CaPcpsAcquisitionTest_msg_rx_sptr GpsL1CaPcpsAcquisitionTest_msg_rx_make(concurrent_queue& queue); +GpsL1CaPcpsAcquisitionTest_msg_rx_sptr GpsL1CaPcpsAcquisitionTest_msg_rx_make(); class GpsL1CaPcpsAcquisitionTest_msg_rx : public gr::block { private: - friend GpsL1CaPcpsAcquisitionTest_msg_rx_sptr GpsL1CaPcpsAcquisitionTest_msg_rx_make(concurrent_queue& queue); + friend GpsL1CaPcpsAcquisitionTest_msg_rx_sptr GpsL1CaPcpsAcquisitionTest_msg_rx_make(); void msg_handler_events(pmt::pmt_t msg); - GpsL1CaPcpsAcquisitionTest_msg_rx(concurrent_queue& queue); - concurrent_queue& channel_internal_queue; + GpsL1CaPcpsAcquisitionTest_msg_rx(); public: int rx_message; ~GpsL1CaPcpsAcquisitionTest_msg_rx(); //!< Default destructor }; -GpsL1CaPcpsAcquisitionTest_msg_rx_sptr GpsL1CaPcpsAcquisitionTest_msg_rx_make(concurrent_queue& queue) +GpsL1CaPcpsAcquisitionTest_msg_rx_sptr GpsL1CaPcpsAcquisitionTest_msg_rx_make() { - return GpsL1CaPcpsAcquisitionTest_msg_rx_sptr(new GpsL1CaPcpsAcquisitionTest_msg_rx(queue)); + return GpsL1CaPcpsAcquisitionTest_msg_rx_sptr(new GpsL1CaPcpsAcquisitionTest_msg_rx()); } @@ -80,7 +81,6 @@ void GpsL1CaPcpsAcquisitionTest_msg_rx::msg_handler_events(pmt::pmt_t msg) { long int message = pmt::to_long(msg); rx_message = message; - channel_internal_queue.push(rx_message); } catch(boost::bad_any_cast& e) { @@ -90,8 +90,8 @@ void GpsL1CaPcpsAcquisitionTest_msg_rx::msg_handler_events(pmt::pmt_t msg) } -GpsL1CaPcpsAcquisitionTest_msg_rx::GpsL1CaPcpsAcquisitionTest_msg_rx(concurrent_queue& queue) : - gr::block("GpsL1CaPcpsAcquisitionTest_msg_rx", gr::io_signature::make(0, 0, 0), gr::io_signature::make(0, 0, 0)), channel_internal_queue(queue) +GpsL1CaPcpsAcquisitionTest_msg_rx::GpsL1CaPcpsAcquisitionTest_msg_rx() : + gr::block("GpsL1CaPcpsAcquisitionTest_msg_rx", gr::io_signature::make(0, 0, 0), gr::io_signature::make(0, 0, 0)) { this->message_port_register_in(pmt::mp("events")); this->set_msg_handler(pmt::mp("events"), boost::bind(&GpsL1CaPcpsAcquisitionTest_msg_rx::msg_handler_events, this, _1)); @@ -110,68 +110,25 @@ class GpsL1CaPcpsAcquisitionTest: public ::testing::Test protected: GpsL1CaPcpsAcquisitionTest() { + factory = std::make_shared(); config = std::make_shared(); item_size = sizeof(gr_complex); gnss_synchro = Gnss_Synchro(); - stop = false; - message = 0; - acquisition = 0; } ~GpsL1CaPcpsAcquisitionTest() {} void init(); - void start_queue(); - void wait_message(); - void process_message(); - void stop_queue(); - concurrent_queue channel_internal_queue; gr::top_block_sptr top_block; - std::shared_ptr acquisition; + std::shared_ptr factory; std::shared_ptr config; Gnss_Synchro gnss_synchro; size_t item_size; - bool stop; - int message; - boost::thread ch_thread; }; -void GpsL1CaPcpsAcquisitionTest::start_queue() -{ - stop = false; - ch_thread = boost::thread(&GpsL1CaPcpsAcquisitionTest::wait_message, this); -} - - -void GpsL1CaPcpsAcquisitionTest::wait_message() -{ - while (!stop) - { - acquisition->reset(); - - channel_internal_queue.wait_and_pop(message); - - process_message(); - } -} - - -void GpsL1CaPcpsAcquisitionTest::process_message() -{ - stop_queue(); - top_block->stop(); -} - - -void GpsL1CaPcpsAcquisitionTest::stop_queue() -{ - stop = true; -} - - void GpsL1CaPcpsAcquisitionTest::init() { gnss_synchro.Channel_ID = 0; @@ -210,8 +167,8 @@ TEST_F(GpsL1CaPcpsAcquisitionTest, ConnectAndRun) top_block = gr::make_top_block("Acquisition test"); init(); - acquisition = std::make_shared(config.get(), "Acquisition", 1, 1); - boost::shared_ptr msg_rx = GpsL1CaPcpsAcquisitionTest_msg_rx_make(channel_internal_queue); + boost::shared_ptr acquisition = boost::make_shared(config.get(), "Acquisition", 1, 1); + boost::shared_ptr msg_rx = GpsL1CaPcpsAcquisitionTest_msg_rx_make(); ASSERT_NO_THROW( { acquisition->connect(top_block); @@ -245,8 +202,8 @@ TEST_F(GpsL1CaPcpsAcquisitionTest, ValidationOfResults) init(); - acquisition = std::make_shared(config.get(), "Acquisition", 1, 1); - boost::shared_ptr msg_rx = GpsL1CaPcpsAcquisitionTest_msg_rx_make(channel_internal_queue); + std::shared_ptr acquisition = std::make_shared(config.get(), "Acquisition", 1, 1); + boost::shared_ptr msg_rx = GpsL1CaPcpsAcquisitionTest_msg_rx_make(); ASSERT_NO_THROW( { acquisition->set_channel(1); @@ -257,7 +214,7 @@ TEST_F(GpsL1CaPcpsAcquisitionTest, ValidationOfResults) }) << "Failure setting gnss_synchro." << std::endl; ASSERT_NO_THROW( { - acquisition->set_threshold(0.0); + acquisition->set_threshold(0.001); }) << "Failure setting threshold." << std::endl; ASSERT_NO_THROW( { @@ -276,16 +233,14 @@ TEST_F(GpsL1CaPcpsAcquisitionTest, ValidationOfResults) std::string path = std::string(TEST_PATH); std::string file = path + "signal_samples/GPS_L1_CA_ID_1_Fs_4Msps_2ms.dat"; const char * file_name = file.c_str(); - gr::blocks::file_source::sptr file_source = gr::blocks::file_source::make(sizeof(gr_complex), file_name, true); + gr::blocks::file_source::sptr file_source = gr::blocks::file_source::make(sizeof(gr_complex), file_name, false); top_block->connect(file_source, 0, acquisition->get_left_block(), 0); top_block->msg_connect(acquisition->get_right_block(), pmt::mp("events"), msg_rx, pmt::mp("events")); }) << "Failure connecting the blocks of acquisition test." << std::endl; acquisition->set_local_code(); - acquisition->init(); acquisition->set_state(1); // Ensure that acquisition starts at the first sample - - start_queue(); + acquisition->init(); EXPECT_NO_THROW( { start = std::chrono::system_clock::now(); @@ -304,14 +259,4 @@ TEST_F(GpsL1CaPcpsAcquisitionTest, ValidationOfResults) EXPECT_LE(doppler_error_hz, 666) << "Doppler error exceeds the expected value: 666 Hz = 2/(3*integration period)"; EXPECT_LT(delay_error_chips, 0.5) << "Delay error exceeds the expected value: 0.5 chips"; -#ifdef OLD_BOOST - ASSERT_NO_THROW( { - ch_thread.timed_join(boost::posix_time::seconds(1)); - }) << "Failure while waiting the queue to stop" << std::endl; -#endif -#ifndef OLD_BOOST - ASSERT_NO_THROW( { - ch_thread.try_join_until(boost::chrono::steady_clock::now() + boost::chrono::milliseconds(50)); - }) << "Failure while waiting the queue to stop" << std::endl; -#endif } diff --git a/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_ca_pcps_multithread_acquisition_gsoc2013_test.cc b/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_ca_pcps_multithread_acquisition_gsoc2013_test.cc deleted file mode 100644 index 6e7098047..000000000 --- a/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_ca_pcps_multithread_acquisition_gsoc2013_test.cc +++ /dev/null @@ -1,566 +0,0 @@ -/*! - * \file gps_l1_ca_pcps_multithread_acquisition_gsoc2013_test.cc - * \brief This class implements an acquisition test for - * GpsL1CaPcpsMultithreadAcquisition class. - * \author Marc Molina, 2013. marc.molina.pena(at)gmail.com - * - * - * ------------------------------------------------------------------------- - * - * Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors) - * - * GNSS-SDR is a software defined Global Navigation - * Satellite Systems receiver - * - * This file is part of GNSS-SDR. - * - * GNSS-SDR is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * GNSS-SDR is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with GNSS-SDR. If not, see . - * - * ------------------------------------------------------------------------- - */ - - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "gnss_block_interface.h" -#include "in_memory_configuration.h" -#include "configuration_interface.h" -#include "gnss_synchro.h" -#include "gps_l1_ca_pcps_multithread_acquisition.h" -#include "signal_generator.h" -#include "signal_generator_c.h" -#include "fir_filter.h" -#include "gen_signal_source.h" -#include "gnss_sdr_valve.h" -#include "signal_generator.h" -#include "signal_generator.cc" -#include "signal_generator_c.h" -#include "signal_generator_c.cc" - - -class GpsL1CaPcpsMultithreadAcquisitionGSoC2013Test: public ::testing::Test -{ -protected: - GpsL1CaPcpsMultithreadAcquisitionGSoC2013Test() - { - item_size = sizeof(gr_complex); - stop = false; - message = 0; - gnss_synchro = Gnss_Synchro(); - } - - ~GpsL1CaPcpsMultithreadAcquisitionGSoC2013Test() - { - } - - void init(); - void config_1(); - void config_2(); - void start_queue(); - void wait_message(); - void process_message(); - void stop_queue(); - - gr::msg_queue::sptr queue; - gr::top_block_sptr top_block; - std::shared_ptr acquisition; - std::shared_ptr config; - Gnss_Synchro gnss_synchro; - size_t item_size; - bool stop; - int message; - boost::thread ch_thread; - - unsigned int integration_time_ms = 0; - unsigned int fs_in = 0; - - double expected_delay_chips = 0.0; - double expected_doppler_hz = 0.0; - float max_doppler_error_hz = 0.0; - float max_delay_error_chips = 0.0; - - unsigned int num_of_realizations = 0; - unsigned int realization_counter = 0; - unsigned int detection_counter = 0; - unsigned int correct_estimation_counter = 0; - unsigned int acquired_samples = 0; - unsigned int mean_acq_time_us = 0; - - double mse_doppler = 0.0; - double mse_delay = 0.0; - - double Pd = 0.0; - double Pfa_p = 0.0; - double Pfa_a = 0.0; -}; - -void GpsL1CaPcpsMultithreadAcquisitionGSoC2013Test::init() -{ - message = 0; - realization_counter = 0; - detection_counter = 0; - correct_estimation_counter = 0; - acquired_samples = 0; - mse_doppler = 0; - mse_delay = 0; - mean_acq_time_us = 0; - Pd = 0; - Pfa_p = 0; - Pfa_a = 0; -} - -void GpsL1CaPcpsMultithreadAcquisitionGSoC2013Test::config_1() -{ - gnss_synchro.Channel_ID = 0; - gnss_synchro.System = 'G'; - std::string signal = "1C"; - signal.copy(gnss_synchro.Signal,2,0); - - integration_time_ms = 1; - fs_in = 4e6; - - expected_delay_chips = 600; - expected_doppler_hz = 750; - max_doppler_error_hz = 2/(3*integration_time_ms*1e-3); - max_delay_error_chips = 0.50; - - num_of_realizations = 1; - - config = std::make_shared(); - - config->set_property("GNSS-SDR.internal_fs_sps", std::to_string(fs_in)); - - config->set_property("SignalSource.fs_hz", std::to_string(fs_in)); - - config->set_property("SignalSource.item_type", "gr_complex"); - - config->set_property("SignalSource.num_satellites", "1"); - - config->set_property("SignalSource.system_0", "G"); - config->set_property("SignalSource.PRN_0", "10"); - config->set_property("SignalSource.CN0_dB_0", "44"); - config->set_property("SignalSource.doppler_Hz_0", std::to_string(expected_doppler_hz)); - config->set_property("SignalSource.delay_chips_0", std::to_string(expected_delay_chips)); - - config->set_property("SignalSource.noise_flag", "false"); - config->set_property("SignalSource.data_flag", "false"); - config->set_property("SignalSource.BW_BB", "0.97"); - - config->set_property("InputFilter.implementation", "Fir_Filter"); - config->set_property("InputFilter.input_item_type", "gr_complex"); - config->set_property("InputFilter.output_item_type", "gr_complex"); - config->set_property("InputFilter.taps_item_type", "float"); - config->set_property("InputFilter.number_of_taps", "11"); - config->set_property("InputFilter.number_of_bands", "2"); - config->set_property("InputFilter.band1_begin", "0.0"); - config->set_property("InputFilter.band1_end", "0.97"); - config->set_property("InputFilter.band2_begin", "0.98"); - config->set_property("InputFilter.band2_end", "1.0"); - config->set_property("InputFilter.ampl1_begin", "1.0"); - config->set_property("InputFilter.ampl1_end", "1.0"); - config->set_property("InputFilter.ampl2_begin", "0.0"); - config->set_property("InputFilter.ampl2_end", "0.0"); - config->set_property("InputFilter.band1_error", "1.0"); - config->set_property("InputFilter.band2_error", "1.0"); - config->set_property("InputFilter.filter_type", "bandpass"); - config->set_property("InputFilter.grid_density", "16"); - - config->set_property("Acquisition.item_type", "gr_complex"); - config->set_property("Acquisition.if", "0"); - config->set_property("Acquisition.coherent_integration_time_ms", - std::to_string(integration_time_ms)); - config->set_property("Acquisition.max_dwells", "1"); - config->set_property("Acquisition.implementation", "GPS_L1_CA_PCPS_Multithread_Acquisition"); - config->set_property("Acquisition.threshold", "0.8"); - config->set_property("Acquisition.doppler_max", "10000"); - config->set_property("Acquisition.doppler_step", "250"); - config->set_property("Acquisition.bit_transition_flag", "false"); - config->set_property("Acquisition.dump", "false"); -} - -void GpsL1CaPcpsMultithreadAcquisitionGSoC2013Test::config_2() -{ - gnss_synchro.Channel_ID = 0; - gnss_synchro.System = 'G'; - std::string signal = "1C"; - signal.copy(gnss_synchro.Signal,2,0); - - integration_time_ms = 1; - fs_in = 4e6; - - expected_delay_chips = 600; - expected_doppler_hz = 750; - max_doppler_error_hz = 2/(3*integration_time_ms*1e-3); - max_delay_error_chips = 0.50; - - num_of_realizations = 100; - - config = std::make_shared(); - - config->set_property("GNSS-SDR.internal_fs_sps", std::to_string(fs_in)); - - config->set_property("SignalSource.fs_hz", std::to_string(fs_in)); - - config->set_property("SignalSource.item_type", "gr_complex"); - - config->set_property("SignalSource.num_satellites", "4"); - - config->set_property("SignalSource.system_0", "G"); - config->set_property("SignalSource.PRN_0", "10"); - config->set_property("SignalSource.CN0_dB_0", "44"); - config->set_property("SignalSource.doppler_Hz_0", std::to_string(expected_doppler_hz)); - config->set_property("SignalSource.delay_chips_0", std::to_string(expected_delay_chips)); - - config->set_property("SignalSource.system_1", "G"); - config->set_property("SignalSource.PRN_1", "15"); - config->set_property("SignalSource.CN0_dB_1", "44"); - config->set_property("SignalSource.doppler_Hz_1", "1000"); - config->set_property("SignalSource.delay_chips_1", "100"); - - config->set_property("SignalSource.system_2", "G"); - config->set_property("SignalSource.PRN_2", "21"); - config->set_property("SignalSource.CN0_dB_2", "44"); - config->set_property("SignalSource.doppler_Hz_2", "2000"); - config->set_property("SignalSource.delay_chips_2", "200"); - - config->set_property("SignalSource.system_3", "G"); - config->set_property("SignalSource.PRN_3", "22"); - config->set_property("SignalSource.CN0_dB_3", "44"); - config->set_property("SignalSource.doppler_Hz_3", "3000"); - config->set_property("SignalSource.delay_chips_3", "300"); - - config->set_property("SignalSource.noise_flag", "true"); - config->set_property("SignalSource.data_flag", "true"); - config->set_property("SignalSource.BW_BB", "0.97"); - - config->set_property("InputFilter.implementation", "Fir_Filter"); - config->set_property("InputFilter.input_item_type", "gr_complex"); - config->set_property("InputFilter.output_item_type", "gr_complex"); - config->set_property("InputFilter.taps_item_type", "float"); - config->set_property("InputFilter.number_of_taps", "11"); - config->set_property("InputFilter.number_of_bands", "2"); - config->set_property("InputFilter.band1_begin", "0.0"); - config->set_property("InputFilter.band1_end", "0.97"); - config->set_property("InputFilter.band2_begin", "0.98"); - config->set_property("InputFilter.band2_end", "1.0"); - config->set_property("InputFilter.ampl1_begin", "1.0"); - config->set_property("InputFilter.ampl1_end", "1.0"); - config->set_property("InputFilter.ampl2_begin", "0.0"); - config->set_property("InputFilter.ampl2_end", "0.0"); - config->set_property("InputFilter.band1_error", "1.0"); - config->set_property("InputFilter.band2_error", "1.0"); - config->set_property("InputFilter.filter_type", "bandpass"); - config->set_property("InputFilter.grid_density", "16"); - - config->set_property("Acquisition.item_type", "gr_complex"); - config->set_property("Acquisition.if", "0"); - config->set_property("Acquisition.coherent_integration_time_ms", - std::to_string(integration_time_ms)); - config->set_property("Acquisition.max_dwells", "1"); - config->set_property("Acquisition.implementation", "GPS_L1_CA_PCPS_Multithread_Acquisition"); - config->set_property("Acquisition.pfa", "0.1"); - config->set_property("Acquisition.doppler_max", "10000"); - config->set_property("Acquisition.doppler_step", "250"); - config->set_property("Acquisition.bit_transition_flag", "false"); - config->set_property("Acquisition.dump", "false"); -} - - -void GpsL1CaPcpsMultithreadAcquisitionGSoC2013Test::start_queue() -{ - stop = false; - ch_thread = boost::thread(&GpsL1CaPcpsMultithreadAcquisitionGSoC2013Test::wait_message, this); -} - - -void GpsL1CaPcpsMultithreadAcquisitionGSoC2013Test::wait_message() -{ - std::chrono::time_point start, end; - std::chrono::duration elapsed_seconds(0); - - while (!stop) - { - acquisition->reset(); - - start = std::chrono::system_clock::now(); - - channel_internal_queue.wait_and_pop(message); - - end = std::chrono::system_clock::now(); - elapsed_seconds = end - start; - - mean_acq_time_us += elapsed_seconds.count() * 1e6; - - process_message(); - } -} - - -void GpsL1CaPcpsMultithreadAcquisitionGSoC2013Test::process_message() -{ - if (message == 1) - { - detection_counter++; - - // The term -5 is here to correct the additional delay introduced by the FIR filter - double delay_error_chips = std::abs(static_cast(expected_delay_chips) - static_cast(gnss_synchro.Acq_delay_samples - 5) * 1023.0 / (static_cast(fs_in) * 1e-3)); - double doppler_error_hz = std::abs(expected_doppler_hz - gnss_synchro.Acq_doppler_hz); - - mse_delay += std::pow(delay_error_chips, 2); - mse_doppler += std::pow(doppler_error_hz, 2); - - if ((delay_error_chips < max_delay_error_chips) && (doppler_error_hz < max_doppler_error_hz)) - { - correct_estimation_counter++; - } - } - - realization_counter++; - - std::cout << "Progress: " << round(static_cast(realization_counter) / static_cast(num_of_realizations) * 100.0) << "% \r" << std::flush; - - if (realization_counter == num_of_realizations) - { - mse_delay /= num_of_realizations; - mse_doppler /= num_of_realizations; - - Pd = static_cast(correct_estimation_counter) / static_cast(num_of_realizations); - Pfa_a = static_cast(detection_counter) / static_cast(num_of_realizations); - Pfa_p = static_cast(detection_counter - correct_estimation_counter) / static_cast(num_of_realizations); - - mean_acq_time_us /= num_of_realizations; - - stop_queue(); - top_block->stop(); - - std::cout << std::endl; - } -} - - -void GpsL1CaPcpsMultithreadAcquisitionGSoC2013Test::stop_queue() -{ - stop = true; -} - - -TEST_F(GpsL1CaPcpsMultithreadAcquisitionGSoC2013Test, Instantiate) -{ - config_1(); - acquisition = std::make_shared(config.get(), "Acquisition", 1, 1); -} - - -TEST_F(GpsL1CaPcpsMultithreadAcquisitionGSoC2013Test, ConnectAndRun) -{ - int nsamples = floor(fs_in*integration_time_ms*1e-3); - std::chrono::time_point start, end; - std::chrono::duration elapsed_seconds(0); - queue = gr::msg_queue::make(0); - top_block = gr::make_top_block("Acquisition test"); - - config_1(); - acquisition = std::make_shared(config.get(), "Acquisition", 1, 1); - - ASSERT_NO_THROW( { - acquisition->connect(top_block); - boost::shared_ptr source = gr::analog::sig_source_c::make(fs_in, gr::analog::GR_SIN_WAVE, 1000, 1, gr_complex(0)); - boost::shared_ptr valve = gnss_sdr_make_valve(sizeof(gr_complex), nsamples, queue); - top_block->connect(source, 0, valve, 0); - top_block->connect(valve, 0, acquisition->get_left_block(), 0); - }) << "Failure connecting the blocks of acquisition test." << std::endl; - - EXPECT_NO_THROW( { - start = std::chrono::system_clock::now(); - top_block->run(); // Start threads and wait - end = std::chrono::system_clock::now(); - elapsed_seconds = end - start; - }) << "Failure running the top_block." << std::endl; - - std::cout << "Processed " << nsamples << " samples in " << elapsed_seconds.count() * 1e6 << " microseconds" << std::endl; -} - - -TEST_F(GpsL1CaPcpsMultithreadAcquisitionGSoC2013Test, ValidationOfResults) -{ - config_1(); - queue = gr::msg_queue::make(0); - top_block = gr::make_top_block("Acquisition test"); - - acquisition = std::make_shared(config.get(), "Acquisition", 1, 1); - - ASSERT_NO_THROW( { - acquisition->set_channel(1); - }) << "Failure setting channel." << std::endl; - - ASSERT_NO_THROW( { - acquisition->set_gnss_synchro(&gnss_synchro); - }) << "Failure setting gnss_synchro." << std::endl; - - ASSERT_NO_THROW( { - acquisition->set_doppler_max(config->property("Acquisition.doppler_max", 10000)); - }) << "Failure setting doppler_max." << std::endl; - - ASSERT_NO_THROW( { - acquisition->set_doppler_step(config->property("Acquisition.doppler_step", 500)); - }) << "Failure setting doppler_step." << std::endl; - - ASSERT_NO_THROW( { - acquisition->set_threshold(config->property("Acquisition.threshold", 0.0)); - }) << "Failure setting threshold." << std::endl; - - ASSERT_NO_THROW( { - acquisition->connect(top_block); - }) << "Failure connecting acquisition to the top_block." << std::endl; - - acquisition->init(); - - ASSERT_NO_THROW( { - boost::shared_ptr signal_source; - SignalGenerator* signal_generator = new SignalGenerator(config.get(), "SignalSource", 0, 1, queue); - FirFilter* filter = new FirFilter(config.get(), "InputFilter", 1, 1); - signal_source.reset(new GenSignalSource(signal_generator, filter, "SignalSource", queue)); - signal_source->connect(top_block); - top_block->connect(signal_source->get_right_block(), 0, acquisition->get_left_block(), 0); - }) << "Failure connecting the blocks of acquisition test." << std::endl; - - // i = 0 --> satellite in acquisition is visible - // i = 1 --> satellite in acquisition is not visible - for (unsigned int i = 0; i < 2; i++) - { - init(); - - if (i == 0) - { - gnss_synchro.PRN = 10; // This satellite is visible - } - else if (i == 1) - { - gnss_synchro.PRN = 20; // This satellite is not visible - } - - acquisition->set_local_code(); - - start_queue(); - - EXPECT_NO_THROW( { - top_block->run(); // Start threads and wait - }) << "Failure running the top_block." << std::endl; - - if (i == 0) - { - EXPECT_EQ(1, message) << "Acquisition failure. Expected message: 1=ACQ SUCCESS."; - if (message == 1) - { - EXPECT_EQ(static_cast(1), correct_estimation_counter) << "Acquisition failure. Incorrect parameters estimation."; - } - - } - else if (i == 1) - { - EXPECT_EQ(2, message) << "Acquisition failure. Expected message: 2=ACQ FAIL."; - } - } -} - - -TEST_F(GpsL1CaPcpsMultithreadAcquisitionGSoC2013Test, ValidationOfResultsProbabilities) -{ - config_2(); - queue = gr::msg_queue::make(0); - top_block = gr::make_top_block("Acquisition test"); - - acquisition = std::make_shared(config.get(), "Acquisition", 1, 1); - - ASSERT_NO_THROW( { - acquisition->set_channel(1); - }) << "Failure setting channel." << std::endl; - - ASSERT_NO_THROW( { - acquisition->set_gnss_synchro(&gnss_synchro); - }) << "Failure setting gnss_synchro." << std::endl; - - ASSERT_NO_THROW( { - acquisition->set_doppler_max(config->property("Acquisition.doppler_max", 10000)); - }) << "Failure setting doppler_max." << std::endl; - - ASSERT_NO_THROW( { - acquisition->set_doppler_step(config->property("Acquisition.doppler_step", 500)); - }) << "Failure setting doppler_step." << std::endl; - - ASSERT_NO_THROW( { - acquisition->set_threshold(config->property("Acquisition.threshold", 0.0)); - }) << "Failure setting threshold." << std::endl; - - ASSERT_NO_THROW( { - acquisition->connect(top_block); - }) << "Failure connecting acquisition to the top_block." << std::endl; - - acquisition->init(); - - ASSERT_NO_THROW( { - boost::shared_ptr signal_source; - SignalGenerator* signal_generator = new SignalGenerator(config.get(), "SignalSource", 0, 1, queue); - FirFilter* filter = new FirFilter(config.get(), "InputFilter", 1, 1); - signal_source.reset(new GenSignalSource(signal_generator, filter, "SignalSource", queue)); - signal_source->connect(top_block); - top_block->connect(signal_source->get_right_block(), 0, acquisition->get_left_block(), 0); - }) << "Failure connecting the blocks of acquisition test." << std::endl; - - std::cout << "Probability of false alarm (target) = " << 0.1 << std::endl; - - // i = 0 --> satellite in acquisition is visible (prob of detection and prob of detection with wrong estimation) - // i = 1 --> satellite in acquisition is not visible (prob of false detection) - for (unsigned int i = 0; i < 2; i++) - { - init(); - - if (i == 0) - { - gnss_synchro.PRN = 10; // This satellite is visible - } - else if (i == 1) - { - gnss_synchro.PRN = 20; // This satellite is not visible - } - - acquisition->set_local_code(); - - start_queue(); - - EXPECT_NO_THROW( { - top_block->run(); // Start threads and wait - }) << "Failure running the top_block." << std::endl; - - if (i == 0) - { - std::cout << "Probability of detection = " << Pd << std::endl; - std::cout << "Probability of false alarm (satellite present) = " << Pfa_p << std::endl; -// std::cout << "Mean acq time = " << mean_acq_time_us << " microseconds." << std::endl; - } - else if (i == 1) - { - std::cout << "Probability of false alarm (satellite absent) = " << Pfa_a << std::endl; -// std::cout << "Mean acq time = " << mean_acq_time_us << " microseconds." << std::endl; - } - } -} From 05320178571c4d9612ba2999a725e0dfdbadfeed Mon Sep 17 00:00:00 2001 From: Carles Fernandez Date: Wed, 4 Oct 2017 01:38:00 +0200 Subject: [PATCH 7/7] Add blocking parameter to Glonass acquisition --- .../acquisition/adapters/glonass_l1_ca_pcps_acquisition.cc | 5 +++-- .../acquisition/adapters/glonass_l1_ca_pcps_acquisition.h | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/algorithms/acquisition/adapters/glonass_l1_ca_pcps_acquisition.cc b/src/algorithms/acquisition/adapters/glonass_l1_ca_pcps_acquisition.cc index 1066eae1f..5afc7e073 100644 --- a/src/algorithms/acquisition/adapters/glonass_l1_ca_pcps_acquisition.cc +++ b/src/algorithms/acquisition/adapters/glonass_l1_ca_pcps_acquisition.cc @@ -24,6 +24,7 @@ GlonassL1CaPcpsAcquisition::GlonassL1CaPcpsAcquisition( fs_in_ = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated); if_ = configuration_->property(role + ".if", 0); dump_ = configuration_->property(role + ".dump", false); + blocking_ = configuration_->property(role + ".blocking", true); doppler_max_ = configuration_->property(role + ".doppler_max", 5000); sampled_ms_ = configuration_->property(role + ".coherent_integration_time_ms", 1); @@ -51,14 +52,14 @@ GlonassL1CaPcpsAcquisition::GlonassL1CaPcpsAcquisition( item_size_ = sizeof(lv_16sc_t); acquisition_sc_ = pcps_make_acquisition_sc(sampled_ms_, max_dwells_, doppler_max_, if_, fs_in_, code_length_, code_length_, - bit_transition_flag_, use_CFAR_algorithm_flag_, dump_, dump_filename_); + bit_transition_flag_, use_CFAR_algorithm_flag_, dump_, blocking_, dump_filename_); DLOG(INFO) << "acquisition(" << acquisition_sc_->unique_id() << ")"; }else{ item_size_ = sizeof(gr_complex); acquisition_cc_ = pcps_make_acquisition_cc(sampled_ms_, max_dwells_, doppler_max_, if_, fs_in_, code_length_, code_length_, - bit_transition_flag_, use_CFAR_algorithm_flag_, dump_, dump_filename_); + bit_transition_flag_, use_CFAR_algorithm_flag_, dump_, blocking_, dump_filename_); DLOG(INFO) << "acquisition(" << acquisition_cc_->unique_id() << ")"; } diff --git a/src/algorithms/acquisition/adapters/glonass_l1_ca_pcps_acquisition.h b/src/algorithms/acquisition/adapters/glonass_l1_ca_pcps_acquisition.h index ff01d7364..65f6b9874 100644 --- a/src/algorithms/acquisition/adapters/glonass_l1_ca_pcps_acquisition.h +++ b/src/algorithms/acquisition/adapters/glonass_l1_ca_pcps_acquisition.h @@ -126,6 +126,7 @@ private: long fs_in_; long if_; bool dump_; + bool blocking_; std::string dump_filename_; std::complex * code_; Gnss_Synchro * gnss_synchro_;