From 9195740d8a6c96e3abf0b6ab0ded4c9054e04356 Mon Sep 17 00:00:00 2001 From: mmajoral Date: Fri, 5 May 2017 16:14:27 +0200 Subject: [PATCH 1/5] acquisition gps unit test for the FPGA. The code is currently being cleaned --- .../gps_l1_ca_pcps_acquisition_fpga.cc | 282 +++++++++++ .../gps_l1_ca_pcps_acquisition_fpga.h | 170 +++++++ .../gps_pcps_acquisition_fpga_sc.cc | 440 ++++++++++++++++++ .../gps_pcps_acquisition_fpga_sc.h | 235 ++++++++++ .../acquisition/libs/CMakeLists.txt | 91 ++++ .../libs/gps_fpga_acquisition_8sc.cc | 336 +++++++++++++ .../libs/gps_fpga_acquisition_8sc.h | 108 +++++ .../gps_l1_ca_pcps_acquisition_test_fpga.cc | 392 ++++++++++++++++ 8 files changed, 2054 insertions(+) create mode 100644 src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fpga.cc create mode 100644 src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fpga.h create mode 100644 src/algorithms/acquisition/gnuradio_blocks/gps_pcps_acquisition_fpga_sc.cc create mode 100644 src/algorithms/acquisition/gnuradio_blocks/gps_pcps_acquisition_fpga_sc.h create mode 100644 src/algorithms/acquisition/libs/CMakeLists.txt create mode 100644 src/algorithms/acquisition/libs/gps_fpga_acquisition_8sc.cc create mode 100644 src/algorithms/acquisition/libs/gps_fpga_acquisition_8sc.h create mode 100644 src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_ca_pcps_acquisition_test_fpga.cc diff --git a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fpga.cc b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fpga.cc new file mode 100644 index 000000000..5a2c4c334 --- /dev/null +++ b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fpga.cc @@ -0,0 +1,282 @@ +/*! + * \file gps_l1_ca_pcps_acquisition_fpga.cc + * \brief Adapts a PCPS acquisition block to an FPGA Acquisition Interface for + * GPS L1 C/A signals. This file is based on the file gps_l1_ca_pcps_acquisition.cc + * \authors + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2017 (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_acquisition_fpga.h" +#include +#include +#include "gps_sdr_signal_processing.h" +#include "GPS_L1_CA.h" +#include "configuration_interface.h" + + +using google::LogMessage; + +GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga( + 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 = "cshort"; + std::string default_dump_filename = "./data/acquisition.dat"; + + DLOG(INFO) << "role " << role; + + item_type_ = configuration_->property(role + ".item_type", default_item_type); + + fs_in_ = configuration_->property("GNSS-SDR.internal_fs_hz", 2048000); + 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); + + // note : the FPGA is implemented according to bit transition flag = 0. Setting bit transition flag to 1 has no effect. + bit_transition_flag_ = configuration_->property(role + ".bit_transition_flag", false); + + // note : the FPGA is implemented according to use_CFAR_algorithm = 0. Setting use_CFAR_algorithm to 1 has no effect. + use_CFAR_algorithm_flag_=configuration_->property(role + ".use_CFAR_algorithm", false); + + max_dwells_ = configuration_->property(role + ".max_dwells", 1); + + dump_filename_ = configuration_->property(role + ".dump_filename", default_dump_filename); + + //--- Find number of samples per spreading code ------------------------- + code_length_ = round(fs_in_ / (GPS_L1_CA_CODE_RATE_HZ / GPS_L1_CA_CODE_LENGTH_CHIPS)); + + // code length has the same value as d_fft_size + float nbits; + nbits = ceilf(log2f(code_length_)); + nsamples_total_ = pow(2,nbits); + + //vector_length_ = code_length_ * sampled_ms_; + vector_length_ = nsamples_total_ * sampled_ms_; + + + if( bit_transition_flag_ ) + { + vector_length_ *= 2; + } + + code_ = new gr_complex[vector_length_]; + + if (item_type_.compare("cshort") == 0 ) + { + item_size_ = sizeof(lv_16sc_t); + gps_acquisition_fpga_sc_ = gps_pcps_make_acquisition_fpga_sc(sampled_ms_, max_dwells_, + doppler_max_, if_, fs_in_, code_length_, code_length_, vector_length_, + bit_transition_flag_, use_CFAR_algorithm_flag_, dump_, dump_filename_); + DLOG(INFO) << "acquisition(" << gps_acquisition_fpga_sc_->unique_id() << ")"; + + } + else{ + LOG(FATAL) << item_type_ << " FPGA only accepts chsort"; + } + + channel_ = 0; + threshold_ = 0.0; + doppler_step_ = 0; + gnss_synchro_ = 0; +} + + +GpsL1CaPcpsAcquisitionFpga::~GpsL1CaPcpsAcquisitionFpga() +{ + delete[] code_; +} + + +void GpsL1CaPcpsAcquisitionFpga::set_channel(unsigned int channel) +{ + channel_ = channel; + + gps_acquisition_fpga_sc_->set_channel(channel_); + +} + + +void GpsL1CaPcpsAcquisitionFpga::set_threshold(float threshold) +{ + float pfa = configuration_->property(role_ + ".pfa", 0.0); + + if(pfa == 0.0) + { + threshold_ = threshold; + } + else + { + threshold_ = calculate_threshold(pfa); + } + + DLOG(INFO) << "Channel " << channel_ << " Threshold = " << threshold_; + + + gps_acquisition_fpga_sc_->set_threshold(threshold_); + +} + + +void GpsL1CaPcpsAcquisitionFpga::set_doppler_max(unsigned int doppler_max) +{ + doppler_max_ = doppler_max; + + gps_acquisition_fpga_sc_->set_doppler_max(doppler_max_); + +} + + +void GpsL1CaPcpsAcquisitionFpga::set_doppler_step(unsigned int doppler_step) +{ + doppler_step_ = doppler_step; + + gps_acquisition_fpga_sc_->set_doppler_step(doppler_step_); + +} + +void GpsL1CaPcpsAcquisitionFpga::set_gnss_synchro(Gnss_Synchro* gnss_synchro) +{ + gnss_synchro_ = gnss_synchro; + + gps_acquisition_fpga_sc_->set_gnss_synchro(gnss_synchro_); +} + + +signed int GpsL1CaPcpsAcquisitionFpga::mag() +{ + + return gps_acquisition_fpga_sc_->mag(); +} + + +void GpsL1CaPcpsAcquisitionFpga::init() +{ + + gps_acquisition_fpga_sc_->init(); + + set_local_code(); +} + + +void GpsL1CaPcpsAcquisitionFpga::set_local_code() +{ + + std::complex* code = new std::complex[vector_length_]; + + + //init to zeros for the zero padding of the fft + for (uint s=0;s(0, 0); + } + + unsigned long long interpolated_sampling_frequency; // warning: we need a long long to do this conversion to avoid running out of bits + + gps_l1_ca_code_gen_complex_sampled(code, gnss_synchro_->PRN, fs_in_ , 0); + + for (unsigned int i = 0; i < sampled_ms_; i++) + { + memcpy(&(code_[i*vector_length_]), code, sizeof(gr_complex)*vector_length_); + + } + + gps_acquisition_fpga_sc_->set_local_code(code_); + + delete[] code; +} + + +void GpsL1CaPcpsAcquisitionFpga::reset() +{ + + gps_acquisition_fpga_sc_->set_active(true); + +} + + +void GpsL1CaPcpsAcquisitionFpga::set_state(int state) +{ + + gps_acquisition_fpga_sc_->set_state(state); +} + + + +float GpsL1CaPcpsAcquisitionFpga::calculate_threshold(float pfa) +{ + //Calculate the threshold + unsigned int frequency_bins = 0; + for (int doppler = (int)(-doppler_max_); doppler <= (int)doppler_max_; doppler += doppler_step_) + { + frequency_bins++; + } + DLOG(INFO) << "Channel " << channel_ << " Pfa = " << pfa; + unsigned int ncells = vector_length_ * frequency_bins; + double exponent = 1 / static_cast(ncells); + double val = pow(1.0 - pfa, exponent); + double lambda = double(vector_length_); + boost::math::exponential_distribution mydist (lambda); + float threshold = (float)quantile(mydist,val); + + return threshold; +} + + +void GpsL1CaPcpsAcquisitionFpga::connect(gr::top_block_sptr top_block) +{ + + //nothing to connect +} + + +void GpsL1CaPcpsAcquisitionFpga::disconnect(gr::top_block_sptr top_block) +{ + + //nothing to disconnect +} + + +gr::basic_block_sptr GpsL1CaPcpsAcquisitionFpga::get_left_block() +{ + + return gps_acquisition_fpga_sc_; + +} + + +gr::basic_block_sptr GpsL1CaPcpsAcquisitionFpga::get_right_block() +{ + + return gps_acquisition_fpga_sc_; + +} + diff --git a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fpga.h b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fpga.h new file mode 100644 index 000000000..290860255 --- /dev/null +++ b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fpga.h @@ -0,0 +1,170 @@ +/*! + * \file gps_l1_ca_pcps_acquisition_fpga.h + * \brief Adapts a PCPS acquisition block to an AcquisitionInterface for + * GPS L1 C/A signals. This file is based on the file gps_l1_ca_pcps_acquisition.h + * \authors
    + *
  • Marc Majoral, 2017. mmajoral(at)cttc.cat + *
+ * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2017 (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_ACQUISITION_FPGA_H_ +#define GNSS_SDR_GPS_L1_CA_PCPS_ACQUISITION_FPGA_H_ + +#include +#include +#include +#include "gnss_synchro.h" +#include "acquisition_interface.h" +#include "gps_pcps_acquisition_fpga_sc.h" +#include "complex_byte_to_float_x2.h" +#include + + + +class ConfigurationInterface; + +/*! + * \brief This class adapts a PCPS acquisition block to an AcquisitionInterface + * for GPS L1 C/A signals + */ +class GpsL1CaPcpsAcquisitionFpga: public AcquisitionInterface +{ +public: + GpsL1CaPcpsAcquisitionFpga(ConfigurationInterface* configuration, + std::string role, unsigned int in_streams, + unsigned int out_streams); + + virtual ~GpsL1CaPcpsAcquisitionFpga(); + + std::string role() + { + return role_; + } + + /*! + * \brief Returns "GPS_L1_CA_PCPS_Acquisition" + */ + std::string implementation() + { + return "GPS_L1_CA_PCPS_Acquisition"; + } + size_t item_size() + { + return item_size_; + } + + void connect(gr::top_block_sptr top_block); + void disconnect(gr::top_block_sptr top_block); + gr::basic_block_sptr get_left_block(); + gr::basic_block_sptr get_right_block(); + + /*! + * \brief Set acquisition/tracking common Gnss_Synchro object pointer + * to efficiently exchange synchronization data between acquisition and + * tracking blocks + */ + void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro); + + /*! + * \brief Set acquisition channel unique ID + */ + void set_channel(unsigned int channel); + + /*! + * \brief Set statistics threshold of PCPS algorithm + */ + void set_threshold(float threshold); + + /*! + * \brief Set maximum Doppler off grid search + */ + void set_doppler_max(unsigned int doppler_max); + + /*! + * \brief Set Doppler steps for the grid search + */ + void set_doppler_step(unsigned int doppler_step); + + /*! + * \brief Initializes acquisition algorithm. + */ + void init(); + + /*! + * \brief Sets local code for GPS L1/CA PCPS acquisition algorithm. + */ + void set_local_code(); + + /*! + * \brief Returns the maximum peak of grid search + */ + signed int mag(); + + /*! + * \brief Restart acquisition algorithm + */ + void reset(); + + /*! + * \brief If state = 1, it forces the block to start acquiring from the first sample + */ + void set_state(int state); + +private: + ConfigurationInterface* configuration_; + gps_pcps_acquisition_fpga_sc_sptr gps_acquisition_fpga_sc_; + gr::blocks::stream_to_vector::sptr stream_to_vector_; + gr::blocks::float_to_complex::sptr float_to_complex_; + complex_byte_to_float_x2_sptr cbyte_to_float_x2_; + size_t item_size_; + std::string item_type_; + unsigned int vector_length_; + unsigned int code_length_; + bool bit_transition_flag_; + bool use_CFAR_algorithm_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_; + + unsigned int nsamples_total_; + + float calculate_threshold(float pfa); +}; + +#endif /* GNSS_SDR_GPS_L1_CA_PCPS_ACQUISITION_H_ */ diff --git a/src/algorithms/acquisition/gnuradio_blocks/gps_pcps_acquisition_fpga_sc.cc b/src/algorithms/acquisition/gnuradio_blocks/gps_pcps_acquisition_fpga_sc.cc new file mode 100644 index 000000000..0162e92f9 --- /dev/null +++ b/src/algorithms/acquisition/gnuradio_blocks/gps_pcps_acquisition_fpga_sc.cc @@ -0,0 +1,440 @@ +/*! + * \file gps_pcps_acquisition_fpga_sc.cc + * \brief This class implements a Parallel Code Phase Search Acquisition in the FPGA. + * This file is based on the file gps_pcps_acquisition_sc.cc + * \authors
    + *
  • Marc Majoral, 2017. mmajoral(at)cttc.cat + *
+ * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2017 (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_pcps_acquisition_fpga_sc.h" +#include +#include +#include +#include +#include +#include +#include "control_message_factory.h" +#include "GPS_L1_CA.h" //GPS_TWO_PI + +using google::LogMessage; + +void wait3(int seconds) +{ + boost::this_thread::sleep_for(boost::chrono::seconds{seconds}); +} + + +gps_pcps_acquisition_fpga_sc_sptr gps_pcps_make_acquisition_fpga_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, int vector_length, + bool bit_transition_flag, bool use_CFAR_algorithm_flag, + bool dump, + std::string dump_filename) +{ + + return gps_pcps_acquisition_fpga_sc_sptr( + new gps_pcps_acquisition_fpga_sc(sampled_ms, max_dwells, doppler_max, freq, fs_in, samples_per_ms, + samples_per_code, vector_length, bit_transition_flag, use_CFAR_algorithm_flag, dump, dump_filename)); +} + +gps_pcps_acquisition_fpga_sc::gps_pcps_acquisition_fpga_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, int vector_length, + bool bit_transition_flag, bool use_CFAR_algorithm_flag, + bool dump, + std::string dump_filename) : + + gr::block("pcps_acquisition_fpga_sc",gr::io_signature::make(0, 0, sizeof(lv_16sc_t)),gr::io_signature::make(0, 0, 0)) +{ + this->message_port_register_out(pmt::mp("events")); + d_sample_counter = 0; // SAMPLE COUNTER + d_active = false; + d_state = 0; + 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_use_CFAR_algorithm_flag = use_CFAR_algorithm_flag; + d_threshold = 0.0; + d_doppler_step = 250; + d_code_phase = 0; + d_test_statistics = 0.0; + d_channel = 0; + d_doppler_freq = 0.0; + + d_nsamples_total = vector_length; + + // COD: + // Experimenting with the overlap/save technique for handling bit trannsitions + // The problem: Circular correlation is asynchronous with the received code. + // In effect the first code phase used in the correlation is the current + // estimate of the code phase at the start of the input buffer. If this is 1/2 + // of the code period a bit transition would move all the signal energy into + // adjacent frequency bands at +/- 1/T where T is the integration time. + // + // We can avoid this by doing linear correlation, effectively doubling the + // size of the input buffer and padding the code with zeros. + if( d_bit_transition_flag ) + { + d_fft_size *= 2; + d_max_dwells = 1; + } + + d_fft_codes = static_cast(volk_gnsssdr_malloc(d_nsamples_total * sizeof(gr_complex), volk_gnsssdr_get_alignment())); + d_magnitude = static_cast(volk_gnsssdr_malloc(d_nsamples_total * 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_nsamples_total * sizeof(gr_complex), volk_gnsssdr_get_alignment())); + + d_fft_codes_padded = static_cast(volk_gnsssdr_malloc(d_nsamples_total * sizeof(gr_complex), volk_gnsssdr_get_alignment())); + + + // Direct FFT + d_fft_if = new gr::fft::fft_complex(d_nsamples_total, true); + + // Inverse FFT + d_ifft = new gr::fft::fft_complex(d_nsamples_total, false); + + // For dumping samples into a file + d_dump = dump; + d_dump_filename = dump_filename; + + d_gnss_synchro = 0; + d_grid_doppler_wipeoffs = 0; + + + + + + +} + + +gps_pcps_acquisition_fpga_sc::~gps_pcps_acquisition_fpga_sc() +{ + if (d_num_doppler_bins > 0) + { + for (unsigned int i = 0; i < d_num_doppler_bins; i++) + { + volk_gnsssdr_free(d_grid_doppler_wipeoffs[i]); + } + delete[] d_grid_doppler_wipeoffs; + } + + volk_gnsssdr_free(d_fft_codes); + volk_gnsssdr_free(d_magnitude); + volk_gnsssdr_free(d_in_32fc); + + delete d_ifft; + delete d_fft_if; + + if (d_dump) + { + d_dump_file.close(); + } + + + + acquisition_fpga_8sc.free(); +} + + +void gps_pcps_acquisition_fpga_sc::set_local_code(std::complex * code) +{ + // COD + // 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; + if( d_bit_transition_flag ) + { + std::fill_n( d_fft_if->get_inbuf(), d_nsamples_total, gr_complex( 0.0, 0.0 ) ); + offset = d_nsamples_total; + } + + + + memcpy(d_fft_if->get_inbuf() + offset, code, sizeof(gr_complex) * d_nsamples_total); + d_fft_if->execute(); // We need the FFT of local code + volk_32fc_conjugate_32fc(d_fft_codes_padded, d_fft_if->get_outbuf(), d_nsamples_total); + + acquisition_fpga_8sc.set_local_code(d_fft_codes_padded); + +} + + +void gps_pcps_acquisition_fpga_sc::update_local_carrier(gr_complex* carrier_vector, int correlator_length_samples, float freq) +{ + static int debugint = 0; + + + float phase_step_rad = GPS_TWO_PI * freq / static_cast(d_fs_in); + + float _phase[1]; + _phase[0] = 0; + volk_gnsssdr_s32f_sincos_32fc(carrier_vector, - phase_step_rad, _phase, correlator_length_samples); + +} + + +void gps_pcps_acquisition_fpga_sc::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->Flag_preamble = 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; + + d_num_doppler_bins = ceil( static_cast(static_cast(d_doppler_max) - static_cast(-d_doppler_max)) / static_cast(d_doppler_step)); + + // 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_gnsssdr_malloc(d_fft_size * sizeof(gr_complex), volk_gnsssdr_get_alignment())); + 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); + } + // PENDING : SELECT_QUEUE MUST GO INTO CONFIGURATION + unsigned select_queue = 0; + acquisition_fpga_8sc.init(d_fft_size, d_nsamples_total, d_freq, d_doppler_max, d_doppler_step, d_num_doppler_bins, d_fs_in, select_queue); + + + + + +} + + + +void gps_pcps_acquisition_fpga_sc::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; + } + else if (d_state == 0) + {} + else + { + LOG(ERROR) << "State can only be set to 0 or 1"; + } + + + + + + +} + +void gps_pcps_acquisition_fpga_sc::set_active(bool active) +{ + + float temp_peak_to_noise_level = 0.0; + float peak_to_noise_level = 0.0; + acquisition_fpga_8sc.block_samples(); // block the samples to run the acquisition this is only necessary for the tests + + + d_active = active; + + + while (d_well_count < d_max_dwells) + { + int acquisition_message = -1; //0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL + + d_state = 1; + + // initialize acquisition algorithm + int doppler; + uint32_t indext = 0; + float magt = 0.0; + 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_mag = 0.0; + + unsigned int initial_sample; + + 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: " + << ", threshold: " + << d_threshold << ", doppler_max: " << d_doppler_max + << ", doppler_step: " << d_doppler_step; + + // Doppler frequency search loop + for (unsigned int doppler_index = 0; doppler_index < d_num_doppler_bins; doppler_index++) + { + + + doppler = -static_cast(d_doppler_max) + d_doppler_step * doppler_index; + + acquisition_fpga_8sc.set_phase_step(doppler_index); + acquisition_fpga_8sc.run_acquisition(); // runs acquisition and waits until it is finished + + acquisition_fpga_8sc.read_acquisition_results(&indext, &magt, &initial_sample, &d_input_power); + + temp_peak_to_noise_level = (float) (magt / d_input_power); + if (peak_to_noise_level < temp_peak_to_noise_level) + { + peak_to_noise_level = temp_peak_to_noise_level; + d_mag = magt; + + d_input_power = (d_input_power - d_mag) / (effective_fft_size - 1); + + 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 = initial_sample; + 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(); + } + } + + + if (d_test_statistics > d_threshold) + { + d_state = 2; // Positive acquisition + + // 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) << "sample_stamp " << initial_sample; + DLOG(INFO) << "test statistics value " << d_test_statistics; + DLOG(INFO) << "test statistics threshold " << d_threshold; + DLOG(INFO) << "code phase " << d_gnss_synchro->Acq_delay_samples; + DLOG(INFO) << "doppler " << d_gnss_synchro->Acq_doppler_hz; + DLOG(INFO) << "magnitude " << d_mag; + DLOG(INFO) << "input signal power " << d_input_power; + + d_active = false; + d_state = 0; + + acquisition_message = 1; + this->message_port_pub(pmt::mp("events"), pmt::from_long(acquisition_message)); + + break; + + } + else //if (d_well_count == d_max_dwells) + { + d_state = 3; // Negative acquisition + + // 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) << "sample_stamp " << initial_sample; + DLOG(INFO) << "test statistics value " << d_test_statistics; + DLOG(INFO) << "test statistics threshold " << d_threshold; + DLOG(INFO) << "code phase " << d_gnss_synchro->Acq_delay_samples; + DLOG(INFO) << "doppler " << d_gnss_synchro->Acq_doppler_hz; + DLOG(INFO) << "magnitude " << d_mag; + DLOG(INFO) << "input signal power " << d_input_power; + + d_active = false; + d_state = 0; + + acquisition_message = 2; + this->message_port_pub(pmt::mp("events"), pmt::from_long(acquisition_message)); + + break; + } + + } + + acquisition_fpga_8sc.unblock_samples(); + + DLOG(INFO) << "Done. Consumed 1 item."; + +} + + +int gps_pcps_acquisition_fpga_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))) +{ + + return noutput_items; +} diff --git a/src/algorithms/acquisition/gnuradio_blocks/gps_pcps_acquisition_fpga_sc.h b/src/algorithms/acquisition/gnuradio_blocks/gps_pcps_acquisition_fpga_sc.h new file mode 100644 index 000000000..62e03b06f --- /dev/null +++ b/src/algorithms/acquisition/gnuradio_blocks/gps_pcps_acquisition_fpga_sc.h @@ -0,0 +1,235 @@ +/*! + * \file gps_pcps_acquisition_fpga_sc.h + * \brief This class implements a Parallel Code Phase Search Acquisition in the FPGA. + * This file is based on the file gps_pcps_acquisition_sc.h + * + * 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
    + *
  • Marc Majoral, 2017. mmajoral(at)cttc.cat + *
+ * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2017 (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_ACQUISITION_FPGA_SC_H_ +#define GNSS_SDR_PCPS_ACQUISITION_FPGA_SC_H_ + +#include +#include +#include +#include +#include +#include "gnss_synchro.h" +#include "gps_fpga_acquisition_8sc.h" + +class gps_pcps_acquisition_fpga_sc; + +typedef boost::shared_ptr gps_pcps_acquisition_fpga_sc_sptr; + +gps_pcps_acquisition_fpga_sc_sptr +gps_pcps_make_acquisition_fpga_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, int vector_length_, + bool bit_transition_flag, bool use_CFAR_algorithm_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 gps_pcps_acquisition_fpga_sc: public gr::block +{ +private: + friend gps_pcps_acquisition_fpga_sc_sptr + gps_pcps_make_acquisition_fpga_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, int vector_length, + bool bit_transition_flag, bool use_CFAR_algorithm_flag, + bool dump, + std::string dump_filename); + + gps_pcps_acquisition_fpga_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, int vector_length, + bool bit_transition_flag, bool use_CFAR_algorithm_flag, + bool dump, + std::string dump_filename); + + void update_local_carrier(gr_complex* carrier_vector, + int correlator_length_samples, + float freq); + + long d_fs_in; + long d_freq; + int d_samples_per_ms; + int d_samples_per_code; + 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 int d_nsamples_total; // the closest power of two approximation to 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_complex* d_fft_codes_padded; + gr_complex* d_in_32fc; + 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; + bool d_use_CFAR_algorithm_flag; + std::ofstream d_dump_file; + bool d_active; + int d_state; + bool d_dump; + unsigned int d_channel; + std::string d_dump_filename; + + gps_fpga_acquisition_8sc acquisition_fpga_8sc; + +public: + /*! + * \brief Default destructor. + */ + ~gps_pcps_acquisition_fpga_sc(); + + /*! + * \brief Set acquisition/tracking common Gnss_Synchro object pointer + * to exchange synchronization data between acquisition and tracking blocks. + * \param p_gnss_synchro Satellite information shared by the processing blocks. + */ + void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) + { + d_gnss_synchro = p_gnss_synchro; + } + + /*! + * \brief Returns the maximum peak of grid search. + */ + unsigned int mag() + { + return d_mag; + } + + /*! + * \brief Initializes acquisition algorithm. + */ + void init(); + + /*! + * \brief Sets local code for PCPS acquisition algorithm. + * \param code - Pointer to the PRN code. + */ + void set_local_code(std::complex * code); + + /*! + * \brief Starts acquisition algorithm, turning from standby mode to + * active mode + * \param active - bool that activates/deactivates the block. + */ + void set_active(bool active); + + /*! + * \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. + */ + void set_channel(unsigned int channel) + { + d_channel = channel; + } + + /*! + * \brief Set statistics threshold of PCPS algorithm. + * \param threshold - Threshold for signal detection (check \ref Navitec2012, + * Algorithm 1, for a definition of this threshold). + */ + void set_threshold(float threshold) + { + d_threshold = threshold; + } + + /*! + * \brief Set maximum Doppler grid search + * \param doppler_max - Maximum Doppler shift considered in the grid search [Hz]. + */ + void set_doppler_max(unsigned int doppler_max) + { + d_doppler_max = doppler_max; + } + + /*! + * \brief Set Doppler steps for the grid search + * \param doppler_step - Frequency bin of the search grid [Hz]. + */ + void set_doppler_step(unsigned int doppler_step) + { + d_doppler_step = doppler_step; + } + + + /*! + * \brief Parallel Code Phase Search Acquisition signal processing. + */ + int general_work(int noutput_items, gr_vector_int &ninput_items, + gr_vector_const_void_star &input_items, + gr_vector_void_star &output_items); + +}; + +#endif /* GNSS_SDR_PCPS_ACQUISITION_SC_H_*/ diff --git a/src/algorithms/acquisition/libs/CMakeLists.txt b/src/algorithms/acquisition/libs/CMakeLists.txt new file mode 100644 index 000000000..01ab3de68 --- /dev/null +++ b/src/algorithms/acquisition/libs/CMakeLists.txt @@ -0,0 +1,91 @@ +# Copyright (C) 2012-2015 (see AUTHORS file for a list of contributors) +# +# This file is part of GNSS-SDR. +# +# GNSS-SDR is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# GNSS-SDR is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNSS-SDR. If not, see . +# + + +#if(ENABLE_CUDA) +# # Append current NVCC flags by something, eg comput capability +# # set(CUDA_NVCC_FLAGS ${CUDA_NVCC_FLAGS} --gpu-architecture sm_30) +# list(APPEND CUDA_NVCC_FLAGS "-gencode arch=compute_30,code=sm_30; -std=c++11;-O3; -use_fast_math -default-stream per-thread") +# set(CUDA_PROPAGATE_HOST_FLAGS OFF) +# CUDA_INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_SOURCE_DIR}) +# set(LIB_TYPE STATIC) #set the lib type +# CUDA_ADD_LIBRARY(CUDA_CORRELATOR_LIB ${LIB_TYPE} cuda_multicorrelator.h cuda_multicorrelator.cu) +# set(OPT_TRACKING_LIBRARIES ${OPT_TRACKING_LIBRARIES} CUDA_CORRELATOR_LIB) +# set(OPT_TRACKING_INCLUDES ${OPT_TRACKING_INCLUDES} ${CUDA_INCLUDE_DIRS} ) +#endif(ENABLE_CUDA) + + + +#set(TRACKING_LIB_SOURCES +set(ACQUISITION_LIB_SOURCES + gps_fpga_acquisition_8sc.cc +# cpu_multicorrelator.cc +# cpu_multicorrelator_16sc.cc +# lock_detectors.cc +# tcp_communication.cc +# tcp_packet_data.cc +# tracking_2nd_DLL_filter.cc +# tracking_2nd_PLL_filter.cc +# tracking_discriminators.cc +# tracking_FLL_PLL_filter.cc +# tracking_loop_filter.cc +) + +#if(ENABLE_FPGA) +# SET(ACQUISITION_LIB_SOURCES ${ACQUISITION_LIB_SOURCES} fpga_acquisition_8sc.cc) +#endif(ENABLE_FPGA) + +include_directories( + $(CMAKE_CURRENT_SOURCE_DIR) + ${CMAKE_SOURCE_DIR}/src/core/system_parameters + ${CMAKE_SOURCE_DIR}/src/core/interfaces + ${CMAKE_SOURCE_DIR}/src/core/receiver + ${VOLK_INCLUDE_DIRS} + ${GLOG_INCLUDE_DIRS} + ${GFlags_INCLUDE_DIRS} + ${OPT_TRACKING_INCLUDES} + ${VOLK_GNSSSDR_INCLUDE_DIRS} +) + +if(ENABLE_GENERIC_ARCH) + add_definitions( -DGENERIC_ARCH=1 ) +endif(ENABLE_GENERIC_ARCH) + +if (SSE3_AVAILABLE) + add_definitions( -DHAVE_SSE3=1 ) +endif(SSE3_AVAILABLE) + + +#file(GLOB TRACKING_LIB_HEADERS "*.h") +file(GLOB ACQUISITION_LIB_HEADERS "*.h") +#list(SORT TRACKING_LIB_HEADERS) +list(SORT ACQUISITION_LIB_HEADERS) +#add_library(tracking_lib ${TRACKING_LIB_SOURCES} ${TRACKING_LIB_HEADERS}) +add_library(acquisition_lib ${ACQUISITION_LIB_SOURCES} ${ACQUISITION_LIB_HEADERS}) +#source_group(Headers FILES ${TRACKING_LIB_HEADERS}) +source_group(Headers FILES ${ACQUISITION_LIB_HEADERS}) +#target_link_libraries(tracking_lib ${OPT_TRACKING_LIBRARIES} ${VOLK_LIBRARIES} ${VOLK_GNSSSDR_LIBRARIES} ${GNURADIO_RUNTIME_LIBRARIES}) +target_link_libraries(acquisition_lib ${OPT_ACQUISITION_LIBRARIES} ${VOLK_LIBRARIES} ${VOLK_GNSSSDR_LIBRARIES} ${GNURADIO_RUNTIME_LIBRARIES}) +if(VOLK_GNSSSDR_FOUND) +# add_dependencies(tracking_lib glog-${glog_RELEASE}) + add_dependencies(acquisition_lib glog-${glog_RELEASE}) +else(VOLK_GNSSSDR_FOUND) +# add_dependencies(tracking_lib glog-${glog_RELEASE} volk_gnsssdr_module) + add_dependencies(acquisition_lib glog-${glog_RELEASE} volk_gnsssdr_module) +endif() + diff --git a/src/algorithms/acquisition/libs/gps_fpga_acquisition_8sc.cc b/src/algorithms/acquisition/libs/gps_fpga_acquisition_8sc.cc new file mode 100644 index 000000000..0178d84a7 --- /dev/null +++ b/src/algorithms/acquisition/libs/gps_fpga_acquisition_8sc.cc @@ -0,0 +1,336 @@ +/*! + * \file gps_fpga_acquisition_8sc.cc + * \brief High optimized FPGA vector correlator class + * \authors
    + *
  • Marc Majoral, 2017. mmajoral(at)cttc.cat + *
+ * + * Class that controls and executes a high optimized vector correlator + * class in the FPGA + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2017 (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_fpga_acquisition_8sc.h" +#include + +// FPGA stuff +#include + +// libraries used by DMA test code and GIPO test code +#include +#include +#include +#include + +// libraries used by DMA test code +#include +#include +#include +#include + +// libraries used by GPIO test code +#include +#include +#include + +// logging +#include + +#include "GPS_L1_CA.h" + +#define PAGE_SIZE 0x10000 +//#define MAX_LENGTH_DEVICEIO_NAME 50 +#define CODE_RESAMPLER_NUM_BITS_PRECISION 20 +#define CODE_PHASE_STEP_CHIPS_NUM_NBITS CODE_RESAMPLER_NUM_BITS_PRECISION +#define pwrtwo(x) (1 << (x)) +#define MAX_CODE_RESAMPLER_COUNTER pwrtwo(CODE_PHASE_STEP_CHIPS_NUM_NBITS) // 2^CODE_PHASE_STEP_CHIPS_NUM_NBITS +#define PHASE_CARR_NBITS 32 +#define PHASE_CARR_NBITS_INT 1 +#define PHASE_CARR_NBITS_FRAC PHASE_CARR_NBITS - PHASE_CARR_NBITS_INT + +#define MAX_PHASE_STEP_RAD 0.999999999534339 // 1 - pow(2,-31); + + + bool gps_fpga_acquisition_8sc::init(unsigned int fft_size, unsigned int nsamples_total, long freq, unsigned int doppler_max, unsigned int doppler_step, int num_doppler_bins, long fs_in, unsigned select_queue) + { + float phase_step_rad_fpga; + float phase_step_rad_fpga_real; + + d_phase_step_rad_vector = new float[num_doppler_bins]; + + for (unsigned int doppler_index = 0; doppler_index < num_doppler_bins; doppler_index++) + { + int doppler = -static_cast(doppler_max) + doppler_step * doppler_index; + float phase_step_rad = GPS_TWO_PI * (freq + doppler) / static_cast(fs_in); + // The doppler step can never be outside the range -pi to +pi, otherwise there would be aliasing + // The FPGA expects phase_step_rad between -1 (-pi) to +1 (+pi) + // The FPGA also expects the phase to be negative since it produces cos(x) -j*sin(x) + // while the gnss-sdr software (volk_gnsssdr_s32f_sincos_32fc) generates cos(x) + j*sin(x) + phase_step_rad_fpga = phase_step_rad/(GPS_TWO_PI/2); + // avoid saturation of the fixed point representation in the fpga + // (only the positive value can saturate due to the 2's complement representation) + if (phase_step_rad_fpga == 1.0) + { + phase_step_rad_fpga = MAX_PHASE_STEP_RAD; + } + d_phase_step_rad_vector[doppler_index] = phase_step_rad_fpga; + + } + + // sanity check : check test register + unsigned writeval = 0x55AA; + unsigned readval; + readval = gps_fpga_acquisition_8sc::fpga_acquisition_test_register(writeval); + if (writeval != readval) + { + printf("test register fail\n"); + LOG(WARNING) << "Acquisition test register sanity check failed"; + } + else + { + printf("test register success\n"); + LOG(INFO) << "Acquisition test register sanity check success !"; + } + + d_nsamples = fft_size; + d_nsamples_total = nsamples_total; + + gps_fpga_acquisition_8sc::configure_acquisition(); + + return true; +} + + + +bool gps_fpga_acquisition_8sc::set_local_code(gr_complex* fft_codes) +{ + int i; + float val; + float max = 0; + d_fft_codes = new lv_16sc_t[d_nsamples_total]; + + for (i=0;i max) + { + max = abs(fft_codes[i].real()); + } + if(abs(fft_codes[i].imag()) > max) + { + max = abs(fft_codes[i].imag()); + } + } + + for (i=0;i + *
  • Marc Majoral, 2017. mmajoral(at)cttc.cat + *
  • Javier Arribas, 2016. jarribas(at)cttc.es + * + * + * Class that controls and executes a high optimized vector correlator + * class in the FPGA + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2017 (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_FPGA_ACQUISITION_8SC_H_ +#define GNSS_SDR_FPGA_ACQUISITION_8SC_H_ + +#include + +#include + + +/*! + * \brief Class that implements carrier wipe-off and correlators. + */ +class gps_fpga_acquisition_8sc +{ +public: + gps_fpga_acquisition_8sc(); + ~gps_fpga_acquisition_8sc(); + //bool init(int max_signal_length_samples, int n_correlators); + bool init(unsigned int fft_size, unsigned int nsamples_total, long d_freq, unsigned int doppler_max, unsigned int doppler_step, int num_doppler_bins, long fs_in, unsigned select_queue); + bool set_local_code(gr_complex* fft_codes); //int code_length_chips, const lv_16sc_t* local_code_in, float *shifts_chips); + bool free(); + void run_acquisition(void); + void set_phase_step(unsigned int doppler_index); + void read_acquisition_results(uint32_t* max_index, float* max_magnitude, unsigned *initial_sample, float *power_sum); + void block_samples(); + void unblock_samples(); +private: + const lv_16sc_t *d_local_code_in; + lv_16sc_t *d_corr_out; + float *d_shifts_chips; + int d_code_length_chips; + int d_n_correlators; + + // data related to the hardware module and the driver + char d_device_io_name[11] = "/dev/uio13"; // driver io name + int d_fd; // driver descriptor + volatile unsigned *d_map_base; // driver memory map + + // configuration data received from the interface + lv_16sc_t *d_fft_codes = nullptr; + float *d_phase_step_rad_vector = nullptr; + + unsigned int d_nsamples_total; // total number of samples in the fft including padding + unsigned int d_nsamples; // number of samples not including padding + unsigned int d_select_queue =0; // queue selection + +// unsigned int d_channel; // channel number +// unsigned d_ncorrelators; // number of correlators +// unsigned d_correlator_length_samples; +// float d_rem_code_phase_chips; +// float d_code_phase_step_chips; +// float d_rem_carrier_phase_in_rad; +// float d_phase_step_rad; + + // configuration data computed in the format that the FPGA expects +// unsigned *d_initial_index; +// unsigned *d_initial_interp_counter; +// unsigned d_code_phase_step_chips_num; +// int d_rem_carr_phase_rad_int; +// int d_phase_step_rad_int; +// unsigned d_initial_sample_counter; + + // FPGA private functions + unsigned fpga_acquisition_test_register(unsigned writeval); + void fpga_configure_acquisition_local_code(lv_16sc_t fft_local_code[]); + void configure_acquisition(); + + + //void fpga_acquisition_8sc::run_acquisition(void); +}; + + +#endif /* GNSS_SDR_FPGA_MULTICORRELATOR_H_ */ diff --git a/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_ca_pcps_acquisition_test_fpga.cc b/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_ca_pcps_acquisition_test_fpga.cc new file mode 100644 index 000000000..0837bfb30 --- /dev/null +++ b/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_ca_pcps_acquisition_test_fpga.cc @@ -0,0 +1,392 @@ +/*! + * \file gps_l1_ca_pcps_acquisition_test_fpga.cc + * \brief This class implements an acquisition test for + * GpsL1CaPcpsAcquisitionFpga class based on some input parameters. + * \author Marc Majoral, 2017. mmajoral(at)cttc.cat + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2017 (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 +#include +#include +#include +#include +#include "gnss_block_factory.h" +#include "gnss_block_interface.h" +#include "in_memory_configuration.h" +#include "gnss_sdr_valve.h" +#include "gnss_synchro.h" +#include "gps_l1_ca_pcps_acquisition_fpga.h" + +#include + +#define DMA_ACQ_TRANSFER_SIZE 4000 +#define RX_SIGNAL_MAX_VALUE 127 // 2^7 - 1 for 8-bit signed values +#define NTIMES_CYCLE_THROUGH_RX_SAMPLES_FILE 50 // number of times we cycle through the file containing the received samples +#define ONE_SECOND 1000000 // one second in microseconds +#define FLOAT_SIZE (sizeof(float)) // size of the float variable in characters + + +// thread that reads the file containing the received samples, scales the samples to the dynamic range of the fixed point values, sends +// the samples to the DMA and finally it stops the top block +void thread_acquisition_send_rx_samples(gr::top_block_sptr top_block, const char * file_name) +{ + + FILE *ptr_myfile; // file descriptor + int fileLen; // length of the file containing the received samples + int tx_fd; // DMA descriptor + + // sleep for 1 second to give some time to GNSS-SDR to activate the acquisition module. + // the acquisition module does not block the RX buffer before activation. + // If this process starts sending samples straight ahead without waiting it could occur that + // the first samples are lost. This is normal behaviour in a real receiver but this is not what + // we want for the test + usleep(ONE_SECOND); + + char *buffer_temp; // temporary buffer to convert from binary char to float and from float to char + signed char *buffer_char; // temporary buffer to store the samples to be sent to the DMA + buffer_temp = (char *)malloc(FLOAT_SIZE); // allocate space for the temporary buffer + if (!buffer_temp) + { + fprintf(stderr, "Memory error!"); + } + + ptr_myfile = fopen(file_name,"rb"); // file containing the received signal + if (!ptr_myfile) + { + printf("Unable to open file!"); + } + + // determine the length of the file that contains the received signal + fseek(ptr_myfile, 0, SEEK_END); + fileLen = ftell(ptr_myfile); + fseek(ptr_myfile, 0, SEEK_SET); + + // first step: check for the maximum value of the received signal + + float max = 0; + float *pointer_float; + pointer_float = (float *) &buffer_temp[0]; + for (int k=0;k max) + { + max = (pointer_float[0]); + } + + } + + // go back to the beginning of the file containing the received samples + fseek(ptr_myfile, 0, SEEK_SET); + + // allocate memory for the samples to be transferred to the DMA + + buffer_char = (signed char *)malloc(DMA_ACQ_TRANSFER_SIZE); + if (!buffer_char) + { + fprintf(stderr, "Memory error!"); + } + + // open the DMA descriptor + tx_fd = open("/dev/loop_tx", O_WRONLY); + if ( tx_fd < 0 ) + { + printf("can't open loop device\n"); + exit(1); + } + + + // cycle through the file containing the received samples + + for (int k=0;k DMA_ACQ_TRANSFER_SIZE) + { + + + transfer_size = DMA_ACQ_TRANSFER_SIZE; + num_transferred_samples = num_transferred_samples + DMA_ACQ_TRANSFER_SIZE; + + } + else + { + transfer_size = fileLen/FLOAT_SIZE - num_transferred_samples; + num_transferred_samples = fileLen/FLOAT_SIZE; + } + + + for (int t=0;tstop(); + + + +} + +// ######## GNURADIO BLOCK MESSAGE RECEVER ######### +class GpsL1CaPcpsAcquisitionTestFpga_msg_rx; + +typedef boost::shared_ptr GpsL1CaPcpsAcquisitionTest_msg_fpga_rx_sptr; + +GpsL1CaPcpsAcquisitionTest_msg_fpga_rx_sptr GpsL1CaPcpsAcquisitionTestFpga_msg_rx_make(); + +class GpsL1CaPcpsAcquisitionTestFpga_msg_rx : public gr::block +{ +private: + friend GpsL1CaPcpsAcquisitionTest_msg_fpga_rx_sptr GpsL1CaPcpsAcquisitionTestFpga_msg_rx_make(); + void msg_handler_events(pmt::pmt_t msg); + GpsL1CaPcpsAcquisitionTestFpga_msg_rx(); +public: + int rx_message; + ~GpsL1CaPcpsAcquisitionTestFpga_msg_rx(); //!< Default destructor +}; + + +GpsL1CaPcpsAcquisitionTest_msg_fpga_rx_sptr GpsL1CaPcpsAcquisitionTestFpga_msg_rx_make() +{ + return GpsL1CaPcpsAcquisitionTest_msg_fpga_rx_sptr(new GpsL1CaPcpsAcquisitionTestFpga_msg_rx()); +} + + +void GpsL1CaPcpsAcquisitionTestFpga_msg_rx::msg_handler_events(pmt::pmt_t msg) +{ + try + { + long int message = pmt::to_long(msg); + rx_message = message; + } + catch(boost::bad_any_cast& e) + { + LOG(WARNING) << "msg_handler_telemetry Bad any cast!"; + rx_message = 0; + } +} + + +GpsL1CaPcpsAcquisitionTestFpga_msg_rx::GpsL1CaPcpsAcquisitionTestFpga_msg_rx() : + gr::block("GpsL1CaPcpsAcquisitionTestFpga_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(&GpsL1CaPcpsAcquisitionTestFpga_msg_rx::msg_handler_events, this, _1)); + rx_message = 0; +} + + +GpsL1CaPcpsAcquisitionTestFpga_msg_rx::~GpsL1CaPcpsAcquisitionTestFpga_msg_rx() +{} + + +// ########################################################### + +class GpsL1CaPcpsAcquisitionTestFpga: public ::testing::Test +{ +protected: + GpsL1CaPcpsAcquisitionTestFpga() + { + factory = std::make_shared(); + config = std::make_shared(); + item_size = sizeof(gr_complex); + gnss_synchro = Gnss_Synchro(); + } + + ~GpsL1CaPcpsAcquisitionTestFpga() + {} + + void init(); + + gr::top_block_sptr top_block; + std::shared_ptr factory; + std::shared_ptr config; + Gnss_Synchro gnss_synchro; + size_t item_size; +}; + + +void GpsL1CaPcpsAcquisitionTestFpga::init() +{ + gnss_synchro.Channel_ID = 0; + gnss_synchro.System = 'G'; + std::string signal = "1C"; + signal.copy(gnss_synchro.Signal, 2, 0); + gnss_synchro.PRN = 1; + config->set_property("GNSS-SDR.internal_fs_hz", "4000000"); + //config->set_property("Acquisition.item_type", "gr_complex"); + config->set_property("Acquisition.item_type", "cshort"); + config->set_property("Acquisition.if", "0"); + config->set_property("Acquisition.coherent_integration_time_ms", "1"); + config->set_property("Acquisition.dump", "false"); + config->set_property("Acquisition.implementation", "GPS_L1_CA_PCPS_Acquisition"); + config->set_property("Acquisition.threshold", "0.001"); + config->set_property("Acquisition.doppler_max", "5000"); + config->set_property("Acquisition.doppler_step", "500"); + config->set_property("Acquisition.repeat_satellite", "false"); + config->set_property("Acquisition.pfa", "0.0"); +} + + + +TEST_F(GpsL1CaPcpsAcquisitionTestFpga, Instantiate) +{ + init(); + boost::shared_ptr acquisition = boost::make_shared(config.get(), "Acquisition", 0, 1); +} + +TEST_F(GpsL1CaPcpsAcquisitionTestFpga, ValidationOfResults) +{ + struct timeval tv; + long long int begin = 0; + long long int end = 0; + top_block = gr::make_top_block("Acquisition test"); + + double expected_delay_samples = 524; + double expected_doppler_hz = 1680; + init(); + + + + + std::shared_ptr acquisition = std::make_shared(config.get(), "Acquisition", 0, 1); + + boost::shared_ptr msg_rx = GpsL1CaPcpsAcquisitionTestFpga_msg_rx_make(); + + 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_threshold(0.1); + }) << "Failure setting threshold." << std::endl; + + ASSERT_NO_THROW( { + acquisition->set_doppler_max(10000); + }) << "Failure setting doppler_max." << std::endl; + + ASSERT_NO_THROW( { + acquisition->set_doppler_step(250); + }) << "Failure setting doppler_step." << std::endl; + + ASSERT_NO_THROW( { + acquisition->connect(top_block); + }) << "Failure connecting acquisition to the top_block." << std::endl; + + std::string file = "./GPS_L1_CA_ID_1_Fs_4Msps_2ms.dat"; + const char * file_name = file.c_str(); + + ASSERT_NO_THROW( { + //std::string path = std::string(TEST_PATH); + //std::string file = path + "signal_samples/GSoC_CTTC_capture_2012_07_26_4Msps_4ms.dat"; + //std::string file = path + "signal_samples/GPS_L1_CA_ID_1_Fs_4Msps_2ms.dat"; + + // for the unit test use dummy blocks to make the flowgraph work and allow the acquisition message to be sent. + // in the actual system there is a flowchart running in parallel so this is not needed + + gr::blocks::file_source::sptr file_source = gr::blocks::file_source::make(sizeof(gr_complex), file_name, false); + gr::blocks::null_sink::sptr null_sink = gr::blocks::null_sink::make(sizeof(gr_complex)); + gr::blocks::throttle::sptr throttle_block = gr::blocks::throttle::make(sizeof(gr_complex),1000); + + top_block->connect(file_source, 0, throttle_block, 0); + top_block->connect(throttle_block, 0, null_sink, 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_state(1); // Ensure that acquisition starts at the first state + acquisition->init(); + top_block->start(); // Start the top block + + // start thread that sends the DMA samples to the FPGA + boost::thread t3{thread_acquisition_send_rx_samples, top_block, file_name}; + + EXPECT_NO_THROW( { + gettimeofday(&tv, NULL); + begin = tv.tv_sec * 1000000 + tv.tv_usec; + acquisition->reset(); // launch the tracking process + top_block->wait(); + gettimeofday(&tv, NULL); + end = tv.tv_sec * 1000000 + tv.tv_usec; + }) << "Failure running the top_block." << std::endl; + + t3.join(); + + + unsigned long int nsamples = gnss_synchro.Acq_samplestamp_samples; + std::cout << "Acquired " << nsamples << " samples in " << (end - begin) << " microseconds" << std::endl; + + ASSERT_EQ(1, msg_rx->rx_message) << "Acquisition failure. Expected message: 1=ACQ SUCCESS."; + + double delay_error_samples = std::abs(expected_delay_samples - gnss_synchro.Acq_delay_samples); + float delay_error_chips = (float)(delay_error_samples * 1023 / 4000); + double doppler_error_hz = std::abs(expected_doppler_hz - gnss_synchro.Acq_doppler_hz); + + 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"; + +} + From eccbd0f97ad200424afac4b43158d52e31fbe5de Mon Sep 17 00:00:00 2001 From: mmajoral Date: Fri, 5 May 2017 16:15:27 +0200 Subject: [PATCH 2/5] acquisition gps unit test for the FPGA. The code is currently being cleaned --- build/.gitignore | 4 ---- src/algorithms/acquisition/CMakeLists.txt | 1 + src/algorithms/acquisition/adapters/CMakeLists.txt | 6 +++++- src/algorithms/acquisition/gnuradio_blocks/CMakeLists.txt | 8 +++++++- src/core/receiver/CMakeLists.txt | 2 ++ src/tests/CMakeLists.txt | 1 + src/tests/test_main.cc | 1 + 7 files changed, 17 insertions(+), 6 deletions(-) delete mode 100644 build/.gitignore diff --git a/build/.gitignore b/build/.gitignore deleted file mode 100644 index 86d0cb272..000000000 --- a/build/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -# Ignore everything in this directory -* -# Except this file -!.gitignore \ No newline at end of file diff --git a/src/algorithms/acquisition/CMakeLists.txt b/src/algorithms/acquisition/CMakeLists.txt index 3c52a9e01..c02eb1ab4 100644 --- a/src/algorithms/acquisition/CMakeLists.txt +++ b/src/algorithms/acquisition/CMakeLists.txt @@ -18,4 +18,5 @@ add_subdirectory(adapters) add_subdirectory(gnuradio_blocks) +add_subdirectory(libs) diff --git a/src/algorithms/acquisition/adapters/CMakeLists.txt b/src/algorithms/acquisition/adapters/CMakeLists.txt index 1ead04df8..d7b00edc1 100644 --- a/src/algorithms/acquisition/adapters/CMakeLists.txt +++ b/src/algorithms/acquisition/adapters/CMakeLists.txt @@ -33,7 +33,10 @@ set(ACQ_ADAPTER_SOURCES galileo_e5a_noncoherent_iq_acquisition_caf.cc ) - +if(ENABLE_FPGA) + set(ACQ_ADAPTER_SOURCES ${ACQ_ADAPTER_SOURCES} gps_l1_ca_pcps_acquisition_fpga.cc) +endif(ENABLE_FPGA) + if(OPENCL_FOUND) set(ACQ_ADAPTER_SOURCES ${ACQ_ADAPTER_SOURCES} gps_l1_ca_pcps_opencl_acquisition.cc) endif(OPENCL_FOUND) @@ -44,6 +47,7 @@ include_directories( ${CMAKE_SOURCE_DIR}/src/core/interfaces ${CMAKE_SOURCE_DIR}/src/core/receiver ${CMAKE_SOURCE_DIR}/src/algorithms/acquisition/gnuradio_blocks + ${CMAKE_SOURCE_DIR}/src/algorithms/acquisition/libs ${CMAKE_SOURCE_DIR}/src/algorithms/libs ${Boost_INCLUDE_DIRS} ${GLOG_INCLUDE_DIRS} diff --git a/src/algorithms/acquisition/gnuradio_blocks/CMakeLists.txt b/src/algorithms/acquisition/gnuradio_blocks/CMakeLists.txt index 945d5e2cc..746432c25 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/CMakeLists.txt +++ b/src/algorithms/acquisition/gnuradio_blocks/CMakeLists.txt @@ -29,6 +29,10 @@ set(ACQ_GR_BLOCKS_SOURCES galileo_pcps_8ms_acquisition_cc.cc galileo_e5a_noncoherent_iq_acquisition_caf_cc.cc ) + +if(ENABLE_FPGA) + set(ACQ_GR_BLOCKS_SOURCES ${ACQ_GR_BLOCKS_SOURCES} gps_pcps_acquisition_fpga_sc.cc) +endif(ENABLE_FPGA) if(OPENCL_FOUND) set(ACQ_GR_BLOCKS_SOURCES ${ACQ_GR_BLOCKS_SOURCES} pcps_opencl_acquisition_cc.cc) @@ -39,6 +43,7 @@ include_directories( ${CMAKE_SOURCE_DIR}/src/core/system_parameters ${CMAKE_SOURCE_DIR}/src/core/interfaces ${CMAKE_SOURCE_DIR}/src/core/receiver + ${CMAKE_SOURCE_DIR}/src/algorithms/acquisition/libs ${CMAKE_SOURCE_DIR}/src/algorithms/libs ${GLOG_INCLUDE_DIRS} ${GFlags_INCLUDE_DIRS} @@ -60,7 +65,8 @@ file(GLOB ACQ_GR_BLOCKS_HEADERS "*.h") list(SORT ACQ_GR_BLOCKS_HEADERS) add_library(acq_gr_blocks ${ACQ_GR_BLOCKS_SOURCES} ${ACQ_GR_BLOCKS_HEADERS}) source_group(Headers FILES ${ACQ_GR_BLOCKS_HEADERS}) -target_link_libraries(acq_gr_blocks gnss_sp_libs gnss_system_parameters ${GNURADIO_RUNTIME_LIBRARIES} ${GNURADIO_FFT_LIBRARIES} ${VOLK_LIBRARIES} ${VOLK_GNSSSDR_LIBRARIES} ${OPT_LIBRARIES}) +#target_link_libraries(acq_gr_blocks gnss_sp_libs gnss_system_parameters ${GNURADIO_RUNTIME_LIBRARIES} ${GNURADIO_FFT_LIBRARIES} +target_link_libraries(acq_gr_blocks acquisition_lib gnss_sp_libs gnss_system_parameters ${GNURADIO_RUNTIME_LIBRARIES} ${GNURADIO_FFT_LIBRARIES} ${VOLK_LIBRARIES} ${VOLK_GNSSSDR_LIBRARIES} ${OPT_LIBRARIES} ${OPT_ACQUISITION_LIBRARIES}) if(NOT VOLK_GNSSSDR_FOUND) add_dependencies(acq_gr_blocks volk_gnsssdr_module) diff --git a/src/core/receiver/CMakeLists.txt b/src/core/receiver/CMakeLists.txt index a443b8a60..14ff036fb 100644 --- a/src/core/receiver/CMakeLists.txt +++ b/src/core/receiver/CMakeLists.txt @@ -59,6 +59,7 @@ include_directories( ${CMAKE_SOURCE_DIR}/src/algorithms/input_filter/gnuradio_blocks ${CMAKE_SOURCE_DIR}/src/algorithms/acquisition/adapters ${CMAKE_SOURCE_DIR}/src/algorithms/acquisition/gnuradio_blocks + ${CMAKE_SOURCE_DIR}/src/algorithms/acquisition/libs ${CMAKE_SOURCE_DIR}/src/algorithms/tracking/adapters ${CMAKE_SOURCE_DIR}/src/algorithms/tracking/gnuradio_blocks ${CMAKE_SOURCE_DIR}/src/algorithms/tracking/libs @@ -139,6 +140,7 @@ target_link_libraries(gnss_rx ${Boost_LIBRARIES} resampler_adapters acq_adapters tracking_lib + acquisition_lib tracking_adapters channel_adapters telemetry_decoder_adapters diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index 48ef5a5df..bc6b4c903 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -266,6 +266,7 @@ include_directories( ${CMAKE_SOURCE_DIR}/src/algorithms/signal_generator/gnuradio_blocks ${CMAKE_SOURCE_DIR}/src/algorithms/input_filter/adapters ${CMAKE_SOURCE_DIR}/src/algorithms/input_filter/gnuradio_blocks + ${CMAKE_SOURCE_DIR}/src/algorithms/acquisition/libs ${CMAKE_SOURCE_DIR}/src/algorithms/acquisition/adapters ${CMAKE_SOURCE_DIR}/src/algorithms/acquisition/gnuradio_blocks ${CMAKE_SOURCE_DIR}/src/algorithms/PVT/libs diff --git a/src/tests/test_main.cc b/src/tests/test_main.cc index 9c41e651b..bafab092a 100644 --- a/src/tests/test_main.cc +++ b/src/tests/test_main.cc @@ -121,6 +121,7 @@ DECLARE_string(log_dir); #if FPGA_BLOCKS_TEST #include "unit-tests/signal-processing-blocks/tracking/gps_l1_ca_dll_pll_tracking_test_fpga.cc" +#include "unit-tests/signal-processing-blocks/acquisition/gps_l1_ca_pcps_acquisition_test_fpga.cc" #endif #include "unit-tests/signal-processing-blocks/pvt/rtcm_test.cc" From 2ee29af3bd4da56fd83a29e2bbc2161ee642749d Mon Sep 17 00:00:00 2001 From: Javier Arribas Date: Fri, 5 May 2017 16:37:29 +0200 Subject: [PATCH 3/5] Adding FPGA accelerators support in gnss-sdr configuration options --- conf/gnss-sdr_GPS_L1_FPGA.conf | 83 +++ .../gps_l1_ca_pcps_acquisition_fpga.h | 2 +- src/core/receiver/CMakeLists.txt | 4 + src/core/receiver/gnss_block_factory.cc | 38 + src/core/receiver/gnss_flowgraph.cc | 701 +++++++++--------- 5 files changed, 490 insertions(+), 338 deletions(-) create mode 100644 conf/gnss-sdr_GPS_L1_FPGA.conf diff --git a/conf/gnss-sdr_GPS_L1_FPGA.conf b/conf/gnss-sdr_GPS_L1_FPGA.conf new file mode 100644 index 000000000..92d361aad --- /dev/null +++ b/conf/gnss-sdr_GPS_L1_FPGA.conf @@ -0,0 +1,83 @@ +; You can define your own receiver and invoke it by doing +; gnss-sdr --config_file=my_GNSS_SDR_configuration.conf +; + +[GNSS-SDR] + +;######### GLOBAL OPTIONS ################## +;internal_fs_hz: Internal signal sampling frequency after the signal conditioning stage [Hz]. +GNSS-SDR.internal_fs_hz=4000000 + + +;######### SIGNAL_SOURCE CONFIG ############ +SignalSource.implementation=Pass_Through +SignalSource.filename=/datalogger/signals/Agilent/New York/4msps.dat ; <- PUT YOUR FILE HERE +SignalSource.item_type=ishort +SignalSource.sampling_frequency=4000000 +SignalSource.freq=1575420000 +SignalSource.repeat=false +SignalSource.dump=false +SignalSource.dump_filename=../data/signal_source.dat +SignalSource.enable_throttle_control=false +SignalSource.enable_FPGA=true + + +;######### SIGNAL_CONDITIONER CONFIG ############ +SignalConditioner.implementation=Pass_Through +SignalConditioner.item_type=cshort +SignalConditioner.enable_FPGA=true + +;######### CHANNELS GLOBAL CONFIG ############ +Channels_1C.count=8 +Channels.in_acquisition=1 +Channel.signal=1C + + +;######### ACQUISITION GLOBAL CONFIG ############ +Acquisition_1C.dump=false +Acquisition_1C.dump_filename=./acq_dump.dat +Acquisition_1C.item_type=cshort +Acquisition_1C.if=0 +Acquisition_1C.sampled_ms=1 +Acquisition_1C.implementation=GPS_L1_CA_PCPS_Acquisition_Fpga +Acquisition_1C.threshold=0.005 +;Acquisition_1C.pfa=0.01 +Acquisition_1C.doppler_max=10000 +Acquisition_1C.doppler_step=500 + +;######### TRACKING GLOBAL CONFIG ############ +Tracking_1C.implementation=GPS_L1_CA_DLL_PLL_C_Aid_Tracking_Fpga +Tracking_1C.item_type=cshort +Tracking_1C.if=0 +Tracking_1C.dump=false +Tracking_1C.dump_filename=../data/epl_tracking_ch_ +Tracking_1C.pll_bw_hz=45.0; +Tracking_1C.dll_bw_hz=2.0; +Tracking_1C.order=3; + +;######### TELEMETRY DECODER GPS CONFIG ############ +TelemetryDecoder_1C.implementation=GPS_L1_CA_Telemetry_Decoder +TelemetryDecoder_1C.dump=false +TelemetryDecoder_1C.decimation_factor=1; + +;######### OBSERVABLES CONFIG ############ +Observables.implementation=GPS_L1_CA_Observables +Observables.dump=false +Observables.dump_filename=./observables.dat + + +;######### PVT CONFIG ############ +PVT.implementation=GPS_L1_CA_PVT +PVT.averaging_depth=100 +PVT.flag_averaging=false +PVT.output_rate_ms=10 +PVT.display_rate_ms=500 +PVT.dump_filename=./PVT +PVT.nmea_dump_filename=./gnss_sdr_pvt.nmea; +PVT.flag_nmea_tty_port=false; +PVT.nmea_dump_devname=/dev/pts/4 +PVT.flag_rtcm_server=false +PVT.flag_rtcm_tty_port=false +PVT.rtcm_dump_devname=/dev/pts/1 +PVT.dump=false + diff --git a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fpga.h b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fpga.h index 290860255..14b1fd646 100644 --- a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fpga.h +++ b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fpga.h @@ -70,7 +70,7 @@ public: */ std::string implementation() { - return "GPS_L1_CA_PCPS_Acquisition"; + return "GPS_L1_CA_PCPS_Acquisition_Fpga"; } size_t item_size() { diff --git a/src/core/receiver/CMakeLists.txt b/src/core/receiver/CMakeLists.txt index 14ff036fb..5a7707132 100644 --- a/src/core/receiver/CMakeLists.txt +++ b/src/core/receiver/CMakeLists.txt @@ -36,6 +36,10 @@ if(ENABLE_CUDA) set(OPT_RECEIVER_INCLUDE_DIRS ${OPT_RECEIVER_INCLUDE_DIRS} ${CUDA_INCLUDE_DIRS}) endif(ENABLE_CUDA) +if(ENABLE_FPGA) + add_definitions(-DENABLE_FPGA=1) +endif(ENABLE_FPGA) + include_directories( $(CMAKE_CURRENT_SOURCE_DIR) diff --git a/src/core/receiver/gnss_block_factory.cc b/src/core/receiver/gnss_block_factory.cc index 8df7faf88..0d66f9225 100644 --- a/src/core/receiver/gnss_block_factory.cc +++ b/src/core/receiver/gnss_block_factory.cc @@ -98,6 +98,11 @@ #include "galileo_e1_pvt.h" #include "hybrid_pvt.h" +#if ENABLE_FPGA +#include "gps_l1_ca_dll_pll_c_aid_tracking_fpga.h" +#include "gps_l1_ca_pcps_acquisition_fpga.h" +#endif + #if OPENCL_BLOCKS #include "gps_l1_ca_pcps_opencl_acquisition.h" #endif @@ -892,6 +897,15 @@ std::unique_ptr GNSSBlockFactory::GetBlock( out_streams)); block = std::move(block_); } + +#if ENABLE_FPGA + else if (implementation.compare("GPS_L1_CA_PCPS_Acquisition_Fpga") == 0) + { + std::unique_ptr block_(new GpsL1CaPcpsAcquisitionFpga(configuration.get(), role, in_streams, + out_streams)); + block = std::move(block_); + } +#endif else if (implementation.compare("GPS_L1_CA_PCPS_Assisted_Acquisition") == 0) { std::unique_ptr block_(new GpsL1CaPcpsAssistedAcquisition(configuration.get(), role, in_streams, @@ -985,6 +999,14 @@ std::unique_ptr GNSSBlockFactory::GetBlock( out_streams)); block = std::move(block_); } +#if ENABLE_FPGA + else if (implementation.compare("GPS_L1_CA_DLL_PLL_C_Aid_Tracking_Fpga") == 0) + { + std::unique_ptr block_(new GpsL1CaDllPllCAidTrackingFpga(configuration.get(), role, in_streams, + out_streams)); + block = std::move(block_); + } +#endif else if (implementation.compare("GPS_L1_CA_TCP_CONNECTOR_Tracking") == 0) { std::unique_ptr block_(new GpsL1CaTcpConnectorTracking(configuration.get(), role, in_streams, @@ -1137,6 +1159,14 @@ std::unique_ptr GNSSBlockFactory::GetAcqBlock( out_streams)); block = std::move(block_); } +#if ENABLE_FPGA + else if (implementation.compare("GPS_L1_CA_PCPS_Acquisition_Fpga") == 0) + { + std::unique_ptr block_(new GpsL1CaPcpsAcquisitionFpga(configuration.get(), role, in_streams, + out_streams)); + block = std::move(block_); + } +#endif else if (implementation.compare("GPS_L1_CA_PCPS_Assisted_Acquisition") == 0) { std::unique_ptr block_(new GpsL1CaPcpsAssistedAcquisition(configuration.get(), role, in_streams, @@ -1250,6 +1280,14 @@ std::unique_ptr GNSSBlockFactory::GetTrkBlock( out_streams)); block = std::move(block_); } +#if ENABLE_FPGA + else if (implementation.compare("GPS_L1_CA_DLL_PLL_C_Aid_Tracking_Fpga") == 0) + { + std::unique_ptr block_(new GpsL1CaDllPllCAidTrackingFpga(configuration.get(), role, in_streams, + out_streams)); + block = std::move(block_); + } +#endif else if (implementation.compare("GPS_L1_CA_TCP_CONNECTOR_Tracking") == 0) { std::unique_ptr block_(new GpsL1CaTcpConnectorTracking(configuration.get(), role, in_streams, diff --git a/src/core/receiver/gnss_flowgraph.cc b/src/core/receiver/gnss_flowgraph.cc index 138140d34..a107eb4e5 100644 --- a/src/core/receiver/gnss_flowgraph.cc +++ b/src/core/receiver/gnss_flowgraph.cc @@ -70,20 +70,20 @@ GNSSFlowgraph::~GNSSFlowgraph() void GNSSFlowgraph::start() { if (running_) - { - LOG(WARNING) << "Already running"; - return; - } + { + LOG(WARNING) << "Already running"; + return; + } try { - top_block_->start(); + top_block_->start(); } catch (std::exception& e) { - LOG(WARNING) << "Unable to start flowgraph"; - LOG(ERROR) << e.what(); - return; + LOG(WARNING) << "Unable to start flowgraph"; + LOG(ERROR) << e.what(); + return; } running_ = true; @@ -111,226 +111,253 @@ void GNSSFlowgraph::connect() */ LOG(INFO) << "Connecting flowgraph"; if (connected_) - { - LOG(WARNING) << "flowgraph already connected"; - return; - } + { + LOG(WARNING) << "flowgraph already connected"; + return; + } for (int i = 0; i < sources_count_; i++) + { + if (configuration_->property(sig_source_.at(i)->role() + ".enable_FPGA", false)==false) { try { - sig_source_.at(i)->connect(top_block_); + sig_source_.at(i)->connect(top_block_); } catch (std::exception& e) { - LOG(INFO) << "Can't connect signal source block " << i << " internally"; - LOG(ERROR) << e.what(); - top_block_->disconnect_all(); - return; + LOG(INFO) << "Can't connect signal source block " << i << " internally"; + LOG(ERROR) << e.what(); + top_block_->disconnect_all(); + return; } + }else{ + DLOG(INFO)<<"Disabled signal source "< Signal conditioner > for (unsigned int i = 0; i < sig_conditioner_.size(); i++) + { + if (configuration_->property(sig_conditioner_.at(i)->role() + ".enable_FPGA", false)==false) { try { - sig_conditioner_.at(i)->connect(top_block_); + sig_conditioner_.at(i)->connect(top_block_); } catch (std::exception& e) { - LOG(INFO) << "Can't connect signal conditioner block " << i << " internally"; - LOG(ERROR) << e.what(); - top_block_->disconnect_all(); - return; + LOG(INFO) << "Can't connect signal conditioner block " << i << " internally"; + LOG(ERROR) << e.what(); + top_block_->disconnect_all(); + return; } + }else{ + DLOG(INFO)<<"Disabled signal conditioner "<connect(top_block_); - } - catch (std::exception& e) - { - LOG(WARNING) << "Can't connect channel " << i << " internally"; - LOG(ERROR) << e.what(); - top_block_->disconnect_all(); - return; - } + channels_.at(i)->connect(top_block_); } - - try - { - observables_->connect(top_block_); - } - catch (std::exception& e) - { - LOG(WARNING) << "Can't connect observables block internally"; + catch (std::exception& e) + { + LOG(WARNING) << "Can't connect channel " << i << " internally"; LOG(ERROR) << e.what(); top_block_->disconnect_all(); return; + } + } + + try + { + observables_->connect(top_block_); + } + catch (std::exception& e) + { + LOG(WARNING) << "Can't connect observables block internally"; + LOG(ERROR) << e.what(); + top_block_->disconnect_all(); + return; } // Signal Source > Signal conditioner >> Channels >> Observables > PVT try { - pvt_->connect(top_block_); + pvt_->connect(top_block_); } catch (std::exception& e) { - LOG(WARNING) << "Can't connect PVT block internally"; - LOG(ERROR) << e.what(); - top_block_->disconnect_all(); - return; + LOG(WARNING) << "Can't connect PVT block internally"; + LOG(ERROR) << e.what(); + top_block_->disconnect_all(); + return; } DLOG(INFO) << "blocks connected internally"; + // Signal Source (i) > Signal conditioner (i) > int RF_Channels = 0; int signal_conditioner_ID = 0; for (int i = 0; i < sources_count_; i++) + { + + //FPGA Accelerators do not need signal sources or conditioners + //as the samples are feed directly to the FPGA fabric, so, if enabled, do not connect any source + if (configuration_->property(sig_source_.at(i)->role() + ".enable_FPGA", false)==false) { try { - //TODO: Remove this array implementation and create generic multistream connector - //(if a signal source has more than 1 stream, then connect it to the multistream signal conditioner) - if(sig_source_.at(i)->implementation().compare("Raw_Array_Signal_Source") == 0) + //TODO: Remove this array implementation and create generic multistream connector + //(if a signal source has more than 1 stream, then connect it to the multistream signal conditioner) + if(sig_source_.at(i)->implementation().compare("Raw_Array_Signal_Source") == 0) + { + //Multichannel Array + std::cout << "ARRAY MODE" << std::endl; + for (int j = 0; j < GNSS_SDR_ARRAY_SIGNAL_CONDITIONER_CHANNELS; j++) + { + std::cout << "connecting ch " << j << std::endl; + top_block_->connect(sig_source_.at(i)->get_right_block(), j, sig_conditioner_.at(i)->get_left_block(), j); + } + } + else + { + //TODO: Create a class interface for SignalSources, derived from GNSSBlockInterface. + //Include GetRFChannels in the interface to avoid read config parameters here + //read the number of RF channels for each front-end + RF_Channels = configuration_->property(sig_source_.at(i)->role() + ".RF_channels", 1); + + for (int j = 0; j < RF_Channels; j++) + { + //Connect the multichannel signal source to multiple signal conditioners + // GNURADIO max_streams=-1 means infinite ports! + LOG(INFO) << "sig_source_.at(i)->get_right_block()->output_signature()->max_streams()=" << sig_source_.at(i)->get_right_block()->output_signature()->max_streams(); + LOG(INFO) << "sig_conditioner_.at(signal_conditioner_ID)->get_left_block()->input_signature()=" << sig_conditioner_.at(signal_conditioner_ID)->get_left_block()->input_signature()->max_streams(); + + if (sig_source_.at(i)->get_right_block()->output_signature()->max_streams() > 1) { - //Multichannel Array - std::cout << "ARRAY MODE" << std::endl; - for (int j = 0; j < GNSS_SDR_ARRAY_SIGNAL_CONDITIONER_CHANNELS; j++) - { - std::cout << "connecting ch " << j << std::endl; - top_block_->connect(sig_source_.at(i)->get_right_block(), j, sig_conditioner_.at(i)->get_left_block(), j); - } + + LOG(INFO) << "connecting sig_source_ " << i << " stream " << j << " to conditioner " << j; + top_block_->connect(sig_source_.at(i)->get_right_block(), j, sig_conditioner_.at(signal_conditioner_ID)->get_left_block(), 0); + } - else + else { - //TODO: Create a class interface for SignalSources, derived from GNSSBlockInterface. - //Include GetRFChannels in the interface to avoid read config parameters here - //read the number of RF channels for each front-end - RF_Channels = configuration_->property(sig_source_.at(i)->role() + ".RF_channels", 1); - - for (int j = 0; j < RF_Channels; j++) - { - //Connect the multichannel signal source to multiple signal conditioners - // GNURADIO max_streams=-1 means infinite ports! - LOG(INFO) << "sig_source_.at(i)->get_right_block()->output_signature()->max_streams()=" << sig_source_.at(i)->get_right_block()->output_signature()->max_streams(); - LOG(INFO) << "sig_conditioner_.at(signal_conditioner_ID)->get_left_block()->input_signature()=" << sig_conditioner_.at(signal_conditioner_ID)->get_left_block()->input_signature()->max_streams(); - - if (sig_source_.at(i)->get_right_block()->output_signature()->max_streams() > 1) - { - - LOG(INFO) << "connecting sig_source_ " << i << " stream " << j << " to conditioner " << j; - top_block_->connect(sig_source_.at(i)->get_right_block(), j, sig_conditioner_.at(signal_conditioner_ID)->get_left_block(), 0); - - } - else - { - if (j == 0) - { - // RF_channel 0 backward compatibility with single channel sources - LOG(INFO) << "connecting sig_source_ " << i << " stream " << 0 << " to conditioner " << j; - top_block_->connect(sig_source_.at(i)->get_right_block(), 0, sig_conditioner_.at(signal_conditioner_ID)->get_left_block(), 0); - } - else - { - // Multiple channel sources using multiple output blocks of single channel (requires RF_channel selector in call) - LOG(INFO) << "connecting sig_source_ " << i << " stream " << j << " to conditioner " << j; - top_block_->connect(sig_source_.at(i)->get_right_block(j), 0, sig_conditioner_.at(signal_conditioner_ID)->get_left_block(), 0); - } - } - - signal_conditioner_ID++; - } + if (j == 0) + { + // RF_channel 0 backward compatibility with single channel sources + LOG(INFO) << "connecting sig_source_ " << i << " stream " << 0 << " to conditioner " << j; + top_block_->connect(sig_source_.at(i)->get_right_block(), 0, sig_conditioner_.at(signal_conditioner_ID)->get_left_block(), 0); + } + else + { + // Multiple channel sources using multiple output blocks of single channel (requires RF_channel selector in call) + LOG(INFO) << "connecting sig_source_ " << i << " stream " << j << " to conditioner " << j; + top_block_->connect(sig_source_.at(i)->get_right_block(j), 0, sig_conditioner_.at(signal_conditioner_ID)->get_left_block(), 0); + } } + + signal_conditioner_ID++; + } + } } catch (std::exception& e) { - LOG(WARNING) << "Can't connect signal source " << i << " to signal conditioner " << i; - LOG(ERROR) << e.what(); - top_block_->disconnect_all(); - return; + LOG(WARNING) << "Can't connect signal source " << i << " to signal conditioner " << i; + LOG(ERROR) << e.what(); + top_block_->disconnect_all(); + return; } + }else{ + DLOG(INFO) << "Signal source "<> channels (i) (dependent of their associated SignalSource_ID) int selected_signal_conditioner_ID; for (unsigned int i = 0; i < channels_count_; i++) + { + + selected_signal_conditioner_ID = configuration_->property("Channel" + boost::lexical_cast(i) + ".RF_channel_ID", 0); + //FPGA Accelerators do not need signal sources or conditioners + //as the samples are feed directly to the FPGA fabric, so, if enabled, do not connect any source + if (configuration_->property(sig_conditioner_.at(selected_signal_conditioner_ID)->role() + ".enable_FPGA", false)==false) { - selected_signal_conditioner_ID = configuration_->property("Channel" + boost::lexical_cast(i) + ".RF_channel_ID", 0); try { - top_block_->connect(sig_conditioner_.at(selected_signal_conditioner_ID)->get_right_block(), 0, - channels_.at(i)->get_left_block(), 0); + top_block_->connect(sig_conditioner_.at(selected_signal_conditioner_ID)->get_right_block(), 0, + channels_.at(i)->get_left_block(), 0); } catch (std::exception& e) { - LOG(WARNING) << "Can't connect signal conditioner " << selected_signal_conditioner_ID << " to channel " << i; - LOG(ERROR) << e.what(); - top_block_->disconnect_all(); - return; + LOG(WARNING) << "Can't connect signal conditioner " << selected_signal_conditioner_ID << " to channel " << i; + LOG(ERROR) << e.what(); + top_block_->disconnect_all(); + return; } DLOG(INFO) << "signal conditioner " << selected_signal_conditioner_ID << " connected to channel " << i; - - // Signal Source > Signal conditioner >> Channels >> Observables - try - { - top_block_->connect(channels_.at(i)->get_right_block(), 0, - observables_->get_left_block(), i); - } - catch (std::exception& e) - { - LOG(WARNING) << "Can't connect channel " << i << " to observables"; - LOG(ERROR) << e.what(); - top_block_->disconnect_all(); - return; - } - - std::string gnss_signal = channels_.at(i)->get_signal().get_signal_str(); // use channel's implicit signal! - while (gnss_signal.compare(available_GNSS_signals_.front().get_signal_str()) != 0 ) - { - available_GNSS_signals_.push_back(available_GNSS_signals_.front()); - available_GNSS_signals_.pop_front(); - } - channels_.at(i)->set_signal(available_GNSS_signals_.front()); - - if (channels_state_[i] == 1) - { - channels_.at(i)->start_acquisition(); - available_GNSS_signals_.pop_front(); - LOG(INFO) << "Channel " << i << " assigned to " << available_GNSS_signals_.front(); - LOG(INFO) << "Channel " << i << " connected to observables and ready for acquisition"; - } - else - { - LOG(INFO) << "Channel " << i << " connected to observables in standby mode"; - } + }else{ + DLOG(INFO) << "signal conditioner disabled by FPGA in channel " << i; } + // Signal Source > Signal conditioner >> Channels >> Observables + try + { + top_block_->connect(channels_.at(i)->get_right_block(), 0, + observables_->get_left_block(), i); + } + catch (std::exception& e) + { + LOG(WARNING) << "Can't connect channel " << i << " to observables"; + LOG(ERROR) << e.what(); + top_block_->disconnect_all(); + return; + } + + std::string gnss_signal = channels_.at(i)->get_signal().get_signal_str(); // use channel's implicit signal! + while (gnss_signal.compare(available_GNSS_signals_.front().get_signal_str()) != 0 ) + { + available_GNSS_signals_.push_back(available_GNSS_signals_.front()); + available_GNSS_signals_.pop_front(); + } + channels_.at(i)->set_signal(available_GNSS_signals_.front()); + + if (channels_state_[i] == 1) + { + channels_.at(i)->start_acquisition(); + available_GNSS_signals_.pop_front(); + LOG(INFO) << "Channel " << i << " assigned to " << available_GNSS_signals_.front(); + LOG(INFO) << "Channel " << i << " connected to observables and ready for acquisition"; + } + else + { + LOG(INFO) << "Channel " << i << " connected to observables in standby mode"; + } + } /* * Connect the observables output of each channel to the PVT block */ try { - for (unsigned int i = 0; i < channels_count_; i++) - { - top_block_->connect(observables_->get_right_block(), i, pvt_->get_left_block(), i); - top_block_->msg_connect(channels_.at(i)->get_right_block(), pmt::mp("telemetry"), pvt_->get_left_block(), pmt::mp("telemetry")); - } + for (unsigned int i = 0; i < channels_count_; i++) + { + top_block_->connect(observables_->get_right_block(), i, pvt_->get_left_block(), i); + top_block_->msg_connect(channels_.at(i)->get_right_block(), pmt::mp("telemetry"), pvt_->get_left_block(), pmt::mp("telemetry")); + } } catch (std::exception& e) { - LOG(WARNING) << "Can't connect observables to PVT"; - LOG(ERROR) << e.what(); - top_block_->disconnect_all(); - return; + LOG(WARNING) << "Can't connect observables to PVT"; + LOG(ERROR) << e.what(); + top_block_->disconnect_all(); + return; } connected_ = true; @@ -342,10 +369,10 @@ void GNSSFlowgraph::connect() void GNSSFlowgraph::wait() { if (!running_) - { - LOG(WARNING) << "Can't apply wait. Flowgraph is not running"; - return; - } + { + LOG(WARNING) << "Can't apply wait. Flowgraph is not running"; + return; + } top_block_->wait(); DLOG(INFO) << "Flowgraph finished calculations"; running_ = false; @@ -377,10 +404,10 @@ void GNSSFlowgraph::apply_action(unsigned int who, unsigned int what) available_GNSS_signals_.push_back(channels_.at(who)->get_signal()); //TODO: Optimize the channel and signal matching! while ( channels_.at(who)->get_signal().get_signal_str().compare(available_GNSS_signals_.front().get_signal_str()) != 0 ) - { - available_GNSS_signals_.push_back(available_GNSS_signals_.front()); - available_GNSS_signals_.pop_front(); - } + { + available_GNSS_signals_.push_back(available_GNSS_signals_.front()); + available_GNSS_signals_.pop_front(); + } channels_.at(who)->set_signal(available_GNSS_signals_.front()); available_GNSS_signals_.pop_front(); usleep(100); @@ -391,42 +418,42 @@ void GNSSFlowgraph::apply_action(unsigned int who, unsigned int what) channels_state_[who] = 2; acq_channels_count_--; if (!available_GNSS_signals_.empty() && acq_channels_count_ < max_acq_channels_) + { + for (unsigned int i = 0; i < channels_count_; i++) { - for (unsigned int i = 0; i < channels_count_; i++) + if (channels_state_[i] == 0) + { + channels_state_[i] = 1; + while (channels_.at(i)->get_signal().get_signal_str().compare(available_GNSS_signals_.front().get_signal_str()) != 0 ) { - if (channels_state_[i] == 0) - { - channels_state_[i] = 1; - while (channels_.at(i)->get_signal().get_signal_str().compare(available_GNSS_signals_.front().get_signal_str()) != 0 ) - { - available_GNSS_signals_.push_back(available_GNSS_signals_.front()); - available_GNSS_signals_.pop_front(); - } - channels_.at(i)->set_signal(available_GNSS_signals_.front()); - available_GNSS_signals_.pop_front(); - acq_channels_count_++; - channels_.at(i)->start_acquisition(); - break; - } - DLOG(INFO) << "Channel " << i << " in state " << channels_state_[i]; + available_GNSS_signals_.push_back(available_GNSS_signals_.front()); + available_GNSS_signals_.pop_front(); } + channels_.at(i)->set_signal(available_GNSS_signals_.front()); + available_GNSS_signals_.pop_front(); + acq_channels_count_++; + channels_.at(i)->start_acquisition(); + break; + } + DLOG(INFO) << "Channel " << i << " in state " << channels_state_[i]; } + } break; case 2: LOG(INFO) << "Channel " << who << " TRK FAILED satellite " << channels_.at(who)->get_signal().get_satellite(); if (acq_channels_count_ < max_acq_channels_) - { - channels_state_[who] = 1; - acq_channels_count_++; - channels_.at(who)->start_acquisition(); - } + { + channels_state_[who] = 1; + acq_channels_count_++; + channels_.at(who)->start_acquisition(); + } else - { - channels_state_[who] = 0; - available_GNSS_signals_.push_back( channels_.at(who)->get_signal() ); - } + { + channels_state_[who] = 0; + available_GNSS_signals_.push_back( channels_.at(who)->get_signal() ); + } // for (unsigned int i = 0; i < channels_count_; i++) // { @@ -445,15 +472,15 @@ void GNSSFlowgraph::apply_action(unsigned int who, unsigned int what) void GNSSFlowgraph::set_configuration(std::shared_ptr configuration) { if (running_) - { - LOG(WARNING) << "Unable to update configuration while flowgraph running"; - return; - } + { + LOG(WARNING) << "Unable to update configuration while flowgraph running"; + return; + } if (connected_) - { - LOG(WARNING) << "Unable to update configuration while flowgraph connected"; - } + { + LOG(WARNING) << "Unable to update configuration while flowgraph connected"; + } configuration_ = configuration; } @@ -473,45 +500,45 @@ void GNSSFlowgraph::init() int signal_conditioner_ID = 0; if (sources_count_ > 1) + { + for (int i = 0; i < sources_count_; i++) { - for (int i = 0; i < sources_count_; i++) - { - std::cout << "Creating source " << i << std::endl; - sig_source_.push_back(block_factory_->GetSignalSource(configuration_, queue_, i)); - //TODO: Create a class interface for SignalSources, derived from GNSSBlockInterface. - //Include GetRFChannels in the interface to avoid read config parameters here - //read the number of RF channels for each front-end - RF_Channels = configuration_->property(sig_source_.at(i)->role() + ".RF_channels", 1); - std::cout << "RF Channels " << RF_Channels << std::endl; - for (int j = 0; j < RF_Channels; j++) - { - sig_conditioner_.push_back(block_factory_->GetSignalConditioner(configuration_, signal_conditioner_ID)); - signal_conditioner_ID++; - } - } - } - else - { - //backwards compatibility for old config files - sig_source_.push_back(block_factory_->GetSignalSource(configuration_, queue_, -1)); + std::cout << "Creating source " << i << std::endl; + sig_source_.push_back(block_factory_->GetSignalSource(configuration_, queue_, i)); //TODO: Create a class interface for SignalSources, derived from GNSSBlockInterface. //Include GetRFChannels in the interface to avoid read config parameters here //read the number of RF channels for each front-end - RF_Channels = configuration_->property(sig_source_.at(0)->role() + ".RF_channels", 0); - if (RF_Channels != 0) - { - for (int j = 0; j < RF_Channels; j++) - { - sig_conditioner_.push_back(block_factory_->GetSignalConditioner(configuration_, signal_conditioner_ID)); - signal_conditioner_ID++; - } - } - else - { - //old config file, single signal source and single channel, not specified - sig_conditioner_.push_back(block_factory_->GetSignalConditioner(configuration_, -1)); - } + RF_Channels = configuration_->property(sig_source_.at(i)->role() + ".RF_channels", 1); + std::cout << "RF Channels " << RF_Channels << std::endl; + for (int j = 0; j < RF_Channels; j++) + { + sig_conditioner_.push_back(block_factory_->GetSignalConditioner(configuration_, signal_conditioner_ID)); + signal_conditioner_ID++; + } } + } + else + { + //backwards compatibility for old config files + sig_source_.push_back(block_factory_->GetSignalSource(configuration_, queue_, -1)); + //TODO: Create a class interface for SignalSources, derived from GNSSBlockInterface. + //Include GetRFChannels in the interface to avoid read config parameters here + //read the number of RF channels for each front-end + RF_Channels = configuration_->property(sig_source_.at(0)->role() + ".RF_channels", 0); + if (RF_Channels != 0) + { + for (int j = 0; j < RF_Channels; j++) + { + sig_conditioner_.push_back(block_factory_->GetSignalConditioner(configuration_, signal_conditioner_ID)); + signal_conditioner_ID++; + } + } + else + { + //old config file, single signal source and single channel, not specified + sig_conditioner_.push_back(block_factory_->GetSignalConditioner(configuration_, -1)); + } + } observables_ = block_factory_->GetObservables(configuration_); pvt_ = block_factory_->GetPVT(configuration_); @@ -521,10 +548,10 @@ void GNSSFlowgraph::init() //todo:check smart pointer coherence... channels_count_ = channels->size(); for (unsigned int i = 0; i < channels_count_; i++) - { - std::shared_ptr chan_ = std::move(channels->at(i)); - channels_.push_back(std::dynamic_pointer_cast(chan_)); - } + { + std::shared_ptr chan_ = std::move(channels->at(i)); + channels_.push_back(std::dynamic_pointer_cast(chan_)); + } top_block_ = gr::make_top_block("GNSSFlowgraph"); @@ -564,133 +591,133 @@ void GNSSFlowgraph::set_signals_list() */ std::set available_gps_prn = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, - 29, 30, 31, 32 }; + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 32 }; std::set available_sbas_prn = {120, 124, 126}; std::set available_galileo_prn = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, - 29, 30, 31, 32, 33, 34, 35, 36}; + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36}; std::string sv_list = configuration_->property("Galileo.prns", std::string("") ); if( sv_list.length() > 0 ) - { - // Reset the available prns: - std::set< unsigned int > tmp_set; - boost::tokenizer<> tok( sv_list ); - std::transform( tok.begin(), tok.end(), std::inserter( tmp_set, tmp_set.begin() ), - boost::lexical_cast ); + { + // Reset the available prns: + std::set< unsigned int > tmp_set; + boost::tokenizer<> tok( sv_list ); + std::transform( tok.begin(), tok.end(), std::inserter( tmp_set, tmp_set.begin() ), + boost::lexical_cast ); - if( tmp_set.size() > 0 ) - { - available_galileo_prn = tmp_set; - } + if( tmp_set.size() > 0 ) + { + available_galileo_prn = tmp_set; } + } sv_list = configuration_->property("GPS.prns", std::string("") ); if( sv_list.length() > 0 ) - { - // Reset the available prns: - std::set< unsigned int > tmp_set; - boost::tokenizer<> tok( sv_list ); - std::transform( tok.begin(), tok.end(), std::inserter( tmp_set, tmp_set.begin() ), - boost::lexical_cast ); + { + // Reset the available prns: + std::set< unsigned int > tmp_set; + boost::tokenizer<> tok( sv_list ); + std::transform( tok.begin(), tok.end(), std::inserter( tmp_set, tmp_set.begin() ), + boost::lexical_cast ); - if( tmp_set.size() > 0 ) - { - available_gps_prn = tmp_set; - } + if( tmp_set.size() > 0 ) + { + available_gps_prn = tmp_set; } + } sv_list = configuration_->property("SBAS.prns", std::string("") ); if( sv_list.length() > 0 ) - { - // Reset the available prns: - std::set< unsigned int > tmp_set; - boost::tokenizer<> tok( sv_list ); - std::transform( tok.begin(), tok.end(), std::inserter( tmp_set, tmp_set.begin() ), - boost::lexical_cast ); + { + // Reset the available prns: + std::set< unsigned int > tmp_set; + boost::tokenizer<> tok( sv_list ); + std::transform( tok.begin(), tok.end(), std::inserter( tmp_set, tmp_set.begin() ), + boost::lexical_cast ); - if( tmp_set.size() > 0 ) - { - available_sbas_prn = tmp_set; - } + if( tmp_set.size() > 0 ) + { + available_sbas_prn = tmp_set; } + } if (configuration_->property("Channels_1C.count", 0) > 0 ) + { + /* + * Loop to create GPS L1 C/A signals + */ + for (available_gnss_prn_iter = available_gps_prn.begin(); + available_gnss_prn_iter != available_gps_prn.end(); + available_gnss_prn_iter++) { - /* - * Loop to create GPS L1 C/A signals - */ - for (available_gnss_prn_iter = available_gps_prn.begin(); - available_gnss_prn_iter != available_gps_prn.end(); - available_gnss_prn_iter++) - { - available_GNSS_signals_.push_back(Gnss_Signal(Gnss_Satellite(std::string("GPS"), - *available_gnss_prn_iter), std::string("1C"))); - } + available_GNSS_signals_.push_back(Gnss_Signal(Gnss_Satellite(std::string("GPS"), + *available_gnss_prn_iter), std::string("1C"))); } + } if (configuration_->property("Channels_2S.count", 0) > 0) + { + /* + * Loop to create GPS L2C M signals + */ + for (available_gnss_prn_iter = available_gps_prn.begin(); + available_gnss_prn_iter != available_gps_prn.end(); + available_gnss_prn_iter++) { - /* - * Loop to create GPS L2C M signals - */ - for (available_gnss_prn_iter = available_gps_prn.begin(); - available_gnss_prn_iter != available_gps_prn.end(); - available_gnss_prn_iter++) - { - available_GNSS_signals_.push_back(Gnss_Signal(Gnss_Satellite(std::string("GPS"), - *available_gnss_prn_iter), std::string("2S"))); - } + available_GNSS_signals_.push_back(Gnss_Signal(Gnss_Satellite(std::string("GPS"), + *available_gnss_prn_iter), std::string("2S"))); } + } if (configuration_->property("Channels_SBAS.count", 0) > 0) + { + /* + * Loop to create SBAS L1 C/A signals + */ + for (available_gnss_prn_iter = available_sbas_prn.begin(); + available_gnss_prn_iter != available_sbas_prn.end(); + available_gnss_prn_iter++) { - /* - * Loop to create SBAS L1 C/A signals - */ - for (available_gnss_prn_iter = available_sbas_prn.begin(); - available_gnss_prn_iter != available_sbas_prn.end(); - available_gnss_prn_iter++) - { - available_GNSS_signals_.push_back(Gnss_Signal(Gnss_Satellite(std::string("SBAS"), - *available_gnss_prn_iter), std::string("1C"))); - } + available_GNSS_signals_.push_back(Gnss_Signal(Gnss_Satellite(std::string("SBAS"), + *available_gnss_prn_iter), std::string("1C"))); } + } if (configuration_->property("Channels_1B.count", 0) > 0) + { + /* + * Loop to create the list of Galileo E1 B signals + */ + for (available_gnss_prn_iter = available_galileo_prn.begin(); + available_gnss_prn_iter != available_galileo_prn.end(); + available_gnss_prn_iter++) { - /* - * Loop to create the list of Galileo E1 B signals - */ - for (available_gnss_prn_iter = available_galileo_prn.begin(); - available_gnss_prn_iter != available_galileo_prn.end(); - available_gnss_prn_iter++) - { - available_GNSS_signals_.push_back(Gnss_Signal(Gnss_Satellite(std::string("Galileo"), - *available_gnss_prn_iter), std::string("1B"))); - } + available_GNSS_signals_.push_back(Gnss_Signal(Gnss_Satellite(std::string("Galileo"), + *available_gnss_prn_iter), std::string("1B"))); } + } if (configuration_->property("Channels_5X.count", 0) > 0 ) + { + /* + * Loop to create the list of Galileo E1 B signals + */ + for (available_gnss_prn_iter = available_galileo_prn.begin(); + available_gnss_prn_iter != available_galileo_prn.end(); + available_gnss_prn_iter++) { - /* - * Loop to create the list of Galileo E1 B signals - */ - for (available_gnss_prn_iter = available_galileo_prn.begin(); - available_gnss_prn_iter != available_galileo_prn.end(); - available_gnss_prn_iter++) - { - available_GNSS_signals_.push_back(Gnss_Signal(Gnss_Satellite(std::string("Galileo"), - *available_gnss_prn_iter), std::string("5X"))); - } + available_GNSS_signals_.push_back(Gnss_Signal(Gnss_Satellite(std::string("Galileo"), + *available_gnss_prn_iter), std::string("5X"))); } + } /* * Ordering the list of signals from configuration file */ @@ -699,24 +726,24 @@ void GNSSFlowgraph::set_signals_list() // Pre-assignation if not defined at ChannelX.signal=1C ...? In what order? for (unsigned int i = 0; i < total_channels; i++) + { + std::string gnss_signal = (configuration_->property("Channel" + boost::lexical_cast(i) + ".signal", std::string("1C"))); + std::string gnss_system; + if((gnss_signal.compare("1C") == 0) or (gnss_signal.compare("2S") == 0) ) gnss_system = "GPS"; + if((gnss_signal.compare("1B") == 0) or (gnss_signal.compare("5X") == 0) ) gnss_system = "Galileo"; + unsigned int sat = configuration_->property("Channel" + boost::lexical_cast(i) + ".satellite", 0); + LOG(INFO) << "Channel " << i << " system " << gnss_system << ", signal " << gnss_signal <<", sat "<property("Channel" + boost::lexical_cast(i) + ".signal", std::string("1C"))); - std::string gnss_system; - if((gnss_signal.compare("1C") == 0) or (gnss_signal.compare("2S") == 0) ) gnss_system = "GPS"; - if((gnss_signal.compare("1B") == 0) or (gnss_signal.compare("5X") == 0) ) gnss_system = "Galileo"; - unsigned int sat = configuration_->property("Channel" + boost::lexical_cast(i) + ".satellite", 0); - LOG(INFO) << "Channel " << i << " system " << gnss_system << ", signal " << gnss_signal <<", sat "<::iterator available_gnss_list_iter; @@ -732,21 +759,21 @@ void GNSSFlowgraph::set_channels_state() { max_acq_channels_ = (configuration_->property("Channels.in_acquisition", channels_count_)); if (max_acq_channels_ > channels_count_) - { - max_acq_channels_ = channels_count_; - LOG(WARNING) << "Channels_in_acquisition is bigger than number of channels. Variable acq_channels_count_ is set to " << channels_count_; - } + { + max_acq_channels_ = channels_count_; + LOG(WARNING) << "Channels_in_acquisition is bigger than number of channels. Variable acq_channels_count_ is set to " << channels_count_; + } channels_state_.reserve(channels_count_); for (unsigned int i = 0; i < channels_count_; i++) + { + if (i < max_acq_channels_) { - if (i < max_acq_channels_) - { - channels_state_.push_back(1); - } - else - channels_state_.push_back(0); - DLOG(INFO) << "Channel " << i << " in state " << channels_state_[i]; + channels_state_.push_back(1); } + else + channels_state_.push_back(0); + DLOG(INFO) << "Channel " << i << " in state " << channels_state_[i]; + } acq_channels_count_ = max_acq_channels_; DLOG(INFO) << acq_channels_count_ << " channels in acquisition state"; } From 28058000dea600eabf1af6ac070536c6c38448ad Mon Sep 17 00:00:00 2001 From: mmajoral Date: Fri, 5 May 2017 17:08:49 +0200 Subject: [PATCH 4/5] set up the receiver to work with the FPGA --- conf/gnss-sdr_GPS_L1_FPGA.conf | 1 + .../libs/gps_fpga_acquisition_8sc.cc | 27 +--------------- .../libs/gps_fpga_acquisition_8sc.h | 22 +------------ src/algorithms/channel/adapters/channel.cc | 31 ++++++++++++++----- src/algorithms/channel/adapters/channel.h | 1 + 5 files changed, 27 insertions(+), 55 deletions(-) diff --git a/conf/gnss-sdr_GPS_L1_FPGA.conf b/conf/gnss-sdr_GPS_L1_FPGA.conf index 92d361aad..423228462 100644 --- a/conf/gnss-sdr_GPS_L1_FPGA.conf +++ b/conf/gnss-sdr_GPS_L1_FPGA.conf @@ -31,6 +31,7 @@ SignalConditioner.enable_FPGA=true Channels_1C.count=8 Channels.in_acquisition=1 Channel.signal=1C +Channel.enable_FPGA=true ;######### ACQUISITION GLOBAL CONFIG ############ diff --git a/src/algorithms/acquisition/libs/gps_fpga_acquisition_8sc.cc b/src/algorithms/acquisition/libs/gps_fpga_acquisition_8sc.cc index 0178d84a7..b1f706402 100644 --- a/src/algorithms/acquisition/libs/gps_fpga_acquisition_8sc.cc +++ b/src/algorithms/acquisition/libs/gps_fpga_acquisition_8sc.cc @@ -36,7 +36,7 @@ #include "gps_fpga_acquisition_8sc.h" #include -// FPGA stuff +// allocate memory dynamically #include // libraries used by DMA test code and GIPO test code @@ -62,7 +62,6 @@ #include "GPS_L1_CA.h" #define PAGE_SIZE 0x10000 -//#define MAX_LENGTH_DEVICEIO_NAME 50 #define CODE_RESAMPLER_NUM_BITS_PRECISION 20 #define CODE_PHASE_STEP_CHIPS_NUM_NBITS CODE_RESAMPLER_NUM_BITS_PRECISION #define pwrtwo(x) (1 << (x)) @@ -228,25 +227,9 @@ void gps_fpga_acquisition_8sc::fpga_configure_acquisition_local_code(lv_16sc_t f tmp = fft_local_code[k].real(); tmp2 = fft_local_code[k].imag(); local_code = (tmp & 0xFF) | ((tmp2*256) & 0xFF00); // put together the real part and the imaginary part - if (k < 20) - { - printf("tmp tmp2 local_code = %d %d %d\n", tmp, tmp2, local_code); - } d_map_base[4] = 0x0C000000 | (local_code & 0xFFFF); } - FILE *f; - f = fopen("captured_local_code_dec.txt", "w"); - if (!f) - { - printf("Unable to open file!"); - } - for(k=0;k< d_nsamples_total;k++) - { - fprintf(f,"%d\n",fft_local_code[k].real()); // real part - fprintf(f,"%d\n",fft_local_code[k].imag()); // real part - } - fclose(f); } @@ -282,9 +265,6 @@ void gps_fpga_acquisition_8sc::configure_acquisition() d_map_base[1] = d_nsamples_total; d_map_base[2] = d_nsamples; - printf("nsamples = %d\n", d_nsamples); - printf("nsamples_total = %d\n", d_nsamples_total); - printf("d_select_queue = %d\n", d_select_queue); } @@ -307,19 +287,14 @@ void gps_fpga_acquisition_8sc::read_acquisition_results(uint32_t* max_index, flo { unsigned readval = 0; readval = d_map_base[0]; - printf("RESULT : result valid = %d\n", readval); readval = d_map_base[1]; *initial_sample = readval; - printf("RESULT : initial sample = %d\n", *initial_sample); readval = d_map_base[2]; *max_magnitude = (float) readval; - printf("RESULT : max_magnitude = %f\n", *max_magnitude); readval = d_map_base[4]; *power_sum = (float) readval; - printf("RESULT : power sum = %f\n", *power_sum); readval = d_map_base[3]; *max_index = readval; - printf("RESULT : max_index = %d\n", *max_index); // to avoid result_read line to stay high } diff --git a/src/algorithms/acquisition/libs/gps_fpga_acquisition_8sc.h b/src/algorithms/acquisition/libs/gps_fpga_acquisition_8sc.h index 94b16fd5b..478ec6dd9 100644 --- a/src/algorithms/acquisition/libs/gps_fpga_acquisition_8sc.h +++ b/src/algorithms/acquisition/libs/gps_fpga_acquisition_8sc.h @@ -1,9 +1,8 @@ /*! * \file fpga_acquisition_8sc.h - * \brief High optimized FPGA vector correlator class for lv_16sc_t (short int complex) + * \brief High optimized FPGA vector correlator class for lv_16sc_t (short int complex). * \authors
      *
    • Marc Majoral, 2017. mmajoral(at)cttc.cat - *
    • Javier Arribas, 2016. jarribas(at)cttc.es *
    * * Class that controls and executes a high optimized vector correlator @@ -50,7 +49,6 @@ class gps_fpga_acquisition_8sc public: gps_fpga_acquisition_8sc(); ~gps_fpga_acquisition_8sc(); - //bool init(int max_signal_length_samples, int n_correlators); bool init(unsigned int fft_size, unsigned int nsamples_total, long d_freq, unsigned int doppler_max, unsigned int doppler_step, int num_doppler_bins, long fs_in, unsigned select_queue); bool set_local_code(gr_complex* fft_codes); //int code_length_chips, const lv_16sc_t* local_code_in, float *shifts_chips); bool free(); @@ -79,29 +77,11 @@ private: unsigned int d_nsamples; // number of samples not including padding unsigned int d_select_queue =0; // queue selection -// unsigned int d_channel; // channel number -// unsigned d_ncorrelators; // number of correlators -// unsigned d_correlator_length_samples; -// float d_rem_code_phase_chips; -// float d_code_phase_step_chips; -// float d_rem_carrier_phase_in_rad; -// float d_phase_step_rad; - - // configuration data computed in the format that the FPGA expects -// unsigned *d_initial_index; -// unsigned *d_initial_interp_counter; -// unsigned d_code_phase_step_chips_num; -// int d_rem_carr_phase_rad_int; -// int d_phase_step_rad_int; -// unsigned d_initial_sample_counter; - // FPGA private functions unsigned fpga_acquisition_test_register(unsigned writeval); void fpga_configure_acquisition_local_code(lv_16sc_t fft_local_code[]); void configure_acquisition(); - - //void fpga_acquisition_8sc::run_acquisition(void); }; diff --git a/src/algorithms/channel/adapters/channel.cc b/src/algorithms/channel/adapters/channel.cc index c60a23d9c..eb59941e9 100644 --- a/src/algorithms/channel/adapters/channel.cc +++ b/src/algorithms/channel/adapters/channel.cc @@ -56,6 +56,7 @@ Channel::Channel(ConfigurationInterface *configuration, unsigned int channel, channel_ = channel; queue_ = queue; + flag_enable_fpga=configuration->property("Channel.enable_FPGA", false); acq_->set_channel(channel_); trk_->set_channel(channel_); nav_->set_channel(channel_); @@ -108,16 +109,22 @@ void Channel::connect(gr::top_block_sptr top_block) LOG(WARNING) << "channel already connected internally"; return; } - pass_through_->connect(top_block); + if (flag_enable_fpga==false) + { + pass_through_->connect(top_block); + } acq_->connect(top_block); trk_->connect(top_block); nav_->connect(top_block); //Synchronous ports - top_block->connect(pass_through_->get_right_block(), 0, acq_->get_left_block(), 0); - DLOG(INFO) << "pass_through_ -> acquisition"; - top_block->connect(pass_through_->get_right_block(), 0, trk_->get_left_block(), 0); - DLOG(INFO) << "pass_through_ -> tracking"; + if (flag_enable_fpga==false) + { + top_block->connect(pass_through_->get_right_block(), 0, acq_->get_left_block(), 0); + DLOG(INFO) << "pass_through_ -> acquisition"; + top_block->connect(pass_through_->get_right_block(), 0, trk_->get_left_block(), 0); + DLOG(INFO) << "pass_through_ -> tracking"; + } top_block->connect(trk_->get_right_block(), 0, nav_->get_left_block(), 0); DLOG(INFO) << "tracking -> telemetry_decoder"; @@ -140,10 +147,18 @@ void Channel::disconnect(gr::top_block_sptr top_block) LOG(WARNING) << "Channel already disconnected internally"; return; } - top_block->disconnect(pass_through_->get_right_block(), 0, acq_->get_left_block(), 0); - top_block->disconnect(pass_through_->get_right_block(), 0, trk_->get_left_block(), 0); + + if (flag_enable_fpga==false) + { + top_block->disconnect(pass_through_->get_right_block(), 0, acq_->get_left_block(), 0); + top_block->disconnect(pass_through_->get_right_block(), 0, trk_->get_left_block(), 0); + } top_block->disconnect(trk_->get_right_block(), 0, nav_->get_left_block(), 0); - pass_through_->disconnect(top_block); + + if (flag_enable_fpga==false) + { + pass_through_->disconnect(top_block); + } acq_->disconnect(top_block); trk_->disconnect(top_block); nav_->disconnect(top_block); diff --git a/src/algorithms/channel/adapters/channel.h b/src/algorithms/channel/adapters/channel.h index 0d2a30431..0060111de 100644 --- a/src/algorithms/channel/adapters/channel.h +++ b/src/algorithms/channel/adapters/channel.h @@ -94,6 +94,7 @@ private: std::shared_ptr nav_; std::string role_; std::string implementation_; + bool flag_enable_fpga; unsigned int channel_; Gnss_Synchro gnss_synchro_; Gnss_Signal gnss_signal_; From de2043ca0035ed2f29cdce197bdb88992546a1ad Mon Sep 17 00:00:00 2001 From: mmajoral Date: Mon, 8 May 2017 17:03:27 +0200 Subject: [PATCH 5/5] cleaned the acquisition code that runs in the Zynq SoC, cleaned some tracking files that run in the Zynq SoC as well. --- conf/gnss-sdr_GPS_L1_FPGA.conf | 1 + .../gps_l1_ca_pcps_acquisition_fpga.cc | 8 +- .../gps_l1_ca_pcps_acquisition_fpga.h | 2 + .../gps_pcps_acquisition_fpga_sc.cc | 83 +++++++++---------- .../gps_pcps_acquisition_fpga_sc.h | 4 + .../libs/gps_fpga_acquisition_8sc.cc | 7 +- .../libs/gps_fpga_acquisition_8sc.h | 2 +- ...ps_l1_ca_dll_pll_c_aid_tracking_fpga_sc.cc | 2 +- .../tracking/libs/fpga_multicorrelator_8sc.cc | 10 +-- .../tracking/libs/fpga_multicorrelator_8sc.h | 4 +- .../gps_l1_ca_pcps_acquisition_test_fpga.cc | 24 +++--- .../gps_l1_ca_dll_pll_tracking_test_fpga.cc | 1 - 12 files changed, 69 insertions(+), 79 deletions(-) diff --git a/conf/gnss-sdr_GPS_L1_FPGA.conf b/conf/gnss-sdr_GPS_L1_FPGA.conf index 423228462..7e7e49aa7 100644 --- a/conf/gnss-sdr_GPS_L1_FPGA.conf +++ b/conf/gnss-sdr_GPS_L1_FPGA.conf @@ -41,6 +41,7 @@ Acquisition_1C.item_type=cshort Acquisition_1C.if=0 Acquisition_1C.sampled_ms=1 Acquisition_1C.implementation=GPS_L1_CA_PCPS_Acquisition_Fpga +Acquisition_1C.select_queue_Fpga=0; Acquisition_1C.threshold=0.005 ;Acquisition_1C.pfa=0.01 Acquisition_1C.doppler_max=10000 diff --git a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fpga.cc b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fpga.cc index 5a2c4c334..48dd946cb 100644 --- a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fpga.cc +++ b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fpga.cc @@ -67,6 +67,7 @@ GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga( // note : the FPGA is implemented according to use_CFAR_algorithm = 0. Setting use_CFAR_algorithm to 1 has no effect. use_CFAR_algorithm_flag_=configuration_->property(role + ".use_CFAR_algorithm", false); + // note : the FPGA does not use the max_dwells variable. max_dwells_ = configuration_->property(role + ".max_dwells", 1); dump_filename_ = configuration_->property(role + ".dump_filename", default_dump_filename); @@ -90,12 +91,14 @@ GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga( code_ = new gr_complex[vector_length_]; + select_queue_Fpga_ = configuration_->property(role + ".select_queue_Fpga", 0); + if (item_type_.compare("cshort") == 0 ) { item_size_ = sizeof(lv_16sc_t); gps_acquisition_fpga_sc_ = gps_pcps_make_acquisition_fpga_sc(sampled_ms_, max_dwells_, doppler_max_, if_, fs_in_, code_length_, code_length_, vector_length_, - bit_transition_flag_, use_CFAR_algorithm_flag_, dump_, dump_filename_); + bit_transition_flag_, use_CFAR_algorithm_flag_, select_queue_Fpga_, dump_, dump_filename_); DLOG(INFO) << "acquisition(" << gps_acquisition_fpga_sc_->unique_id() << ")"; } @@ -103,6 +106,7 @@ GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga( LOG(FATAL) << item_type_ << " FPGA only accepts chsort"; } + channel_ = 0; threshold_ = 0.0; doppler_step_ = 0; @@ -199,8 +203,6 @@ void GpsL1CaPcpsAcquisitionFpga::set_local_code() code[s] = std::complex(0, 0); } - unsigned long long interpolated_sampling_frequency; // warning: we need a long long to do this conversion to avoid running out of bits - gps_l1_ca_code_gen_complex_sampled(code, gnss_synchro_->PRN, fs_in_ , 0); for (unsigned int i = 0; i < sampled_ms_; i++) diff --git a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fpga.h b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fpga.h index 14b1fd646..95d7cc8dd 100644 --- a/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fpga.h +++ b/src/algorithms/acquisition/adapters/gps_l1_ca_pcps_acquisition_fpga.h @@ -164,6 +164,8 @@ private: unsigned int nsamples_total_; + unsigned int select_queue_Fpga_; + float calculate_threshold(float pfa); }; diff --git a/src/algorithms/acquisition/gnuradio_blocks/gps_pcps_acquisition_fpga_sc.cc b/src/algorithms/acquisition/gnuradio_blocks/gps_pcps_acquisition_fpga_sc.cc index 0162e92f9..7cb177ded 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/gps_pcps_acquisition_fpga_sc.cc +++ b/src/algorithms/acquisition/gnuradio_blocks/gps_pcps_acquisition_fpga_sc.cc @@ -54,13 +54,14 @@ gps_pcps_acquisition_fpga_sc_sptr gps_pcps_make_acquisition_fpga_sc( unsigned int doppler_max, long freq, long fs_in, int samples_per_ms, int samples_per_code, int vector_length, bool bit_transition_flag, bool use_CFAR_algorithm_flag, + unsigned int select_queue_Fpga, bool dump, std::string dump_filename) { return gps_pcps_acquisition_fpga_sc_sptr( new gps_pcps_acquisition_fpga_sc(sampled_ms, max_dwells, doppler_max, freq, fs_in, samples_per_ms, - samples_per_code, vector_length, bit_transition_flag, use_CFAR_algorithm_flag, dump, dump_filename)); + samples_per_code, vector_length, bit_transition_flag, use_CFAR_algorithm_flag, select_queue_Fpga, dump, dump_filename)); } gps_pcps_acquisition_fpga_sc::gps_pcps_acquisition_fpga_sc( @@ -68,6 +69,7 @@ gps_pcps_acquisition_fpga_sc::gps_pcps_acquisition_fpga_sc( unsigned int doppler_max, long freq, long fs_in, int samples_per_ms, int samples_per_code, int vector_length, bool bit_transition_flag, bool use_CFAR_algorithm_flag, + unsigned int select_queue_Fpga, bool dump, std::string dump_filename) : @@ -82,15 +84,15 @@ gps_pcps_acquisition_fpga_sc::gps_pcps_acquisition_fpga_sc( 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_max_dwells = max_dwells; // Note : d_max_dwells is not used in the FPGA implementation 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_use_CFAR_algorithm_flag = use_CFAR_algorithm_flag; + d_bit_transition_flag = bit_transition_flag; // Note : bit transition flag is ignored and assumed 0 in the FPGA implementation + d_use_CFAR_algorithm_flag = use_CFAR_algorithm_flag; // Note : user CFAR algorithm flag is ignored and assumed 0 in the FPGA implementation d_threshold = 0.0; d_doppler_step = 250; d_code_phase = 0; @@ -100,21 +102,11 @@ gps_pcps_acquisition_fpga_sc::gps_pcps_acquisition_fpga_sc( d_nsamples_total = vector_length; - // COD: - // Experimenting with the overlap/save technique for handling bit trannsitions - // The problem: Circular correlation is asynchronous with the received code. - // In effect the first code phase used in the correlation is the current - // estimate of the code phase at the start of the input buffer. If this is 1/2 - // of the code period a bit transition would move all the signal energy into - // adjacent frequency bands at +/- 1/T where T is the integration time. - // - // We can avoid this by doing linear correlation, effectively doubling the - // size of the input buffer and padding the code with zeros. - if( d_bit_transition_flag ) - { - d_fft_size *= 2; - d_max_dwells = 1; - } + //if( d_bit_transition_flag ) + // { + // d_fft_size *= 2; + // d_max_dwells = 1; + // } d_fft_codes = static_cast(volk_gnsssdr_malloc(d_nsamples_total * sizeof(gr_complex), volk_gnsssdr_get_alignment())); d_magnitude = static_cast(volk_gnsssdr_malloc(d_nsamples_total * sizeof(float), volk_gnsssdr_get_alignment())); @@ -130,6 +122,9 @@ gps_pcps_acquisition_fpga_sc::gps_pcps_acquisition_fpga_sc( // Inverse FFT d_ifft = new gr::fft::fft_complex(d_nsamples_total, false); + // FPGA queue selection + d_select_queue_Fpga = select_queue_Fpga; + // For dumping samples into a file d_dump = dump; d_dump_filename = dump_filename; @@ -185,11 +180,11 @@ void gps_pcps_acquisition_fpga_sc::set_local_code(std::complex * code) int offset = 0; - if( d_bit_transition_flag ) - { - std::fill_n( d_fft_if->get_inbuf(), d_nsamples_total, gr_complex( 0.0, 0.0 ) ); - offset = d_nsamples_total; - } +// if( d_bit_transition_flag ) +// { +// std::fill_n( d_fft_if->get_inbuf(), d_nsamples_total, gr_complex( 0.0, 0.0 ) ); +// offset = d_nsamples_total; +// } @@ -204,8 +199,6 @@ void gps_pcps_acquisition_fpga_sc::set_local_code(std::complex * code) void gps_pcps_acquisition_fpga_sc::update_local_carrier(gr_complex* carrier_vector, int correlator_length_samples, float freq) { - static int debugint = 0; - float phase_step_rad = GPS_TWO_PI * freq / static_cast(d_fs_in); @@ -240,9 +233,7 @@ void gps_pcps_acquisition_fpga_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); } - // PENDING : SELECT_QUEUE MUST GO INTO CONFIGURATION - unsigned select_queue = 0; - acquisition_fpga_8sc.init(d_fft_size, d_nsamples_total, d_freq, d_doppler_max, d_doppler_step, d_num_doppler_bins, d_fs_in, select_queue); + acquisition_fpga_8sc.init(d_fft_size, d_nsamples_total, d_freq, d_doppler_max, d_doppler_step, d_num_doppler_bins, d_fs_in, d_select_queue_Fpga); @@ -290,8 +281,8 @@ void gps_pcps_acquisition_fpga_sc::set_active(bool active) d_active = active; - while (d_well_count < d_max_dwells) - { +// while (d_well_count < d_max_dwells) +// { int acquisition_message = -1; //0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL d_state = 1; @@ -300,9 +291,9 @@ void gps_pcps_acquisition_fpga_sc::set_active(bool active) int doppler; uint32_t indext = 0; float magt = 0.0; - 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); + //int effective_fft_size = ( d_bit_transition_flag ? d_fft_size/2 : d_fft_size ); + int effective_fft_size = d_fft_size; + //float fft_normalization_factor = static_cast(d_fft_size) * static_cast(d_fft_size); d_mag = 0.0; @@ -312,7 +303,7 @@ void gps_pcps_acquisition_fpga_sc::set_active(bool active) DLOG(INFO) << "Channel: " << d_channel << " , doing acquisition of satellite: " << d_gnss_synchro->System << " "<< d_gnss_synchro->PRN - //<< " ,sample stamp: " << d_sample_counter << ", threshold: " + << " ,sample stamp: " << d_sample_counter << ", threshold: " << ", threshold: " << d_threshold << ", doppler_max: " << d_doppler_max << ", doppler_step: " << d_doppler_step; @@ -329,6 +320,8 @@ void gps_pcps_acquisition_fpga_sc::set_active(bool active) acquisition_fpga_8sc.read_acquisition_results(&indext, &magt, &initial_sample, &d_input_power); + d_sample_counter = initial_sample; + temp_peak_to_noise_level = (float) (magt / d_input_power); if (peak_to_noise_level < temp_peak_to_noise_level) { @@ -337,13 +330,13 @@ void gps_pcps_acquisition_fpga_sc::set_active(bool active) d_input_power = (d_input_power - d_mag) / (effective_fft_size - 1); - if (d_test_statistics < (d_mag / d_input_power) || !d_bit_transition_flag) - { + //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 = initial_sample; + d_gnss_synchro->Acq_samplestamp_samples = d_sample_counter; d_test_statistics = d_mag / d_input_power; - } + // } } // Record results to file if required @@ -379,8 +372,7 @@ void gps_pcps_acquisition_fpga_sc::set_active(bool active) // 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) << "sample_stamp " << initial_sample; + 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; @@ -394,7 +386,7 @@ void gps_pcps_acquisition_fpga_sc::set_active(bool active) acquisition_message = 1; this->message_port_pub(pmt::mp("events"), pmt::from_long(acquisition_message)); - break; +// break; } else //if (d_well_count == d_max_dwells) @@ -405,7 +397,6 @@ void gps_pcps_acquisition_fpga_sc::set_active(bool active) DLOG(INFO) << "negative acquisition"; DLOG(INFO) << "satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN; DLOG(INFO) << "sample_stamp " << d_sample_counter; - DLOG(INFO) << "sample_stamp " << initial_sample; 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; @@ -419,10 +410,10 @@ void gps_pcps_acquisition_fpga_sc::set_active(bool active) acquisition_message = 2; this->message_port_pub(pmt::mp("events"), pmt::from_long(acquisition_message)); - break; +// break; } - } +// } acquisition_fpga_8sc.unblock_samples(); @@ -435,6 +426,6 @@ int gps_pcps_acquisition_fpga_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))) { - + // general work not used with the acquisition return noutput_items; } diff --git a/src/algorithms/acquisition/gnuradio_blocks/gps_pcps_acquisition_fpga_sc.h b/src/algorithms/acquisition/gnuradio_blocks/gps_pcps_acquisition_fpga_sc.h index 62e03b06f..a3b4c1b64 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/gps_pcps_acquisition_fpga_sc.h +++ b/src/algorithms/acquisition/gnuradio_blocks/gps_pcps_acquisition_fpga_sc.h @@ -66,6 +66,7 @@ gps_pcps_make_acquisition_fpga_sc(unsigned int sampled_ms, unsigned int max_dwel unsigned int doppler_max, long freq, long fs_in, int samples_per_ms, int samples_per_code, int vector_length_, bool bit_transition_flag, bool use_CFAR_algorithm_flag, + unsigned int select_queue_Fpga, bool dump, std::string dump_filename); @@ -83,6 +84,7 @@ private: unsigned int doppler_max, long freq, long fs_in, int samples_per_ms, int samples_per_code, int vector_length, bool bit_transition_flag, bool use_CFAR_algorithm_flag, + unsigned int select_queue_Fpga, bool dump, std::string dump_filename); @@ -90,6 +92,7 @@ private: unsigned int doppler_max, long freq, long fs_in, int samples_per_ms, int samples_per_code, int vector_length, bool bit_transition_flag, bool use_CFAR_algorithm_flag, + unsigned int select_queue_Fpga, bool dump, std::string dump_filename); @@ -132,6 +135,7 @@ private: int d_state; bool d_dump; unsigned int d_channel; + unsigned int d_select_queue_Fpga; std::string d_dump_filename; gps_fpga_acquisition_8sc acquisition_fpga_8sc; diff --git a/src/algorithms/acquisition/libs/gps_fpga_acquisition_8sc.cc b/src/algorithms/acquisition/libs/gps_fpga_acquisition_8sc.cc index b1f706402..214dc3d93 100644 --- a/src/algorithms/acquisition/libs/gps_fpga_acquisition_8sc.cc +++ b/src/algorithms/acquisition/libs/gps_fpga_acquisition_8sc.cc @@ -76,11 +76,10 @@ bool gps_fpga_acquisition_8sc::init(unsigned int fft_size, unsigned int nsamples_total, long freq, unsigned int doppler_max, unsigned int doppler_step, int num_doppler_bins, long fs_in, unsigned select_queue) { float phase_step_rad_fpga; - float phase_step_rad_fpga_real; d_phase_step_rad_vector = new float[num_doppler_bins]; - for (unsigned int doppler_index = 0; doppler_index < num_doppler_bins; doppler_index++) + for (int doppler_index = 0; doppler_index < num_doppler_bins; doppler_index++) { int doppler = -static_cast(doppler_max) + doppler_step * doppler_index; float phase_step_rad = GPS_TWO_PI * (freq + doppler) / static_cast(fs_in); @@ -116,6 +115,7 @@ d_nsamples = fft_size; d_nsamples_total = nsamples_total; + d_select_queue = select_queue; gps_fpga_acquisition_8sc::configure_acquisition(); @@ -126,8 +126,7 @@ bool gps_fpga_acquisition_8sc::set_local_code(gr_complex* fft_codes) { - int i; - float val; + unsigned int i; float max = 0; d_fft_codes = new lv_16sc_t[d_nsamples_total]; diff --git a/src/algorithms/acquisition/libs/gps_fpga_acquisition_8sc.h b/src/algorithms/acquisition/libs/gps_fpga_acquisition_8sc.h index 478ec6dd9..b34566308 100644 --- a/src/algorithms/acquisition/libs/gps_fpga_acquisition_8sc.h +++ b/src/algorithms/acquisition/libs/gps_fpga_acquisition_8sc.h @@ -75,7 +75,7 @@ private: unsigned int d_nsamples_total; // total number of samples in the fft including padding unsigned int d_nsamples; // number of samples not including padding - unsigned int d_select_queue =0; // queue selection + unsigned int d_select_queue; // queue selection // FPGA private functions unsigned fpga_acquisition_test_register(unsigned writeval); diff --git a/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc.cc b/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc.cc index dba9d1a5e..eaa4237c7 100644 --- a/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc.cc +++ b/src/algorithms/tracking/gnuradio_blocks/gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc.cc @@ -151,7 +151,7 @@ gps_l1_ca_dll_pll_c_aid_tracking_fpga_sc::gps_l1_ca_dll_pll_c_aid_tracking_fpga_ d_local_code_shift_chips[1] = 0.0; d_local_code_shift_chips[2] = d_early_late_spc_chips; - multicorrelator_fpga_8sc.init(2 * d_correlation_length_samples, d_n_correlator_taps); + multicorrelator_fpga_8sc.init(d_n_correlator_taps); //--- Perform initializations ------------------------------ // define initial code frequency basis of NCO diff --git a/src/algorithms/tracking/libs/fpga_multicorrelator_8sc.cc b/src/algorithms/tracking/libs/fpga_multicorrelator_8sc.cc index a18eb3647..3ce33110e 100644 --- a/src/algorithms/tracking/libs/fpga_multicorrelator_8sc.cc +++ b/src/algorithms/tracking/libs/fpga_multicorrelator_8sc.cc @@ -72,11 +72,8 @@ -bool fpga_multicorrelator_8sc::init( - int max_signal_length_samples, - int n_correlators) +bool fpga_multicorrelator_8sc::init(int n_correlators) { - size_t size = max_signal_length_samples * sizeof(lv_16sc_t); d_n_correlators = n_correlators; // instantiate variable length vectors @@ -117,7 +114,7 @@ bool fpga_multicorrelator_8sc::set_output_vectors(lv_16sc_t* corr_out) } -void fpga_multicorrelator_8sc::update_local_code(int correlator_length_samples, float rem_code_phase_chips, float code_phase_step_chips) +void fpga_multicorrelator_8sc::update_local_code(float rem_code_phase_chips) { d_rem_code_phase_chips = rem_code_phase_chips; @@ -133,7 +130,7 @@ bool fpga_multicorrelator_8sc::Carrier_wipeoff_multicorrelator_resampler( float code_phase_step_chips, int signal_length_samples) { - update_local_code(signal_length_samples, rem_code_phase_chips, code_phase_step_chips); + update_local_code(rem_code_phase_chips); d_rem_carrier_phase_in_rad = rem_carrier_phase_in_rad; d_code_phase_step_chips = code_phase_step_chips; @@ -327,7 +324,6 @@ void fpga_multicorrelator_8sc::fpga_configure_code_parameters_in_fpga(void) void fpga_multicorrelator_8sc::fpga_compute_signal_parameters_in_fpga(void) { float d_rem_carrier_phase_in_rad_temp; - float d_phase_step_rad_int_temp; d_code_phase_step_chips_num = (unsigned) roundf(MAX_CODE_RESAMPLER_COUNTER * d_code_phase_step_chips); diff --git a/src/algorithms/tracking/libs/fpga_multicorrelator_8sc.h b/src/algorithms/tracking/libs/fpga_multicorrelator_8sc.h index a4ee69ed2..0655b26e0 100644 --- a/src/algorithms/tracking/libs/fpga_multicorrelator_8sc.h +++ b/src/algorithms/tracking/libs/fpga_multicorrelator_8sc.h @@ -50,10 +50,10 @@ class fpga_multicorrelator_8sc public: fpga_multicorrelator_8sc(); ~fpga_multicorrelator_8sc(); - bool init(int max_signal_length_samples, int n_correlators); + bool init(int n_correlators); bool set_local_code_and_taps(int code_length_chips, const lv_16sc_t* local_code_in, float *shifts_chips); bool set_output_vectors(lv_16sc_t* corr_out); - void update_local_code(int correlator_length_samples, float rem_code_phase_chips, float code_phase_step_chips); + void update_local_code(float rem_code_phase_chips); bool Carrier_wipeoff_multicorrelator_resampler(float rem_carrier_phase_in_rad, float phase_step_rad, float rem_code_phase_chips, float code_phase_step_chips, int signal_length_samples); bool free(); diff --git a/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_ca_pcps_acquisition_test_fpga.cc b/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_ca_pcps_acquisition_test_fpga.cc index 0837bfb30..17d905f98 100644 --- a/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_ca_pcps_acquisition_test_fpga.cc +++ b/src/tests/unit-tests/signal-processing-blocks/acquisition/gps_l1_ca_pcps_acquisition_test_fpga.cc @@ -37,7 +37,6 @@ #include #include #include -//#include #include #include #include @@ -143,7 +142,7 @@ void thread_acquisition_send_rx_samples(gr::top_block_sptr top_block, const char int transfer_size; int num_transferred_samples = 0; - while (num_transferred_samples< fileLen/FLOAT_SIZE) + while (num_transferred_samples < (int) (fileLen/FLOAT_SIZE)) { if (((fileLen/FLOAT_SIZE) - num_transferred_samples) > DMA_ACQ_TRANSFER_SIZE) { @@ -274,7 +273,6 @@ void GpsL1CaPcpsAcquisitionTestFpga::init() signal.copy(gnss_synchro.Signal, 2, 0); gnss_synchro.PRN = 1; config->set_property("GNSS-SDR.internal_fs_hz", "4000000"); - //config->set_property("Acquisition.item_type", "gr_complex"); config->set_property("Acquisition.item_type", "cshort"); config->set_property("Acquisition.if", "0"); config->set_property("Acquisition.coherent_integration_time_ms", "1"); @@ -285,6 +283,7 @@ void GpsL1CaPcpsAcquisitionTestFpga::init() config->set_property("Acquisition.doppler_step", "500"); config->set_property("Acquisition.repeat_satellite", "false"); config->set_property("Acquisition.pfa", "0.0"); + config->set_property("Acquisition.select_queue_Fpga", "0"); } @@ -306,9 +305,6 @@ TEST_F(GpsL1CaPcpsAcquisitionTestFpga, ValidationOfResults) double expected_doppler_hz = 1680; init(); - - - std::shared_ptr acquisition = std::make_shared(config.get(), "Acquisition", 0, 1); boost::shared_ptr msg_rx = GpsL1CaPcpsAcquisitionTestFpga_msg_rx_make(); @@ -337,15 +333,17 @@ TEST_F(GpsL1CaPcpsAcquisitionTestFpga, ValidationOfResults) acquisition->connect(top_block); }) << "Failure connecting acquisition to the top_block." << std::endl; + // uncomment the next line to load the file from the current directory std::string file = "./GPS_L1_CA_ID_1_Fs_4Msps_2ms.dat"; + + // uncomment the next two lines to load the file from the signal samples subdirectory + //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(); ASSERT_NO_THROW( { - //std::string path = std::string(TEST_PATH); - //std::string file = path + "signal_samples/GSoC_CTTC_capture_2012_07_26_4Msps_4ms.dat"; - //std::string file = path + "signal_samples/GPS_L1_CA_ID_1_Fs_4Msps_2ms.dat"; - - // for the unit test use dummy blocks to make the flowgraph work and allow the acquisition message to be sent. + // for the unit test use dummy blocks to make the flowgraph work and allow the acquisition message to be sent. // in the actual system there is a flowchart running in parallel so this is not needed gr::blocks::file_source::sptr file_source = gr::blocks::file_source::make(sizeof(gr_complex), file_name, false); @@ -375,9 +373,7 @@ TEST_F(GpsL1CaPcpsAcquisitionTestFpga, ValidationOfResults) t3.join(); - - unsigned long int nsamples = gnss_synchro.Acq_samplestamp_samples; - std::cout << "Acquired " << nsamples << " samples in " << (end - begin) << " microseconds" << std::endl; + std::cout << "Ran GpsL1CaPcpsAcquisitionTestFpga in " << (end - begin) << " microseconds" << std::endl; ASSERT_EQ(1, msg_rx->rx_message) << "Acquisition failure. Expected message: 1=ACQ SUCCESS."; diff --git a/src/tests/unit-tests/signal-processing-blocks/tracking/gps_l1_ca_dll_pll_tracking_test_fpga.cc b/src/tests/unit-tests/signal-processing-blocks/tracking/gps_l1_ca_dll_pll_tracking_test_fpga.cc index f2ac99755..855115567 100644 --- a/src/tests/unit-tests/signal-processing-blocks/tracking/gps_l1_ca_dll_pll_tracking_test_fpga.cc +++ b/src/tests/unit-tests/signal-processing-blocks/tracking/gps_l1_ca_dll_pll_tracking_test_fpga.cc @@ -77,7 +77,6 @@ void wait(int seconds) void send_tracking_gps_input_samples(FILE *ptr_myfile, int num_remaining_samples, gr::top_block_sptr top_block) { - int sample_pointer; int num_samples_transferred = 0; static int flowgraph_stopped = 0;