From 75cbc3fcdddabd24bec774c4380a9a2c4727edd3 Mon Sep 17 00:00:00 2001 From: mmajoral Date: Tue, 22 May 2018 12:25:14 +0200 Subject: [PATCH 1/7] Added Galileo E1 acquisition + tracking classes that use the generic acquisition and tracking classes for the FPGA HW accelerators (still to be tested). Did some minor code cleaning to the GPS files that use the FPGA HW accelerator. --- .../acquisition/adapters/CMakeLists.txt | 2 +- ...ileo_e1_pcps_ambiguous_acquisition_fpga.cc | 428 ++++++++++++++++++ ...lileo_e1_pcps_ambiguous_acquisition_fpga.h | 172 +++++++ .../gps_l1_ca_pcps_acquisition_fpga.cc | 11 +- .../gps_l1_ca_pcps_acquisition_fpga.h | 2 +- .../tracking/adapters/CMakeLists.txt | 2 +- .../galileo_e1_dll_pll_veml_tracking_fpga.cc | 239 ++++++++++ .../galileo_e1_dll_pll_veml_tracking_fpga.h | 109 +++++ .../gps_l1_ca_dll_pll_tracking_fpga.cc | 92 +--- .../gps_l1_ca_dll_pll_tracking_fpga.h | 3 +- .../dll_pll_veml_tracking_fpga.cc | 10 +- .../dll_pll_veml_tracking_fpga.h | 1 + .../tracking/libs/fpga_multicorrelator.cc | 18 +- .../tracking/libs/fpga_multicorrelator.h | 11 +- src/core/receiver/gnss_block_factory.cc | 35 ++ 15 files changed, 1010 insertions(+), 125 deletions(-) create mode 100644 src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition_fpga.cc create mode 100644 src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition_fpga.h create mode 100644 src/algorithms/tracking/adapters/galileo_e1_dll_pll_veml_tracking_fpga.cc create mode 100644 src/algorithms/tracking/adapters/galileo_e1_dll_pll_veml_tracking_fpga.h diff --git a/src/algorithms/acquisition/adapters/CMakeLists.txt b/src/algorithms/acquisition/adapters/CMakeLists.txt index ff708f433..fe54e8880 100644 --- a/src/algorithms/acquisition/adapters/CMakeLists.txt +++ b/src/algorithms/acquisition/adapters/CMakeLists.txt @@ -37,7 +37,7 @@ set(ACQ_ADAPTER_SOURCES ) if(ENABLE_FPGA) - set(ACQ_ADAPTER_SOURCES ${ACQ_ADAPTER_SOURCES} gps_l1_ca_pcps_acquisition_fpga.cc) + set(ACQ_ADAPTER_SOURCES ${ACQ_ADAPTER_SOURCES} gps_l1_ca_pcps_acquisition_fpga.cc galileo_e1_pcps_ambiguous_acquisition_fpga.cc) endif(ENABLE_FPGA) if(OPENCL_FOUND) diff --git a/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition_fpga.cc b/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition_fpga.cc new file mode 100644 index 000000000..287730d1e --- /dev/null +++ b/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition_fpga.cc @@ -0,0 +1,428 @@ +/*! + * \file galileo_e1_pcps_ambiguous_acquisition.cc + * \brief Adapts a PCPS acquisition block to an AcquisitionInterface for + * Galileo E1 Signals + * \author Luis Esteve, 2012. luis(at)epsilon-formacion.com + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors) + * + * GNSS-SDR is a software defined Global Navigation + * Satellite Systems receiver + * + * This file is part of GNSS-SDR. + * + * GNSS-SDR is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GNSS-SDR is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNSS-SDR. If not, see . + * + * ------------------------------------------------------------------------- + */ + +#include "galileo_e1_pcps_ambiguous_acquisition_fpga.h" +#include "configuration_interface.h" +#include "galileo_e1_signal_processing.h" +#include "Galileo_E1.h" +#include "gnss_sdr_flags.h" +#include +#include +#include + +#define NUM_PRNs_GALILEO_E1 50 + +using google::LogMessage; + +GalileoE1PcpsAmbiguousAcquisitionFpga::GalileoE1PcpsAmbiguousAcquisitionFpga( + ConfigurationInterface* configuration, std::string role, + unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams) +{ + printf("galileo e1 fpga constructor called\n"); + pcpsconf_fpga_t acq_parameters; + configuration_ = configuration; + std::string default_item_type = "gr_complex"; + std::string default_dump_filename = "./data/acquisition.dat"; + + DLOG(INFO) << "role " << role; + +// item_type_ = configuration_->property(role + ".item_type", default_item_type); + + long fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 4000000); + long fs_in = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated); + acq_parameters.fs_in = fs_in; + if_ = configuration_->property(role + ".if", 0); + acq_parameters.freq = if_; + dump_ = configuration_->property(role + ".dump", false); + // acq_parameters.dump = dump_; + blocking_ = configuration_->property(role + ".blocking", true); +// acq_parameters.blocking = blocking_; + doppler_max_ = configuration_->property(role + ".doppler_max", 5000); + if (FLAGS_doppler_max != 0) doppler_max_ = FLAGS_doppler_max; + acq_parameters.doppler_max = doppler_max_; + unsigned int sampled_ms = 4; + acq_parameters.sampled_ms = sampled_ms; + bit_transition_flag_ = configuration_->property(role + ".bit_transition_flag", false); + // acq_parameters.bit_transition_flag = bit_transition_flag_; + // use_CFAR_algorithm_flag_ = configuration_->property(role + ".use_CFAR_algorithm", true); //will be false in future versions + // acq_parameters.use_CFAR_algorithm_flag = use_CFAR_algorithm_flag_; + acquire_pilot_ = configuration_->property(role + ".acquire_pilot", false); //will be true in future versions + + // max_dwells_ = configuration_->property(role + ".max_dwells", 1); + // acq_parameters.max_dwells = max_dwells_; + dump_filename_ = configuration_->property(role + ".dump_filename", default_dump_filename); + // acq_parameters.dump_filename = dump_filename_; + //--- Find number of samples per spreading code (4 ms) ----------------- + unsigned int code_length = static_cast(std::round(static_cast(fs_in) / (Galileo_E1_CODE_CHIP_RATE_HZ / Galileo_E1_B_CODE_LENGTH_CHIPS))); + //acq_parameters.samples_per_code = code_length_; + //int samples_per_ms = static_cast(std::round(static_cast(fs_in_) * 0.001)); + //acq_parameters.samples_per_ms = samples_per_ms; + //unsigned int vector_length = sampled_ms * samples_per_ms; + +// if (bit_transition_flag_) +// { +// vector_length_ *= 2; +// } + + + + // The FPGA can only use FFT lengths that are a power of two. + float nbits = ceilf(log2f((float)code_length)); + unsigned int nsamples_total = pow(2, nbits); + unsigned int vector_length = nsamples_total; + unsigned int select_queue_Fpga = configuration_->property(role + ".select_queue_Fpga", 0); + acq_parameters.select_queue_Fpga = select_queue_Fpga; + std::string default_device_name = "/dev/uio0"; + std::string device_name = configuration_->property(role + ".devicename", default_device_name); + acq_parameters.device_name = device_name; + acq_parameters.samples_per_ms = nsamples_total/sampled_ms; + acq_parameters.samples_per_code = nsamples_total; + + + + // compute all the GALILEO E1 PRN Codes (this is done only once upon the class constructor in order to avoid re-computing the PRN codes every time + // a channel is assigned) + gr::fft::fft_complex* fft_if = new gr::fft::fft_complex(nsamples_total, true); // Direct FFT + std::complex* code = new std::complex[nsamples_total]; // buffer for the local code + gr_complex* fft_codes_padded = static_cast(volk_gnsssdr_malloc(nsamples_total * sizeof(gr_complex), volk_gnsssdr_get_alignment())); + d_all_fft_codes_ = new lv_16sc_t[nsamples_total * NUM_PRNs_GALILEO_E1]; // memory containing all the possible fft codes for PRN 0 to 32 + float max; // temporary maxima search + + + for (unsigned int PRN = 1; PRN <= NUM_PRNs_GALILEO_E1; PRN++) + { + + //code_ = new gr_complex[vector_length_]; + + bool cboc = false; // cboc is set to 0 when using the FPGA + + //std::complex* code = new std::complex[code_length_]; + + if (acquire_pilot_ == true) + { + //set local signal generator to Galileo E1 pilot component (1C) + char pilot_signal[3] = "1C"; + galileo_e1_code_gen_complex_sampled(code, pilot_signal, + cboc, gnss_synchro_->PRN, fs_in, 0, false); + } + else + { + galileo_e1_code_gen_complex_sampled(code, gnss_synchro_->Signal, + cboc, gnss_synchro_->PRN, fs_in, 0, false); + } + +// for (unsigned int i = 0; i < sampled_ms / 4; i++) +// { +// //memcpy(&(code_[i * code_length_]), code, sizeof(gr_complex) * code_length_); +// memcpy(&(d_all_fft_codes_[i * code_length_]), code, sizeof(gr_complex) * code_length_); +// } + +// // fill in zero padding + for (int s = code_length; s < nsamples_total; s++) + { + code[s] = 0; + } + + memcpy(fft_if->get_inbuf(), code, sizeof(gr_complex) * nsamples_total); // copy to FFT buffer + fft_if->execute(); // Run the FFT of local code + volk_32fc_conjugate_32fc(fft_codes_padded, fft_if->get_outbuf(), nsamples_total); // conjugate values + + + // normalize the code + max = 0; // initialize maximum value + for (unsigned int i = 0; i < nsamples_total; i++) // search for maxima + { + if (std::abs(fft_codes_padded[i].real()) > max) + { + max = std::abs(fft_codes_padded[i].real()); + } + if (std::abs(fft_codes_padded[i].imag()) > max) + { + max = std::abs(fft_codes_padded[i].imag()); + } + } + for (unsigned int i = 0; i < nsamples_total; i++) // map the FFT to the dynamic range of the fixed point values an copy to buffer containing all FFTs + { + d_all_fft_codes_[i + nsamples_total * (PRN - 1)] = lv_16sc_t(static_cast(floor(fft_codes_padded[i].real() * (pow(2, 7) - 1) / max)), + static_cast(floor(fft_codes_padded[i].imag() * (pow(2, 7) - 1) / max))); + } + + + } + + //acq_parameters + + acq_parameters.all_fft_codes = d_all_fft_codes_; + + // temporary buffers that we can delete + delete[] code; + delete fft_if; + delete[] fft_codes_padded; + + acquisition_fpga_ = pcps_make_acquisition_fpga(acq_parameters); + DLOG(INFO) << "acquisition(" << acquisition_fpga_->unique_id() << ")"; + +// stream_to_vector_ = gr::blocks::stream_to_vector::make(item_size_, vector_length_); +// DLOG(INFO) << "stream_to_vector(" << stream_to_vector_->unique_id() << ")"; + +// if (item_type_.compare("cbyte") == 0) +// { +// cbyte_to_float_x2_ = make_complex_byte_to_float_x2(); +// float_to_complex_ = gr::blocks::float_to_complex::make(); +// } + + channel_ = 0; + //threshold_ = 0.0; + doppler_step_ = 0; + gnss_synchro_ = 0; +} + + +GalileoE1PcpsAmbiguousAcquisitionFpga::~GalileoE1PcpsAmbiguousAcquisitionFpga() +{ + //delete[] code_; + delete[] d_all_fft_codes_; +} + + +void GalileoE1PcpsAmbiguousAcquisitionFpga::set_channel(unsigned int channel) +{ + channel_ = channel; + acquisition_fpga_->set_channel(channel_); +} + + +void GalileoE1PcpsAmbiguousAcquisitionFpga::set_threshold(float threshold) +{ + // the .pfa parameter and the threshold calculation is only used for the CFAR algorithm. + // We don't use the CFAR algorithm in the FPGA. Therefore the threshold is set as such. + +// float pfa = configuration_->property(role_ + boost::lexical_cast(channel_) + ".pfa", 0.0); +// +// if (pfa == 0.0) pfa = configuration_->property(role_ + ".pfa", 0.0); +// +// if (pfa == 0.0) +// { +// threshold_ = threshold; +// } +// else +// { +// threshold_ = calculate_threshold(pfa); +// } + + DLOG(INFO) << "Channel " << channel_ << " Threshold = " << threshold; + acquisition_fpga_->set_threshold(threshold); +// acquisition_fpga_->set_threshold(threshold_); +} + + +void GalileoE1PcpsAmbiguousAcquisitionFpga::set_doppler_max(unsigned int doppler_max) +{ + doppler_max_ = doppler_max; + + acquisition_fpga_->set_doppler_max(doppler_max_); +} + + +void GalileoE1PcpsAmbiguousAcquisitionFpga::set_doppler_step(unsigned int doppler_step) +{ + doppler_step_ = doppler_step; + + acquisition_fpga_->set_doppler_step(doppler_step_); +} + + +void GalileoE1PcpsAmbiguousAcquisitionFpga::set_gnss_synchro(Gnss_Synchro* gnss_synchro) +{ + gnss_synchro_ = gnss_synchro; + + acquisition_fpga_->set_gnss_synchro(gnss_synchro_); +} + + +signed int GalileoE1PcpsAmbiguousAcquisitionFpga::mag() +{ + return acquisition_fpga_->mag(); +} + + +void GalileoE1PcpsAmbiguousAcquisitionFpga::init() +{ + acquisition_fpga_->init(); + //set_local_code(); +} + + +void GalileoE1PcpsAmbiguousAcquisitionFpga::set_local_code() +{ +// bool cboc = configuration_->property( +// "Acquisition" + boost::lexical_cast(channel_) + ".cboc", false); +// +// std::complex* code = new std::complex[code_length_]; +// +// if (acquire_pilot_ == true) +// { +// //set local signal generator to Galileo E1 pilot component (1C) +// char pilot_signal[3] = "1C"; +// galileo_e1_code_gen_complex_sampled(code, pilot_signal, +// cboc, gnss_synchro_->PRN, fs_in_, 0, false); +// } +// else +// { +// galileo_e1_code_gen_complex_sampled(code, gnss_synchro_->Signal, +// cboc, gnss_synchro_->PRN, fs_in_, 0, false); +// } +// +// +// for (unsigned int i = 0; i < sampled_ms_ / 4; i++) +// { +// memcpy(&(code_[i * code_length_]), code, sizeof(gr_complex) * code_length_); +// } + + //acquisition_fpga_->set_local_code(code_); + acquisition_fpga_->set_local_code(); +// delete[] code; +} + + +void GalileoE1PcpsAmbiguousAcquisitionFpga::reset() +{ + acquisition_fpga_->set_active(true); +} + + +void GalileoE1PcpsAmbiguousAcquisitionFpga::set_state(int state) +{ + acquisition_fpga_->set_state(state); +} + + +//float GalileoE1PcpsAmbiguousAcquisitionFpga::calculate_threshold(float pfa) +//{ +// unsigned int frequency_bins = 0; +// for (int doppler = static_cast(-doppler_max_); doppler <= static_cast(doppler_max_); doppler += doppler_step_) +// { +// frequency_bins++; +// } +// +// DLOG(INFO) << "Channel " << channel_ << " Pfa = " << pfa; +// +// unsigned int ncells = vector_length_ * frequency_bins; +// double exponent = 1 / static_cast(ncells); +// double val = pow(1.0 - pfa, exponent); +// double lambda = double(vector_length_); +// boost::math::exponential_distribution mydist(lambda); +// float threshold = static_cast(quantile(mydist, val)); +// +// return threshold; +//} + + +void GalileoE1PcpsAmbiguousAcquisitionFpga::connect(gr::top_block_sptr top_block) +{ +// if (item_type_.compare("gr_complex") == 0) +// { +// top_block->connect(stream_to_vector_, 0, acquisition_fpga_, 0); +// } +// else if (item_type_.compare("cshort") == 0) +// { +// top_block->connect(stream_to_vector_, 0, acquisition_fpga_, 0); +// } +// else if (item_type_.compare("cbyte") == 0) +// { +// top_block->connect(cbyte_to_float_x2_, 0, float_to_complex_, 0); +// top_block->connect(cbyte_to_float_x2_, 1, float_to_complex_, 1); +// top_block->connect(float_to_complex_, 0, stream_to_vector_, 0); +// top_block->connect(stream_to_vector_, 0, acquisition_fpga_, 0); +// } +// else +// { +// LOG(WARNING) << item_type_ << " unknown acquisition item type"; +// } + + // nothing to connect +} + + +void GalileoE1PcpsAmbiguousAcquisitionFpga::disconnect(gr::top_block_sptr top_block) +{ +// if (item_type_.compare("gr_complex") == 0) +// { +// top_block->disconnect(stream_to_vector_, 0, acquisition_fpga_, 0); +// } +// else if (item_type_.compare("cshort") == 0) +// { +// top_block->disconnect(stream_to_vector_, 0, acquisition_fpga_, 0); +// } +// else if (item_type_.compare("cbyte") == 0) +// { +// // Since a byte-based acq implementation is not available, +// // we just convert cshorts to gr_complex +// top_block->disconnect(cbyte_to_float_x2_, 0, float_to_complex_, 0); +// top_block->disconnect(cbyte_to_float_x2_, 1, float_to_complex_, 1); +// top_block->disconnect(float_to_complex_, 0, stream_to_vector_, 0); +// top_block->disconnect(stream_to_vector_, 0, acquisition_fpga_, 0); +// } +// else +// { +// LOG(WARNING) << item_type_ << " unknown acquisition item type"; +// } + + // nothing to disconnect +} + + +gr::basic_block_sptr GalileoE1PcpsAmbiguousAcquisitionFpga::get_left_block() +{ +// if (item_type_.compare("gr_complex") == 0) +// { +// return stream_to_vector_; +// } +// else if (item_type_.compare("cshort") == 0) +// { +// return stream_to_vector_; +// } +// else if (item_type_.compare("cbyte") == 0) +// { +// return cbyte_to_float_x2_; +// } +// else +// { +// LOG(WARNING) << item_type_ << " unknown acquisition item type"; + return nullptr; +// } +} + + +gr::basic_block_sptr GalileoE1PcpsAmbiguousAcquisitionFpga::get_right_block() +{ + return acquisition_fpga_; +} diff --git a/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition_fpga.h b/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition_fpga.h new file mode 100644 index 000000000..36edead1f --- /dev/null +++ b/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition_fpga.h @@ -0,0 +1,172 @@ +/*! + * \file galileo_e1_pcps_ambiguous_acquisition.h + * \brief Adapts a PCPS acquisition block to an AcquisitionInterface for + * Galileo E1 Signals + * \author Luis Esteve, 2012. luis(at)epsilon-formacion.com + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors) + * + * GNSS-SDR is a software defined Global Navigation + * Satellite Systems receiver + * + * This file is part of GNSS-SDR. + * + * GNSS-SDR is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GNSS-SDR is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNSS-SDR. If not, see . + * + * ------------------------------------------------------------------------- + */ + +#ifndef GNSS_SDR_GALILEO_E1_PCPS_AMBIGUOUS_ACQUISITION_FPGA_H_ +#define GNSS_SDR_GALILEO_E1_PCPS_AMBIGUOUS_ACQUISITION_FPGA_H_ + +#include "acquisition_interface.h" +#include "gnss_synchro.h" +#include "pcps_acquisition_fpga.h" +#include "complex_byte_to_float_x2.h" +#include +#include +#include +#include + + +class ConfigurationInterface; + +/*! + * \brief This class adapts a PCPS acquisition block to an + * AcquisitionInterface for Galileo E1 Signals + */ +class GalileoE1PcpsAmbiguousAcquisitionFpga : public AcquisitionInterface +{ +public: + GalileoE1PcpsAmbiguousAcquisitionFpga(ConfigurationInterface* configuration, + std::string role, unsigned int in_streams, + unsigned int out_streams); + + virtual ~GalileoE1PcpsAmbiguousAcquisitionFpga(); + + inline std::string role() override + { + return role_; + } + + /*! + * \brief Returns "Galileo_E1_PCPS_Ambiguous_Acquisition" + */ + inline std::string implementation() override + { + return "Galileo_E1_PCPS_Ambiguous_Acquisition_Fpga"; + } + + size_t item_size() override + { + size_t item_size = sizeof(lv_16sc_t); + return item_size; + } + + void connect(gr::top_block_sptr top_block) override; + void disconnect(gr::top_block_sptr top_block) override; + gr::basic_block_sptr get_left_block() override; + gr::basic_block_sptr get_right_block() override; + + /*! + * \brief Set acquisition/tracking common Gnss_Synchro object pointer + * to efficiently exchange synchronization data between acquisition and + * tracking blocks + */ + void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) override; + + /*! + * \brief Set acquisition channel unique ID + */ + void set_channel(unsigned int channel) override; + + /*! + * \brief Set statistics threshold of PCPS algorithm + */ + void set_threshold(float threshold) override; + + /*! + * \brief Set maximum Doppler off grid search + */ + void set_doppler_max(unsigned int doppler_max) override; + + /*! + * \brief Set Doppler steps for the grid search + */ + void set_doppler_step(unsigned int doppler_step) override; + + /*! + * \brief Initializes acquisition algorithm. + */ + void init() override; + + /*! + * \brief Sets local code for Galileo E1 PCPS acquisition algorithm. + */ + void set_local_code() override; + + /*! + * \brief Returns the maximum peak of grid search + */ + signed int mag() override; + + /*! + * \brief Restart acquisition algorithm + */ + void reset() override; + + /*! + * \brief If state = 1, it forces the block to start acquiring from the first sample + */ + void set_state(int state); + +private: + ConfigurationInterface* configuration_; + //pcps_acquisition_sptr acquisition_; + pcps_acquisition_fpga_sptr acquisition_fpga_; + 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_; + bool acquire_pilot_; + 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_; + bool blocking_; + std::string dump_filename_; + //std::complex* code_; + Gnss_Synchro* gnss_synchro_; + std::string role_; + unsigned int in_streams_; + unsigned int out_streams_; + //float calculate_threshold(float pfa); + + // extra for the FPGA + lv_16sc_t* d_all_fft_codes_; // memory that contains all the code ffts +}; + +#endif /* GNSS_SDR_GALILEO_E1_PCPS_AMBIGUOUS_ACQUISITION_FPGA_H_ */ 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 2e5fecee9..2a15d7e6f 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 @@ -73,25 +73,23 @@ GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga( // The FPGA can only use FFT lengths that are a power of two. float nbits = ceilf(log2f((float)code_length)); unsigned int nsamples_total = pow(2, nbits); - unsigned int vector_length = nsamples_total * sampled_ms; + unsigned int vector_length = nsamples_total; unsigned int select_queue_Fpga = configuration_->property(role + ".select_queue_Fpga", 0); acq_parameters.select_queue_Fpga = select_queue_Fpga; std::string default_device_name = "/dev/uio0"; std::string device_name = configuration_->property(role + ".devicename", default_device_name); acq_parameters.device_name = device_name; - acq_parameters.samples_per_ms = nsamples_total; + acq_parameters.samples_per_ms = nsamples_total/sampled_ms; acq_parameters.samples_per_code = nsamples_total; // compute all the GPS L1 PRN Codes (this is done only once upon the class constructor in order to avoid re-computing the PRN codes every time // a channel is assigned) - gr::fft::fft_complex* fft_if = new gr::fft::fft_complex(vector_length, true); // Direct FFT // allocate memory to compute all the PRNs and compute all the possible codes std::complex* code = new std::complex[nsamples_total]; // buffer for the local code gr_complex* fft_codes_padded = static_cast(volk_gnsssdr_malloc(nsamples_total * sizeof(gr_complex), volk_gnsssdr_get_alignment())); d_all_fft_codes_ = new lv_16sc_t[nsamples_total * NUM_PRNs]; // memory containing all the possible fft codes for PRN 0 to 32 float max; // temporary maxima search - for (unsigned int PRN = 1; PRN <= NUM_PRNs; PRN++) { gps_l1_ca_code_gen_complex_sampled(code, PRN, fs_in, 0); // generate PRN code @@ -124,7 +122,6 @@ GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga( } //acq_parameters - acq_parameters.all_fft_codes = d_all_fft_codes_; // temporary buffers that we can delete @@ -157,6 +154,8 @@ void GpsL1CaPcpsAcquisitionFpga::set_channel(unsigned int channel) void GpsL1CaPcpsAcquisitionFpga::set_threshold(float threshold) { + // the .pfa parameter and the threshold calculation is only used for the CFAR algorithm. + // We don't use the CFAR algorithm in the FPGA. Therefore the threshold is set as such. DLOG(INFO) << "Channel " << channel_ << " Threshold = " << threshold; acquisition_fpga_->set_threshold(threshold); } @@ -226,7 +225,7 @@ void GpsL1CaPcpsAcquisitionFpga::disconnect(gr::top_block_sptr top_block) gr::basic_block_sptr GpsL1CaPcpsAcquisitionFpga::get_left_block() { - return acquisition_fpga_; + return nullptr; } 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 f070e8818..5a7d2c471 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 @@ -68,7 +68,7 @@ public: */ inline std::string implementation() override { - return "GPS_L1_CA_PCPS_Acquisition"; + return "GPS_L1_CA_PCPS_Acquisition_Fpga"; } inline size_t item_size() override diff --git a/src/algorithms/tracking/adapters/CMakeLists.txt b/src/algorithms/tracking/adapters/CMakeLists.txt index 6b60f35b1..345c23acc 100644 --- a/src/algorithms/tracking/adapters/CMakeLists.txt +++ b/src/algorithms/tracking/adapters/CMakeLists.txt @@ -22,7 +22,7 @@ if(ENABLE_CUDA) endif(ENABLE_CUDA) if(ENABLE_FPGA) - SET(OPT_TRACKING_ADAPTERS ${OPT_TRACKING_ADAPTERS} gps_l1_ca_dll_pll_tracking_fpga.cc) + SET(OPT_TRACKING_ADAPTERS ${OPT_TRACKING_ADAPTERS} gps_l1_ca_dll_pll_tracking_fpga.cc galileo_e1_dll_pll_veml_tracking_fpga.cc) endif(ENABLE_FPGA) set(TRACKING_ADAPTER_SOURCES diff --git a/src/algorithms/tracking/adapters/galileo_e1_dll_pll_veml_tracking_fpga.cc b/src/algorithms/tracking/adapters/galileo_e1_dll_pll_veml_tracking_fpga.cc new file mode 100644 index 000000000..afa3d7828 --- /dev/null +++ b/src/algorithms/tracking/adapters/galileo_e1_dll_pll_veml_tracking_fpga.cc @@ -0,0 +1,239 @@ +/*! + * \file galileo_e1_dll_pll_veml_tracking.cc + * \brief Adapts a DLL+PLL VEML (Very Early Minus Late) tracking loop block + * to a TrackingInterface for Galileo E1 signals + * \author Luis Esteve, 2012. luis(at)epsilon-formacion.com + * + * Code DLL + carrier PLL according to the algorithms described in: + * K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen, + * A Software-Defined GPS and Galileo Receiver. A Single-Frequency + * Approach, Birkhauser, 2007 + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors) + * + * GNSS-SDR is a software defined Global Navigation + * Satellite Systems receiver + * + * This file is part of GNSS-SDR. + * + * GNSS-SDR is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GNSS-SDR is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNSS-SDR. If not, see . + * + * ------------------------------------------------------------------------- + */ + +#include "galileo_e1_dll_pll_veml_tracking_fpga.h" +#include "configuration_interface.h" +#include "Galileo_E1.h" +#include "galileo_e1_signal_processing.h" +#include "gnss_sdr_flags.h" +#include "display.h" +#include + +#define NUM_PRNs_GALILEO_E1 50 + +using google::LogMessage; + +GalileoE1DllPllVemlTrackingFpga::GalileoE1DllPllVemlTrackingFpga( + ConfigurationInterface* configuration, std::string role, + unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams) +{ + printf("galileo e1 fpga constructor called\n"); + //dllpllconf_t trk_param; + dllpllconf_fpga_t trk_param_fpga; + DLOG(INFO) << "role " << role; + //################# CONFIGURATION PARAMETERS ######################## + std::string default_item_type = "gr_complex"; + std::string item_type = configuration->property(role + ".item_type", default_item_type); + int fs_in_deprecated = configuration->property("GNSS-SDR.internal_fs_hz", 2048000); + int fs_in = configuration->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated); + trk_param_fpga.fs_in = fs_in; + bool dump = configuration->property(role + ".dump", false); + trk_param_fpga.dump = dump; + float pll_bw_hz = configuration->property(role + ".pll_bw_hz", 5.0); + if (FLAGS_pll_bw_hz != 0.0) pll_bw_hz = static_cast(FLAGS_pll_bw_hz); + trk_param_fpga.pll_bw_hz = pll_bw_hz; + float dll_bw_hz = configuration->property(role + ".dll_bw_hz", 0.5); + if (FLAGS_dll_bw_hz != 0.0) dll_bw_hz = static_cast(FLAGS_dll_bw_hz); + trk_param_fpga.dll_bw_hz = dll_bw_hz; + float pll_bw_narrow_hz = configuration->property(role + ".pll_bw_narrow_hz", 2.0); + trk_param_fpga.pll_bw_narrow_hz = pll_bw_narrow_hz; + float dll_bw_narrow_hz = configuration->property(role + ".dll_bw_narrow_hz", 0.25); + trk_param_fpga.dll_bw_narrow_hz = dll_bw_narrow_hz; + int extend_correlation_symbols = configuration->property(role + ".extend_correlation_symbols", 1); + float early_late_space_chips = configuration->property(role + ".early_late_space_chips", 0.15); + trk_param_fpga.early_late_space_chips = early_late_space_chips; + float very_early_late_space_chips = configuration->property(role + ".very_early_late_space_chips", 0.6); + trk_param_fpga.very_early_late_space_chips = very_early_late_space_chips; + float early_late_space_narrow_chips = configuration->property(role + ".early_late_space_narrow_chips", 0.15); + trk_param_fpga.early_late_space_narrow_chips = early_late_space_narrow_chips; + float very_early_late_space_narrow_chips = configuration->property(role + ".very_early_late_space_narrow_chips", 0.6); + trk_param_fpga.very_early_late_space_narrow_chips = very_early_late_space_narrow_chips; + bool track_pilot = configuration->property(role + ".track_pilot", false); + if (extend_correlation_symbols < 1) + { + extend_correlation_symbols = 1; + std::cout << TEXT_RED << "WARNING: Galileo E1. extend_correlation_symbols must be bigger than 0. Coherent integration has been set to 1 symbol (4 ms)" << TEXT_RESET << std::endl; + } + else if (!track_pilot and extend_correlation_symbols > 1) + { + extend_correlation_symbols = 1; + std::cout << TEXT_RED << "WARNING: Galileo E1. Extended coherent integration is not allowed when tracking the data component. Coherent integration has been set to 4 ms (1 symbol)" << TEXT_RESET << std::endl; + } + if ((extend_correlation_symbols > 1) and (pll_bw_narrow_hz > pll_bw_hz or dll_bw_narrow_hz > dll_bw_hz)) + { + std::cout << TEXT_RED << "WARNING: Galileo E1. PLL or DLL narrow tracking bandwidth is higher than wide tracking one" << TEXT_RESET << std::endl; + } + trk_param_fpga.track_pilot = track_pilot; + trk_param_fpga.extend_correlation_symbols = extend_correlation_symbols; + std::string default_dump_filename = "./track_ch"; + std::string dump_filename = configuration->property(role + ".dump_filename", default_dump_filename); + trk_param_fpga.dump_filename = dump_filename; + int vector_length = std::round(fs_in / (Galileo_E1_CODE_CHIP_RATE_HZ / Galileo_E1_B_CODE_LENGTH_CHIPS)); + trk_param_fpga.vector_length = vector_length; + trk_param_fpga.system = 'E'; + char sig_[3] = "1B"; + std::memcpy(trk_param_fpga.signal, sig_, 3); + int cn0_samples = configuration->property(role + ".cn0_samples", 20); + if (FLAGS_cn0_samples != 20) cn0_samples = FLAGS_cn0_samples; + trk_param_fpga.cn0_samples = cn0_samples; + int cn0_min = configuration->property(role + ".cn0_min", 25); + if (FLAGS_cn0_min != 25) cn0_min = FLAGS_cn0_min; + trk_param_fpga.cn0_min = cn0_min; + int max_lock_fail = configuration->property(role + ".max_lock_fail", 50); + if (FLAGS_max_lock_fail != 50) max_lock_fail = FLAGS_max_lock_fail; + trk_param_fpga.max_lock_fail = max_lock_fail; + double carrier_lock_th = configuration->property(role + ".carrier_lock_th", 0.85); + if (FLAGS_carrier_lock_th != 0.85) carrier_lock_th = FLAGS_carrier_lock_th; + trk_param_fpga.carrier_lock_th = carrier_lock_th; + + // FPGA configuration parameters + std::string default_device_name = "/dev/uio"; + std::string device_name = configuration->property(role + ".devicename", default_device_name); + trk_param_fpga.device_name = device_name; + unsigned int device_base = configuration->property(role + ".device_base", 1); + trk_param_fpga.device_base = device_base; + + //################# PRE-COMPUTE ALL THE CODES ################# + + d_ca_codes = static_cast(volk_gnsssdr_malloc(static_cast(Galileo_E1_B_CODE_LENGTH_CHIPS)* 2 * NUM_PRNs_GALILEO_E1 * sizeof(int), volk_gnsssdr_get_alignment())); + d_data_codes = static_cast(volk_gnsssdr_malloc((static_cast(Galileo_E1_B_CODE_LENGTH_CHIPS)) * 2 * NUM_PRNs_GALILEO_E1 * sizeof(int), volk_gnsssdr_get_alignment())); + + float* ca_codes_f = static_cast(volk_gnsssdr_malloc(static_cast(Galileo_E1_B_CODE_LENGTH_CHIPS)* 2 * sizeof(float), volk_gnsssdr_get_alignment())); + float* data_codes_f = static_cast(volk_gnsssdr_malloc((static_cast(Galileo_E1_B_CODE_LENGTH_CHIPS)) * 2 * sizeof(float), volk_gnsssdr_get_alignment())); + + for (unsigned int PRN = 1; PRN <= NUM_PRNs_GALILEO_E1; PRN++) + { + char data_signal[3] = "1B"; + if (trk_param_fpga.track_pilot) + { + char pilot_signal[3] = "1C"; + galileo_e1_code_gen_sinboc11_float(ca_codes_f, pilot_signal, PRN); + galileo_e1_code_gen_sinboc11_float(data_codes_f, data_signal, PRN); + + for (unsigned int s = 0; s < Galileo_E1_B_CODE_LENGTH_CHIPS; s++) + { + d_ca_codes[static_cast(Galileo_E1_B_CODE_LENGTH_CHIPS)* 2 * (PRN - 1) + s] = static_cast(ca_codes_f[s]); + d_data_codes[static_cast(Galileo_E1_B_CODE_LENGTH_CHIPS)* 2 * (PRN - 1) + s] = static_cast(d_data_codes[s]); + } + } + else + { + galileo_e1_code_gen_sinboc11_float(ca_codes_f, data_signal, PRN); + + for (unsigned int s = 0; s < Galileo_E1_B_CODE_LENGTH_CHIPS; s++) + { + d_ca_codes[static_cast(Galileo_E1_B_CODE_LENGTH_CHIPS)* 2 * (PRN - 1) + s] = static_cast(ca_codes_f[s]); + } + } + + } + + delete[] ca_codes_f; + delete[] data_codes_f; + + trk_param_fpga.ca_codes = d_ca_codes; + trk_param_fpga.data_codes = d_data_codes; + trk_param_fpga.code_length = Galileo_E1_B_CODE_LENGTH_CHIPS; + + //################# MAKE TRACKING GNURadio object ################### + tracking_fpga_sc = dll_pll_veml_make_tracking_fpga(trk_param_fpga); + channel_ = 0; + DLOG(INFO) << "tracking(" << tracking_fpga_sc->unique_id() << ")"; +} + + +GalileoE1DllPllVemlTrackingFpga::~GalileoE1DllPllVemlTrackingFpga() +{ + delete[] d_ca_codes; + delete[] d_data_codes; +} + + +void GalileoE1DllPllVemlTrackingFpga::start_tracking() +{ + //tracking_->start_tracking(); + tracking_fpga_sc->start_tracking(); +} + + +/* + * Set tracking channel unique ID + */ +void GalileoE1DllPllVemlTrackingFpga::set_channel(unsigned int channel) +{ + channel_ = channel; + //tracking_->set_channel(channel); + tracking_fpga_sc->set_channel(channel); +} + + +void GalileoE1DllPllVemlTrackingFpga::set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) +{ + //tracking_->set_gnss_synchro(p_gnss_synchro); + tracking_fpga_sc->set_gnss_synchro(p_gnss_synchro); +} + + +void GalileoE1DllPllVemlTrackingFpga::connect(gr::top_block_sptr top_block) +{ + if (top_block) + { /* top_block is not null */ + }; + //nothing to connect, now the tracking uses gr_sync_decimator +} + + +void GalileoE1DllPllVemlTrackingFpga::disconnect(gr::top_block_sptr top_block) +{ + if (top_block) + { /* top_block is not null */ + }; + //nothing to disconnect, now the tracking uses gr_sync_decimator +} + + +gr::basic_block_sptr GalileoE1DllPllVemlTrackingFpga::get_left_block() +{ + //return tracking_; + return tracking_fpga_sc; +} + + +gr::basic_block_sptr GalileoE1DllPllVemlTrackingFpga::get_right_block() +{ + //return tracking_; + return tracking_fpga_sc; +} diff --git a/src/algorithms/tracking/adapters/galileo_e1_dll_pll_veml_tracking_fpga.h b/src/algorithms/tracking/adapters/galileo_e1_dll_pll_veml_tracking_fpga.h new file mode 100644 index 000000000..2290e3e67 --- /dev/null +++ b/src/algorithms/tracking/adapters/galileo_e1_dll_pll_veml_tracking_fpga.h @@ -0,0 +1,109 @@ +/*! + * \file galileo_e1_dll_pll_veml_tracking.h + * \brief Adapts a DLL+PLL VEML (Very Early Minus Late) tracking loop block + * to a TrackingInterface for Galileo E1 signals + * \author Luis Esteve, 2012. luis(at)epsilon-formacion.com + * + * Code DLL + carrier PLL according to the algorithms described in: + * K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen, + * A Software-Defined GPS and Galileo Receiver. A Single-Frequency + * Approach, Birkhauser, 2007 + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors) + * + * GNSS-SDR is a software defined Global Navigation + * Satellite Systems receiver + * + * This file is part of GNSS-SDR. + * + * GNSS-SDR is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GNSS-SDR is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNSS-SDR. If not, see . + * + * ------------------------------------------------------------------------- + */ + +#ifndef GNSS_SDR_GALILEO_E1_DLL_PLL_VEML_TRACKING_FPGA_H_ +#define GNSS_SDR_GALILEO_E1_DLL_PLL_VEML_TRACKING_FPGA_H_ + +#include "tracking_interface.h" +#include "dll_pll_veml_tracking_fpga.h" +#include + + +class ConfigurationInterface; + +/*! + * \brief This class Adapts a DLL+PLL VEML (Very Early Minus Late) tracking + * loop block to a TrackingInterface for Galileo E1 signals + */ +class GalileoE1DllPllVemlTrackingFpga : public TrackingInterface +{ +public: + GalileoE1DllPllVemlTrackingFpga(ConfigurationInterface* configuration, + std::string role, + unsigned int in_streams, + unsigned int out_streams); + + virtual ~GalileoE1DllPllVemlTrackingFpga(); + + inline std::string role() override + { + return role_; + } + + //! Returns "Galileo_E1_DLL_PLL_VEML_Tracking" + inline std::string implementation() override + { + return "Galileo_E1_DLL_PLL_VEML_Tracking"; + } + + inline size_t item_size() override + { + return item_size_; + } + + void connect(gr::top_block_sptr top_block) override; + void disconnect(gr::top_block_sptr top_block) override; + gr::basic_block_sptr get_left_block() override; + gr::basic_block_sptr get_right_block() override; + + /*! + * \brief Set tracking channel unique ID + */ + void set_channel(unsigned int channel) override; + + /*! + * \brief Set acquisition/tracking common Gnss_Synchro object pointer + * to efficiently exchange synchronization data between acquisition and + * tracking blocks + */ + void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) override; + + void start_tracking() override; + +private: + //dll_pll_veml_tracking_sptr tracking_; + dll_pll_veml_tracking_fpga_sptr tracking_fpga_sc; + size_t item_size_; + unsigned int channel_; + std::string role_; + unsigned int in_streams_; + unsigned int out_streams_; + int* d_ca_codes; + int* d_data_codes; +}; + + +#endif // GNSS_SDR_GALILEO_E1_DLL_PLL_VEML_TRACKING_FPGA_H_ diff --git a/src/algorithms/tracking/adapters/gps_l1_ca_dll_pll_tracking_fpga.cc b/src/algorithms/tracking/adapters/gps_l1_ca_dll_pll_tracking_fpga.cc index df4f193eb..3f0a4cd98 100644 --- a/src/algorithms/tracking/adapters/gps_l1_ca_dll_pll_tracking_fpga.cc +++ b/src/algorithms/tracking/adapters/gps_l1_ca_dll_pll_tracking_fpga.cc @@ -1,5 +1,5 @@ /*! - * \file gps_l1_ca_dll_pll_tracking.cc + * \file gps_l1_ca_dll_pll_tracking_fpga.cc * \brief Implementation of an adapter of a DLL+PLL tracking loop block * for GPS L1 C/A to a TrackingInterface that uses the FPGA * \author Marc Majoral, 2018, mmajoral(at)cttc.es @@ -36,10 +36,6 @@ * ------------------------------------------------------------------------- */ - - -//#include - #include #include "gps_sdr_signal_processing.h" #include "gps_l1_ca_dll_pll_tracking_fpga.h" @@ -48,7 +44,6 @@ #include "gnss_sdr_flags.h" #include "display.h" - #define NUM_PRNs 32 using google::LogMessage; @@ -149,91 +144,6 @@ GpsL1CaDllPllTrackingFpga::GpsL1CaDllPllTrackingFpga( channel_ = 0; DLOG(INFO) << "tracking(" << tracking_fpga_sc->unique_id() << ")"; - - - - - - - /* - - - //################# CONFIGURATION PARAMETERS ######################## - int fs_in_deprecated = configuration->property("GNSS-SDR.internal_fs_hz", 2048000); - int fs_in = configuration->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated); - trk_param_fpga.fs_in = fs_in; - bool dump = configuration->property(role + ".dump", false); - trk_param_fpga.dump = dump; - float pll_bw_hz = configuration->property(role + ".pll_bw_hz", 50.0); - if (FLAGS_pll_bw_hz != 0.0) pll_bw_hz = static_cast(FLAGS_pll_bw_hz); - trk_param_fpga.pll_bw_hz = pll_bw_hz; - float pll_bw_narrow_hz = configuration->property(role + ".pll_bw_narrow_hz", 20.0); - trk_param_fpga.pll_bw_narrow_hz = pll_bw_narrow_hz; - float dll_bw_narrow_hz = configuration->property(role + ".dll_bw_narrow_hz", 2.0); - trk_param_fpga.dll_bw_narrow_hz = dll_bw_narrow_hz; - float dll_bw_hz = configuration->property(role + ".dll_bw_hz", 2.0); - if (FLAGS_dll_bw_hz != 0.0) dll_bw_hz = static_cast(FLAGS_dll_bw_hz); - trk_param_fpga.dll_bw_hz = dll_bw_hz; - float early_late_space_chips = configuration->property(role + ".early_late_space_chips", 0.5); - trk_param_fpga.early_late_space_chips = early_late_space_chips; - float early_late_space_narrow_chips = configuration->property(role + ".early_late_space_narrow_chips", 0.5); - trk_param_fpga.early_late_space_narrow_chips = early_late_space_narrow_chips; - std::string default_dump_filename = "./track_ch"; - std::string dump_filename = configuration->property(role + ".dump_filename", default_dump_filename); - trk_param_fpga.dump_filename = dump_filename; - int vector_length = std::round(fs_in / (GPS_L1_CA_CODE_RATE_HZ / GPS_L1_CA_CODE_LENGTH_CHIPS)); - trk_param_fpga.vector_length = vector_length; - int symbols_extended_correlator = configuration->property(role + ".extend_correlation_symbols", 1); - if (symbols_extended_correlator < 1) - { - symbols_extended_correlator = 1; - std::cout << TEXT_RED << "WARNING: GPS L1 C/A. extend_correlation_symbols must be bigger than 1. Coherent integration has been set to 1 symbol (1 ms)" << TEXT_RESET << std::endl; - } - else if (symbols_extended_correlator > 20) - { - symbols_extended_correlator = 20; - std::cout << TEXT_RED << "WARNING: GPS L1 C/A. extend_correlation_symbols must be lower than 21. Coherent integration has been set to 20 symbols (20 ms)" << TEXT_RESET << std::endl; - } - trk_param_fpga.extend_correlation_symbols = symbols_extended_correlator; - bool track_pilot = configuration->property(role + ".track_pilot", false); - if (track_pilot) - { - std::cout << TEXT_RED << "WARNING: GPS L1 C/A does not have pilot signal. Data tracking has been enabled" << TEXT_RESET << std::endl; - } - if ((symbols_extended_correlator > 1) and (pll_bw_narrow_hz > pll_bw_hz or dll_bw_narrow_hz > dll_bw_hz)) - { - std::cout << TEXT_RED << "WARNING: GPS L1 C/A. PLL or DLL narrow tracking bandwidth is higher than wide tracking one" << TEXT_RESET << std::endl; - } - trk_param_fpga.very_early_late_space_chips = 0.0; - trk_param_fpga.very_early_late_space_narrow_chips = 0.0; - trk_param_fpga.track_pilot = false; - trk_param_fpga.system = 'G'; - char sig_[3] = "1C"; - std::memcpy(trk_param_fpga.signal, sig_, 3); - - // FPGA configuration parameters - std::string default_device_name = "/dev/uio"; - std::string device_name = configuration->property(role + ".devicename", default_device_name); - trk_param_fpga.device_name = device_name; - unsigned int device_base = configuration->property(role + ".device_base", 1); - trk_param_fpga.device_base = device_base; - - //################# PRE-COMPUTE ALL THE CODES ################# - d_ca_codes = static_cast(volk_gnsssdr_malloc(static_cast(GPS_L1_CA_CODE_LENGTH_CHIPS*NUM_PRNs) * sizeof(int), volk_gnsssdr_get_alignment())); - for (unsigned int PRN = 1; PRN <= NUM_PRNs; PRN++) - { - gps_l1_ca_code_gen_int(&d_ca_codes[(int(GPS_L1_CA_CODE_LENGTH_CHIPS)) * (PRN - 1)], PRN, 0); - } - trk_param_fpga.ca_codes = d_ca_codes; - trk_param_fpga.code_length = GPS_L1_CA_CODE_LENGTH_CHIPS; - - //################# MAKE TRACKING GNURadio object ################### - tracking_fpga_sc = dll_pll_veml_make_tracking_fpga(trk_param_fpga); - channel_ = 0; - DLOG(INFO) << "tracking(" << tracking_fpga_sc->unique_id() << ")"; - - */ - } GpsL1CaDllPllTrackingFpga::~GpsL1CaDllPllTrackingFpga() diff --git a/src/algorithms/tracking/adapters/gps_l1_ca_dll_pll_tracking_fpga.h b/src/algorithms/tracking/adapters/gps_l1_ca_dll_pll_tracking_fpga.h index b7798be81..ea9c98423 100644 --- a/src/algorithms/tracking/adapters/gps_l1_ca_dll_pll_tracking_fpga.h +++ b/src/algorithms/tracking/adapters/gps_l1_ca_dll_pll_tracking_fpga.h @@ -1,5 +1,5 @@ /*! - * \file gps_l1_ca_dll_pll_tracking.h + * \file gps_l1_ca_dll_pll_tracking_fpga.h * \brief Interface of an adapter of a DLL+PLL tracking loop block * for GPS L1 C/A to a TrackingInterface that uses the FPGA * \author Marc Majoral, 2018. mmajoral(at)cttc.es @@ -96,7 +96,6 @@ public: //void reset(void); private: - //gps_l1_ca_dll_pll_tracking_cc_sptr tracking_; dll_pll_veml_tracking_fpga_sptr tracking_fpga_sc; size_t item_size_; unsigned int channel_; diff --git a/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking_fpga.cc b/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking_fpga.cc index 2a75713c4..d20e49338 100644 --- a/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking_fpga.cc +++ b/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking_fpga.cc @@ -1,5 +1,5 @@ /*! - * \file dll_pll_veml_tracking.cc + * \file dll_pll_veml_tracking_fpga.cc * \brief Implementation of a code DLL + carrier PLL tracking block using an FPGA * \author Marc Majoral, 2018. marc.majoral(at)cttc.es * Antonio Ramos, 2018 antonio.ramosdet(at)gmail.com @@ -365,9 +365,10 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_) std::string device_name = trk_parameters.device_name; unsigned int device_base = trk_parameters.device_base; int* ca_codes = trk_parameters.ca_codes; + int* data_codes = trk_parameters.data_codes; unsigned int code_length = trk_parameters.code_length; - multicorrelator_fpga = std::make_shared (d_n_correlator_taps, device_name, device_base, ca_codes, code_length); - multicorrelator_fpga->set_output_vectors(d_correlator_outs); + multicorrelator_fpga = std::make_shared (d_n_correlator_taps, device_name, device_base, ca_codes, data_codes, code_length, trk_parameters.track_pilot); + multicorrelator_fpga->set_output_vectors(d_correlator_outs, d_Prompt_Data); d_pull_in = 0; } @@ -438,6 +439,7 @@ void dll_pll_veml_tracking_fpga::start_tracking() { char pilot_signal[3] = "1C"; d_Prompt_Data[0] = gr_complex(0.0, 0.0); + // MISSING _: set_local_code_and_taps for the data correlator } else { @@ -505,7 +507,7 @@ void dll_pll_veml_tracking_fpga::start_tracking() LOG(INFO) << "PULL-IN Doppler [Hz] = " << d_carrier_doppler_hz << ". Code Phase correction [samples] = " << delay_correction_samples << ". PULL-IN Code Phase [samples] = " << d_acq_code_phase_samples; - multicorrelator_fpga->set_local_code_and_taps(static_cast(GPS_L1_CA_CODE_LENGTH_CHIPS), d_local_code_shift_chips, d_acquisition_gnss_synchro->PRN); + multicorrelator_fpga->set_local_code_and_taps(d_code_length_chips, d_local_code_shift_chips, d_acquisition_gnss_synchro->PRN); d_pull_in = 1; // enable tracking pull-in and d_state at the end to avoid general work from starting pull-in before the start tracking function is finished d_state = 1; diff --git a/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking_fpga.h b/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking_fpga.h index 750d24a42..ea4e556f4 100644 --- a/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking_fpga.h +++ b/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking_fpga.h @@ -76,6 +76,7 @@ typedef struct unsigned int device_base; unsigned int code_length; int* ca_codes; + int* data_codes; } dllpllconf_fpga_t; class dll_pll_veml_tracking_fpga; diff --git a/src/algorithms/tracking/libs/fpga_multicorrelator.cc b/src/algorithms/tracking/libs/fpga_multicorrelator.cc index 281bf2bc2..b13a084e9 100644 --- a/src/algorithms/tracking/libs/fpga_multicorrelator.cc +++ b/src/algorithms/tracking/libs/fpga_multicorrelator.cc @@ -104,9 +104,10 @@ void fpga_multicorrelator_8sc::set_local_code_and_taps(int code_length_chips, fpga_multicorrelator_8sc::fpga_configure_tracking_gps_local_code(PRN); } -void fpga_multicorrelator_8sc::set_output_vectors(gr_complex* corr_out) +void fpga_multicorrelator_8sc::set_output_vectors(gr_complex* corr_out, gr_complex* Prompt_Data) { d_corr_out = corr_out; + d_Prompt_Data = Prompt_Data; } void fpga_multicorrelator_8sc::update_local_code(float rem_code_phase_chips) @@ -144,11 +145,12 @@ void fpga_multicorrelator_8sc::Carrier_wipeoff_multicorrelator_resampler( } fpga_multicorrelator_8sc::fpga_multicorrelator_8sc(int n_correlators, - std::string device_name, unsigned int device_base, int *ca_codes, unsigned int code_length) + std::string device_name, unsigned int device_base, int *ca_codes, int *data_codes, unsigned int code_length, bool track_pilot) { d_n_correlators = n_correlators; d_device_name = device_name; d_device_base = device_base; + d_track_pilot = track_pilot; d_device_descriptor = 0; d_map_base = nullptr; @@ -158,7 +160,6 @@ fpga_multicorrelator_8sc::fpga_multicorrelator_8sc(int n_correlators, d_initial_interp_counter = static_cast(volk_gnsssdr_malloc( n_correlators * sizeof(unsigned), volk_gnsssdr_get_alignment())); - //d_local_code_in = nullptr; d_shifts_chips = nullptr; d_corr_out = nullptr; d_code_length_chips = 0; @@ -172,13 +173,6 @@ fpga_multicorrelator_8sc::fpga_multicorrelator_8sc(int n_correlators, d_channel = 0; d_correlator_length_samples = 0, d_code_length = code_length; - - // pre-compute all the codes -// d_ca_codes = static_cast(volk_gnsssdr_malloc(static_cast(GPS_L1_CA_CODE_LENGTH_CHIPS*NUM_PRNs) * sizeof(int), volk_gnsssdr_get_alignment())); -// for (unsigned int PRN = 1; PRN <= NUM_PRNs; PRN++) -// { -// gps_l1_ca_code_gen_int(&d_ca_codes[(int(GPS_L1_CA_CODE_LENGTH_CHIPS)) * (PRN - 1)], PRN, 0); -// } d_ca_codes = ca_codes; DLOG(INFO) << "TRACKING FPGA CLASS CREATED"; @@ -429,10 +423,6 @@ void fpga_multicorrelator_8sc::close_device() { printf("Failed to unmap memory uio\n"); } -/* else - { - printf("memory uio unmapped\n"); - } */ close(d_device_descriptor); } diff --git a/src/algorithms/tracking/libs/fpga_multicorrelator.h b/src/algorithms/tracking/libs/fpga_multicorrelator.h index 5012651d4..f054cc4d0 100644 --- a/src/algorithms/tracking/libs/fpga_multicorrelator.h +++ b/src/algorithms/tracking/libs/fpga_multicorrelator.h @@ -49,10 +49,10 @@ class fpga_multicorrelator_8sc { public: fpga_multicorrelator_8sc(int n_correlators, std::string device_name, - unsigned int device_base, int *ca_codes, unsigned int code_length); + unsigned int device_base, int *ca_codes, int *data_codes, unsigned int code_length, bool track_pilot); ~fpga_multicorrelator_8sc(); //bool set_output_vectors(gr_complex* corr_out); - void set_output_vectors(gr_complex* corr_out); + void set_output_vectors(gr_complex* corr_out, gr_complex* Prompt_Data); // bool set_local_code_and_taps( // int code_length_chips, const int* local_code_in, // float *shifts_chips, int PRN); @@ -78,6 +78,7 @@ public: private: //const int *d_local_code_in; gr_complex * d_corr_out; + gr_complex * d_Prompt_Data; float *d_shifts_chips; int d_code_length_chips; int d_n_correlators; @@ -112,6 +113,8 @@ private: unsigned int d_code_length; // nominal number of chips + bool d_track_pilot; + // private functions unsigned fpga_acquisition_test_register(unsigned writeval); void fpga_configure_tracking_gps_local_code(int PRN); @@ -123,9 +126,7 @@ private: void read_tracking_gps_results(void); void reset_multicorrelator(void); void close_device(void); - - // debug - //unsigned int first_time = 1; + }; #endif /* GNSS_SDR_FPGA_MULTICORRELATOR_H_ */ diff --git a/src/core/receiver/gnss_block_factory.cc b/src/core/receiver/gnss_block_factory.cc index 329f2e168..7bd7a23bc 100644 --- a/src/core/receiver/gnss_block_factory.cc +++ b/src/core/receiver/gnss_block_factory.cc @@ -4,6 +4,7 @@ * \author Carlos Aviles, 2010. carlos.avilesr(at)googlemail.com * Luis Esteve, 2012. luis(at)epsilon-formacion.com * Javier Arribas, 2011. jarribas(at)cttc.es + * Marc Majoral, 2018. mmajoral(at)cttc.es * * This class encapsulates the complexity behind the instantiation * of GNSS blocks. @@ -105,7 +106,9 @@ #if ENABLE_FPGA #include "gps_l1_ca_pcps_acquisition_fpga.h" +#include "galileo_e1_pcps_ambiguous_acquisition_fpga.h" #include "gps_l1_ca_dll_pll_tracking_fpga.h" +#include "galileo_e1_dll_pll_veml_tracking_fpga.h" #endif #if OPENCL_BLOCKS @@ -1383,6 +1386,14 @@ std::unique_ptr GNSSBlockFactory::GetBlock( out_streams)); block = std::move(block_); } +#if ENABLE_FPGA + else if (implementation.compare("Galileo_E1_PCPS_Ambiguous_Acquisition_Fpga") == 0) + { + std::unique_ptr block_(new GalileoE1PcpsAmbiguousAcquisitionFpga(configuration.get(), role, in_streams, + out_streams)); + block = std::move(block_); + } +#endif else if (implementation.compare("Galileo_E1_PCPS_8ms_Ambiguous_Acquisition") == 0) { std::unique_ptr block_(new GalileoE1Pcps8msAmbiguousAcquisition(configuration.get(), role, in_streams, @@ -1484,6 +1495,14 @@ std::unique_ptr GNSSBlockFactory::GetBlock( out_streams)); block = std::move(block_); } +#if ENABLE_FPGA + else if (implementation.compare("Galileo_E1_DLL_PLL_VEML_Tracking_Fpga") == 0) + { + std::unique_ptr block_(new GalileoE1DllPllVemlTrackingFpga(configuration.get(), role, in_streams, + out_streams)); + block = std::move(block_); + } +#endif else if (implementation.compare("Galileo_E1_TCP_CONNECTOR_Tracking") == 0) { std::unique_ptr block_(new GalileoE1TcpConnectorTracking(configuration.get(), role, in_streams, @@ -1676,6 +1695,14 @@ std::unique_ptr GNSSBlockFactory::GetAcqBlock( out_streams)); block = std::move(block_); } +#if ENABLE_FPGA + else if (implementation.compare("Galileo_E1_PCPS_Ambiguous_Acquisition_Fpga") == 0) + { + std::unique_ptr block_(new GalileoE1PcpsAmbiguousAcquisitionFpga(configuration.get(), role, in_streams, + out_streams)); + block = std::move(block_); + } +#endif else if (implementation.compare("Galileo_E1_PCPS_8ms_Ambiguous_Acquisition") == 0) { std::unique_ptr block_(new GalileoE1Pcps8msAmbiguousAcquisition(configuration.get(), role, in_streams, @@ -1775,6 +1802,14 @@ std::unique_ptr GNSSBlockFactory::GetTrkBlock( out_streams)); block = std::move(block_); } +#if ENABLE_FPGA + else if (implementation.compare("Galileo_E1_DLL_PLL_VEML_Tracking_Fpga") == 0) + { + std::unique_ptr block_(new GalileoE1DllPllVemlTrackingFpga(configuration.get(), role, in_streams, + out_streams)); + block = std::move(block_); + } +#endif else if (implementation.compare("Galileo_E1_TCP_CONNECTOR_Tracking") == 0) { std::unique_ptr block_(new GalileoE1TcpConnectorTracking(configuration.get(), role, in_streams, From bb33faea21a9c29ef5bd48bbc8c44d7912d08fe8 Mon Sep 17 00:00:00 2001 From: Marc Majoral Date: Wed, 1 Aug 2018 15:55:40 +0200 Subject: [PATCH 2/7] improved existing code started the GPS L2 FPGA class implementation (not finished yet) implemented the GPS L5 FPGA class (not tested yet) implemented the Galileo E5 FPGA class (not tested yet) The code is still "dirty": it is yet to be cleaned of debug comments/code and any possible redundant code and not used variables. --- .../acquisition/adapters/CMakeLists.txt | 2 +- ...ileo_e1_pcps_ambiguous_acquisition_fpga.cc | 157 ++++++- ...lileo_e1_pcps_ambiguous_acquisition_fpga.h | 3 + .../galileo_e5a_pcps_acquisition_fpga.cc | 399 +++++++++++++++++ .../galileo_e5a_pcps_acquisition_fpga.h | 176 ++++++++ .../gps_l1_ca_pcps_acquisition_fpga.cc | 48 +- .../gps_l2_m_pcps_acquisition_fpga.cc | 398 +++++++++++++++++ .../adapters/gps_l2_m_pcps_acquisition_fpga.h | 171 ++++++++ .../adapters/gps_l5i_pcps_acquisition_fpga.cc | 388 +++++++++++++++++ .../adapters/gps_l5i_pcps_acquisition_fpga.h | 171 ++++++++ .../gnuradio_blocks/pcps_acquisition_fpga.cc | 117 ++++- .../gnuradio_blocks/pcps_acquisition_fpga.h | 18 + .../acquisition/libs/fpga_acquisition.cc | 170 +++++++- .../acquisition/libs/fpga_acquisition.h | 5 +- .../tracking/adapters/CMakeLists.txt | 2 +- .../galileo_e1_dll_pll_veml_tracking_fpga.cc | 61 ++- .../galileo_e1_dll_pll_veml_tracking_fpga.h | 4 +- .../galileo_e5a_dll_pll_tracking_fpga.cc | 285 ++++++++++++ .../galileo_e5a_dll_pll_tracking_fpga.h | 110 +++++ .../gps_l1_ca_dll_pll_tracking_fpga.cc | 5 +- .../gps_l2_m_dll_pll_tracking_fpga.cc | 223 ++++++++++ .../adapters/gps_l2_m_dll_pll_tracking_fpga.h | 106 +++++ .../adapters/gps_l5_dll_pll_tracking_fpga.cc | 268 ++++++++++++ .../adapters/gps_l5_dll_pll_tracking_fpga.h | 106 +++++ .../dll_pll_veml_tracking_fpga.cc | 81 +++- .../dll_pll_veml_tracking_fpga.h | 5 +- .../tracking/libs/fpga_multicorrelator.cc | 411 +++++++++++++++--- .../tracking/libs/fpga_multicorrelator.h | 47 +- src/core/receiver/gnss_block_factory.cc | 102 +++++ 29 files changed, 3894 insertions(+), 145 deletions(-) create mode 100644 src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition_fpga.cc create mode 100644 src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition_fpga.h create mode 100644 src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition_fpga.cc create mode 100644 src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition_fpga.h create mode 100644 src/algorithms/acquisition/adapters/gps_l5i_pcps_acquisition_fpga.cc create mode 100644 src/algorithms/acquisition/adapters/gps_l5i_pcps_acquisition_fpga.h create mode 100644 src/algorithms/tracking/adapters/galileo_e5a_dll_pll_tracking_fpga.cc create mode 100644 src/algorithms/tracking/adapters/galileo_e5a_dll_pll_tracking_fpga.h create mode 100644 src/algorithms/tracking/adapters/gps_l2_m_dll_pll_tracking_fpga.cc create mode 100644 src/algorithms/tracking/adapters/gps_l2_m_dll_pll_tracking_fpga.h create mode 100644 src/algorithms/tracking/adapters/gps_l5_dll_pll_tracking_fpga.cc create mode 100644 src/algorithms/tracking/adapters/gps_l5_dll_pll_tracking_fpga.h diff --git a/src/algorithms/acquisition/adapters/CMakeLists.txt b/src/algorithms/acquisition/adapters/CMakeLists.txt index fe54e8880..d9900f257 100644 --- a/src/algorithms/acquisition/adapters/CMakeLists.txt +++ b/src/algorithms/acquisition/adapters/CMakeLists.txt @@ -37,7 +37,7 @@ set(ACQ_ADAPTER_SOURCES ) if(ENABLE_FPGA) - set(ACQ_ADAPTER_SOURCES ${ACQ_ADAPTER_SOURCES} gps_l1_ca_pcps_acquisition_fpga.cc galileo_e1_pcps_ambiguous_acquisition_fpga.cc) + set(ACQ_ADAPTER_SOURCES ${ACQ_ADAPTER_SOURCES} gps_l1_ca_pcps_acquisition_fpga.cc gps_l2_m_pcps_acquisition_fpga.cc galileo_e1_pcps_ambiguous_acquisition_fpga.cc galileo_e5a_pcps_acquisition_fpga.cc gps_l5i_pcps_acquisition_fpga.cc) endif(ENABLE_FPGA) if(OPENCL_FOUND) diff --git a/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition_fpga.cc b/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition_fpga.cc index 287730d1e..a605c70c1 100644 --- a/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition_fpga.cc +++ b/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition_fpga.cc @@ -38,7 +38,7 @@ #include #include -#define NUM_PRNs_GALILEO_E1 50 + using google::LogMessage; @@ -46,7 +46,7 @@ GalileoE1PcpsAmbiguousAcquisitionFpga::GalileoE1PcpsAmbiguousAcquisitionFpga( ConfigurationInterface* configuration, std::string role, unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams) { - printf("galileo e1 fpga constructor called\n"); + //printf("top acq constructor start\n"); pcpsconf_fpga_t acq_parameters; configuration_ = configuration; std::string default_item_type = "gr_complex"; @@ -61,16 +61,17 @@ GalileoE1PcpsAmbiguousAcquisitionFpga::GalileoE1PcpsAmbiguousAcquisitionFpga( acq_parameters.fs_in = fs_in; if_ = configuration_->property(role + ".if", 0); acq_parameters.freq = if_; - dump_ = configuration_->property(role + ".dump", false); + + // dump_ = configuration_->property(role + ".dump", false); // acq_parameters.dump = dump_; - blocking_ = configuration_->property(role + ".blocking", true); + // blocking_ = configuration_->property(role + ".blocking", true); // acq_parameters.blocking = blocking_; doppler_max_ = configuration_->property(role + ".doppler_max", 5000); if (FLAGS_doppler_max != 0) doppler_max_ = FLAGS_doppler_max; acq_parameters.doppler_max = doppler_max_; unsigned int sampled_ms = 4; acq_parameters.sampled_ms = sampled_ms; - bit_transition_flag_ = configuration_->property(role + ".bit_transition_flag", false); + // bit_transition_flag_ = configuration_->property(role + ".bit_transition_flag", false); // acq_parameters.bit_transition_flag = bit_transition_flag_; // use_CFAR_algorithm_flag_ = configuration_->property(role + ".use_CFAR_algorithm", true); //will be false in future versions // acq_parameters.use_CFAR_algorithm_flag = use_CFAR_algorithm_flag_; @@ -78,7 +79,7 @@ GalileoE1PcpsAmbiguousAcquisitionFpga::GalileoE1PcpsAmbiguousAcquisitionFpga( // max_dwells_ = configuration_->property(role + ".max_dwells", 1); // acq_parameters.max_dwells = max_dwells_; - dump_filename_ = configuration_->property(role + ".dump_filename", default_dump_filename); + // dump_filename_ = configuration_->property(role + ".dump_filename", default_dump_filename); // acq_parameters.dump_filename = dump_filename_; //--- Find number of samples per spreading code (4 ms) ----------------- unsigned int code_length = static_cast(std::round(static_cast(fs_in) / (Galileo_E1_CODE_CHIP_RATE_HZ / Galileo_E1_B_CODE_LENGTH_CHIPS))); @@ -92,12 +93,16 @@ GalileoE1PcpsAmbiguousAcquisitionFpga::GalileoE1PcpsAmbiguousAcquisitionFpga( // vector_length_ *= 2; // } - - + //printf("fs_in = %d\n", fs_in); + //printf("Galileo_E1_B_CODE_LENGTH_CHIPS = %f\n", Galileo_E1_B_CODE_LENGTH_CHIPS); + //printf("Galileo_E1_CODE_CHIP_RATE_HZ = %f\n", Galileo_E1_CODE_CHIP_RATE_HZ); + //printf("acq adapter code_length = %d\n", code_length); + acq_parameters.code_length = code_length; // The FPGA can only use FFT lengths that are a power of two. float nbits = ceilf(log2f((float)code_length)); unsigned int nsamples_total = pow(2, nbits); unsigned int vector_length = nsamples_total; + //printf("acq adapter nsamples_total (= vector_length) = %d\n", vector_length); unsigned int select_queue_Fpga = configuration_->property(role + ".select_queue_Fpga", 0); acq_parameters.select_queue_Fpga = select_queue_Fpga; std::string default_device_name = "/dev/uio0"; @@ -106,18 +111,17 @@ GalileoE1PcpsAmbiguousAcquisitionFpga::GalileoE1PcpsAmbiguousAcquisitionFpga( acq_parameters.samples_per_ms = nsamples_total/sampled_ms; acq_parameters.samples_per_code = nsamples_total; - - // compute all the GALILEO E1 PRN Codes (this is done only once upon the class constructor in order to avoid re-computing the PRN codes every time // a channel is assigned) gr::fft::fft_complex* fft_if = new gr::fft::fft_complex(nsamples_total, true); // Direct FFT std::complex* code = new std::complex[nsamples_total]; // buffer for the local code gr_complex* fft_codes_padded = static_cast(volk_gnsssdr_malloc(nsamples_total * sizeof(gr_complex), volk_gnsssdr_get_alignment())); - d_all_fft_codes_ = new lv_16sc_t[nsamples_total * NUM_PRNs_GALILEO_E1]; // memory containing all the possible fft codes for PRN 0 to 32 + d_all_fft_codes_ = new lv_16sc_t[nsamples_total * Galileo_E1_NUMBER_OF_CODES]; // memory containing all the possible fft codes for PRN 0 to 32 float max; // temporary maxima search + //int tmp_re, tmp_im; - for (unsigned int PRN = 1; PRN <= NUM_PRNs_GALILEO_E1; PRN++) + for (unsigned int PRN = 1; PRN <= Galileo_E1_NUMBER_OF_CODES; PRN++) { //code_ = new gr_complex[vector_length_]; @@ -128,15 +132,17 @@ GalileoE1PcpsAmbiguousAcquisitionFpga::GalileoE1PcpsAmbiguousAcquisitionFpga( if (acquire_pilot_ == true) { + //printf("yes acquiring pilot!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1\n"); //set local signal generator to Galileo E1 pilot component (1C) char pilot_signal[3] = "1C"; galileo_e1_code_gen_complex_sampled(code, pilot_signal, - cboc, gnss_synchro_->PRN, fs_in, 0, false); + cboc, PRN, fs_in, 0, false); } else { - galileo_e1_code_gen_complex_sampled(code, gnss_synchro_->Signal, - cboc, gnss_synchro_->PRN, fs_in, 0, false); + char data_signal[3] = "1B"; + galileo_e1_code_gen_complex_sampled(code, data_signal, + cboc, PRN, fs_in, 0, false); } // for (unsigned int i = 0; i < sampled_ms / 4; i++) @@ -145,16 +151,43 @@ GalileoE1PcpsAmbiguousAcquisitionFpga::GalileoE1PcpsAmbiguousAcquisitionFpga( // memcpy(&(d_all_fft_codes_[i * code_length_]), code, sizeof(gr_complex) * code_length_); // } + +// // debug +// char filename[25]; +// FILE *fid; +// sprintf(filename,"gal_prn%d.txt", PRN); +// fid = fopen(filename, "w"); +// for (unsigned int kk=0;kk< nsamples_total; kk++) +// { +// fprintf(fid, "%f\n", code[kk].real()); +// fprintf(fid, "%f\n", code[kk].imag()); +// } +// fclose(fid); + + // // fill in zero padding for (int s = code_length; s < nsamples_total; s++) { - code[s] = 0; + code[s] = std::complex(static_cast(0,0)); + //code[s] = 0; } memcpy(fft_if->get_inbuf(), code, sizeof(gr_complex) * nsamples_total); // copy to FFT buffer fft_if->execute(); // Run the FFT of local code volk_32fc_conjugate_32fc(fft_codes_padded, fft_if->get_outbuf(), nsamples_total); // conjugate values +// // debug +// char filename[25]; +// FILE *fid; +// sprintf(filename,"fft_gal_prn%d.txt", PRN); +// fid = fopen(filename, "w"); +// for (unsigned int kk=0;kk< nsamples_total; kk++) +// { +// fprintf(fid, "%f\n", fft_codes_padded[kk].real()); +// fprintf(fid, "%f\n", fft_codes_padded[kk].imag()); +// } +// fclose(fid); + // normalize the code max = 0; // initialize maximum value @@ -171,13 +204,71 @@ GalileoE1PcpsAmbiguousAcquisitionFpga::GalileoE1PcpsAmbiguousAcquisitionFpga( } for (unsigned int i = 0; i < nsamples_total; i++) // map the FFT to the dynamic range of the fixed point values an copy to buffer containing all FFTs { - d_all_fft_codes_[i + nsamples_total * (PRN - 1)] = lv_16sc_t(static_cast(floor(fft_codes_padded[i].real() * (pow(2, 7) - 1) / max)), - static_cast(floor(fft_codes_padded[i].imag() * (pow(2, 7) - 1) / max))); + //d_all_fft_codes_[i + nsamples_total * (PRN - 1)] = lv_16sc_t(static_cast(floor(4096*fft_codes_padded[i].real() * (pow(2, 3) - 1) / max)), + // static_cast(floor(4096*fft_codes_padded[i].imag() * (pow(2, 3) - 1) / max))); +// d_all_fft_codes_[i + nsamples_total * (PRN - 1)] = lv_16sc_t(static_cast(floor(1024*fft_codes_padded[i].real() * (pow(2, 5) - 1) / max)), +// static_cast(floor(1024*fft_codes_padded[i].imag() * (pow(2, 5) - 1) / max))); + d_all_fft_codes_[i + nsamples_total * (PRN - 1)] = lv_16sc_t(static_cast(floor(256*fft_codes_padded[i].real() * (pow(2, 7) - 1) / max)), + static_cast(floor(256*fft_codes_padded[i].imag() * (pow(2, 7) - 1) / max))); +// d_all_fft_codes_[i + nsamples_total * (PRN - 1)] = lv_16sc_t(static_cast(floor(16*fft_codes_padded[i].real() * (pow(2, 11) - 1) / max)), +// static_cast(floor(16*fft_codes_padded[i].imag() * (pow(2, 11) - 1) / max))); +// d_all_fft_codes_[i + nsamples_total * (PRN - 1)] = lv_16sc_t(static_cast(floor(fft_codes_padded[i].real() * (pow(2, 15) - 1) / max)), +// static_cast(floor(fft_codes_padded[i].imag() * (pow(2, 15) - 1) / max))); + +// tmp_re = static_cast(floor(fft_codes_padded[i].real() * (pow(2, 7) - 1) / max)); +// tmp_im = static_cast(floor(fft_codes_padded[i].imag() * (pow(2, 7) - 1) / max)); + +// if (tmp_re > 127) +// { +// tmp_re = 127; +// } +// if (tmp_re < -128) +// { +// tmp_re = -128; +// } +// if (tmp_im > 127) +// { +// tmp_im = 127; +// } +// if (tmp_im < -128) +// { +// tmp_im = -128; +// } +// d_all_fft_codes_[i + nsamples_total * (PRN - 1)] = lv_16sc_t(static_cast(tmp_re), static_cast(tmp_im)); +// } +// // debug +// char filename2[25]; +// FILE *fid2; +// sprintf(filename2,"fft_gal_prn%d_norm.txt", PRN); +// fid2 = fopen(filename2, "w"); +// for (unsigned int kk=0;kk< nsamples_total; kk++) +// { +// fprintf(fid2, "%d\n", d_all_fft_codes_[kk + nsamples_total * (PRN - 1)].real()); +// fprintf(fid2, "%d\n", d_all_fft_codes_[kk + nsamples_total * (PRN - 1)].imag()); +// } +// fclose(fid2); + } + +// for (unsigned int PRN = 1; PRN <= Galileo_E1_NUMBER_OF_CODES; PRN++) +// { +// // debug +// char filename2[25]; +// FILE *fid2; +// sprintf(filename2,"fft_gal_prn%d_norm_last.txt", PRN); +// fid2 = fopen(filename2, "w"); +// for (unsigned int kk=0;kk< nsamples_total; kk++) +// { +// fprintf(fid2, "%d\n", d_all_fft_codes_[kk + nsamples_total * (PRN - 1)].real()); +// fprintf(fid2, "%d\n", d_all_fft_codes_[kk + nsamples_total * (PRN - 1)].imag()); +// } +// fclose(fid2); +// } + //acq_parameters acq_parameters.all_fft_codes = d_all_fft_codes_; @@ -203,25 +294,31 @@ GalileoE1PcpsAmbiguousAcquisitionFpga::GalileoE1PcpsAmbiguousAcquisitionFpga( //threshold_ = 0.0; doppler_step_ = 0; gnss_synchro_ = 0; + //printf("top acq constructor end\n"); } GalileoE1PcpsAmbiguousAcquisitionFpga::~GalileoE1PcpsAmbiguousAcquisitionFpga() { + //printf("top acq destructor start\n"); //delete[] code_; delete[] d_all_fft_codes_; + //printf("top acq destructor end\n"); } void GalileoE1PcpsAmbiguousAcquisitionFpga::set_channel(unsigned int channel) { + //printf("top acq set channel start\n"); channel_ = channel; acquisition_fpga_->set_channel(channel_); + //printf("top acq set channel end\n"); } void GalileoE1PcpsAmbiguousAcquisitionFpga::set_threshold(float threshold) { + //printf("top acq set threshold start\n"); // the .pfa parameter and the threshold calculation is only used for the CFAR algorithm. // We don't use the CFAR algorithm in the FPGA. Therefore the threshold is set as such. @@ -241,48 +338,60 @@ void GalileoE1PcpsAmbiguousAcquisitionFpga::set_threshold(float threshold) DLOG(INFO) << "Channel " << channel_ << " Threshold = " << threshold; acquisition_fpga_->set_threshold(threshold); // acquisition_fpga_->set_threshold(threshold_); + //printf("top acq set threshold end\n"); } void GalileoE1PcpsAmbiguousAcquisitionFpga::set_doppler_max(unsigned int doppler_max) { + //printf("top acq set doppler max start\n"); doppler_max_ = doppler_max; acquisition_fpga_->set_doppler_max(doppler_max_); + //printf("top acq set doppler max end\n"); } void GalileoE1PcpsAmbiguousAcquisitionFpga::set_doppler_step(unsigned int doppler_step) { + //printf("top acq set doppler step start\n"); doppler_step_ = doppler_step; acquisition_fpga_->set_doppler_step(doppler_step_); + //printf("top acq set doppler step end\n"); } void GalileoE1PcpsAmbiguousAcquisitionFpga::set_gnss_synchro(Gnss_Synchro* gnss_synchro) { + //printf("top acq set gnss synchro start\n"); gnss_synchro_ = gnss_synchro; acquisition_fpga_->set_gnss_synchro(gnss_synchro_); + //printf("top acq set gnss synchro end\n"); } signed int GalileoE1PcpsAmbiguousAcquisitionFpga::mag() { + // printf("top acq mag start\n"); return acquisition_fpga_->mag(); + //printf("top acq mag end\n"); } void GalileoE1PcpsAmbiguousAcquisitionFpga::init() { + // printf("top acq init start\n"); acquisition_fpga_->init(); + // printf("top acq init end\n"); //set_local_code(); } void GalileoE1PcpsAmbiguousAcquisitionFpga::set_local_code() { + // printf("top acq set local code start\n"); // bool cboc = configuration_->property( // "Acquisition" + boost::lexical_cast(channel_) + ".cboc", false); // @@ -310,18 +419,23 @@ void GalileoE1PcpsAmbiguousAcquisitionFpga::set_local_code() //acquisition_fpga_->set_local_code(code_); acquisition_fpga_->set_local_code(); // delete[] code; + // printf("top acq set local code end\n"); } void GalileoE1PcpsAmbiguousAcquisitionFpga::reset() { + // printf("top acq reset start\n"); acquisition_fpga_->set_active(true); + // printf("top acq reset end\n"); } void GalileoE1PcpsAmbiguousAcquisitionFpga::set_state(int state) { + // printf("top acq set state start\n"); acquisition_fpga_->set_state(state); + // printf("top acq set state end\n"); } @@ -348,6 +462,7 @@ void GalileoE1PcpsAmbiguousAcquisitionFpga::set_state(int state) void GalileoE1PcpsAmbiguousAcquisitionFpga::connect(gr::top_block_sptr top_block) { + // printf("top acq connect\n"); // if (item_type_.compare("gr_complex") == 0) // { // top_block->connect(stream_to_vector_, 0, acquisition_fpga_, 0); @@ -397,11 +512,13 @@ void GalileoE1PcpsAmbiguousAcquisitionFpga::disconnect(gr::top_block_sptr top_bl // } // nothing to disconnect + // printf("top acq disconnect\n"); } gr::basic_block_sptr GalileoE1PcpsAmbiguousAcquisitionFpga::get_left_block() { + // printf("top acq get left block start\n"); // if (item_type_.compare("gr_complex") == 0) // { // return stream_to_vector_; @@ -419,10 +536,14 @@ gr::basic_block_sptr GalileoE1PcpsAmbiguousAcquisitionFpga::get_left_block() // LOG(WARNING) << item_type_ << " unknown acquisition item type"; return nullptr; // } + // printf("top acq get left block end\n"); } gr::basic_block_sptr GalileoE1PcpsAmbiguousAcquisitionFpga::get_right_block() { + // printf("top acq get right block start\n"); return acquisition_fpga_; + // printf("top acq get right block end\n"); } + diff --git a/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition_fpga.h b/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition_fpga.h index 36edead1f..bb0c5871f 100644 --- a/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition_fpga.h +++ b/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition_fpga.h @@ -59,6 +59,7 @@ public: inline std::string role() override { + // printf("top acq role\n"); return role_; } @@ -67,11 +68,13 @@ public: */ inline std::string implementation() override { + // printf("top acq implementation\n"); return "Galileo_E1_PCPS_Ambiguous_Acquisition_Fpga"; } size_t item_size() override { + // printf("top acq item size\n"); size_t item_size = sizeof(lv_16sc_t); return item_size; } diff --git a/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition_fpga.cc b/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition_fpga.cc new file mode 100644 index 000000000..aba5d9931 --- /dev/null +++ b/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition_fpga.cc @@ -0,0 +1,399 @@ +/*! + * \file galileo_e5a_pcps_acquisition.cc + * \brief Adapts a PCPS acquisition block to an AcquisitionInterface for + * Galileo E5a data and pilot Signals + * \author Antonio Ramos, 2018. antonio.ramos(at)cttc.es + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2018 (see AUTHORS file for a list of contributors) + * + * GNSS-SDR is a software defined Global Navigation + * Satellite Systems receiver + * + * This file is part of GNSS-SDR. + * + * GNSS-SDR is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GNSS-SDR is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNSS-SDR. If not, see . + * + * ------------------------------------------------------------------------- + */ + +#include "galileo_e5a_pcps_acquisition_fpga.h" +#include "configuration_interface.h" +#include "galileo_e5_signal_processing.h" +#include "Galileo_E5a.h" +#include "gnss_sdr_flags.h" +#include +#include +#include +#include + + + + + +using google::LogMessage; + +GalileoE5aPcpsAcquisitionFpga::GalileoE5aPcpsAcquisitionFpga(ConfigurationInterface* configuration, + std::string role, unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams) +{ + pcpsconf_fpga_t acq_parameters; + configuration_ = configuration; + std::string default_item_type = "gr_complex"; + std::string default_dump_filename = "../data/acquisition.dat"; + + DLOG(INFO) << "Role " << role; + + //item_type_ = configuration_->property(role + ".item_type", default_item_type); + + long fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 32000000); + long fs_in = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated); + acq_parameters.fs_in = fs_in; + acq_parameters.freq = 0; + + + //dump_ = configuration_->property(role + ".dump", false); + //acq_parameters.dump = dump_; + doppler_max_ = configuration_->property(role + ".doppler_max", 5000); + if (FLAGS_doppler_max != 0) doppler_max_ = FLAGS_doppler_max; + acq_parameters.doppler_max = doppler_max_; + unsigned int sampled_ms = 1; + //max_dwells_ = configuration_->property(role + ".max_dwells", 1); + //acq_parameters.max_dwells = max_dwells_; + //dump_filename_ = configuration_->property(role + ".dump_filename", default_dump_filename); + //acq_parameters.dump_filename = dump_filename_; + //bit_transition_flag_ = configuration_->property(role + ".bit_transition_flag", false); + //acq_parameters.bit_transition_flag = bit_transition_flag_; + //use_CFAR_ = configuration_->property(role + ".use_CFAR_algorithm", false); + //acq_parameters.use_CFAR_algorithm_flag = use_CFAR_; + //blocking_ = configuration_->property(role + ".blocking", true); + //acq_parameters.blocking = blocking_; + //--- Find number of samples per spreading code (1ms)------------------------- + + acq_pilot_ = configuration_->property(role + ".acquire_pilot", false); + acq_iq_ = configuration_->property(role + ".acquire_iq", false); + if (acq_iq_) + { + acq_pilot_ = false; + } + + unsigned int code_length = static_cast(std::round(static_cast(fs_in) / Galileo_E5a_CODE_CHIP_RATE_HZ * static_cast(Galileo_E5a_CODE_LENGTH_CHIPS))); + acq_parameters.code_length = code_length; + // The FPGA can only use FFT lengths that are a power of two. + float nbits = ceilf(log2f((float)code_length)); + unsigned int nsamples_total = pow(2, nbits); + unsigned int vector_length = nsamples_total; + unsigned int select_queue_Fpga = configuration_->property(role + ".select_queue_Fpga", 1); + acq_parameters.select_queue_Fpga = select_queue_Fpga; + std::string default_device_name = "/dev/uio0"; + std::string device_name = configuration_->property(role + ".devicename", default_device_name); + acq_parameters.device_name = device_name; + acq_parameters.samples_per_ms = nsamples_total/sampled_ms; + acq_parameters.samples_per_code = nsamples_total; + + //vector_length_ = code_length_ * sampled_ms_; + + // compute all the GALILEO E5 PRN Codes (this is done only once upon the class constructor in order to avoid re-computing the PRN codes every time + // a channel is assigned) + gr::fft::fft_complex* fft_if = new gr::fft::fft_complex(nsamples_total, true); // Direct FFT + std::complex* code = new std::complex[nsamples_total]; // buffer for the local code + gr_complex* fft_codes_padded = static_cast(volk_gnsssdr_malloc(nsamples_total * sizeof(gr_complex), volk_gnsssdr_get_alignment())); + d_all_fft_codes_ = new lv_16sc_t[nsamples_total * Galileo_E5a_NUMBER_OF_CODES]; // memory containing all the possible fft codes for PRN 0 to 32 + float max; // temporary maxima search + + + for (unsigned int PRN = 1; PRN <= Galileo_E5a_NUMBER_OF_CODES; PRN++) + { + // gr_complex* code = new gr_complex[code_length_]; + char signal_[3]; + + if (acq_iq_) + { + strcpy(signal_, "5X"); + } + else if (acq_pilot_) + { + strcpy(signal_, "5Q"); + } + else + { + strcpy(signal_, "5I"); + } + + galileo_e5_a_code_gen_complex_sampled(code, signal_, gnss_synchro_->PRN, fs_in_, 0); + + // fill in zero padding + for (int s = code_length; s < nsamples_total; s++) + { + code[s] = std::complex(static_cast(0,0)); + //code[s] = 0; + } + + memcpy(fft_if->get_inbuf(), code, sizeof(gr_complex) * nsamples_total); // copy to FFT buffer + fft_if->execute(); // Run the FFT of local code + volk_32fc_conjugate_32fc(fft_codes_padded, fft_if->get_outbuf(), nsamples_total); // conjugate values + + max = 0; // initialize maximum value + for (unsigned int i = 0; i < nsamples_total; i++) // search for maxima + { + if (std::abs(fft_codes_padded[i].real()) > max) + { + max = std::abs(fft_codes_padded[i].real()); + } + if (std::abs(fft_codes_padded[i].imag()) > max) + { + max = std::abs(fft_codes_padded[i].imag()); + } + } + for (unsigned int i = 0; i < nsamples_total; i++) // map the FFT to the dynamic range of the fixed point values an copy to buffer containing all FFTs + { + d_all_fft_codes_[i + nsamples_total * (PRN - 1)] = lv_16sc_t(static_cast(floor(fft_codes_padded[i].real() * (pow(2, 15) - 1) / max)), + static_cast(floor(fft_codes_padded[i].imag() * (pow(2, 15) - 1) / max))); + } + + } + + + acq_parameters.all_fft_codes = d_all_fft_codes_; + + // temporary buffers that we can delete + delete[] code; + delete fft_if; + delete[] fft_codes_padded; + + //code_ = new gr_complex[vector_length_]; + +// if (item_type_.compare("gr_complex") == 0) +// { +// item_size_ = sizeof(gr_complex); +// } +// else if (item_type_.compare("cshort") == 0) +// { +// item_size_ = sizeof(lv_16sc_t); +// } +// else +// { +// item_size_ = sizeof(gr_complex); +// LOG(WARNING) << item_type_ << " unknown acquisition item type"; +// } + //acq_parameters.it_size = item_size_; + //acq_parameters.samples_per_code = code_length_; + //acq_parameters.samples_per_ms = code_length_; + //acq_parameters.sampled_ms = sampled_ms_; + //acq_parameters.num_doppler_bins_step2 = configuration_->property(role + ".second_nbins", 4); + //acq_parameters.doppler_step2 = configuration_->property(role + ".second_doppler_step", 125.0); + //acq_parameters.make_2_steps = configuration_->property(role + ".make_two_steps", false); + //acquisition_ = pcps_make_acquisition(acq_parameters); + //acquisition_fpga_ = pcps_make_acquisition_fpga(acq_parameters); + //DLOG(INFO) << "acquisition(" << acquisition_fpga_->unique_id() << ")"; + + acquisition_fpga_ = pcps_make_acquisition_fpga(acq_parameters); + DLOG(INFO) << "acquisition(" << acquisition_fpga_->unique_id() << ")"; + + //stream_to_vector_ = gr::blocks::stream_to_vector::make(item_size_, vector_length_); + channel_ = 0; + //threshold_ = 0.0; + doppler_step_ = 0; + gnss_synchro_ = 0; +} + + +GalileoE5aPcpsAcquisitionFpga::~GalileoE5aPcpsAcquisitionFpga() +{ + //delete[] code_; + delete[] d_all_fft_codes_; +} + + +void GalileoE5aPcpsAcquisitionFpga::set_channel(unsigned int channel) +{ + channel_ = channel; + //acquisition_->set_channel(channel_); + acquisition_fpga_->set_channel(channel_); +} + + +void GalileoE5aPcpsAcquisitionFpga::set_threshold(float threshold) +{ +// float pfa = configuration_->property(role_ + boost::lexical_cast(channel_) + ".pfa", 0.0); +// +// if (pfa == 0.0) +// { +// pfa = configuration_->property(role_ + ".pfa", 0.0); +// } +// +// if (pfa == 0.0) +// { +// threshold_ = threshold; +// } +// +// else +// { +// threshold_ = calculate_threshold(pfa); +// } + + DLOG(INFO) << "Channel " << channel_ << " Threshold = " << threshold; + + //acquisition_->set_threshold(threshold_); + acquisition_fpga_->set_threshold(threshold); +} + + +void GalileoE5aPcpsAcquisitionFpga::set_doppler_max(unsigned int doppler_max) +{ + doppler_max_ = doppler_max; + //acquisition_->set_doppler_max(doppler_max_); + acquisition_fpga_->set_doppler_max(doppler_max_); +} + + +void GalileoE5aPcpsAcquisitionFpga::set_doppler_step(unsigned int doppler_step) +{ + doppler_step_ = doppler_step; + //acquisition_->set_doppler_step(doppler_step_); + acquisition_fpga_->set_doppler_step(doppler_step_); +} + + +void GalileoE5aPcpsAcquisitionFpga::set_gnss_synchro(Gnss_Synchro* gnss_synchro) +{ + gnss_synchro_ = gnss_synchro; + //acquisition_->set_gnss_synchro(gnss_synchro_); + acquisition_fpga_->set_gnss_synchro(gnss_synchro_); +} + + +signed int GalileoE5aPcpsAcquisitionFpga::mag() +{ + //return acquisition_->mag(); + return acquisition_fpga_->mag(); +} + + +void GalileoE5aPcpsAcquisitionFpga::init() +{ + //acquisition_->init(); + acquisition_fpga_->init(); +} + + +void GalileoE5aPcpsAcquisitionFpga::set_local_code() +{ +// gr_complex* code = new gr_complex[code_length_]; +// char signal_[3]; +// +// if (acq_iq_) +// { +// strcpy(signal_, "5X"); +// } +// else if (acq_pilot_) +// { +// strcpy(signal_, "5Q"); +// } +// else +// { +// strcpy(signal_, "5I"); +// } +// +// galileo_e5_a_code_gen_complex_sampled(code, signal_, gnss_synchro_->PRN, fs_in_, 0); +// +// for (unsigned int i = 0; i < sampled_ms_; i++) +// { +// memcpy(code_ + (i * code_length_), code, sizeof(gr_complex) * code_length_); +// } + + //acquisition_->set_local_code(code_); + acquisition_fpga_->set_local_code(); +// delete[] code; +} + + +void GalileoE5aPcpsAcquisitionFpga::reset() +{ + //acquisition_->set_active(true); + acquisition_fpga_->set_active(true); +} + + +//float GalileoE5aPcpsAcquisitionFpga::calculate_threshold(float pfa) +//{ +// unsigned int frequency_bins = 0; +// for (int doppler = static_cast(-doppler_max_); doppler <= static_cast(doppler_max_); doppler += doppler_step_) +// { +// frequency_bins++; +// } +// DLOG(INFO) << "Channel " << channel_ << " Pfa = " << pfa; +// unsigned int ncells = vector_length_ * frequency_bins; +// double exponent = 1 / static_cast(ncells); +// double val = pow(1.0 - pfa, exponent); +// double lambda = double(vector_length_); +// boost::math::exponential_distribution mydist(lambda); +// float threshold = static_cast(quantile(mydist, val)); +// +// return threshold; +//} + + +void GalileoE5aPcpsAcquisitionFpga::set_state(int state) +{ + //acquisition_->set_state(state); + acquisition_fpga_->set_state(state); +} + + +void GalileoE5aPcpsAcquisitionFpga::connect(gr::top_block_sptr top_block) +{ +// if (item_type_.compare("gr_complex") == 0) +// { +// top_block->connect(stream_to_vector_, 0, acquisition_, 0); +// } +// else if (item_type_.compare("cshort") == 0) +// { +// top_block->connect(stream_to_vector_, 0, acquisition_, 0); +// } +// else +// { +// LOG(WARNING) << item_type_ << " unknown acquisition item type"; +// } +} + + +void GalileoE5aPcpsAcquisitionFpga::disconnect(gr::top_block_sptr top_block) +{ +// if (item_type_.compare("gr_complex") == 0) +// { +// top_block->disconnect(stream_to_vector_, 0, acquisition_, 0); +// } +// else if (item_type_.compare("cshort") == 0) +// { +// top_block->disconnect(stream_to_vector_, 0, acquisition_, 0); +// } +// else +// { +// LOG(WARNING) << item_type_ << " unknown acquisition item type"; +// } +} + + +gr::basic_block_sptr GalileoE5aPcpsAcquisitionFpga::get_left_block() +{ + //return stream_to_vector_; + return nullptr; +} + + +gr::basic_block_sptr GalileoE5aPcpsAcquisitionFpga::get_right_block() +{ + //return acquisition_; + return acquisition_fpga_; +} diff --git a/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition_fpga.h b/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition_fpga.h new file mode 100644 index 000000000..1372d60ef --- /dev/null +++ b/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition_fpga.h @@ -0,0 +1,176 @@ +/*! + * \file galileo_e5a_pcps_acquisition.h + * \brief Adapts a PCPS acquisition block to an AcquisitionInterface for + * Galileo E5a data and pilot Signals + * \author Antonio Ramos, 2018. antonio.ramos(at)cttc.es + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2018 (see AUTHORS file for a list of contributors) + * + * GNSS-SDR is a software defined Global Navigation + * Satellite Systems receiver + * + * This file is part of GNSS-SDR. + * + * GNSS-SDR is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GNSS-SDR is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNSS-SDR. If not, see . + * + * ------------------------------------------------------------------------- + */ + +#ifndef GALILEO_E5A_PCPS_ACQUISITION_FPGA_H_ +#define GALILEO_E5A_PCPS_ACQUISITION_FPGA_H_ + + +#include "acquisition_interface.h" +#include "gnss_synchro.h" +#include "pcps_acquisition_fpga.h" +#include +#include +#include + +class ConfigurationInterface; + +class GalileoE5aPcpsAcquisitionFpga : public AcquisitionInterface +{ +public: + GalileoE5aPcpsAcquisitionFpga(ConfigurationInterface* configuration, + std::string role, unsigned int in_streams, + unsigned int out_streams); + + virtual ~GalileoE5aPcpsAcquisitionFpga(); + + inline std::string role() override + { + return role_; + } + + inline std::string implementation() override + { + return "Galileo_E5a_Pcps_Acquisition_Fpga"; + } + + inline size_t item_size() override + { + return item_size_; + } + + void connect(gr::top_block_sptr top_block) override; + void disconnect(gr::top_block_sptr top_block) override; + gr::basic_block_sptr get_left_block() override; + gr::basic_block_sptr get_right_block() override; + + /*! + * \brief Set acquisition/tracking common Gnss_Synchro object pointer + * to efficiently exchange synchronization data between acquisition and + * tracking blocks + */ + void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) override; + + /*! + * \brief Set acquisition channel unique ID + */ + void set_channel(unsigned int channel) override; + + /*! + * \brief Set statistics threshold of PCPS algorithm + */ + void set_threshold(float threshold) override; + + /*! + * \brief Set maximum Doppler off grid search + */ + void set_doppler_max(unsigned int doppler_max) override; + + /*! + * \brief Set Doppler steps for the grid search + */ + void set_doppler_step(unsigned int doppler_step) override; + + /*! + * \brief Initializes acquisition algorithm. + */ + void init() override; + + /*! + * \brief Sets local Galileo E5a code for PCPS acquisition algorithm. + */ + void set_local_code() override; + + /*! + * \brief Returns the maximum peak of grid search + */ + signed int mag() override; + + /*! + * \brief Restart acquisition algorithm + */ + void reset() override; + + /*! + * \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); + +private: + //float calculate_threshold(float pfa); + + ConfigurationInterface* configuration_; + + pcps_acquisition_fpga_sptr acquisition_fpga_; + gr::blocks::stream_to_vector::sptr stream_to_vector_; + + size_t item_size_; + + std::string item_type_; + std::string dump_filename_; + std::string role_; + + bool bit_transition_flag_; + bool dump_; + bool acq_pilot_; + bool use_CFAR_; + bool blocking_; + bool acq_iq_; + + unsigned int vector_length_; + unsigned int code_length_; + unsigned int channel_; + unsigned int doppler_max_; + unsigned int doppler_step_; + unsigned int sampled_ms_; + unsigned int max_dwells_; + unsigned int in_streams_; + unsigned int out_streams_; + + long fs_in_; + + + float threshold_; + + /* + std::complex* codeI_; + std::complex* codeQ_; + */ + + gr_complex* code_; + + Gnss_Synchro* gnss_synchro_; + + // extra for the FPGA + lv_16sc_t* d_all_fft_codes_; // memory that contains all the code ffts + +}; +#endif /* GALILEO_E5A_PCPS_ACQUISITION_FPGA_H_ */ 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 2a15d7e6f..c456a0e98 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 @@ -60,6 +60,8 @@ GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga( long fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 2048000); long fs_in = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated); + //fs_in = fs_in/2.0; // downampling filter + //printf("####### DEBUG Acq: fs_in = %d\n", fs_in); acq_parameters.fs_in = fs_in; long ifreq = configuration_->property(role + ".if", 0); acq_parameters.freq = ifreq; @@ -69,7 +71,7 @@ GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga( unsigned int sampled_ms = configuration_->property(role + ".coherent_integration_time_ms", 1); acq_parameters.sampled_ms = sampled_ms; unsigned int code_length = static_cast(std::round(static_cast(fs_in) / (GPS_L1_CA_CODE_RATE_HZ / GPS_L1_CA_CODE_LENGTH_CHIPS))); - + acq_parameters.code_length = code_length; // The FPGA can only use FFT lengths that are a power of two. float nbits = ceilf(log2f((float)code_length)); unsigned int nsamples_total = pow(2, nbits); @@ -96,12 +98,29 @@ GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga( // fill in zero padding for (int s = code_length; s < nsamples_total; s++) { - code[s] = 0; + code[s] = std::complex(static_cast(0,0)); + //code[s] = 0; } int offset = 0; memcpy(fft_if->get_inbuf() + offset, code, sizeof(gr_complex) * nsamples_total); // copy to FFT buffer fft_if->execute(); // Run the FFT of local code volk_32fc_conjugate_32fc(fft_codes_padded, fft_if->get_outbuf(), nsamples_total); // conjugate values + + +// // debug +// char filename[25]; +// FILE *fid; +// sprintf(filename,"fft_gps_prn%d.txt", PRN); +// fid = fopen(filename, "w"); +// for (unsigned int kk=0;kk< nsamples_total; kk++) +// { +// fprintf(fid, "%f\n", fft_codes_padded[kk].real()); +// fprintf(fid, "%f\n", fft_codes_padded[kk].imag()); +// } +// fclose(fid); + + + max = 0; // initialize maximum value for (unsigned int i = 0; i < nsamples_total; i++) // search for maxima { @@ -116,9 +135,30 @@ GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga( } for (unsigned int i = 0; i < nsamples_total; i++) // map the FFT to the dynamic range of the fixed point values an copy to buffer containing all FFTs { - d_all_fft_codes_[i + nsamples_total * (PRN - 1)] = lv_16sc_t(static_cast(floor(fft_codes_padded[i].real() * (pow(2, 7) - 1) / max)), - static_cast(floor(fft_codes_padded[i].imag() * (pow(2, 7) - 1) / max))); + //d_all_fft_codes_[i + nsamples_total * (PRN - 1)] = lv_16sc_t(static_cast(floor(256*fft_codes_padded[i].real() * (pow(2, 7) - 1) / max)), + // static_cast(floor(256*fft_codes_padded[i].imag() * (pow(2, 7) - 1) / max))); + //d_all_fft_codes_[i + nsamples_total * (PRN - 1)] = lv_16sc_t(static_cast(16*floor(fft_codes_padded[i].real() * (pow(2, 11) - 1) / max)), + // static_cast(16*floor(fft_codes_padded[i].imag() * (pow(2, 11) - 1) / max))); + //d_all_fft_codes_[i + nsamples_total * (PRN - 1)] = lv_16sc_t(static_cast(floor(fft_codes_padded[i].real() * (pow(2, 15) - 1) / max)), + // static_cast(floor(fft_codes_padded[i].imag() * (pow(2, 15) - 1) / max))); + d_all_fft_codes_[i + nsamples_total * (PRN - 1)] = lv_16sc_t(static_cast(floor(fft_codes_padded[i].real() * (pow(2, 15) - 1) / max)), + static_cast(floor(fft_codes_padded[i].imag() * (pow(2, 15) - 1) / max))); } + + +//// // debug +// char filename2[25]; +// FILE *fid2; +// sprintf(filename2,"fft_gps_prn%d_norm_new.txt", PRN); +// fid2 = fopen(filename2, "w"); +// for (unsigned int kk=0;kk< nsamples_total; kk++) +// { +// fprintf(fid2, "%d\n", d_all_fft_codes_[kk + nsamples_total * (PRN - 1)].real()); +// fprintf(fid2, "%d\n", d_all_fft_codes_[kk + nsamples_total * (PRN - 1)].imag()); +// } +// fclose(fid2); + + } //acq_parameters diff --git a/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition_fpga.cc b/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition_fpga.cc new file mode 100644 index 000000000..c20916e16 --- /dev/null +++ b/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition_fpga.cc @@ -0,0 +1,398 @@ +/*! + * \file gps_l2_m_pcps_acquisition.cc + * \brief Adapts a PCPS acquisition block to an AcquisitionInterface for + * GPS L2 M signals + * \authors
    + *
  • Javier Arribas, 2015. jarribas(at)cttc.es + *
+ * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors) + * + * GNSS-SDR is a software defined Global Navigation + * Satellite Systems receiver + * + * This file is part of GNSS-SDR. + * + * GNSS-SDR is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GNSS-SDR is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNSS-SDR. If not, see . + * + * ------------------------------------------------------------------------- + */ + +#include "gps_l2_m_pcps_acquisition_fpga.h" +#include "configuration_interface.h" +#include "gps_l2c_signal.h" +#include "GPS_L2C.h" +#include "gnss_sdr_flags.h" +#include +#include + +#define NUM_PRNs 32 + +using google::LogMessage; + +GpsL2MPcpsAcquisitionFpga::GpsL2MPcpsAcquisitionFpga( + ConfigurationInterface* configuration, std::string role, + unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams) +{ + //pcpsconf_t acq_parameters; + pcpsconf_fpga_t acq_parameters; + configuration_ = configuration; + std::string default_item_type = "gr_complex"; + std::string default_dump_filename = "./data/acquisition.dat"; + + LOG(INFO) << "role " << role; + + item_type_ = configuration_->property(role + ".item_type", default_item_type); + //float pfa = configuration_->property(role + ".pfa", 0.0); + + long fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 2048000); + fs_in_ = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated); + acq_parameters.fs_in = fs_in_; + if_ = configuration_->property(role + ".if", 0); + acq_parameters.freq = if_; + //dump_ = configuration_->property(role + ".dump", false); + //acq_parameters.dump = dump_; + //blocking_ = configuration_->property(role + ".blocking", true); + //acq_parameters.blocking = blocking_; + doppler_max_ = configuration->property(role + ".doppler_max", 5000); + if (FLAGS_doppler_max != 0) doppler_max_ = FLAGS_doppler_max; + acq_parameters.doppler_max = doppler_max_; + //bit_transition_flag_ = configuration_->property(role + ".bit_transition_flag", false); + //acq_parameters.bit_transition_flag = bit_transition_flag_; + //use_CFAR_algorithm_flag_ = configuration_->property(role + ".use_CFAR_algorithm", true); //will be false in future versions + //acq_parameters.use_CFAR_algorithm_flag = use_CFAR_algorithm_flag_; + //max_dwells_ = configuration_->property(role + ".max_dwells", 1); + //acq_parameters.max_dwells = max_dwells_; + //dump_filename_ = configuration_->property(role + ".dump_filename", default_dump_filename); + //acq_parameters.dump_filename = dump_filename_; + //--- Find number of samples per spreading code ------------------------- + //code_length_ = std::round(static_cast(fs_in_) / (GPS_L2_M_CODE_RATE_HZ / static_cast(GPS_L2_M_CODE_LENGTH_CHIPS))); + + acq_parameters.sampled_ms = 20; + unsigned code_length = std::round(static_cast(fs_in_) / (GPS_L2_M_CODE_RATE_HZ / static_cast(GPS_L2_M_CODE_LENGTH_CHIPS))); + acq_parameters.code_length = code_length; + // The FPGA can only use FFT lengths that are a power of two. + float nbits = ceilf(log2f((float)code_length)); + unsigned int nsamples_total = pow(2, nbits); + unsigned int vector_length = nsamples_total; + unsigned int select_queue_Fpga = configuration_->property(role + ".select_queue_Fpga", 0); + acq_parameters.select_queue_Fpga = select_queue_Fpga; + std::string default_device_name = "/dev/uio0"; + std::string device_name = configuration_->property(role + ".devicename", default_device_name); + acq_parameters.device_name = device_name; + acq_parameters.samples_per_ms = nsamples_total/acq_parameters.sampled_ms; + //acq_parameters.samples_per_ms = static_cast(std::round(static_cast(fs_in_) * 0.001)); + acq_parameters.samples_per_code = nsamples_total; + + // compute all the GPS L1 PRN Codes (this is done only once upon the class constructor in order to avoid re-computing the PRN codes every time + // a channel is assigned) + gr::fft::fft_complex* fft_if = new gr::fft::fft_complex(vector_length, true); // Direct FFT + // allocate memory to compute all the PRNs and compute all the possible codes + std::complex* code = new std::complex[nsamples_total]; // buffer for the local code + gr_complex* fft_codes_padded = static_cast(volk_gnsssdr_malloc(nsamples_total * sizeof(gr_complex), volk_gnsssdr_get_alignment())); + d_all_fft_codes_ = new lv_16sc_t[nsamples_total * NUM_PRNs]; // memory containing all the possible fft codes for PRN 0 to 32 + float max; // temporary maxima search + for (unsigned int PRN = 1; PRN <= NUM_PRNs; PRN++) + { + gps_l2c_m_code_gen_complex_sampled(code, PRN, fs_in_); + // fill in zero padding + for (int s = code_length; s < nsamples_total; s++) + { + code[s] = std::complex(static_cast(0,0)); + //code[s] = 0; + } + memcpy(fft_if->get_inbuf(), code, sizeof(gr_complex) * nsamples_total); // copy to FFT buffer + fft_if->execute(); // Run the FFT of local code + volk_32fc_conjugate_32fc(fft_codes_padded, fft_if->get_outbuf(), nsamples_total); // conjugate values + max = 0; // initialize maximum value + for (unsigned int i = 0; i < nsamples_total; i++) // search for maxima + { + if (std::abs(fft_codes_padded[i].real()) > max) + { + max = std::abs(fft_codes_padded[i].real()); + } + if (std::abs(fft_codes_padded[i].imag()) > max) + { + max = std::abs(fft_codes_padded[i].imag()); + } + } + for (unsigned int i = 0; i < nsamples_total; i++) // map the FFT to the dynamic range of the fixed point values an copy to buffer containing all FFTs + { + d_all_fft_codes_[i + nsamples_total * (PRN - 1)] = lv_16sc_t(static_cast(floor(fft_codes_padded[i].real() * (pow(2, 7) - 1) / max)), + static_cast(floor(fft_codes_padded[i].imag() * (pow(2, 7) - 1) / max))); + } + + } + + //acq_parameters + acq_parameters.all_fft_codes = d_all_fft_codes_; + + // temporary buffers that we can delete + delete[] code; + delete fft_if; + delete[] fft_codes_padded; + + acquisition_fpga_ = pcps_make_acquisition_fpga(acq_parameters); + DLOG(INFO) << "acquisition(" << acquisition_fpga_->unique_id() << ")"; + + channel_ = 0; + doppler_step_ = 0; + gnss_synchro_ = 0; + + + + + +// vector_length_ = code_length_; +// +// 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); +// } +// else +// { +// item_size_ = sizeof(gr_complex); +// } + //acq_parameters.samples_per_ms = static_cast(std::round(static_cast(fs_in_) * 0.001)); + //acq_parameters.samples_per_code = code_length_; + //acq_parameters.it_size = item_size_; + //acq_parameters.sampled_ms = 20; + //acq_parameters.num_doppler_bins_step2 = configuration_->property(role + ".second_nbins", 4); + //acq_parameters.doppler_step2 = configuration_->property(role + ".second_doppler_step", 125.0); + //acq_parameters.make_2_steps = configuration_->property(role + ".make_two_steps", true); + //acquisition_ = pcps_make_acquisition(acq_parameters); + DLOG(INFO) << "acquisition(" << acquisition_fpga_->unique_id() << ")"; + +// stream_to_vector_ = gr::blocks::stream_to_vector::make(item_size_, vector_length_); +// DLOG(INFO) << "stream_to_vector(" << stream_to_vector_->unique_id() << ")"; +// +// if (item_type_.compare("cbyte") == 0) +// { +// cbyte_to_float_x2_ = make_complex_byte_to_float_x2(); +// float_to_complex_ = gr::blocks::float_to_complex::make(); +// } + +// channel_ = 0; + threshold_ = 0.0; +// doppler_step_ = 0; +// gnss_synchro_ = 0; +} + + +GpsL2MPcpsAcquisitionFpga::~GpsL2MPcpsAcquisitionFpga() +{ + //delete[] code_; + delete[] d_all_fft_codes_; +} + + +void GpsL2MPcpsAcquisitionFpga::set_channel(unsigned int channel) +{ + channel_ = channel; + acquisition_fpga_->set_channel(channel_); +} + + +void GpsL2MPcpsAcquisitionFpga::set_threshold(float threshold) +{ +// float pfa = configuration_->property(role_ + boost::lexical_cast(channel_) + ".pfa", 0.0); +// +// if (pfa == 0.0) +// { +// pfa = configuration_->property(role_ + ".pfa", 0.0); +// } +// if (pfa == 0.0) +// { +// threshold_ = threshold; +// } +// else +// { +// threshold_ = calculate_threshold(pfa); +// } + + DLOG(INFO) << "Channel " << channel_ << " Threshold = " << threshold_; + + acquisition_fpga_->set_threshold(threshold_); +} + + +void GpsL2MPcpsAcquisitionFpga::set_doppler_max(unsigned int doppler_max) +{ + doppler_max_ = doppler_max; + + acquisition_fpga_->set_doppler_max(doppler_max_); +} + + +// Be aware that Doppler step should be set to 2/(3T) Hz, where T is the coherent integration time (GPS L2 period is 0.02s) +// Doppler bin minimum size= 33 Hz +void GpsL2MPcpsAcquisitionFpga::set_doppler_step(unsigned int doppler_step) +{ + doppler_step_ = doppler_step; + + acquisition_fpga_->set_doppler_step(doppler_step_); +} + + +void GpsL2MPcpsAcquisitionFpga::set_gnss_synchro(Gnss_Synchro* gnss_synchro) +{ + gnss_synchro_ = gnss_synchro; + + acquisition_fpga_->set_gnss_synchro(gnss_synchro_); +} + + +signed int GpsL2MPcpsAcquisitionFpga::mag() +{ + return acquisition_fpga_->mag(); +} + + +void GpsL2MPcpsAcquisitionFpga::init() +{ + acquisition_fpga_->init(); + //set_local_code(); +} + + +void GpsL2MPcpsAcquisitionFpga::set_local_code() +{ + //gps_l2c_m_code_gen_complex_sampled(code_, gnss_synchro_->PRN, fs_in_); + + //acquisition_fpga_->set_local_code(code_); + acquisition_fpga_->set_local_code(); +} + + +void GpsL2MPcpsAcquisitionFpga::reset() +{ + acquisition_fpga_->set_active(true); +} + +void GpsL2MPcpsAcquisitionFpga::set_state(int state) +{ + acquisition_fpga_->set_state(state); +} + + +//float GpsL2MPcpsAcquisitionFpga::calculate_threshold(float pfa) +//{ +// //Calculate the threshold +// unsigned int frequency_bins = 0; +// for (int doppler = static_cast(-doppler_max_); doppler <= static_cast(doppler_max_); doppler += doppler_step_) +// { +// frequency_bins++; +// } +// DLOG(INFO) << "Channel " << channel_ << " Pfa = " << pfa; +// unsigned int ncells = vector_length_ * frequency_bins; +// double exponent = 1.0 / static_cast(ncells); +// double val = pow(1.0 - pfa, exponent); +// double lambda = double(vector_length_); +// boost::math::exponential_distribution mydist(lambda); +// float threshold = static_cast(quantile(mydist, val)); +// +// return threshold; +//} + + +void GpsL2MPcpsAcquisitionFpga::connect(gr::top_block_sptr top_block) +{ +// if (item_type_.compare("gr_complex") == 0) +// { +// top_block->connect(stream_to_vector_, 0, acquisition_, 0); +// } +// else if (item_type_.compare("cshort") == 0) +// { +// top_block->connect(stream_to_vector_, 0, acquisition_, 0); +// } +// else if (item_type_.compare("cbyte") == 0) +// { +// top_block->connect(cbyte_to_float_x2_, 0, float_to_complex_, 0); +// top_block->connect(cbyte_to_float_x2_, 1, float_to_complex_, 1); +// top_block->connect(float_to_complex_, 0, stream_to_vector_, 0); +// top_block->connect(stream_to_vector_, 0, acquisition_, 0); +// } +// else +// { +// LOG(WARNING) << item_type_ << " unknown acquisition item type"; +// } + + // nothing to connect +} + + +void GpsL2MPcpsAcquisitionFpga::disconnect(gr::top_block_sptr top_block) +{ +// if (item_type_.compare("gr_complex") == 0) +// { +// top_block->disconnect(stream_to_vector_, 0, acquisition_, 0); +// } +// else if (item_type_.compare("cshort") == 0) +// { +// top_block->disconnect(stream_to_vector_, 0, acquisition_, 0); +// } +// else if (item_type_.compare("cbyte") == 0) +// { +// // Since a byte-based acq implementation is not available, +// // we just convert cshorts to gr_complex +// top_block->disconnect(cbyte_to_float_x2_, 0, float_to_complex_, 0); +// top_block->disconnect(cbyte_to_float_x2_, 1, float_to_complex_, 1); +// top_block->disconnect(float_to_complex_, 0, stream_to_vector_, 0); +// top_block->disconnect(stream_to_vector_, 0, acquisition_, 0); +// } +// else +// { +// LOG(WARNING) << item_type_ << " unknown acquisition item type"; +// } + + // nothing to disconnect +} + + +gr::basic_block_sptr GpsL2MPcpsAcquisitionFpga::get_left_block() +{ +// if (item_type_.compare("gr_complex") == 0) +// { +// return stream_to_vector_; +// } +// else if (item_type_.compare("cshort") == 0) +// { +// return stream_to_vector_; +// } +// else if (item_type_.compare("cbyte") == 0) +// { +// return cbyte_to_float_x2_; +// } +// else +// { +// LOG(WARNING) << item_type_ << " unknown acquisition item type"; +// return nullptr; +// } + return nullptr; +} + + +gr::basic_block_sptr GpsL2MPcpsAcquisitionFpga::get_right_block() +{ + return acquisition_fpga_; +} diff --git a/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition_fpga.h b/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition_fpga.h new file mode 100644 index 000000000..47f55d10f --- /dev/null +++ b/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition_fpga.h @@ -0,0 +1,171 @@ +/*! + * \file gps_l2_m_pcps_acquisition.h + * \brief Adapts a PCPS acquisition block to an AcquisitionInterface for + * GPS L2 M signals + * \authors
    + *
  • Javier Arribas, 2015. jarribas(at)cttc.es + *
+ * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors) + * + * GNSS-SDR is a software defined Global Navigation + * Satellite Systems receiver + * + * This file is part of GNSS-SDR. + * + * GNSS-SDR is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GNSS-SDR is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNSS-SDR. If not, see . + * + * ------------------------------------------------------------------------- + */ + +#ifndef GNSS_SDR_GPS_L2_M_PCPS_ACQUISITION_FPGA_H_ +#define GNSS_SDR_GPS_L2_M_PCPS_ACQUISITION_FPGA_H_ + +#include "acquisition_interface.h" +#include "gnss_synchro.h" +#include "pcps_acquisition_fpga.h" +#include "complex_byte_to_float_x2.h" +#include +#include +#include +#include + + +class ConfigurationInterface; + +/*! + * \brief This class adapts a PCPS acquisition block to an AcquisitionInterface + * for GPS L2 M signals + */ +class GpsL2MPcpsAcquisitionFpga : public AcquisitionInterface +{ +public: + GpsL2MPcpsAcquisitionFpga(ConfigurationInterface* configuration, + std::string role, unsigned int in_streams, + unsigned int out_streams); + + virtual ~GpsL2MPcpsAcquisitionFpga(); + + inline std::string role() override + { + return role_; + } + + /*! + * \brief Returns "GPS_L2_M_PCPS_Acquisition" + */ + inline std::string implementation() override + { + return "GPS_L2_M_PCPS_Acquisition"; + } + + inline size_t item_size() override + { + return item_size_; + } + + void connect(gr::top_block_sptr top_block) override; + void disconnect(gr::top_block_sptr top_block) override; + gr::basic_block_sptr get_left_block() override; + gr::basic_block_sptr get_right_block() override; + + /*! + * \brief Set acquisition/tracking common Gnss_Synchro object pointer + * to efficiently exchange synchronization data between acquisition and + * tracking blocks + */ + void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) override; + + /*! + * \brief Set acquisition channel unique ID + */ + void set_channel(unsigned int channel) override; + + /*! + * \brief Set statistics threshold of PCPS algorithm + */ + void set_threshold(float threshold) override; + + /*! + * \brief Set maximum Doppler off grid search + */ + void set_doppler_max(unsigned int doppler_max) override; + + /*! + * \brief Set Doppler steps for the grid search + */ + void set_doppler_step(unsigned int doppler_step) override; + + /*! + * \brief Initializes acquisition algorithm. + */ + void init() override; + + /*! + * \brief Sets local code for GPS L2/M PCPS acquisition algorithm. + */ + void set_local_code() override; + + /*! + * \brief Returns the maximum peak of grid search + */ + signed int mag() override; + + /*! + * \brief Restart acquisition algorithm + */ + void reset() override; + + /*! + * \brief If state = 1, it forces the block to start acquiring from the first sample + */ + void set_state(int state); + +private: + ConfigurationInterface* configuration_; + //pcps_acquisition_sptr acquisition_; + pcps_acquisition_fpga_sptr acquisition_fpga_; + 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 max_dwells_; + long fs_in_; + long if_; + bool dump_; + bool blocking_; + std::string dump_filename_; + std::complex* code_; + Gnss_Synchro* gnss_synchro_; + std::string role_; + unsigned int in_streams_; + unsigned int out_streams_; + + lv_16sc_t* d_all_fft_codes_; // memory that contains all the code ffts + + //float calculate_threshold(float pfa); +}; + +#endif /* GNSS_SDR_GPS_L2_M_PCPS_ACQUISITION_FPGA_H_ */ diff --git a/src/algorithms/acquisition/adapters/gps_l5i_pcps_acquisition_fpga.cc b/src/algorithms/acquisition/adapters/gps_l5i_pcps_acquisition_fpga.cc new file mode 100644 index 000000000..038f56567 --- /dev/null +++ b/src/algorithms/acquisition/adapters/gps_l5i_pcps_acquisition_fpga.cc @@ -0,0 +1,388 @@ +/*! + * \file gps_l5i pcps_acquisition.cc + * \brief Adapts a PCPS acquisition block to an Acquisition Interface for + * GPS L5i signals + * \authors
    + *
  • Javier Arribas, 2017. jarribas(at)cttc.es + *
+ * + * ------------------------------------------------------------------------- + * + * 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_l5i_pcps_acquisition_fpga.h" +#include "configuration_interface.h" +#include "gps_l5_signal.h" +#include "GPS_L5.h" +#include "gnss_sdr_flags.h" +#include +#include + +#define NUM_PRNs 32 + +using google::LogMessage; + +GpsL5iPcpsAcquisitionFpga::GpsL5iPcpsAcquisitionFpga( + ConfigurationInterface* configuration, std::string role, + unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams) +{ + pcpsconf_fpga_t acq_parameters; + configuration_ = configuration; + std::string default_item_type = "gr_complex"; + std::string default_dump_filename = "./data/acquisition.dat"; + + LOG(INFO) << "role " << role; + + //item_type_ = configuration_->property(role + ".item_type", default_item_type); + + long fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 2048000); + long fs_in = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated); + acq_parameters.fs_in = fs_in; + if_ = configuration_->property(role + ".if", 0); + acq_parameters.freq = if_; + //dump_ = configuration_->property(role + ".dump", false); + //acq_parameters.dump = dump_; + //blocking_ = configuration_->property(role + ".blocking", true); + //acq_parameters.blocking = blocking_; + doppler_max_ = configuration->property(role + ".doppler_max", 5000); + if (FLAGS_doppler_max != 0) doppler_max_ = FLAGS_doppler_max; + acq_parameters.doppler_max = doppler_max_; + acq_parameters.sampled_ms = 1; + //bit_transition_flag_ = configuration_->property(role + ".bit_transition_flag", false); + //acq_parameters.bit_transition_flag = bit_transition_flag_; + //use_CFAR_algorithm_flag_ = configuration_->property(role + ".use_CFAR_algorithm", true); //will be false in future versions + //acq_parameters.use_CFAR_algorithm_flag = use_CFAR_algorithm_flag_; + //max_dwells_ = configuration_->property(role + ".max_dwells", 1); + //acq_parameters.max_dwells = max_dwells_; + //dump_filename_ = configuration_->property(role + ".dump_filename", default_dump_filename); + //acq_parameters.dump_filename = dump_filename_; + //--- Find number of samples per spreading code ------------------------- + unsigned int code_length = static_cast(std::round(static_cast(fs_in_) / (GPS_L5i_CODE_RATE_HZ / static_cast(GPS_L5i_CODE_LENGTH_CHIPS)))); + acq_parameters.code_length = code_length; + // The FPGA can only use FFT lengths that are a power of two. + float nbits = ceilf(log2f((float)code_length)); + unsigned int nsamples_total = pow(2, nbits); + unsigned int vector_length = nsamples_total; + unsigned int select_queue_Fpga = configuration_->property(role + ".select_queue_Fpga", 0); + acq_parameters.select_queue_Fpga = select_queue_Fpga; + std::string default_device_name = "/dev/uio0"; + std::string device_name = configuration_->property(role + ".devicename", default_device_name); + acq_parameters.device_name = device_name; + acq_parameters.samples_per_ms = nsamples_total; + acq_parameters.samples_per_code = nsamples_total; + + // compute all the GPS L5 PRN Codes (this is done only once upon the class constructor in order to avoid re-computing the PRN codes every time + // a channel is assigned) + gr::fft::fft_complex* fft_if = new gr::fft::fft_complex(vector_length, true); // Direct FFT + std::complex* code = new gr_complex[vector_length_]; + gr_complex* fft_codes_padded = static_cast(volk_gnsssdr_malloc(nsamples_total * sizeof(gr_complex), volk_gnsssdr_get_alignment())); + d_all_fft_codes_ = new lv_16sc_t[nsamples_total * NUM_PRNs]; // memory containing all the possible fft codes for PRN 0 to 32 + + float max; // temporary maxima search + for (unsigned int PRN = 1; PRN <= NUM_PRNs; PRN++) + { + + gps_l5i_code_gen_complex_sampled(code, PRN, fs_in); + // fill in zero padding + for (int s = code_length; s < nsamples_total; s++) + { + code[s] = std::complex(static_cast(0,0)); + //code[s] = 0; + } + memcpy(fft_if->get_inbuf(), code, sizeof(gr_complex) * nsamples_total); // copy to FFT buffer + fft_if->execute(); // Run the FFT of local code + volk_32fc_conjugate_32fc(fft_codes_padded, fft_if->get_outbuf(), nsamples_total); // conjugate values + + max = 0; // initialize maximum value + for (unsigned int i = 0; i < nsamples_total; i++) // search for maxima + { + if (std::abs(fft_codes_padded[i].real()) > max) + { + max = std::abs(fft_codes_padded[i].real()); + } + if (std::abs(fft_codes_padded[i].imag()) > max) + { + max = std::abs(fft_codes_padded[i].imag()); + } + } + for (unsigned int i = 0; i < nsamples_total; i++) // map the FFT to the dynamic range of the fixed point values an copy to buffer containing all FFTs + { + //d_all_fft_codes_[i + nsamples_total * (PRN - 1)] = lv_16sc_t(static_cast(floor(256*fft_codes_padded[i].real() * (pow(2, 7) - 1) / max)), + // static_cast(floor(256*fft_codes_padded[i].imag() * (pow(2, 7) - 1) / max))); + //d_all_fft_codes_[i + nsamples_total * (PRN - 1)] = lv_16sc_t(static_cast(16*floor(fft_codes_padded[i].real() * (pow(2, 11) - 1) / max)), + // static_cast(16*floor(fft_codes_padded[i].imag() * (pow(2, 11) - 1) / max))); + //d_all_fft_codes_[i + nsamples_total * (PRN - 1)] = lv_16sc_t(static_cast(floor(fft_codes_padded[i].real() * (pow(2, 15) - 1) / max)), + // static_cast(floor(fft_codes_padded[i].imag() * (pow(2, 15) - 1) / max))); + d_all_fft_codes_[i + nsamples_total * (PRN - 1)] = lv_16sc_t(static_cast(floor(fft_codes_padded[i].real() * (pow(2, 15) - 1) / max)), + static_cast(floor(fft_codes_padded[i].imag() * (pow(2, 15) - 1) / max))); + } + + + } + + //acq_parameters + acq_parameters.all_fft_codes = d_all_fft_codes_; + + // temporary buffers that we can delete + delete[] code; + delete fft_if; + delete[] fft_codes_padded; +// vector_length_ = code_length_; +// +// 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); +// } +// else +// { +// item_size_ = sizeof(gr_complex); +// } +// acq_parameters.samples_per_code = code_length_; +// acq_parameters.samples_per_ms = code_length_; +// acq_parameters.it_size = item_size_; + //acq_parameters.sampled_ms = 1; +// acq_parameters.num_doppler_bins_step2 = configuration_->property(role + ".second_nbins", 4); +// acq_parameters.doppler_step2 = configuration_->property(role + ".second_doppler_step", 125.0); +// acq_parameters.make_2_steps = configuration_->property(role + ".make_two_steps", false); +// acquisition_fpga_ = pcps_make_acquisition(acq_parameters); +// DLOG(INFO) << "acquisition(" << acquisition_fpga_->unique_id() << ")"; + + acquisition_fpga_ = pcps_make_acquisition_fpga(acq_parameters); + DLOG(INFO) << "acquisition(" << acquisition_fpga_->unique_id() << ")"; + +// stream_to_vector_ = gr::blocks::stream_to_vector::make(item_size_, vector_length_); +// DLOG(INFO) << "stream_to_vector(" << stream_to_vector_->unique_id() << ")"; +// +// if (item_type_.compare("cbyte") == 0) +// { +// cbyte_to_float_x2_ = make_complex_byte_to_float_x2(); +// float_to_complex_ = gr::blocks::float_to_complex::make(); +// } + + channel_ = 0; +// threshold_ = 0.0; + doppler_step_ = 0; + gnss_synchro_ = 0; +} + + +GpsL5iPcpsAcquisitionFpga::~GpsL5iPcpsAcquisitionFpga() +{ + //delete[] code_; + delete[] d_all_fft_codes_; +} + + +void GpsL5iPcpsAcquisitionFpga::set_channel(unsigned int channel) +{ + channel_ = channel; + acquisition_fpga_->set_channel(channel_); + +} + + +void GpsL5iPcpsAcquisitionFpga::set_threshold(float threshold) +{ +// float pfa = configuration_->property(role_ + boost::lexical_cast(channel_) + ".pfa", 0.0); +// +// if (pfa == 0.0) +// { +// pfa = configuration_->property(role_ + ".pfa", 0.0); +// } +// if (pfa == 0.0) +// { +// threshold_ = threshold; +// } +// else +// { +// threshold_ = calculate_threshold(pfa); +// } + +// DLOG(INFO) << "Channel " << channel_ << " Threshold = " << threshold_; + + // the .pfa parameter and the threshold calculation is only used for the CFAR algorithm. + // We don't use the CFAR algorithm in the FPGA. Therefore the threshold is set as such. + DLOG(INFO) << "Channel " << channel_ << " Threshold = " << threshold; + acquisition_fpga_->set_threshold(threshold); + +} + + +void GpsL5iPcpsAcquisitionFpga::set_doppler_max(unsigned int doppler_max) +{ + doppler_max_ = doppler_max; + acquisition_fpga_->set_doppler_max(doppler_max_); +} + + +// Be aware that Doppler step should be set to 2/(3T) Hz, where T is the coherent integration time (GPS L2 period is 0.02s) +// Doppler bin minimum size= 33 Hz +void GpsL5iPcpsAcquisitionFpga::set_doppler_step(unsigned int doppler_step) +{ + doppler_step_ = doppler_step; + acquisition_fpga_->set_doppler_step(doppler_step_); +} + + +void GpsL5iPcpsAcquisitionFpga::set_gnss_synchro(Gnss_Synchro* gnss_synchro) +{ + gnss_synchro_ = gnss_synchro; + acquisition_fpga_->set_gnss_synchro(gnss_synchro_); +} + + +signed int GpsL5iPcpsAcquisitionFpga::mag() +{ + return acquisition_fpga_->mag(); +} + + +void GpsL5iPcpsAcquisitionFpga::init() +{ + acquisition_fpga_->init(); +} + +void GpsL5iPcpsAcquisitionFpga::set_local_code() +{ + acquisition_fpga_->set_local_code(); +} + + +void GpsL5iPcpsAcquisitionFpga::reset() +{ + acquisition_fpga_->set_active(true); +} + +void GpsL5iPcpsAcquisitionFpga::set_state(int state) +{ + acquisition_fpga_->set_state(state); +} + + +//float GpsL5iPcpsAcquisitionFpga::calculate_threshold(float pfa) +//{ +// //Calculate the threshold +// unsigned int frequency_bins = 0; +// for (int doppler = static_cast(-doppler_max_); doppler <= static_cast(doppler_max_); doppler += doppler_step_) +// { +// frequency_bins++; +// } +// DLOG(INFO) << "Channel " << channel_ << " Pfa = " << pfa; +// unsigned int ncells = vector_length_ * frequency_bins; +// double exponent = 1.0 / static_cast(ncells); +// double val = pow(1.0 - pfa, exponent); +// double lambda = double(vector_length_); +// boost::math::exponential_distribution mydist(lambda); +// float threshold = static_cast(quantile(mydist, val)); +// +// return threshold; +//} + + +void GpsL5iPcpsAcquisitionFpga::connect(gr::top_block_sptr top_block) +{ +// if (item_type_.compare("gr_complex") == 0) +// { +// top_block->connect(stream_to_vector_, 0, acquisition_fpga_, 0); +// } +// else if (item_type_.compare("cshort") == 0) +// { +// top_block->connect(stream_to_vector_, 0, acquisition_fpga_, 0); +// } +// else if (item_type_.compare("cbyte") == 0) +// { +// top_block->connect(cbyte_to_float_x2_, 0, float_to_complex_, 0); +// top_block->connect(cbyte_to_float_x2_, 1, float_to_complex_, 1); +// top_block->connect(float_to_complex_, 0, stream_to_vector_, 0); +// top_block->connect(stream_to_vector_, 0, acquisition_fpga_, 0); +// } +// else +// { +// LOG(WARNING) << item_type_ << " unknown acquisition item type"; +// } + // nothing to connect +} + + +void GpsL5iPcpsAcquisitionFpga::disconnect(gr::top_block_sptr top_block) +{ +// if (item_type_.compare("gr_complex") == 0) +// { +// top_block->disconnect(stream_to_vector_, 0, acquisition_fpga_, 0); +// } +// else if (item_type_.compare("cshort") == 0) +// { +// top_block->disconnect(stream_to_vector_, 0, acquisition_fpga_, 0); +// } +// else if (item_type_.compare("cbyte") == 0) +// { +// // Since a byte-based acq implementation is not available, +// // we just convert cshorts to gr_complex +// top_block->disconnect(cbyte_to_float_x2_, 0, float_to_complex_, 0); +// top_block->disconnect(cbyte_to_float_x2_, 1, float_to_complex_, 1); +// top_block->disconnect(float_to_complex_, 0, stream_to_vector_, 0); +// top_block->disconnect(stream_to_vector_, 0, acquisition_fpga_, 0); +// } +// else +// { +// LOG(WARNING) << item_type_ << " unknown acquisition item type"; +// } + // nothing to disconnect +} + + +gr::basic_block_sptr GpsL5iPcpsAcquisitionFpga::get_left_block() +{ +// if (item_type_.compare("gr_complex") == 0) +// { +// return stream_to_vector_; +// } +// else if (item_type_.compare("cshort") == 0) +// { +// return stream_to_vector_; +// } +// else if (item_type_.compare("cbyte") == 0) +// { +// return cbyte_to_float_x2_; +// } +// else +// { +// LOG(WARNING) << item_type_ << " unknown acquisition item type"; +// return nullptr; +// } + return nullptr; +} + + +gr::basic_block_sptr GpsL5iPcpsAcquisitionFpga::get_right_block() +{ + return acquisition_fpga_; +} diff --git a/src/algorithms/acquisition/adapters/gps_l5i_pcps_acquisition_fpga.h b/src/algorithms/acquisition/adapters/gps_l5i_pcps_acquisition_fpga.h new file mode 100644 index 000000000..d125192dd --- /dev/null +++ b/src/algorithms/acquisition/adapters/gps_l5i_pcps_acquisition_fpga.h @@ -0,0 +1,171 @@ +/*! + * \file GPS_L5i_PCPS_Acquisition.h + * \brief Adapts a PCPS acquisition block to an AcquisitionInterface for + * GPS L5i signals + * \authors
    + *
  • Javier Arribas, 2017. jarribas(at)cttc.es + *
+ * + * ------------------------------------------------------------------------- + * + * 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_L5i_PCPS_ACQUISITION_FPGA_H_ +#define GNSS_SDR_GPS_L5i_PCPS_ACQUISITION_FPGA_H_ + +#include "acquisition_interface.h" +#include "gnss_synchro.h" +#include "pcps_acquisition_fpga.h" +#include "complex_byte_to_float_x2.h" +#include +#include +#include +#include + + +class ConfigurationInterface; + +/*! + * \brief This class adapts a PCPS acquisition block to an AcquisitionInterface + * for GPS L5i signals + */ +class GpsL5iPcpsAcquisitionFpga : public AcquisitionInterface +{ +public: + GpsL5iPcpsAcquisitionFpga(ConfigurationInterface* configuration, + std::string role, unsigned int in_streams, + unsigned int out_streams); + + virtual ~GpsL5iPcpsAcquisitionFpga(); + + inline std::string role() override + { + return role_; + } + + /*! + * \brief Returns "GPS_L5i_PCPS_Acquisition" + */ + inline std::string implementation() override + { + return "GPS_L5i_PCPS_Acquisition"; + } + + inline size_t item_size() override + { + return item_size_; + } + + void connect(gr::top_block_sptr top_block) override; + void disconnect(gr::top_block_sptr top_block) override; + gr::basic_block_sptr get_left_block() override; + gr::basic_block_sptr get_right_block() override; + + /*! + * \brief Set acquisition/tracking common Gnss_Synchro object pointer + * to efficiently exchange synchronization data between acquisition and + * tracking blocks + */ + void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) override; + + /*! + * \brief Set acquisition channel unique ID + */ + void set_channel(unsigned int channel) override; + + /*! + * \brief Set statistics threshold of PCPS algorithm + */ + void set_threshold(float threshold) override; + + /*! + * \brief Set maximum Doppler off grid search + */ + void set_doppler_max(unsigned int doppler_max) override; + + /*! + * \brief Set Doppler steps for the grid search + */ + void set_doppler_step(unsigned int doppler_step) override; + + /*! + * \brief Initializes acquisition algorithm. + */ + void init() override; + + /*! + * \brief Sets local code for GPS L2/M PCPS acquisition algorithm. + */ + void set_local_code() override; + + /*! + * \brief Returns the maximum peak of grid search + */ + signed int mag() override; + + /*! + * \brief Restart acquisition algorithm + */ + void reset() override; + + /*! + * \brief If state = 1, it forces the block to start acquiring from the first sample + */ + void set_state(int state); + +private: + ConfigurationInterface* configuration_; + //pcps_acquisition_sptr acquisition_; + pcps_acquisition_fpga_sptr acquisition_fpga_; + 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 max_dwells_; + long fs_in_; + long if_; + bool dump_; + bool blocking_; + std::string dump_filename_; + std::complex* code_; + Gnss_Synchro* gnss_synchro_; + std::string role_; + unsigned int in_streams_; + unsigned int out_streams_; + + lv_16sc_t* d_all_fft_codes_; // memory that contains all the code ffts + + float calculate_threshold(float pfa); +}; + +#endif /* GNSS_SDR_GPS_L5i_PCPS_ACQUISITION_FPGA_H_ */ diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.cc b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.cc index 5bc5b2b3d..8df1c9fd0 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.cc +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.cc @@ -43,6 +43,9 @@ #include #include "pcps_acquisition_fpga.h" + +#define AQ_DOWNSAMPLING_DELAY 40 // delay due to the downsampling filter in the acquisition + using google::LogMessage; pcps_acquisition_fpga_sptr pcps_make_acquisition_fpga(pcpsconf_fpga_t conf_) @@ -55,13 +58,15 @@ pcps_acquisition_fpga::pcps_acquisition_fpga(pcpsconf_fpga_t conf_) : gr::block( gr::io_signature::make(0, 0, 0), gr::io_signature::make(0, 0, 0)) { + // printf("acq constructor start\n"); this->message_port_register_out(pmt::mp("events")); acq_parameters = conf_; d_sample_counter = 0; // SAMPLE COUNTER d_active = false; d_state = 0; - d_fft_size = acq_parameters.sampled_ms * acq_parameters.samples_per_ms; + //d_fft_size = acq_parameters.sampled_ms * acq_parameters.samples_per_ms; + d_fft_size = acq_parameters.samples_per_code; d_mag = 0; d_input_power = 0.0; d_num_doppler_bins = 0; @@ -71,27 +76,50 @@ pcps_acquisition_fpga::pcps_acquisition_fpga(pcpsconf_fpga_t conf_) : gr::block( d_channel = 0; d_gnss_synchro = 0; + //printf("zzzz acq_parameters.code_length = %d\n", acq_parameters.code_length); + //printf("zzzz acq_parameters.samples_per_ms = %d\n", acq_parameters.samples_per_ms); + //printf("zzzz d_fft_size = %d\n", d_fft_size); + + // this one works we don't know why +// acquisition_fpga = std::make_shared +// (acq_parameters.device_name, acq_parameters.code_length, acq_parameters.doppler_max, acq_parameters.samples_per_ms, +// acq_parameters.fs_in, acq_parameters.freq, acq_parameters.sampled_ms, acq_parameters.select_queue_Fpga, acq_parameters.all_fft_codes); + + // this one is the one it should be but it doesn't work acquisition_fpga = std::make_shared - (acq_parameters.device_name, d_fft_size, acq_parameters.doppler_max, acq_parameters.samples_per_ms, + (acq_parameters.device_name, acq_parameters.code_length, acq_parameters.doppler_max, d_fft_size, acq_parameters.fs_in, acq_parameters.freq, acq_parameters.sampled_ms, acq_parameters.select_queue_Fpga, acq_parameters.all_fft_codes); +// acquisition_fpga = std::make_shared +// (acq_parameters.device_name, acq_parameters.samples_per_code, acq_parameters.doppler_max, acq_parameters.samples_per_code, +// acq_parameters.fs_in, acq_parameters.freq, acq_parameters.sampled_ms, acq_parameters.select_queue_Fpga, acq_parameters.all_fft_codes); + + // debug + //debug_d_max_absolute = 0.0; + //debug_d_input_power_absolute = 0.0; + // printf("acq constructor end\n"); } pcps_acquisition_fpga::~pcps_acquisition_fpga() { + // printf("acq destructor start\n"); acquisition_fpga->free(); + // printf("acq destructor end\n"); } void pcps_acquisition_fpga::set_local_code() { + // printf("acq set local code start\n"); acquisition_fpga->set_local_code(d_gnss_synchro->PRN); + // printf("acq set local code end\n"); } void pcps_acquisition_fpga::init() { + // printf("acq init start\n"); d_gnss_synchro->Flag_valid_acquisition = false; d_gnss_synchro->Flag_valid_symbol_output = false; d_gnss_synchro->Flag_valid_pseudorange = false; @@ -104,11 +132,13 @@ void pcps_acquisition_fpga::init() d_num_doppler_bins = static_cast(std::ceil(static_cast(static_cast(acq_parameters.doppler_max) - static_cast(-acq_parameters.doppler_max)) / static_cast(d_doppler_step))); acquisition_fpga->init(); + // printf("acq init end\n"); } void pcps_acquisition_fpga::set_state(int state) { + // printf("acq set state start\n"); d_state = state; if (d_state == 1) { @@ -128,11 +158,13 @@ void pcps_acquisition_fpga::set_state(int state) { LOG(ERROR) << "State can only be set to 0 or 1"; } + // printf("acq set state end\n"); } void pcps_acquisition_fpga::send_positive_acquisition() { +// printf("acq send positive acquisition start\n"); // 6.1- Declare positive acquisition using a message port //0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL DLOG(INFO) << "positive acquisition" @@ -146,11 +178,13 @@ void pcps_acquisition_fpga::send_positive_acquisition() << ", input signal power " << d_input_power; this->message_port_pub(pmt::mp("events"), pmt::from_long(1)); +// printf("acq send positive acquisition end\n"); } void pcps_acquisition_fpga::send_negative_acquisition() { + // printf("acq send negative acquisition start\n"); // 6.2- Declare negative acquisition using a message port //0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL DLOG(INFO) << "negative acquisition" @@ -164,11 +198,13 @@ void pcps_acquisition_fpga::send_negative_acquisition() << ", input signal power " << d_input_power; this->message_port_pub(pmt::mp("events"), pmt::from_long(2)); +// printf("acq send negative acquisition end\n"); } void pcps_acquisition_fpga::set_active(bool active) { + // printf("acq set active start\n"); d_active = active; // initialize acquisition algorithm @@ -190,21 +226,29 @@ void pcps_acquisition_fpga::set_active(bool active) unsigned int initial_sample; float input_power_all = 0.0; float input_power_computed = 0.0; + + float temp_d_input_power; + + // loop through acquisition +/* for (unsigned int doppler_index = 0; doppler_index < d_num_doppler_bins; doppler_index++) { // doppler search steps int doppler = -static_cast(acq_parameters.doppler_max) + d_doppler_step * doppler_index; - acquisition_fpga->set_phase_step(doppler_index); + //acquisition_fpga->set_phase_step(doppler_index); + acquisition_fpga->set_doppler_sweep_debug(1, doppler_index); acquisition_fpga->run_acquisition(); // runs acquisition and waits until it is finished acquisition_fpga->read_acquisition_results(&indext, &magt, - &initial_sample, &d_input_power); + &initial_sample, &d_input_power, &d_doppler_index); d_sample_counter = initial_sample; if (d_mag < magt) { d_mag = magt; + temp_d_input_power = d_input_power; + input_power_all = d_input_power / (d_fft_size - 1); input_power_computed = (d_input_power - d_mag) / (d_fft_size - 1); d_input_power = (d_input_power - d_mag) / (d_fft_size - 1); @@ -219,10 +263,72 @@ void pcps_acquisition_fpga::set_active(bool active) // In the case of the FPGA the option of dumping the results of the acquisition to a file is not available // because the IFFT vector is not available } +*/ + + // debug + //acquisition_fpga->block_samples(); + + // run loop in hw + acquisition_fpga->set_doppler_sweep(d_num_doppler_bins); + acquisition_fpga->run_acquisition(); + acquisition_fpga->read_acquisition_results(&indext, &magt, + &initial_sample, &d_input_power, &d_doppler_index); + + + // debug + //acquisition_fpga->unblock_samples(); + + d_mag = magt; + + + // debug + debug_d_max_absolute = magt; + debug_d_input_power_absolute = d_input_power; + debug_indext = indext; + debug_doppler_index = d_doppler_index; + + // temp_d_input_power = d_input_power; + + d_input_power = (d_input_power - d_mag) / (d_fft_size - 1); + int doppler = -static_cast(acq_parameters.doppler_max) + d_doppler_step * d_doppler_index; + //d_gnss_synchro->Acq_delay_samples = static_cast(2*(indext % (2*acq_parameters.samples_per_code))); + d_gnss_synchro->Acq_delay_samples = static_cast(indext % acq_parameters.samples_per_code); + d_gnss_synchro->Acq_doppler_hz = static_cast(doppler); + d_sample_counter = initial_sample; + //d_gnss_synchro->Acq_samplestamp_samples = 2*d_sample_counter - 81; // delay due to the downsampling filter in the acquisition + //d_gnss_synchro->Acq_samplestamp_samples = d_sample_counter - 40; // delay due to the downsampling filter in the acquisition + d_gnss_synchro->Acq_samplestamp_samples = d_sample_counter; // delay due to the downsampling filter in the acquisition + d_test_statistics = (d_mag / d_input_power); //* correction_factor; + + // debug +// if (d_gnss_synchro->Acq_delay_samples > acq_parameters.code_length) +// { +// printf("d_gnss_synchro->Acq_samplestamp_samples = %d\n", d_gnss_synchro->Acq_samplestamp_samples); +// printf("d_gnss_synchro->Acq_delay_samples = %f\n", d_gnss_synchro->Acq_delay_samples); +// } + + // if (temp_d_input_power > debug_d_input_power_absolute) + // { + // debug_d_max_absolute = d_mag; + // debug_d_input_power_absolute = temp_d_input_power; + // } + // printf ("max debug_d_max_absolute = %f\n", debug_d_max_absolute); + // printf ("debug_d_input_power_absolute = %f\n", debug_d_input_power_absolute); + +// printf("&&&&& d_test_statistics = %f\n", d_test_statistics); +// printf("&&&&& debug_d_max_absolute =%f\n",debug_d_max_absolute); +// printf("&&&&& debug_d_input_power_absolute =%f\n",debug_d_input_power_absolute); +// printf("&&&&& debug_indext = %d\n",debug_indext); +// printf("&&&&& debug_doppler_index = %d\n",debug_doppler_index); if (d_test_statistics > d_threshold) { d_active = false; + printf("##### d_test_statistics = %f\n", d_test_statistics); + printf("##### debug_d_max_absolute =%f\n",debug_d_max_absolute); + printf("##### debug_d_input_power_absolute =%f\n",debug_d_input_power_absolute); + printf("##### debug_indext = %d\n",debug_indext); + printf("##### debug_doppler_index = %d\n",debug_doppler_index); send_positive_acquisition(); d_state = 0; // Positive acquisition } @@ -232,6 +338,9 @@ void pcps_acquisition_fpga::set_active(bool active) d_active = false; send_negative_acquisition(); } + + // printf("acq set active end\n"); + } diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.h b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.h index 36ddcd70f..2288b03a1 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.h +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.h @@ -70,6 +70,7 @@ typedef struct long fs_in; int samples_per_ms; int samples_per_code; + int code_length; unsigned int select_queue_Fpga; std::string device_name; lv_16sc_t* all_fft_codes; // memory that contains all the code ffts @@ -107,6 +108,7 @@ private: float d_threshold; float d_mag; float d_input_power; + unsigned d_doppler_index; float d_test_statistics; int d_state; unsigned int d_channel; @@ -117,6 +119,12 @@ private: Gnss_Synchro* d_gnss_synchro; std::shared_ptr acquisition_fpga; + // debug + float debug_d_max_absolute; + float debug_d_input_power_absolute; + int debug_indext; + int debug_doppler_index; + public: ~pcps_acquisition_fpga(); @@ -127,7 +135,9 @@ public: */ inline void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) { + // printf("acq set gnss synchro start\n"); d_gnss_synchro = p_gnss_synchro; + // printf("acq set gnss synchro end\n"); } /*! @@ -135,7 +145,9 @@ public: */ inline unsigned int mag() const { + // printf("acq dmag start\n"); return d_mag; + // printf("acq dmag end\n"); } /*! @@ -179,7 +191,9 @@ public: */ inline void set_threshold(float threshold) { + // printf("acq set threshold start\n"); d_threshold = threshold; + // printf("acq set threshold end\n"); } /*! @@ -188,8 +202,10 @@ public: */ inline void set_doppler_max(unsigned int doppler_max) { + // printf("acq set doppler max start\n"); acq_parameters.doppler_max = doppler_max; acquisition_fpga->set_doppler_max(doppler_max); + // printf("acq set doppler max end\n"); } /*! @@ -198,8 +214,10 @@ public: */ inline void set_doppler_step(unsigned int doppler_step) { + // printf("acq set doppler step start\n"); d_doppler_step = doppler_step; acquisition_fpga->set_doppler_step(doppler_step); + // printf("acq set doppler step end\n"); } /*! diff --git a/src/algorithms/acquisition/libs/fpga_acquisition.cc b/src/algorithms/acquisition/libs/fpga_acquisition.cc index 81995faab..bdb845e19 100644 --- a/src/algorithms/acquisition/libs/fpga_acquisition.cc +++ b/src/algorithms/acquisition/libs/fpga_acquisition.cc @@ -55,6 +55,18 @@ #define SELECT_16_BITS 0xFFFF // value to select 16 bits #define SHL_8_BITS 256 // value used to shift a value 8 bits to the left +// 12-bits +//#define SELECT_LSBits 0x0FFF +//#define SELECT_MSBbits 0x00FFF000 +//#define SELECT_24_BITS 0x00FFFFFF +//#define SHL_12_BITS 4096 +// 16-bits +#define SELECT_LSBits 0x0FFFF +#define SELECT_MSBbits 0xFFFF0000 +#define SELECT_32_BITS 0xFFFFFFFF +#define SHL_16_BITS 65536 + + bool fpga_acquisition::init() { @@ -69,6 +81,10 @@ bool fpga_acquisition::set_local_code(unsigned int PRN) // select the code with the chosen PRN fpga_acquisition::fpga_configure_acquisition_local_code( &d_all_fft_codes[d_nsamples_total * (PRN - 1)]); + + //fpga_acquisition::fpga_configure_acquisition_local_code( + // &d_all_fft_codes[0]); + return true; } @@ -80,7 +96,11 @@ fpga_acquisition::fpga_acquisition(std::string device_name, unsigned int sampled_ms, unsigned select_queue, lv_16sc_t *all_fft_codes) { - unsigned int vector_length = nsamples_total * sampled_ms; + //printf("AAA- sampled_ms = %d\n ", sampled_ms); + + unsigned int vector_length = nsamples_total; // * sampled_ms; + + //printf("AAA- vector_length = %d\n ", vector_length); // initial values d_device_name = device_name; d_freq = freq; @@ -99,6 +119,7 @@ fpga_acquisition::fpga_acquisition(std::string device_name, if ((d_fd = open(d_device_name.c_str(), O_RDWR | O_SYNC)) == -1) { LOG(WARNING) << "Cannot open deviceio" << d_device_name; + std::cout << "Acq: cannot open deviceio" << d_device_name << std::endl; } d_map_base = reinterpret_cast(mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, d_fd, 0)); @@ -106,6 +127,7 @@ fpga_acquisition::fpga_acquisition(std::string device_name, if (d_map_base == reinterpret_cast(-1)) { LOG(WARNING) << "Cannot map the FPGA acquisition module into user memory"; + std::cout << "Acq: cannot map deviceio" << d_device_name << std::endl; } // sanity check : check test register @@ -119,6 +141,7 @@ fpga_acquisition::fpga_acquisition(std::string device_name, else { LOG(INFO) << "Acquisition test register sanity check success!"; + //std::cout << "Acquisition test register sanity check success!" << std::endl; } fpga_acquisition::reset_acquisition(); DLOG(INFO) << "Acquisition FPGA class created"; @@ -151,35 +174,53 @@ unsigned fpga_acquisition::fpga_acquisition_test_register(unsigned writeval) void fpga_acquisition::fpga_configure_acquisition_local_code(lv_16sc_t fft_local_code[]) { - unsigned short local_code; + //unsigned short local_code; + unsigned int local_code; unsigned int k, tmp, tmp2; unsigned int fft_data; // clear memory address counter - d_map_base[4] = LOCAL_CODE_CLEAR_MEM; + //d_map_base[6] = LOCAL_CODE_CLEAR_MEM; + d_map_base[9] = LOCAL_CODE_CLEAR_MEM; // write local code for (k = 0; k < d_vector_length; k++) { tmp = fft_local_code[k].real(); tmp2 = fft_local_code[k].imag(); - local_code = (tmp & SELECT_LSB) | ((tmp2 * SHL_8_BITS) & SELECT_MSB); // put together the real part and the imaginary part - fft_data = MEM_LOCAL_CODE_WR_ENABLE | (local_code & SELECT_16_BITS); - d_map_base[4] = fft_data; + //tmp = k; + //tmp2 = k; + + //local_code = (tmp & SELECT_LSB) | ((tmp2 * SHL_8_BITS) & SELECT_MSB); // put together the real part and the imaginary part + //fft_data = MEM_LOCAL_CODE_WR_ENABLE | (local_code & SELECT_16_BITS); + //local_code = (tmp & SELECT_LSBits) | ((tmp2 * SHL_12_BITS) & SELECT_MSBbits); // put together the real part and the imaginary part + local_code = (tmp & SELECT_LSBits) | ((tmp2 * SHL_16_BITS) & SELECT_MSBbits); // put together the real part and the imaginary part + //fft_data = MEM_LOCAL_CODE_WR_ENABLE | (local_code & SELECT_24_BITS); + fft_data = local_code & SELECT_32_BITS; + d_map_base[6] = fft_data; + + + //printf("debug local code %d real = %d imag = %d local_code = %d fft_data = %d\n", k, tmp, tmp2, local_code, fft_data); + //printf("debug local code %d real = 0x%08X imag = 0x%08X local_code = 0x%08X fft_data = 0x%08X\n", k, tmp, tmp2, local_code, fft_data); } + //printf("d_vector_length = %d\n", d_vector_length); + //while(1); } void fpga_acquisition::run_acquisition(void) { + // enable interrupts int reenable = 1; write(d_fd, reinterpret_cast(&reenable), sizeof(int)); // launch the acquisition process - d_map_base[6] = LAUNCH_ACQUISITION; // writing anything to reg 6 launches the acquisition process + //printf("launchin acquisition ...\n"); + d_map_base[8] = LAUNCH_ACQUISITION; // writing a 1 to reg 8 launches the acquisition process int irq_count; ssize_t nb; // wait for interrupt nb = read(d_fd, &irq_count, sizeof(irq_count)); + //printf("interrupt received\n"); if (nb != sizeof(irq_count)) { printf("acquisition module Read failed to retrieve 4 bytes!\n"); @@ -188,12 +229,111 @@ void fpga_acquisition::run_acquisition(void) } + +void fpga_acquisition::set_doppler_sweep(unsigned int num_sweeps) +{ + float phase_step_rad_real; + float phase_step_rad_int_temp; + int32_t phase_step_rad_int; + //int doppler = static_cast(-d_doppler_max) + d_doppler_step * doppler_index; + int doppler = static_cast(-d_doppler_max); + float phase_step_rad = GPS_TWO_PI * (d_freq + doppler) / static_cast(d_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_real = 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) + + //printf("AAA phase_step_rad_real for initial doppler = %f\n", phase_step_rad_real); + if (phase_step_rad_real >= 1.0) + { + phase_step_rad_real = MAX_PHASE_STEP_RAD; + } + //printf("AAA phase_step_rad_real for initial doppler after checking = %f\n", phase_step_rad_real); + phase_step_rad_int_temp = phase_step_rad_real * POW_2_2; // * 2^2 + phase_step_rad_int = (int32_t)(phase_step_rad_int_temp * (POW_2_29)); // * 2^29 (in total it makes x2^31 in two steps to avoid the warnings + //printf("AAA writing phase_step_rad_int for initial doppler = %d to d map base 3\n", phase_step_rad_int); + d_map_base[3] = phase_step_rad_int; + + // repeat the calculation with the doppler step + doppler = static_cast(d_doppler_step); + phase_step_rad = GPS_TWO_PI * (doppler) / static_cast(d_fs_in); + phase_step_rad_real = phase_step_rad / (GPS_TWO_PI / 2); + //printf("AAA phase_step_rad_real for doppler step = %f\n", phase_step_rad_real); + if (phase_step_rad_real >= 1.0) + { + phase_step_rad_real = MAX_PHASE_STEP_RAD; + } + //printf("AAA phase_step_rad_real for doppler step after checking = %f\n", phase_step_rad_real); + phase_step_rad_int_temp = phase_step_rad_real * POW_2_2; // * 2^2 + phase_step_rad_int = (int32_t)(phase_step_rad_int_temp * (POW_2_29)); // * 2^29 (in total it makes x2^31 in two steps to avoid the warnings + //printf("AAA writing phase_step_rad_int for doppler step = %d to d map base 4\n", phase_step_rad_int); + d_map_base[4] = phase_step_rad_int; + //printf("AAA writing num sweeps to d map base 5 = %d\n", num_sweeps); + d_map_base[5] = num_sweeps; +} + +void fpga_acquisition::set_doppler_sweep_debug(unsigned int num_sweeps, unsigned int doppler_index) +{ + float phase_step_rad_real; + float phase_step_rad_int_temp; + int32_t phase_step_rad_int; + int doppler = static_cast(-d_doppler_max) + d_doppler_step * doppler_index; + //int doppler = static_cast(-d_doppler_max); + float phase_step_rad = GPS_TWO_PI * (d_freq + doppler) / static_cast(d_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_real = 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) + + //printf("AAAh phase_step_rad_real for initial doppler = %f\n", phase_step_rad_real); + if (phase_step_rad_real >= 1.0) + { + phase_step_rad_real = MAX_PHASE_STEP_RAD; + } + //printf("AAAh phase_step_rad_real for initial doppler after checking = %f\n", phase_step_rad_real); + phase_step_rad_int_temp = phase_step_rad_real * POW_2_2; // * 2^2 + phase_step_rad_int = (int32_t)(phase_step_rad_int_temp * (POW_2_29)); // * 2^29 (in total it makes x2^31 in two steps to avoid the warnings + //printf("AAAh writing phase_step_rad_int for initial doppler = %d to d map base 3\n", phase_step_rad_int); + d_map_base[3] = phase_step_rad_int; + + // repeat the calculation with the doppler step + doppler = static_cast(d_doppler_step); + phase_step_rad = GPS_TWO_PI * (doppler) / static_cast(d_fs_in); + phase_step_rad_real = phase_step_rad / (GPS_TWO_PI / 2); + //printf("AAAh phase_step_rad_real for doppler step = %f\n", phase_step_rad_real); + if (phase_step_rad_real >= 1.0) + { + phase_step_rad_real = MAX_PHASE_STEP_RAD; + } + //printf("AAAh phase_step_rad_real for doppler step after checking = %f\n", phase_step_rad_real); + phase_step_rad_int_temp = phase_step_rad_real * POW_2_2; // * 2^2 + phase_step_rad_int = (int32_t)(phase_step_rad_int_temp * (POW_2_29)); // * 2^29 (in total it makes x2^31 in two steps to avoid the warnings + //printf("AAAh writing phase_step_rad_int for doppler step = %d to d map base 4\n", phase_step_rad_int); + d_map_base[4] = phase_step_rad_int; + //printf("AAAh writing num sweeps to d map base 5 = %d\n", num_sweeps); + d_map_base[5] = num_sweeps; +} + + + + void fpga_acquisition::configure_acquisition() { d_map_base[0] = d_select_queue; + //printf("AAA writing d_vector_length = %d to d map base 1\n ", d_vector_length); d_map_base[1] = d_vector_length; + //printf("AAA writing d_nsamples = %d to d map base 2\n ", d_nsamples); d_map_base[2] = d_nsamples; - d_map_base[5] = (int)log2((float)d_vector_length); // log2 FFTlength + //printf("AAA writing LOG2 d_vector_length = %d to d map base 7\n ", (int)log2((float)d_vector_length)); + d_map_base[7] = (int)log2((float)d_vector_length); // log2 FFTlength + //printf("acquisition debug vector length = %d\n", d_vector_length); + //printf("acquisition debug vector length = %d\n", (int)log2((float)d_vector_length)); } @@ -211,28 +351,38 @@ void fpga_acquisition::set_phase_step(unsigned int doppler_index) phase_step_rad_real = 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) + //printf("AAA+ phase_step_rad_real = %f\n", phase_step_rad_real); if (phase_step_rad_real >= 1.0) { phase_step_rad_real = MAX_PHASE_STEP_RAD; } + //printf("AAA+ phase_step_rad_real after checking = %f\n", phase_step_rad_real); phase_step_rad_int_temp = phase_step_rad_real * POW_2_2; // * 2^2 phase_step_rad_int = (int32_t)(phase_step_rad_int_temp * (POW_2_29)); // * 2^29 (in total it makes x2^31 in two steps to avoid the warnings + //printf("writing phase_step_rad_int = %d to d_map_base 3\n", phase_step_rad_int); d_map_base[3] = phase_step_rad_int; } void fpga_acquisition::read_acquisition_results(uint32_t *max_index, - float *max_magnitude, unsigned *initial_sample, float *power_sum) + float *max_magnitude, unsigned *initial_sample, float *power_sum, unsigned *doppler_index) { unsigned readval = 0; readval = d_map_base[1]; *initial_sample = readval; + //printf("read initial sample dmap 1 = %d\n", readval); readval = d_map_base[2]; *max_magnitude = static_cast(readval); + //printf("read max_magnitude dmap 2 = %d\n", readval); readval = d_map_base[4]; *power_sum = static_cast(readval); + //printf("read power sum dmap 4 = %d\n", readval); + readval = d_map_base[5]; // read doppler index + *doppler_index = readval; + //printf("read doppler_index dmap 5 = %d\n", readval); readval = d_map_base[3]; *max_index = readval; + //printf("read max index dmap 3 = %d\n", readval); } @@ -261,5 +411,5 @@ void fpga_acquisition::close_device() void fpga_acquisition::reset_acquisition(void) { - d_map_base[6] = RESET_ACQUISITION; // writing a 2 to d_map_base[6] resets the multicorrelator + d_map_base[8] = RESET_ACQUISITION; // writing a 2 to d_map_base[8] resets the multicorrelator } diff --git a/src/algorithms/acquisition/libs/fpga_acquisition.h b/src/algorithms/acquisition/libs/fpga_acquisition.h index 00641e1cd..80f197c02 100644 --- a/src/algorithms/acquisition/libs/fpga_acquisition.h +++ b/src/algorithms/acquisition/libs/fpga_acquisition.h @@ -56,10 +56,12 @@ public: bool set_local_code( unsigned int PRN); bool free(); + void set_doppler_sweep(unsigned int num_sweeps); + void set_doppler_sweep_debug(unsigned int num_sweeps, unsigned int doppler_index); 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); + unsigned *initial_sample, float *power_sum, unsigned *doppler_index); void block_samples(); void unblock_samples(); @@ -102,6 +104,7 @@ private: void configure_acquisition(); void reset_acquisition(void); void close_device(); + }; #endif /* GNSS_SDR_FPGA_ACQUISITION_H_ */ diff --git a/src/algorithms/tracking/adapters/CMakeLists.txt b/src/algorithms/tracking/adapters/CMakeLists.txt index 345c23acc..060130ff5 100644 --- a/src/algorithms/tracking/adapters/CMakeLists.txt +++ b/src/algorithms/tracking/adapters/CMakeLists.txt @@ -22,7 +22,7 @@ if(ENABLE_CUDA) endif(ENABLE_CUDA) if(ENABLE_FPGA) - SET(OPT_TRACKING_ADAPTERS ${OPT_TRACKING_ADAPTERS} gps_l1_ca_dll_pll_tracking_fpga.cc galileo_e1_dll_pll_veml_tracking_fpga.cc) + SET(OPT_TRACKING_ADAPTERS ${OPT_TRACKING_ADAPTERS} gps_l1_ca_dll_pll_tracking_fpga.cc gps_l2_m_dll_pll_tracking_fpga.cc galileo_e1_dll_pll_veml_tracking_fpga.cc galileo_e5a_dll_pll_tracking_fpga.cc gps_l5_dll_pll_tracking_fpga.cc) endif(ENABLE_FPGA) set(TRACKING_ADAPTER_SOURCES diff --git a/src/algorithms/tracking/adapters/galileo_e1_dll_pll_veml_tracking_fpga.cc b/src/algorithms/tracking/adapters/galileo_e1_dll_pll_veml_tracking_fpga.cc index afa3d7828..10e1b45c9 100644 --- a/src/algorithms/tracking/adapters/galileo_e1_dll_pll_veml_tracking_fpga.cc +++ b/src/algorithms/tracking/adapters/galileo_e1_dll_pll_veml_tracking_fpga.cc @@ -42,7 +42,7 @@ #include "display.h" #include -#define NUM_PRNs_GALILEO_E1 50 +//#define NUM_PRNs_GALILEO_E1 50 using google::LogMessage; @@ -50,7 +50,6 @@ GalileoE1DllPllVemlTrackingFpga::GalileoE1DllPllVemlTrackingFpga( ConfigurationInterface* configuration, std::string role, unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams) { - printf("galileo e1 fpga constructor called\n"); //dllpllconf_t trk_param; dllpllconf_fpga_t trk_param_fpga; DLOG(INFO) << "role " << role; @@ -97,6 +96,7 @@ GalileoE1DllPllVemlTrackingFpga::GalileoE1DllPllVemlTrackingFpga( std::cout << TEXT_RED << "WARNING: Galileo E1. PLL or DLL narrow tracking bandwidth is higher than wide tracking one" << TEXT_RESET << std::endl; } trk_param_fpga.track_pilot = track_pilot; + d_track_pilot = track_pilot; trk_param_fpga.extend_correlation_symbols = extend_correlation_symbols; std::string default_dump_filename = "./track_ch"; std::string dump_filename = configuration->property(role + ".dump_filename", default_dump_filename); @@ -125,49 +125,75 @@ GalileoE1DllPllVemlTrackingFpga::GalileoE1DllPllVemlTrackingFpga( trk_param_fpga.device_name = device_name; unsigned int device_base = configuration->property(role + ".device_base", 1); trk_param_fpga.device_base = device_base; + //unsigned int multicorr_type = configuration->property(role + ".multicorr_type", 1); + trk_param_fpga.multicorr_type = 1; // 0 -> 3 correlators, 1 -> 5 correlators //################# PRE-COMPUTE ALL THE CODES ################# + unsigned int code_samples_per_chip = 2; + d_ca_codes = static_cast(volk_gnsssdr_malloc(static_cast(Galileo_E1_B_CODE_LENGTH_CHIPS)* code_samples_per_chip * Galileo_E1_NUMBER_OF_CODES * sizeof(int), volk_gnsssdr_get_alignment())); + float * ca_codes_f; + float * data_codes_f; - d_ca_codes = static_cast(volk_gnsssdr_malloc(static_cast(Galileo_E1_B_CODE_LENGTH_CHIPS)* 2 * NUM_PRNs_GALILEO_E1 * sizeof(int), volk_gnsssdr_get_alignment())); - d_data_codes = static_cast(volk_gnsssdr_malloc((static_cast(Galileo_E1_B_CODE_LENGTH_CHIPS)) * 2 * NUM_PRNs_GALILEO_E1 * sizeof(int), volk_gnsssdr_get_alignment())); + if (trk_param_fpga.track_pilot) + { + d_data_codes = static_cast(volk_gnsssdr_malloc((static_cast(Galileo_E1_B_CODE_LENGTH_CHIPS)) * code_samples_per_chip * Galileo_E1_NUMBER_OF_CODES * sizeof(int), volk_gnsssdr_get_alignment())); + } + ca_codes_f = static_cast(volk_gnsssdr_malloc(static_cast(Galileo_E1_B_CODE_LENGTH_CHIPS)* code_samples_per_chip * sizeof(float), volk_gnsssdr_get_alignment())); - float* ca_codes_f = static_cast(volk_gnsssdr_malloc(static_cast(Galileo_E1_B_CODE_LENGTH_CHIPS)* 2 * sizeof(float), volk_gnsssdr_get_alignment())); - float* data_codes_f = static_cast(volk_gnsssdr_malloc((static_cast(Galileo_E1_B_CODE_LENGTH_CHIPS)) * 2 * sizeof(float), volk_gnsssdr_get_alignment())); + if (trk_param_fpga.track_pilot) + { + data_codes_f = static_cast(volk_gnsssdr_malloc((static_cast(Galileo_E1_B_CODE_LENGTH_CHIPS)) * code_samples_per_chip * sizeof(float), volk_gnsssdr_get_alignment())); + } - for (unsigned int PRN = 1; PRN <= NUM_PRNs_GALILEO_E1; PRN++) + //printf("pppppppp trk_param_fpga.track_pilot = %d\n", trk_param_fpga.track_pilot); + + //int kk; + + for (unsigned int PRN = 1; PRN <= Galileo_E1_NUMBER_OF_CODES; PRN++) { char data_signal[3] = "1B"; if (trk_param_fpga.track_pilot) { + //printf("yes tracking pilot !!!!!!!!!!!!!!!\n"); char pilot_signal[3] = "1C"; galileo_e1_code_gen_sinboc11_float(ca_codes_f, pilot_signal, PRN); galileo_e1_code_gen_sinboc11_float(data_codes_f, data_signal, PRN); - for (unsigned int s = 0; s < Galileo_E1_B_CODE_LENGTH_CHIPS; s++) + for (unsigned int s = 0; s < 2*Galileo_E1_B_CODE_LENGTH_CHIPS; s++) { d_ca_codes[static_cast(Galileo_E1_B_CODE_LENGTH_CHIPS)* 2 * (PRN - 1) + s] = static_cast(ca_codes_f[s]); - d_data_codes[static_cast(Galileo_E1_B_CODE_LENGTH_CHIPS)* 2 * (PRN - 1) + s] = static_cast(d_data_codes[s]); + d_data_codes[static_cast(Galileo_E1_B_CODE_LENGTH_CHIPS)* 2 * (PRN - 1) + s] = static_cast(data_codes_f[s]); + //printf("%f %d | ", data_codes_f[s], d_data_codes[static_cast(Galileo_E1_B_CODE_LENGTH_CHIPS)* 2 * (PRN - 1) + s]); + } + //printf("\n next \n"); + //scanf ("%d",&kk); } else { + //printf("no tracking pilot\n"); galileo_e1_code_gen_sinboc11_float(ca_codes_f, data_signal, PRN); - for (unsigned int s = 0; s < Galileo_E1_B_CODE_LENGTH_CHIPS; s++) + for (unsigned int s = 0; s < 2*Galileo_E1_B_CODE_LENGTH_CHIPS; s++) { d_ca_codes[static_cast(Galileo_E1_B_CODE_LENGTH_CHIPS)* 2 * (PRN - 1) + s] = static_cast(ca_codes_f[s]); + //printf("%f %d | ", ca_codes_f[s], d_ca_codes[static_cast(Galileo_E1_B_CODE_LENGTH_CHIPS)* 2 * (PRN - 1) + s]); } + //printf("\n next \n"); + //scanf ("%d",&kk); } } delete[] ca_codes_f; - delete[] data_codes_f; - + if (trk_param_fpga.track_pilot) + { + delete[] data_codes_f; + } trk_param_fpga.ca_codes = d_ca_codes; trk_param_fpga.data_codes = d_data_codes; - trk_param_fpga.code_length = Galileo_E1_B_CODE_LENGTH_CHIPS; - + trk_param_fpga.code_length_chips = Galileo_E1_B_CODE_LENGTH_CHIPS; + trk_param_fpga.code_samples_per_chip = code_samples_per_chip; // 2 sample per chip //################# MAKE TRACKING GNURadio object ################### tracking_fpga_sc = dll_pll_veml_make_tracking_fpga(trk_param_fpga); channel_ = 0; @@ -178,9 +204,12 @@ GalileoE1DllPllVemlTrackingFpga::GalileoE1DllPllVemlTrackingFpga( GalileoE1DllPllVemlTrackingFpga::~GalileoE1DllPllVemlTrackingFpga() { delete[] d_ca_codes; - delete[] d_data_codes; -} + if (d_track_pilot) + { + delete[] d_data_codes; + } +} void GalileoE1DllPllVemlTrackingFpga::start_tracking() { diff --git a/src/algorithms/tracking/adapters/galileo_e1_dll_pll_veml_tracking_fpga.h b/src/algorithms/tracking/adapters/galileo_e1_dll_pll_veml_tracking_fpga.h index 2290e3e67..794e5596c 100644 --- a/src/algorithms/tracking/adapters/galileo_e1_dll_pll_veml_tracking_fpga.h +++ b/src/algorithms/tracking/adapters/galileo_e1_dll_pll_veml_tracking_fpga.h @@ -66,7 +66,7 @@ public: //! Returns "Galileo_E1_DLL_PLL_VEML_Tracking" inline std::string implementation() override { - return "Galileo_E1_DLL_PLL_VEML_Tracking"; + return "Galileo_E1_DLL_PLL_VEML_Tracking_Fpga"; } inline size_t item_size() override @@ -103,6 +103,8 @@ private: unsigned int out_streams_; int* d_ca_codes; int* d_data_codes; + bool d_track_pilot; + }; diff --git a/src/algorithms/tracking/adapters/galileo_e5a_dll_pll_tracking_fpga.cc b/src/algorithms/tracking/adapters/galileo_e5a_dll_pll_tracking_fpga.cc new file mode 100644 index 000000000..08ae613c6 --- /dev/null +++ b/src/algorithms/tracking/adapters/galileo_e5a_dll_pll_tracking_fpga.cc @@ -0,0 +1,285 @@ +/*! + * \file galileo_e5a_dll_pll_tracking.cc + * \brief Adapts a code DLL + carrier PLL + * tracking block to a TrackingInterface for Galileo E5a signals + * \brief Adapts a PCPS acquisition block to an AcquisitionInterface for + * Galileo E5a data and pilot Signals + * \author Marc Sales, 2014. marcsales92(at)gmail.com + * \based on work from: + *
    + *
  • Javier Arribas, 2011. jarribas(at)cttc.es + *
  • Luis Esteve, 2012. luis(at)epsilon-formacion.com + *
+ * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors) + * + * GNSS-SDR is a software defined Global Navigation + * Satellite Systems receiver + * + * This file is part of GNSS-SDR. + * + * GNSS-SDR is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GNSS-SDR is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNSS-SDR. If not, see . + * + * ------------------------------------------------------------------------- + */ + +#include "galileo_e5a_dll_pll_tracking_fpga.h" +#include "configuration_interface.h" +#include "Galileo_E5a.h" +#include "galileo_e5_signal_processing.h" +#include "gnss_sdr_flags.h" +#include "display.h" +#include + +using google::LogMessage; + +GalileoE5aDllPllTrackingFpga::GalileoE5aDllPllTrackingFpga( + ConfigurationInterface* configuration, std::string role, + unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams) +{ + dllpllconf_fpga_t trk_param_fpga; + DLOG(INFO) << "role " << role; + //################# CONFIGURATION PARAMETERS ######################## + std::string default_item_type = "gr_complex"; + std::string item_type = configuration->property(role + ".item_type", default_item_type); + int fs_in_deprecated = configuration->property("GNSS-SDR.internal_fs_hz", 12000000); + int fs_in = configuration->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated); + trk_param_fpga.fs_in = fs_in; + bool dump = configuration->property(role + ".dump", false); + trk_param_fpga.dump = dump; + float pll_bw_hz = configuration->property(role + ".pll_bw_hz", 20.0); + if (FLAGS_pll_bw_hz != 0.0) pll_bw_hz = static_cast(FLAGS_pll_bw_hz); + trk_param_fpga.pll_bw_hz = pll_bw_hz; + float dll_bw_hz = configuration->property(role + ".dll_bw_hz", 20.0); + if (FLAGS_dll_bw_hz != 0.0) dll_bw_hz = static_cast(FLAGS_dll_bw_hz); + trk_param_fpga.dll_bw_hz = dll_bw_hz; + float pll_bw_narrow_hz = configuration->property(role + ".pll_bw_narrow_hz", 5.0); + trk_param_fpga.pll_bw_narrow_hz = pll_bw_narrow_hz; + float dll_bw_narrow_hz = configuration->property(role + ".dll_bw_narrow_hz", 2.0); + trk_param_fpga.dll_bw_narrow_hz = dll_bw_narrow_hz; + float early_late_space_chips = configuration->property(role + ".early_late_space_chips", 0.5); + trk_param_fpga.early_late_space_chips = early_late_space_chips; + std::string default_dump_filename = "./track_ch"; + std::string dump_filename = configuration->property(role + ".dump_filename", default_dump_filename); + trk_param_fpga.dump_filename = dump_filename; + int vector_length = std::round(fs_in / (Galileo_E5a_CODE_CHIP_RATE_HZ / Galileo_E5a_CODE_LENGTH_CHIPS)); + trk_param_fpga.vector_length = vector_length; + int extend_correlation_symbols = configuration->property(role + ".extend_correlation_symbols", 1); + float early_late_space_narrow_chips = configuration->property(role + ".early_late_space_narrow_chips", 0.15); + trk_param_fpga.early_late_space_narrow_chips = early_late_space_narrow_chips; + bool track_pilot = configuration->property(role + ".track_pilot", false); + d_track_pilot = track_pilot; + if (extend_correlation_symbols < 1) + { + extend_correlation_symbols = 1; + std::cout << TEXT_RED << "WARNING: Galileo E5a. extend_correlation_symbols must be bigger than 0. Coherent integration has been set to 1 symbol (1 ms)" << TEXT_RESET << std::endl; + } + else if (!track_pilot and extend_correlation_symbols > Galileo_E5a_I_SECONDARY_CODE_LENGTH) + { + extend_correlation_symbols = Galileo_E5a_I_SECONDARY_CODE_LENGTH; + std::cout << TEXT_RED << "WARNING: Galileo E5a. extend_correlation_symbols must be lower than 21 when tracking the data component. Coherent integration has been set to 20 symbols (20 ms)" << TEXT_RESET << std::endl; + } + if ((extend_correlation_symbols > 1) and (pll_bw_narrow_hz > pll_bw_hz or dll_bw_narrow_hz > dll_bw_hz)) + { + std::cout << TEXT_RED << "WARNING: Galileo E5a. PLL or DLL narrow tracking bandwidth is higher than wide tracking one" << TEXT_RESET << std::endl; + } + trk_param_fpga.extend_correlation_symbols = extend_correlation_symbols; + trk_param_fpga.track_pilot = track_pilot; + trk_param_fpga.very_early_late_space_chips = 0.0; + trk_param_fpga.very_early_late_space_narrow_chips = 0.0; + trk_param_fpga.system = 'E'; + char sig_[3] = "5X"; + std::memcpy(trk_param_fpga.signal, sig_, 3); + int cn0_samples = configuration->property(role + ".cn0_samples", 20); + if (FLAGS_cn0_samples != 20) cn0_samples = FLAGS_cn0_samples; + trk_param_fpga.cn0_samples = cn0_samples; + int cn0_min = configuration->property(role + ".cn0_min", 25); + if (FLAGS_cn0_min != 25) cn0_min = FLAGS_cn0_min; + trk_param_fpga.cn0_min = cn0_min; + int max_lock_fail = configuration->property(role + ".max_lock_fail", 50); + if (FLAGS_max_lock_fail != 50) max_lock_fail = FLAGS_max_lock_fail; + trk_param_fpga.max_lock_fail = max_lock_fail; + double carrier_lock_th = configuration->property(role + ".carrier_lock_th", 0.85); + if (FLAGS_carrier_lock_th != 0.85) carrier_lock_th = FLAGS_carrier_lock_th; + trk_param_fpga.carrier_lock_th = carrier_lock_th; + + // FPGA configuration parameters + std::string default_device_name = "/dev/uio"; + std::string device_name = configuration->property(role + ".devicename", default_device_name); + trk_param_fpga.device_name = device_name; + unsigned int device_base = configuration->property(role + ".device_base", 1); + trk_param_fpga.device_base = device_base; + //unsigned int multicorr_type = configuration->property(role + ".multicorr_type", 1); + trk_param_fpga.multicorr_type = 1; // 0 -> 3 correlators, 1 -> 5 correlators + + //################# PRE-COMPUTE ALL THE CODES ################# + unsigned int code_samples_per_chip = 1; + unsigned int code_length_chips = static_cast(Galileo_E5a_CODE_LENGTH_CHIPS); + + gr_complex *aux_code = static_cast(volk_gnsssdr_malloc(sizeof(gr_complex) * code_length_chips * code_samples_per_chip, volk_gnsssdr_get_alignment())); + + float *tracking_code; + float *data_code; + + if (trk_param_fpga.track_pilot) + { + data_code = static_cast(volk_gnsssdr_malloc(code_samples_per_chip * code_length_chips * sizeof(float), volk_gnsssdr_get_alignment())); + } + tracking_code = static_cast(volk_gnsssdr_malloc(code_samples_per_chip * code_length_chips * sizeof(float), volk_gnsssdr_get_alignment())); + + d_ca_codes = static_cast(volk_gnsssdr_malloc(static_cast(code_length_chips)* code_samples_per_chip * Galileo_E5a_NUMBER_OF_CODES * sizeof(int), volk_gnsssdr_get_alignment())); + + if (trk_param_fpga.track_pilot) + { + d_data_codes = static_cast(volk_gnsssdr_malloc((static_cast(code_length_chips)) * code_samples_per_chip * Galileo_E5a_NUMBER_OF_CODES * sizeof(int), volk_gnsssdr_get_alignment())); + } + + + for (unsigned int PRN = 1; PRN <= Galileo_E5a_NUMBER_OF_CODES; PRN++) + { + + + + //galileo_e5_a_code_gen_complex_primary(aux_code, PRN, const_cast(trk_param_fpga.signal.c_str())); + galileo_e5_a_code_gen_complex_primary(aux_code, PRN, const_cast(sig_)); + if (trk_param_fpga.track_pilot) + { + //d_secondary_code_string = const_cast(&Galileo_E5a_Q_SECONDARY_CODE[PRN - 1]); + for (unsigned int i = 0; i < code_length_chips; i++) + { + tracking_code[i] = aux_code[i].imag(); + data_code[i] = aux_code[i].real(); + } + for (unsigned int s = 0; s < code_length_chips; s++) + { + d_ca_codes[static_cast(code_length_chips) * (PRN - 1) + s] = static_cast(tracking_code[s]); + d_data_codes[static_cast(code_length_chips) * (PRN - 1) + s] = static_cast(data_code[s]); + //printf("%f %d | ", data_codes_f[s], d_data_codes[static_cast(Galileo_E1_B_CODE_LENGTH_CHIPS)* 2 * (PRN - 1) + s]); + + } + + } + else + { + for (unsigned int i = 0; i < code_length_chips; i++) + { + tracking_code[i] = aux_code[i].real(); + } + + for (unsigned int s = 0; s < code_length_chips; s++) + { + d_ca_codes[static_cast(code_length_chips)* (PRN - 1) + s] = static_cast(tracking_code[s]); + //printf("%f %d | ", ca_codes_f[s], d_ca_codes[static_cast(Galileo_E1_B_CODE_LENGTH_CHIPS)* 2 * (PRN - 1) + s]); + } + + } + + + } + + volk_gnsssdr_free(aux_code); + volk_gnsssdr_free(tracking_code); + if (trk_param_fpga.track_pilot) + { + volk_gnsssdr_free(data_code); + } + trk_param_fpga.ca_codes = d_ca_codes; + trk_param_fpga.data_codes = d_data_codes; + trk_param_fpga.code_length_chips = code_length_chips; + trk_param_fpga.code_samples_per_chip = code_samples_per_chip; // 2 sample per chip + //################# MAKE TRACKING GNURadio object ################### +// if (item_type.compare("gr_complex") == 0) +// { +// item_size_ = sizeof(gr_complex); +// tracking_ = dll_pll_veml_make_tracking(trk_param_fpga); +// } +// else +// { +// item_size_ = sizeof(gr_complex); +// LOG(WARNING) << item_type << " unknown tracking item type."; +// } + channel_ = 0; + //DLOG(INFO) << "tracking(" << tracking_->unique_id() << ")"; + DLOG(INFO) << "tracking(" << tracking_fpga_sc->unique_id() << ")"; +} + + +GalileoE5aDllPllTrackingFpga::~GalileoE5aDllPllTrackingFpga() +{ + delete[] d_ca_codes; + if (d_track_pilot) + { + delete[] d_data_codes; + + } +} + + +void GalileoE5aDllPllTrackingFpga::start_tracking() +{ + //tracking_->start_tracking(); + tracking_fpga_sc->start_tracking(); +} + + +/* + * Set tracking channel unique ID + */ +void GalileoE5aDllPllTrackingFpga::set_channel(unsigned int channel) +{ + channel_ = channel; + //tracking_->set_channel(channel); + tracking_fpga_sc->set_channel(channel); +} + + +void GalileoE5aDllPllTrackingFpga::set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) +{ + //tracking_->set_gnss_synchro(p_gnss_synchro); + tracking_fpga_sc->set_gnss_synchro(p_gnss_synchro); +} + + +void GalileoE5aDllPllTrackingFpga::connect(gr::top_block_sptr top_block) +{ + if (top_block) + { /* top_block is not null */ + }; + //nothing to connect, now the tracking uses gr_sync_decimator +} + + +void GalileoE5aDllPllTrackingFpga::disconnect(gr::top_block_sptr top_block) +{ + if (top_block) + { /* top_block is not null */ + }; + //nothing to disconnect, now the tracking uses gr_sync_decimator +} + + +gr::basic_block_sptr GalileoE5aDllPllTrackingFpga::get_left_block() +{ + //return tracking_; + return tracking_fpga_sc; +} + + +gr::basic_block_sptr GalileoE5aDllPllTrackingFpga::get_right_block() +{ + //return tracking_; + return tracking_fpga_sc; +} diff --git a/src/algorithms/tracking/adapters/galileo_e5a_dll_pll_tracking_fpga.h b/src/algorithms/tracking/adapters/galileo_e5a_dll_pll_tracking_fpga.h new file mode 100644 index 000000000..8dce1b428 --- /dev/null +++ b/src/algorithms/tracking/adapters/galileo_e5a_dll_pll_tracking_fpga.h @@ -0,0 +1,110 @@ +/*! + * \file galileo_e5a_dll_pll_tracking.h + * \brief Adapts a code DLL + carrier PLL + * tracking block to a TrackingInterface for Galileo E5a signals + * \brief Adapts a PCPS acquisition block to an AcquisitionInterface for + * Galileo E5a data and pilot Signals + * \author Marc Sales, 2014. marcsales92(at)gmail.com + * \based on work from: + *
    + *
  • Javier Arribas, 2011. jarribas(at)cttc.es + *
  • Luis Esteve, 2012. luis(at)epsilon-formacion.com + *
+ * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors) + * + * GNSS-SDR is a software defined Global Navigation + * Satellite Systems receiver + * + * This file is part of GNSS-SDR. + * + * GNSS-SDR is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GNSS-SDR is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNSS-SDR. If not, see . + * + * ------------------------------------------------------------------------- + */ + +#ifndef GNSS_SDR_GALILEO_E5A_DLL_PLL_TRACKING_FPGA_H_ +#define GNSS_SDR_GALILEO_E5A_DLL_PLL_TRACKING_FPGA_H_ + +#include "tracking_interface.h" +#include "dll_pll_veml_tracking_fpga.h" +#include + +class ConfigurationInterface; + +/*! + * \brief This class implements a code DLL + carrier PLL tracking loop + */ +class GalileoE5aDllPllTrackingFpga : public TrackingInterface +{ +public: + GalileoE5aDllPllTrackingFpga(ConfigurationInterface* configuration, + std::string role, + unsigned int in_streams, + unsigned int out_streams); + + virtual ~GalileoE5aDllPllTrackingFpga(); + + inline std::string role() override + { + return role_; + } + + //! Returns "Galileo_E5a_DLL_PLL_Tracking" + inline std::string implementation() override + { + return "Galileo_E5a_DLL_PLL_Tracking"; + } + + inline size_t item_size() override + { + return item_size_; + } + + void connect(gr::top_block_sptr top_block) override; + void disconnect(gr::top_block_sptr top_block) override; + gr::basic_block_sptr get_left_block() override; + gr::basic_block_sptr get_right_block() override; + + /*! + * \brief Set tracking channel unique ID + */ + void set_channel(unsigned int channel) override; + + /*! + * \brief Set acquisition/tracking common Gnss_Synchro object pointer + * to efficiently exchange synchronization data between acquisition and tracking blocks + */ + void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) override; + + void start_tracking() override; + +private: + dll_pll_veml_tracking_fpga_sptr tracking_fpga_sc; + size_t item_size_; + unsigned int channel_; + std::string role_; + unsigned int in_streams_; + unsigned int out_streams_; + + + int* d_ca_codes; + int* d_data_codes; + bool d_track_pilot; + +}; + +#endif /* GNSS_SDR_GALILEO_E5A_DLL_PLL_TRACKING_FPGA_H_ */ diff --git a/src/algorithms/tracking/adapters/gps_l1_ca_dll_pll_tracking_fpga.cc b/src/algorithms/tracking/adapters/gps_l1_ca_dll_pll_tracking_fpga.cc index 3f0a4cd98..70b1b290e 100644 --- a/src/algorithms/tracking/adapters/gps_l1_ca_dll_pll_tracking_fpga.cc +++ b/src/algorithms/tracking/adapters/gps_l1_ca_dll_pll_tracking_fpga.cc @@ -129,6 +129,8 @@ GpsL1CaDllPllTrackingFpga::GpsL1CaDllPllTrackingFpga( trk_param_fpga.device_name = device_name; unsigned int device_base = configuration->property(role + ".device_base", 1); trk_param_fpga.device_base = device_base; + //unsigned int multicorr_type = configuration->property(role + ".multicorr_type", 0); + trk_param_fpga.multicorr_type = 0; //multicorr_type : 0 -> 3 correlators, 1 -> 5 correlators //################# PRE-COMPUTE ALL THE CODES ################# d_ca_codes = static_cast(volk_gnsssdr_malloc(static_cast(GPS_L1_CA_CODE_LENGTH_CHIPS*NUM_PRNs) * sizeof(int), volk_gnsssdr_get_alignment())); @@ -137,7 +139,8 @@ GpsL1CaDllPllTrackingFpga::GpsL1CaDllPllTrackingFpga( gps_l1_ca_code_gen_int(&d_ca_codes[(int(GPS_L1_CA_CODE_LENGTH_CHIPS)) * (PRN - 1)], PRN, 0); } trk_param_fpga.ca_codes = d_ca_codes; - trk_param_fpga.code_length = GPS_L1_CA_CODE_LENGTH_CHIPS; + trk_param_fpga.code_length_chips = GPS_L1_CA_CODE_LENGTH_CHIPS; + trk_param_fpga.code_samples_per_chip = 1; // 1 sample per chip //################# MAKE TRACKING GNURadio object ################### tracking_fpga_sc = dll_pll_veml_make_tracking_fpga(trk_param_fpga); diff --git a/src/algorithms/tracking/adapters/gps_l2_m_dll_pll_tracking_fpga.cc b/src/algorithms/tracking/adapters/gps_l2_m_dll_pll_tracking_fpga.cc new file mode 100644 index 000000000..862d21590 --- /dev/null +++ b/src/algorithms/tracking/adapters/gps_l2_m_dll_pll_tracking_fpga.cc @@ -0,0 +1,223 @@ +/*! + * \file gps_l2_m_dll_pll_tracking.cc + * \brief Implementation of an adapter of a DLL+PLL tracking loop block + * for GPS L1 C/A to a TrackingInterface + * \author Javier Arribas, 2015. jarribas(at)cttc.es + * + * Code DLL + carrier PLL according to the algorithms described in: + * K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen, + * A Software-Defined GPS and Galileo Receiver. A Single-Frequency + * Approach, Birkhauser, 2007 + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors) + * + * GNSS-SDR is a software defined Global Navigation + * Satellite Systems receiver + * + * This file is part of GNSS-SDR. + * + * GNSS-SDR is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GNSS-SDR is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNSS-SDR. If not, see . + * + * ------------------------------------------------------------------------- + */ + + +#include "gps_l2_m_dll_pll_tracking_fpga.h" +#include "configuration_interface.h" +#include "GPS_L2C.h" +#include "gps_l2c_signal.h" +#include "gnss_sdr_flags.h" +#include "display.h" +#include + +#define NUM_PRNs 32 + +using google::LogMessage; + +GpsL2MDllPllTrackingFpga::GpsL2MDllPllTrackingFpga( + ConfigurationInterface* configuration, std::string role, + unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams) +{ + //dllpllconf_t trk_param; + dllpllconf_fpga_t trk_param_fpga; + DLOG(INFO) << "role " << role; + //################# CONFIGURATION PARAMETERS ######################## + //std::string default_item_type = "gr_complex"; + //std::string item_type = configuration->property(role + ".item_type", default_item_type); + int fs_in_deprecated = configuration->property("GNSS-SDR.internal_fs_hz", 2048000); + int fs_in = configuration->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated); + trk_param_fpga.fs_in = fs_in; + bool dump = configuration->property(role + ".dump", false); + trk_param_fpga.dump = dump; + float pll_bw_hz = configuration->property(role + ".pll_bw_hz", 2.0); + if (FLAGS_pll_bw_hz != 0.0) pll_bw_hz = static_cast(FLAGS_pll_bw_hz); + trk_param_fpga.pll_bw_hz = pll_bw_hz; + float dll_bw_hz = configuration->property(role + ".dll_bw_hz", 0.75); + if (FLAGS_dll_bw_hz != 0.0) dll_bw_hz = static_cast(FLAGS_dll_bw_hz); + trk_param_fpga.dll_bw_hz = dll_bw_hz; + float early_late_space_chips = configuration->property(role + ".early_late_space_chips", 0.5); + trk_param_fpga.early_late_space_chips = early_late_space_chips; + trk_param_fpga.early_late_space_narrow_chips = 0.0; + std::string default_dump_filename = "./track_ch"; + std::string dump_filename = configuration->property(role + ".dump_filename", default_dump_filename); + trk_param_fpga.dump_filename = dump_filename; + int vector_length = std::round(static_cast(fs_in) / (static_cast(GPS_L2_M_CODE_RATE_HZ) / static_cast(GPS_L2_M_CODE_LENGTH_CHIPS))); + trk_param_fpga.vector_length = vector_length; + int symbols_extended_correlator = configuration->property(role + ".extend_correlation_symbols", 1); + if (symbols_extended_correlator != 1) + { + std::cout << TEXT_RED << "WARNING: Extended coherent integration is not allowed in GPS L2. Coherent integration has been set to 20 ms (1 symbol)" << TEXT_RESET << std::endl; + } + trk_param_fpga.extend_correlation_symbols = 1; + bool track_pilot = configuration->property(role + ".track_pilot", false); + if (track_pilot) + { + std::cout << TEXT_RED << "WARNING: GPS L2 does not have pilot signal. Data tracking has been enabled" << TEXT_RESET << std::endl; + } + trk_param_fpga.track_pilot = false; + trk_param_fpga.very_early_late_space_chips = 0.0; + trk_param_fpga.very_early_late_space_narrow_chips = 0.0; + trk_param_fpga.pll_bw_narrow_hz = 0.0; + trk_param_fpga.dll_bw_narrow_hz = 0.0; + trk_param_fpga.system = 'G'; + char sig_[3] = "2S"; + std::memcpy(trk_param_fpga.signal, sig_, 3); + int cn0_samples = configuration->property(role + ".cn0_samples", 20); + if (FLAGS_cn0_samples != 20) cn0_samples = FLAGS_cn0_samples; + trk_param_fpga.cn0_samples = cn0_samples; + int cn0_min = configuration->property(role + ".cn0_min", 25); + if (FLAGS_cn0_min != 25) cn0_min = FLAGS_cn0_min; + trk_param_fpga.cn0_min = cn0_min; + int max_lock_fail = configuration->property(role + ".max_lock_fail", 50); + if (FLAGS_max_lock_fail != 50) max_lock_fail = FLAGS_max_lock_fail; + trk_param_fpga.max_lock_fail = max_lock_fail; + double carrier_lock_th = configuration->property(role + ".carrier_lock_th", 0.85); + if (FLAGS_carrier_lock_th != 0.85) carrier_lock_th = FLAGS_carrier_lock_th; + trk_param_fpga.carrier_lock_th = carrier_lock_th; + + // FPGA configuration parameters + std::string default_device_name = "/dev/uio"; + std::string device_name = configuration->property(role + ".devicename", default_device_name); + trk_param_fpga.device_name = device_name; + unsigned int device_base = configuration->property(role + ".device_base", 1); + trk_param_fpga.device_base = device_base; + //unsigned int multicorr_type = configuration->property(role + ".multicorr_type", 0); + trk_param_fpga.multicorr_type = 0; //multicorr_type : 0 -> 3 correlators, 1 -> 5 correlators + + //d_tracking_code = static_cast(volk_gnsssdr_malloc(2 * static_cast(GPS_L2_M_CODE_LENGTH_CHIPS) * sizeof(float), volk_gnsssdr_get_alignment())); + d_ca_codes = static_cast(volk_gnsssdr_malloc(static_cast(GPS_L2_M_CODE_LENGTH_CHIPS)* NUM_PRNs * sizeof(int), volk_gnsssdr_get_alignment())); + float* ca_codes_f = static_cast(volk_gnsssdr_malloc(static_cast(GPS_L2_M_CODE_LENGTH_CHIPS)* sizeof(float), volk_gnsssdr_get_alignment())); + + //################# PRE-COMPUTE ALL THE CODES ################# + d_ca_codes = static_cast(volk_gnsssdr_malloc(static_cast(GPS_L2_M_CODE_LENGTH_CHIPS*NUM_PRNs) * sizeof(int), volk_gnsssdr_get_alignment())); + for (unsigned int PRN = 1; PRN <= NUM_PRNs; PRN++) + { + //gps_l1_ca_code_gen_int(&d_ca_codes[(int(GPS_L1_CA_CODE_LENGTH_CHIPS)) * (PRN - 1)], PRN, 0); + gps_l2c_m_code_gen_float(ca_codes_f, PRN); + for (unsigned int s = 0; s < 2*static_cast(GPS_L2_M_CODE_LENGTH_CHIPS); s++) + { + d_ca_codes[static_cast(GPS_L2_M_CODE_LENGTH_CHIPS)* (PRN - 1) + s] = static_cast(ca_codes_f[s]); + } + } + + delete[] ca_codes_f; + + trk_param_fpga.ca_codes = d_ca_codes; + trk_param_fpga.code_length_chips = GPS_L2_M_CODE_LENGTH_CHIPS; + trk_param_fpga.code_samples_per_chip = 1; // 1 sample per chip + + //################# MAKE TRACKING GNURadio object ################### + +// //################# MAKE TRACKING GNURadio object ################### +// if (item_type.compare("gr_complex") == 0) +// { +// item_size_ = sizeof(gr_complex); +// tracking_ = dll_pll_veml_make_tracking(trk_param); +// } +// else +// { +// item_size_ = sizeof(gr_complex); +// LOG(WARNING) << item_type << " unknown tracking item type."; +// } + + //################# MAKE TRACKING GNURadio object ################### + tracking_fpga_sc = dll_pll_veml_make_tracking_fpga(trk_param_fpga); + + channel_ = 0; + DLOG(INFO) << "tracking(" << tracking_fpga_sc->unique_id() << ")"; +} + + +GpsL2MDllPllTrackingFpga::~GpsL2MDllPllTrackingFpga() +{ +} + + +void GpsL2MDllPllTrackingFpga::start_tracking() +{ + //tracking_->start_tracking(); + tracking_fpga_sc->start_tracking(); +} + + +/* + * Set tracking channel unique ID + */ +void GpsL2MDllPllTrackingFpga::set_channel(unsigned int channel) +{ + channel_ = channel; + //tracking_->set_channel(channel); + tracking_fpga_sc->set_channel(channel); +} + + +void GpsL2MDllPllTrackingFpga::set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) +{ + //tracking_->set_gnss_synchro(p_gnss_synchro); + tracking_fpga_sc->set_gnss_synchro(p_gnss_synchro); +} + + +void GpsL2MDllPllTrackingFpga::connect(gr::top_block_sptr top_block) +{ + if (top_block) + { /* top_block is not null */ + }; + //nothing to connect, now the tracking uses gr_sync_decimator +} + + +void GpsL2MDllPllTrackingFpga::disconnect(gr::top_block_sptr top_block) +{ + if (top_block) + { /* top_block is not null */ + }; + //nothing to disconnect, now the tracking uses gr_sync_decimator +} + + +gr::basic_block_sptr GpsL2MDllPllTrackingFpga::get_left_block() +{ + //return tracking_; + return tracking_fpga_sc; +} + + +gr::basic_block_sptr GpsL2MDllPllTrackingFpga::get_right_block() +{ + //return tracking_; + return tracking_fpga_sc; +} diff --git a/src/algorithms/tracking/adapters/gps_l2_m_dll_pll_tracking_fpga.h b/src/algorithms/tracking/adapters/gps_l2_m_dll_pll_tracking_fpga.h new file mode 100644 index 000000000..d4dde0713 --- /dev/null +++ b/src/algorithms/tracking/adapters/gps_l2_m_dll_pll_tracking_fpga.h @@ -0,0 +1,106 @@ +/*! + * \file gps_l2_m_dll_pll_tracking.h + * \brief Interface of an adapter of a DLL+PLL tracking loop block + * for GPS L1 C/A to a TrackingInterface + * \author Carlos Aviles, 2010. carlos.avilesr(at)googlemail.com + * Javier Arribas, 2011. jarribas(at)cttc.es + * + * Code DLL + carrier PLL according to the algorithms described in: + * K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen, + * A Software-Defined GPS and Galileo Receiver. A Single-Frequency + * Approach, Birkhauser, 2007 + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors) + * + * GNSS-SDR is a software defined Global Navigation + * Satellite Systems receiver + * + * This file is part of GNSS-SDR. + * + * GNSS-SDR is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GNSS-SDR is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNSS-SDR. If not, see . + * + * ------------------------------------------------------------------------- + */ + +#ifndef GNSS_SDR_gps_l2_m_dll_pll_tracking_FPGA_H_ +#define GNSS_SDR_gps_l2_m_dll_pll_tracking_FPGA_H_ + +#include "tracking_interface.h" +//#include "dll_pll_veml_tracking.h" +#include "dll_pll_veml_tracking_fpga.h" +#include + +class ConfigurationInterface; + +/*! + * \brief This class implements a code DLL + carrier PLL tracking loop + */ +class GpsL2MDllPllTrackingFpga : public TrackingInterface +{ +public: + GpsL2MDllPllTrackingFpga(ConfigurationInterface* configuration, + std::string role, + unsigned int in_streams, + unsigned int out_streams); + + virtual ~GpsL2MDllPllTrackingFpga(); + + inline std::string role() override + { + return role_; + } + + //! Returns "GPS_L2_M_DLL_PLL_Tracking" + inline std::string implementation() override + { + return "GPS_L2_M_DLL_PLL_Tracking_Fpga"; + } + + inline size_t item_size() override + { + return item_size_; + } + + void connect(gr::top_block_sptr top_block) override; + void disconnect(gr::top_block_sptr top_block) override; + gr::basic_block_sptr get_left_block() override; + gr::basic_block_sptr get_right_block() override; + + /*! + * \brief Set tracking channel unique ID + */ + void set_channel(unsigned int channel) override; + + /*! + * \brief Set acquisition/tracking common Gnss_Synchro object pointer + * to efficiently exchange synchronization data between acquisition and tracking blocks + */ + void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) override; + + void start_tracking() override; + +private: + //dll_pll_veml_tracking_sptr tracking_; + dll_pll_veml_tracking_fpga_sptr tracking_fpga_sc; + size_t item_size_; + unsigned int channel_; + std::string role_; + unsigned int in_streams_; + unsigned int out_streams_; + int* d_ca_codes; +}; + +#endif // GNSS_SDR_gps_l2_m_dll_pll_tracking_FPGA_H_ diff --git a/src/algorithms/tracking/adapters/gps_l5_dll_pll_tracking_fpga.cc b/src/algorithms/tracking/adapters/gps_l5_dll_pll_tracking_fpga.cc new file mode 100644 index 000000000..f9b318869 --- /dev/null +++ b/src/algorithms/tracking/adapters/gps_l5_dll_pll_tracking_fpga.cc @@ -0,0 +1,268 @@ +/*! + * \file gps_l5_dll_pll_tracking.cc + * \brief Interface of an adapter of a DLL+PLL tracking loop block + * for GPS L5 to a TrackingInterface + * \author Javier Arribas, 2017. jarribas(at)cttc.es + * + * Code DLL + carrier PLL according to the algorithms described in: + * K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen, + * A Software-Defined GPS and Galileo Receiver. A Single-Frequency + * Approach, Birkhauser, 2007 + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors) + * + * GNSS-SDR is a software defined Global Navigation + * Satellite Systems receiver + * + * This file is part of GNSS-SDR. + * + * GNSS-SDR is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GNSS-SDR is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNSS-SDR. If not, see . + * + * ------------------------------------------------------------------------- + */ + + +#include "gps_l5_dll_pll_tracking_fpga.h" +#include "configuration_interface.h" +#include "GPS_L5.h" +#include "gps_l5_signal.h" +#include "gnss_sdr_flags.h" +#include "display.h" +#include + +#define NUM_PRNs 32 + +using google::LogMessage; + +GpsL5DllPllTrackingFpga::GpsL5DllPllTrackingFpga( + ConfigurationInterface* configuration, std::string role, + unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams) +{ + //dllpllconf_t trk_param; + dllpllconf_fpga_t trk_param_fpga; + DLOG(INFO) << "role " << role; + //################# CONFIGURATION PARAMETERS ######################## + //std::string default_item_type = "gr_complex"; + //std::string item_type = configuration->property(role + ".item_type", default_item_type); + int fs_in_deprecated = configuration->property("GNSS-SDR.internal_fs_hz", 2048000); + int fs_in = configuration->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated); + trk_param_fpga.fs_in = fs_in; + bool dump = configuration->property(role + ".dump", false); + trk_param_fpga.dump = dump; + float pll_bw_hz = configuration->property(role + ".pll_bw_hz", 50.0); + if (FLAGS_pll_bw_hz != 0.0) pll_bw_hz = static_cast(FLAGS_pll_bw_hz); + trk_param_fpga.pll_bw_hz = pll_bw_hz; + float dll_bw_hz = configuration->property(role + ".dll_bw_hz", 2.0); + if (FLAGS_dll_bw_hz != 0.0) dll_bw_hz = static_cast(FLAGS_dll_bw_hz); + trk_param_fpga.dll_bw_hz = dll_bw_hz; + float pll_bw_narrow_hz = configuration->property(role + ".pll_bw_narrow_hz", 2.0); + trk_param_fpga.pll_bw_narrow_hz = pll_bw_narrow_hz; + float dll_bw_narrow_hz = configuration->property(role + ".dll_bw_narrow_hz", 0.25); + trk_param_fpga.dll_bw_narrow_hz = dll_bw_narrow_hz; + float early_late_space_chips = configuration->property(role + ".early_late_space_chips", 0.5); + trk_param_fpga.early_late_space_chips = early_late_space_chips; + std::string default_dump_filename = "./track_ch"; + std::string dump_filename = configuration->property(role + ".dump_filename", default_dump_filename); + trk_param_fpga.dump_filename = dump_filename; + int vector_length = std::round(static_cast(fs_in) / (static_cast(GPS_L5i_CODE_RATE_HZ) / static_cast(GPS_L5i_CODE_LENGTH_CHIPS))); + trk_param_fpga.vector_length = vector_length; + int extend_correlation_symbols = configuration->property(role + ".extend_correlation_symbols", 1); + float early_late_space_narrow_chips = configuration->property(role + ".early_late_space_narrow_chips", 0.15); + trk_param_fpga.early_late_space_narrow_chips = early_late_space_narrow_chips; + bool track_pilot = configuration->property(role + ".track_pilot", false); + if (extend_correlation_symbols < 1) + { + extend_correlation_symbols = 1; + std::cout << TEXT_RED << "WARNING: GPS L5. extend_correlation_symbols must be bigger than 0. Coherent integration has been set to 1 symbol (1 ms)" << TEXT_RESET << std::endl; + } + else if (!track_pilot and extend_correlation_symbols > GPS_L5i_NH_CODE_LENGTH) + { + extend_correlation_symbols = GPS_L5i_NH_CODE_LENGTH; + std::cout << TEXT_RED << "WARNING: GPS L5. extend_correlation_symbols must be lower than 11 when tracking the data component. Coherent integration has been set to 10 symbols (10 ms)" << TEXT_RESET << std::endl; + } + if ((extend_correlation_symbols > 1) and (pll_bw_narrow_hz > pll_bw_hz or dll_bw_narrow_hz > dll_bw_hz)) + { + std::cout << TEXT_RED << "WARNING: GPS L5. PLL or DLL narrow tracking bandwidth is higher than wide tracking one" << TEXT_RESET << std::endl; + } + trk_param_fpga.extend_correlation_symbols = extend_correlation_symbols; + trk_param_fpga.track_pilot = track_pilot; + d_track_pilot = track_pilot; + trk_param_fpga.very_early_late_space_chips = 0.0; + trk_param_fpga.very_early_late_space_narrow_chips = 0.0; + trk_param_fpga.system = 'G'; + char sig_[3] = "L5"; + std::memcpy(trk_param_fpga.signal, sig_, 3); + int cn0_samples = configuration->property(role + ".cn0_samples", 20); + if (FLAGS_cn0_samples != 20) cn0_samples = FLAGS_cn0_samples; + trk_param_fpga.cn0_samples = cn0_samples; + int cn0_min = configuration->property(role + ".cn0_min", 25); + if (FLAGS_cn0_min != 25) cn0_min = FLAGS_cn0_min; + trk_param_fpga.cn0_min = cn0_min; + int max_lock_fail = configuration->property(role + ".max_lock_fail", 50); + if (FLAGS_max_lock_fail != 50) max_lock_fail = FLAGS_max_lock_fail; + trk_param_fpga.max_lock_fail = max_lock_fail; + double carrier_lock_th = configuration->property(role + ".carrier_lock_th", 0.85); + if (FLAGS_carrier_lock_th != 0.85) carrier_lock_th = FLAGS_carrier_lock_th; + trk_param_fpga.carrier_lock_th = carrier_lock_th; + + // FPGA configuration parameters + std::string default_device_name = "/dev/uio"; + std::string device_name = configuration->property(role + ".devicename", default_device_name); + trk_param_fpga.device_name = device_name; + unsigned int device_base = configuration->property(role + ".device_base", 1); + trk_param_fpga.device_base = device_base; + //unsigned int multicorr_type = configuration->property(role + ".multicorr_type", 0); + trk_param_fpga.multicorr_type = 0; //multicorr_type : 0 -> 3 correlators, 1 -> 5 correlators + + //################# PRE-COMPUTE ALL THE CODES ################# + unsigned int code_samples_per_chip = 1; + unsigned int code_length_chips = static_cast(GPS_L5i_CODE_LENGTH_CHIPS); + + float *tracking_code; + float *data_code; + + tracking_code = static_cast(volk_gnsssdr_malloc(code_length_chips * sizeof(float), volk_gnsssdr_get_alignment())); + + if (trk_param_fpga.track_pilot) + { + data_code = static_cast(volk_gnsssdr_malloc(code_length_chips * sizeof(float), volk_gnsssdr_get_alignment())); + } + + d_ca_codes = static_cast(volk_gnsssdr_malloc(static_cast(code_length_chips*NUM_PRNs) * sizeof(int), volk_gnsssdr_get_alignment())); + + if (trk_param_fpga.track_pilot) + { + d_data_codes = static_cast(volk_gnsssdr_malloc((static_cast(code_length_chips)) * NUM_PRNs * sizeof(int), volk_gnsssdr_get_alignment())); + } + + for (unsigned int PRN = 1; PRN <= NUM_PRNs; PRN++) + { + if (track_pilot) + { + gps_l5q_code_gen_float(tracking_code, PRN); + gps_l5i_code_gen_float(data_code, PRN); + + + for (unsigned int s = 0; s < 2*code_length_chips; s++) + { + d_ca_codes[static_cast(code_length_chips)* (PRN - 1) + s] = static_cast(tracking_code[s]); + d_data_codes[static_cast(code_length_chips)* (PRN - 1) + s] = static_cast(data_code[s]); + //printf("%f %d | ", data_codes_f[s], d_data_codes[static_cast(Galileo_E1_B_CODE_LENGTH_CHIPS)* 2 * (PRN - 1) + s]); + + } + } + + else + { + gps_l5i_code_gen_float(tracking_code, PRN); + + for (unsigned int s = 0; s < code_length_chips; s++) + { + d_ca_codes[static_cast(code_length_chips) * (PRN - 1) + s] = static_cast(data_code[s]); + //printf("%f %d | ", ca_codes_f[s], d_ca_codes[static_cast(Galileo_E1_B_CODE_LENGTH_CHIPS)* 2 * (PRN - 1) + s]); + } + } + } + + + delete[] tracking_code; + if (trk_param_fpga.track_pilot) + { + delete[] data_code; + } + trk_param_fpga.ca_codes = d_ca_codes; + trk_param_fpga.data_codes = d_data_codes; + trk_param_fpga.code_length_chips = code_length_chips; + trk_param_fpga.code_samples_per_chip = code_samples_per_chip; // 2 sample per chip + //################# MAKE TRACKING GNURadio object ################### +// if (item_type.compare("gr_complex") == 0) +// { +// item_size_ = sizeof(gr_complex); +// tracking_ = dll_pll_veml_make_tracking(trk_param_fpga); +// } +// else +// { +// item_size_ = sizeof(gr_complex); +// LOG(WARNING) << item_type << " unknown tracking item type."; +// } + tracking_fpga_sc = dll_pll_veml_make_tracking_fpga(trk_param_fpga); + channel_ = 0; + DLOG(INFO) << "tracking(" << tracking_fpga_sc->unique_id() << ")"; +} + + +GpsL5DllPllTrackingFpga::~GpsL5DllPllTrackingFpga() +{ + + delete[] d_ca_codes; + if (d_track_pilot) + { + delete[] d_data_codes; + + } +} + + +void GpsL5DllPllTrackingFpga::start_tracking() +{ + tracking_fpga_sc->start_tracking(); +} + + +/* + * Set tracking channel unique ID + */ +void GpsL5DllPllTrackingFpga::set_channel(unsigned int channel) +{ + channel_ = channel; + tracking_fpga_sc->set_channel(channel); +} + + +void GpsL5DllPllTrackingFpga::set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) +{ + tracking_fpga_sc->set_gnss_synchro(p_gnss_synchro); +} + + +void GpsL5DllPllTrackingFpga::connect(gr::top_block_sptr top_block) +{ + if (top_block) + { /* top_block is not null */ + }; + //nothing to connect, now the tracking uses gr_sync_decimator +} + + +void GpsL5DllPllTrackingFpga::disconnect(gr::top_block_sptr top_block) +{ + if (top_block) + { /* top_block is not null */ + }; + //nothing to disconnect, now the tracking uses gr_sync_decimator +} + + +gr::basic_block_sptr GpsL5DllPllTrackingFpga::get_left_block() +{ + return tracking_fpga_sc; +} + + +gr::basic_block_sptr GpsL5DllPllTrackingFpga::get_right_block() +{ + return tracking_fpga_sc; +} diff --git a/src/algorithms/tracking/adapters/gps_l5_dll_pll_tracking_fpga.h b/src/algorithms/tracking/adapters/gps_l5_dll_pll_tracking_fpga.h new file mode 100644 index 000000000..6cb3bc170 --- /dev/null +++ b/src/algorithms/tracking/adapters/gps_l5_dll_pll_tracking_fpga.h @@ -0,0 +1,106 @@ +/*! + * \file gps_l5_dll_pll_tracking.h + * \brief Interface of an adapter of a DLL+PLL tracking loop block + * for GPS L5 to a TrackingInterface + * \author Javier Arribas, 2017. jarribas(at)cttc.es + * + * Code DLL + carrier PLL according to the algorithms described in: + * K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen, + * A Software-Defined GPS and Galileo Receiver. A Single-Frequency + * Approach, Birkhauser, 2007 + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors) + * + * GNSS-SDR is a software defined Global Navigation + * Satellite Systems receiver + * + * This file is part of GNSS-SDR. + * + * GNSS-SDR is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GNSS-SDR is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GNSS-SDR. If not, see . + * + * ------------------------------------------------------------------------- + */ + +#ifndef GNSS_SDR_GPS_L5_DLL_PLL_TRACKING_FPGA_H_ +#define GNSS_SDR_GPS_L5_DLL_PLL_TRACKING_FPGA_H_ + +#include "tracking_interface.h" +#include "dll_pll_veml_tracking_fpga.h" +#include + +class ConfigurationInterface; + +/*! + * \brief This class implements a code DLL + carrier PLL tracking loop + */ +class GpsL5DllPllTrackingFpga : public TrackingInterface +{ +public: + GpsL5DllPllTrackingFpga(ConfigurationInterface* configuration, + std::string role, + unsigned int in_streams, + unsigned int out_streams); + + virtual ~GpsL5DllPllTrackingFpga(); + + inline std::string role() override + { + return role_; + } + + //! Returns "GPS_L5_DLL_PLL_Tracking" + inline std::string implementation() override + { + return "GPS_L5_DLL_PLL_Tracking"; + } + + inline size_t item_size() override + { + return item_size_; + } + + void connect(gr::top_block_sptr top_block) override; + void disconnect(gr::top_block_sptr top_block) override; + gr::basic_block_sptr get_left_block() override; + gr::basic_block_sptr get_right_block() override; + + /*! + * \brief Set tracking channel unique ID + */ + void set_channel(unsigned int channel) override; + + /*! + * \brief Set acquisition/tracking common Gnss_Synchro object pointer + * to efficiently exchange synchronization data between acquisition and tracking blocks + */ + void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) override; + + void start_tracking() override; + +private: + //dll_pll_veml_tracking_sptr tracking_; + dll_pll_veml_tracking_fpga_sptr tracking_fpga_sc; + size_t item_size_; + unsigned int channel_; + std::string role_; + unsigned int in_streams_; + unsigned int out_streams_; + bool d_track_pilot; + int* d_ca_codes; + int* d_data_codes; +}; + +#endif // GNSS_SDR_GPS_L5_DLL_PLL_TRACKING_FPGA_H_ diff --git a/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking_fpga.cc b/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking_fpga.cc index d20e49338..8d54d34b6 100644 --- a/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking_fpga.cc +++ b/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking_fpga.cc @@ -56,6 +56,8 @@ #include #include + + using google::LogMessage; dll_pll_veml_tracking_fpga_sptr dll_pll_veml_make_tracking_fpga(dllpllconf_fpga_t conf_) @@ -93,6 +95,9 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_) signal_pretty_name = map_signal_pretty_name[signal_type]; + + d_prompt_data_shift = nullptr; + if (trk_parameters.system == 'G') { systemName = "GPS"; @@ -103,8 +108,8 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_) d_code_chip_rate = GPS_L1_CA_CODE_RATE_HZ; d_symbols_per_bit = GPS_CA_TELEMETRY_SYMBOLS_PER_BIT; d_correlation_length_ms = 1; - d_code_samples_per_chip = 1; - d_code_length_chips = static_cast(GPS_L1_CA_CODE_LENGTH_CHIPS); + //d_code_samples_per_chip = 1; + //d_code_length_chips = static_cast(GPS_L1_CA_CODE_LENGTH_CHIPS); // GPS L1 C/A does not have pilot component nor secondary code d_secondary = false; trk_parameters.track_pilot = false; @@ -115,10 +120,10 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_) d_signal_carrier_freq = GPS_L2_FREQ_HZ; d_code_period = GPS_L2_M_PERIOD; d_code_chip_rate = GPS_L2_M_CODE_RATE_HZ; - d_code_length_chips = static_cast(GPS_L2_M_CODE_LENGTH_CHIPS); + //d_code_length_chips = static_cast(GPS_L2_M_CODE_LENGTH_CHIPS); d_symbols_per_bit = GPS_L2_SAMPLES_PER_SYMBOL; d_correlation_length_ms = 20; - d_code_samples_per_chip = 1; + //d_code_samples_per_chip = 1; // GPS L2 does not have pilot component nor secondary code d_secondary = false; trk_parameters.track_pilot = false; @@ -131,8 +136,8 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_) d_code_chip_rate = GPS_L5i_CODE_RATE_HZ; d_symbols_per_bit = GPS_L5_SAMPLES_PER_SYMBOL; d_correlation_length_ms = 1; - d_code_samples_per_chip = 1; - d_code_length_chips = static_cast(GPS_L5i_CODE_LENGTH_CHIPS); + //d_code_samples_per_chip = 1; + //d_code_length_chips = static_cast(GPS_L5i_CODE_LENGTH_CHIPS); // GPS L5 does not have pilot secondary code d_secondary = true; interchange_iq = false; @@ -159,8 +164,8 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_) interchange_iq = false; d_signal_carrier_freq = 0.0; d_code_period = 0.0; - d_code_length_chips = 0; - d_code_samples_per_chip = 0; + //d_code_length_chips = 0; + //d_code_samples_per_chip = 0; d_symbols_per_bit = 0; } } @@ -172,10 +177,10 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_) d_signal_carrier_freq = Galileo_E1_FREQ_HZ; d_code_period = Galileo_E1_CODE_PERIOD; d_code_chip_rate = Galileo_E1_CODE_CHIP_RATE_HZ; - d_code_length_chips = static_cast(Galileo_E1_B_CODE_LENGTH_CHIPS); + //d_code_length_chips = static_cast(Galileo_E1_B_CODE_LENGTH_CHIPS); d_symbols_per_bit = 1; d_correlation_length_ms = 4; - d_code_samples_per_chip = 2; // CBOC disabled: 2 samples per chip. CBOC enabled: 12 samples per chip + //d_code_samples_per_chip = 2; // CBOC disabled: 2 samples per chip. CBOC enabled: 12 samples per chip d_veml = true; if (trk_parameters.track_pilot) { @@ -198,8 +203,8 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_) d_code_chip_rate = Galileo_E5a_CODE_CHIP_RATE_HZ; d_symbols_per_bit = 20; d_correlation_length_ms = 1; - d_code_samples_per_chip = 1; - d_code_length_chips = static_cast(Galileo_E5a_CODE_LENGTH_CHIPS); + //d_code_samples_per_chip = 1; + //d_code_length_chips = static_cast(Galileo_E5a_CODE_LENGTH_CHIPS); d_secondary = true; interchange_iq = false; if (trk_parameters.track_pilot) @@ -224,8 +229,8 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_) interchange_iq = false; d_signal_carrier_freq = 0.0; d_code_period = 0.0; - d_code_length_chips = 0; - d_code_samples_per_chip = 0; + //d_code_length_chips = 0; + //d_code_samples_per_chip = 0; d_symbols_per_bit = 0; } } @@ -238,8 +243,8 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_) interchange_iq = false; d_signal_carrier_freq = 0.0; d_code_period = 0.0; - d_code_length_chips = 0; - d_code_samples_per_chip = 0; + //d_code_length_chips = 0; + //d_code_samples_per_chip = 0; d_symbols_per_bit = 0; } T_chip_seconds = 0.0; @@ -269,6 +274,8 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_) d_local_code_shift_chips = static_cast(volk_gnsssdr_malloc(d_n_correlator_taps * sizeof(float), volk_gnsssdr_get_alignment())); std::fill_n(d_correlator_outs, d_n_correlator_taps, gr_complex(0.0, 0.0)); + d_code_samples_per_chip = trk_parameters.code_samples_per_chip; // number of samples per chip + // map memory pointers of correlator outputs if (d_veml) { @@ -277,6 +284,11 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_) d_Prompt = &d_correlator_outs[2]; d_Late = &d_correlator_outs[3]; d_Very_Late = &d_correlator_outs[4]; +// printf("aaaa very early %f\n",-trk_parameters.very_early_late_space_chips); +// printf("aaaa early %f\n",-trk_parameters.early_late_space_chips); +// printf("aaaa normal %f\n",0); +// printf("aaaa late %f\n",trk_parameters.early_late_space_chips); +// printf("aaaa very late %f\n",trk_parameters.very_early_late_space_chips); d_local_code_shift_chips[0] = -trk_parameters.very_early_late_space_chips * static_cast(d_code_samples_per_chip); d_local_code_shift_chips[1] = -trk_parameters.early_late_space_chips * static_cast(d_code_samples_per_chip); d_local_code_shift_chips[2] = 0.0; @@ -291,6 +303,10 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_) d_Prompt = &d_correlator_outs[1]; d_Late = &d_correlator_outs[2]; d_Very_Late = nullptr; +// printf("aaaa early %f\n",-trk_parameters.early_late_space_chips); +// printf("aaaa normal %f\n",0); +// printf("aaaa late %f\n",trk_parameters.early_late_space_chips); + d_local_code_shift_chips[0] = -trk_parameters.early_late_space_chips * static_cast(d_code_samples_per_chip); d_local_code_shift_chips[1] = 0.0; d_local_code_shift_chips[2] = trk_parameters.early_late_space_chips * static_cast(d_code_samples_per_chip); @@ -361,13 +377,17 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_) d_last_prompt = gr_complex(0.0, 0.0); d_state = 0; // initial state: standby + //printf("hhhhhhhhhhh d_n_correlator_taps = %d\n", d_n_correlator_taps); + // create multicorrelator class std::string device_name = trk_parameters.device_name; unsigned int device_base = trk_parameters.device_base; int* ca_codes = trk_parameters.ca_codes; int* data_codes = trk_parameters.data_codes; - unsigned int code_length = trk_parameters.code_length; - multicorrelator_fpga = std::make_shared (d_n_correlator_taps, device_name, device_base, ca_codes, data_codes, code_length, trk_parameters.track_pilot); + //unsigned int code_length = trk_parameters.code_length_chips; + d_code_length_chips = trk_parameters.code_length_chips; + unsigned int multicorr_type = trk_parameters.multicorr_type; + multicorrelator_fpga = std::make_shared (d_n_correlator_taps, device_name, device_base, ca_codes, data_codes, d_code_length_chips, trk_parameters.track_pilot, multicorr_type, d_code_samples_per_chip); multicorrelator_fpga->set_output_vectors(d_correlator_outs, d_Prompt_Data); d_pull_in = 0; @@ -388,6 +408,7 @@ void dll_pll_veml_tracking_fpga::start_tracking() // new chip and prn sequence periods based on acq Doppler d_code_freq_chips = radial_velocity * d_code_chip_rate; d_code_phase_step_chips = d_code_freq_chips / trk_parameters.fs_in; + double T_chip_mod_seconds = 1.0 / d_code_freq_chips; double T_prn_mod_seconds = T_chip_mod_seconds * static_cast(d_code_length_chips); double T_prn_mod_samples = T_prn_mod_seconds * trk_parameters.fs_in; @@ -437,7 +458,7 @@ void dll_pll_veml_tracking_fpga::start_tracking() { if (trk_parameters.track_pilot) { - char pilot_signal[3] = "1C"; + //char pilot_signal[3] = "1C"; d_Prompt_Data[0] = gr_complex(0.0, 0.0); // MISSING _: set_local_code_and_taps for the data correlator } @@ -507,7 +528,8 @@ void dll_pll_veml_tracking_fpga::start_tracking() LOG(INFO) << "PULL-IN Doppler [Hz] = " << d_carrier_doppler_hz << ". Code Phase correction [samples] = " << delay_correction_samples << ". PULL-IN Code Phase [samples] = " << d_acq_code_phase_samples; - multicorrelator_fpga->set_local_code_and_taps(d_code_length_chips, d_local_code_shift_chips, d_acquisition_gnss_synchro->PRN); + //multicorrelator_fpga->set_local_code_and_taps(d_code_length_chips, d_local_code_shift_chips, d_acquisition_gnss_synchro->PRN); + multicorrelator_fpga->set_local_code_and_taps(d_local_code_shift_chips, d_prompt_data_shift, d_acquisition_gnss_synchro->PRN); d_pull_in = 1; // enable tracking pull-in and d_state at the end to avoid general work from starting pull-in before the start tracking function is finished d_state = 1; @@ -600,6 +622,7 @@ bool dll_pll_veml_tracking_fpga::acquire_secondary() bool dll_pll_veml_tracking_fpga::cn0_and_tracking_lock_status(double coh_integration_time_s) { + //printf("kkkkkkkkkkkkk d_cn0_estimation_counter = %d\n", d_cn0_estimation_counter); // ####### CN0 ESTIMATION AND LOCK DETECTORS ###### if (d_cn0_estimation_counter < trk_parameters.cn0_samples) { @@ -610,6 +633,7 @@ bool dll_pll_veml_tracking_fpga::cn0_and_tracking_lock_status(double coh_integra } else { + //printf("KKKKKKKKKKK checking count fail ...\n"); d_cn0_estimation_counter = 0; // Code lock indicator d_CN0_SNV_dB_Hz = cn0_svn_estimator(d_Prompt_buffer, trk_parameters.cn0_samples, coh_integration_time_s); @@ -719,6 +743,11 @@ void dll_pll_veml_tracking_fpga::update_tracking_vars() // remnant code phase [chips] d_rem_code_phase_samples = K_blk_samples - static_cast(d_current_prn_length_samples); // rounding error < 1 sample d_rem_code_phase_chips = d_code_freq_chips * d_rem_code_phase_samples / trk_parameters.fs_in; + //printf("lll d_code_freq_chips = %f\n", d_code_freq_chips); + //printf("lll d_rem_code_phase_samples = %f\n", d_rem_code_phase_samples); + //printf("lll trk_parameters.fs_in = %f\n", trk_parameters.fs_in); + //printf("lll d_rem_code_phase_chips = %f\n", d_rem_code_phase_chips); + } @@ -1176,8 +1205,14 @@ int dll_pll_veml_tracking_fpga::general_work (int noutput_items __attribute__((u d_pull_in = 0; multicorrelator_fpga->lock_channel(); unsigned counter_value = multicorrelator_fpga->read_sample_counter(); + //printf("333333 counter_value = %d\n", counter_value); + //printf("333333 current_synchro_data.Acq_samplestamp_samples = %d\n", current_synchro_data.Acq_samplestamp_samples); + //printf("333333 current_synchro_data.Acq_delay_samples = %f\n", current_synchro_data.Acq_delay_samples); + //printf("333333 d_correlation_length_samples = %d\n", d_correlation_length_samples); unsigned num_frames = ceil((counter_value - current_synchro_data.Acq_samplestamp_samples - current_synchro_data.Acq_delay_samples)/d_correlation_length_samples); + //printf("333333 num_frames = %d\n", num_frames); unsigned absolute_samples_offset = current_synchro_data.Acq_delay_samples + current_synchro_data.Acq_samplestamp_samples + num_frames*d_correlation_length_samples; + //printf("333333 absolute_samples_offset = %d\n", absolute_samples_offset); multicorrelator_fpga->set_initial_sample(absolute_samples_offset); d_sample_counter = absolute_samples_offset; current_synchro_data.Tracking_sample_counter = absolute_samples_offset; @@ -1196,7 +1231,7 @@ int dll_pll_veml_tracking_fpga::general_work (int noutput_items __attribute__((u // perform carrier wipe-off and compute Early, Prompt and Late correlation multicorrelator_fpga->Carrier_wipeoff_multicorrelator_resampler( d_rem_carr_phase_rad, d_carrier_phase_step_rad, - d_rem_code_phase_chips, d_code_phase_step_chips, + d_rem_code_phase_chips * static_cast(d_code_samples_per_chip), d_code_phase_step_chips * static_cast(d_code_samples_per_chip), d_current_prn_length_samples); // Save single correlation step variables @@ -1339,7 +1374,7 @@ int dll_pll_veml_tracking_fpga::general_work (int noutput_items __attribute__((u // perform a correlation step multicorrelator_fpga->Carrier_wipeoff_multicorrelator_resampler( d_rem_carr_phase_rad, d_carrier_phase_step_rad, - d_rem_code_phase_chips, d_code_phase_step_chips, + d_rem_code_phase_chips * static_cast(d_code_samples_per_chip), d_code_phase_step_chips * static_cast(d_code_samples_per_chip), d_current_prn_length_samples); update_tracking_vars(); save_correlation_results(); @@ -1398,7 +1433,7 @@ int dll_pll_veml_tracking_fpga::general_work (int noutput_items __attribute__((u //do_correlation_step(in); multicorrelator_fpga->Carrier_wipeoff_multicorrelator_resampler( d_rem_carr_phase_rad, d_carrier_phase_step_rad, - d_rem_code_phase_chips, d_code_phase_step_chips, + d_rem_code_phase_chips * static_cast(d_code_samples_per_chip), d_code_phase_step_chips * static_cast(d_code_samples_per_chip), d_current_prn_length_samples); save_correlation_results(); diff --git a/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking_fpga.h b/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking_fpga.h index ea4e556f4..1d4944bde 100644 --- a/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking_fpga.h +++ b/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking_fpga.h @@ -74,7 +74,9 @@ typedef struct char signal[3]; std::string device_name; unsigned int device_base; - unsigned int code_length; + unsigned int multicorr_type; + unsigned int code_length_chips; + unsigned int code_samples_per_chip; int* ca_codes; int* data_codes; } dllpllconf_fpga_t; @@ -223,6 +225,7 @@ private: unsigned long int d_sample_counter_next; unsigned int d_pull_in = 0; + }; #endif //GNSS_SDR_DLL_PLL_VEML_TRACKING_FPGA_H diff --git a/src/algorithms/tracking/libs/fpga_multicorrelator.cc b/src/algorithms/tracking/libs/fpga_multicorrelator.cc index b13a084e9..65222232d 100644 --- a/src/algorithms/tracking/libs/fpga_multicorrelator.cc +++ b/src/algorithms/tracking/libs/fpga_multicorrelator.cc @@ -86,21 +86,25 @@ int fpga_multicorrelator_8sc::read_sample_counter() { - return d_map_base[7]; + return d_map_base[d_SAMPLE_COUNTER_REG_ADDR]; } void fpga_multicorrelator_8sc::set_initial_sample(int samples_offset) { d_initial_sample_counter = samples_offset; - d_map_base[13] = d_initial_sample_counter; + //printf("www writing d map base %d = d_initial_sample_counter = %d\n", d_INITIAL_COUNTER_VALUE_REG_ADDR, d_initial_sample_counter); + d_map_base[d_INITIAL_COUNTER_VALUE_REG_ADDR] = d_initial_sample_counter; } -void fpga_multicorrelator_8sc::set_local_code_and_taps(int code_length_chips, - float *shifts_chips, int PRN) +//void fpga_multicorrelator_8sc::set_local_code_and_taps(int code_length_chips, +// float *shifts_chips, int PRN) + +void fpga_multicorrelator_8sc::set_local_code_and_taps(float *shifts_chips, float *prompt_data_shift, int PRN) { d_shifts_chips = shifts_chips; - d_code_length_chips = code_length_chips; + d_prompt_data_shift = prompt_data_shift; + //d_code_length_chips = code_length_chips; fpga_multicorrelator_8sc::fpga_configure_tracking_gps_local_code(PRN); } @@ -113,6 +117,7 @@ void fpga_multicorrelator_8sc::set_output_vectors(gr_complex* corr_out, gr_compl void fpga_multicorrelator_8sc::update_local_code(float rem_code_phase_chips) { d_rem_code_phase_chips = rem_code_phase_chips; + //printf("uuuuu d_rem_code_phase_chips = %f\n", d_rem_code_phase_chips); fpga_multicorrelator_8sc::fpga_compute_code_shift_parameters(); fpga_multicorrelator_8sc::fpga_configure_code_parameters_in_fpga(); } @@ -135,7 +140,9 @@ void fpga_multicorrelator_8sc::Carrier_wipeoff_multicorrelator_resampler( fpga_multicorrelator_8sc::fpga_launch_multicorrelator_fpga(); int irq_count; ssize_t nb; + //printf("$$$$$ waiting for interrupt ... \n"); nb = read(d_device_descriptor, &irq_count, sizeof(irq_count)); + //printf("$$$$$ interrupt received ... \n"); if (nb != sizeof(irq_count)) { printf("Tracking_module Read failed to retrieve 4 bytes!\n"); @@ -145,7 +152,8 @@ void fpga_multicorrelator_8sc::Carrier_wipeoff_multicorrelator_resampler( } fpga_multicorrelator_8sc::fpga_multicorrelator_8sc(int n_correlators, - std::string device_name, unsigned int device_base, int *ca_codes, int *data_codes, unsigned int code_length, bool track_pilot) + std::string device_name, unsigned int device_base, int *ca_codes, int *data_codes, unsigned int code_length_chips, bool track_pilot, + unsigned int multicorr_type, unsigned int code_samples_per_chip) { d_n_correlators = n_correlators; d_device_name = device_name; @@ -155,12 +163,23 @@ fpga_multicorrelator_8sc::fpga_multicorrelator_8sc(int n_correlators, d_map_base = nullptr; // instantiate variable length vectors - d_initial_index = static_cast(volk_gnsssdr_malloc( - n_correlators * sizeof(unsigned), volk_gnsssdr_get_alignment())); - d_initial_interp_counter = static_cast(volk_gnsssdr_malloc( - n_correlators * sizeof(unsigned), volk_gnsssdr_get_alignment())); + if (d_track_pilot) + { + d_initial_index = static_cast(volk_gnsssdr_malloc( + (n_correlators + 1) * sizeof(unsigned), volk_gnsssdr_get_alignment())); + d_initial_interp_counter = static_cast(volk_gnsssdr_malloc( + (n_correlators + 1)* sizeof(unsigned), volk_gnsssdr_get_alignment())); + } + else + { + d_initial_index = static_cast(volk_gnsssdr_malloc( + n_correlators * sizeof(unsigned), volk_gnsssdr_get_alignment())); + d_initial_interp_counter = static_cast(volk_gnsssdr_malloc( + n_correlators * sizeof(unsigned), volk_gnsssdr_get_alignment())); + } d_shifts_chips = nullptr; + d_prompt_data_shift = nullptr; d_corr_out = nullptr; d_code_length_chips = 0; d_rem_code_phase_chips = 0; @@ -172,8 +191,92 @@ fpga_multicorrelator_8sc::fpga_multicorrelator_8sc(int n_correlators, d_initial_sample_counter = 0; d_channel = 0; d_correlator_length_samples = 0, - d_code_length = code_length; + //d_code_length = code_length; + d_code_length_chips = code_length_chips; d_ca_codes = ca_codes; + d_data_codes = data_codes; + d_multicorr_type = multicorr_type; + + d_code_samples_per_chip = code_samples_per_chip; + // set up register mapping + + // write-only registers + d_CODE_PHASE_STEP_CHIPS_NUM_REG_ADDR = 0; + d_INITIAL_INDEX_REG_BASE_ADDR = 1; + if (d_multicorr_type == 0) + { + // multicorrelator with 3 correlators (16 registers only) + d_INITIAL_INTERP_COUNTER_REG_BASE_ADDR = 4; + d_NSAMPLES_MINUS_1_REG_ADDR = 7; + d_CODE_LENGTH_MINUS_1_REG_ADDR = 8; + d_REM_CARR_PHASE_RAD_REG_ADDR = 9; + d_PHASE_STEP_RAD_REG_ADDR = 10; + d_PROG_MEMS_ADDR = 11; + d_DROP_SAMPLES_REG_ADDR = 12; + d_INITIAL_COUNTER_VALUE_REG_ADDR = 13; + d_START_FLAG_ADDR = 14; + } + else + { + // other types of multicorrelators (32 registers) + d_INITIAL_INTERP_COUNTER_REG_BASE_ADDR = 7; + d_NSAMPLES_MINUS_1_REG_ADDR = 13; + d_CODE_LENGTH_MINUS_1_REG_ADDR = 14; + d_REM_CARR_PHASE_RAD_REG_ADDR = 15; + d_PHASE_STEP_RAD_REG_ADDR = 16; + d_PROG_MEMS_ADDR = 17; + d_DROP_SAMPLES_REG_ADDR = 18; + d_INITIAL_COUNTER_VALUE_REG_ADDR = 19; + d_START_FLAG_ADDR = 30; + } + + // read-write registers + if (d_multicorr_type == 0) + { + // multicorrelator with 3 correlators (16 registers only) + d_TEST_REG_ADDR = 15; + } + else + { + // other types of multicorrelators (32 registers) + d_TEST_REG_ADDR = 31; + } + + // result 2's complement saturation value + if (d_multicorr_type == 0) + { + // multicorrelator with 3 correlators (16 registers only) + d_result_SAT_value = 1048576; // 21 bits 2's complement -> 2^20 + } + else + { + // other types of multicorrelators (32 registers) + d_result_SAT_value = 4194304; // 23 bits 2's complement -> 2^22 + } + + // read only registers + d_RESULT_REG_REAL_BASE_ADDR = 1; + if (d_multicorr_type == 0) + { + // multicorrelator with 3 correlators (16 registers only) + d_RESULT_REG_IMAG_BASE_ADDR = 4; + d_RESULT_REG_DATA_REAL_BASE_ADDR = 0; // no pilot tracking + d_RESULT_REG_DATA_IMAG_BASE_ADDR = 0; + d_SAMPLE_COUNTER_REG_ADDR = 7; + + } + else + { + // other types of multicorrelators (32 registers) + d_RESULT_REG_IMAG_BASE_ADDR = 7; + d_RESULT_REG_DATA_REAL_BASE_ADDR = 6; // no pilot tracking + d_RESULT_REG_DATA_IMAG_BASE_ADDR = 12; + d_SAMPLE_COUNTER_REG_ADDR = 13; + + } + + //printf("d_SAMPLE_COUNTER_REG_ADDR = %d\n", d_SAMPLE_COUNTER_REG_ADDR); + //printf("mmmmmmmmmmmmm d_n_correlators = %d\n", d_n_correlators); DLOG(INFO) << "TRACKING FPGA CLASS CREATED"; } @@ -181,7 +284,7 @@ fpga_multicorrelator_8sc::fpga_multicorrelator_8sc(int n_correlators, fpga_multicorrelator_8sc::~fpga_multicorrelator_8sc() { - delete[] d_ca_codes; + //delete[] d_ca_codes; close_device(); } @@ -220,10 +323,21 @@ void fpga_multicorrelator_8sc::set_channel(unsigned int channel) devicebasetemp << numdevice; mergedname = d_device_name + devicebasetemp.str(); strcpy(device_io_name, mergedname.c_str()); + + //printf("ppps opening device %s\n", device_io_name); + if ((d_device_descriptor = open(device_io_name, O_RDWR | O_SYNC)) == -1) { LOG(WARNING) << "Cannot open deviceio" << device_io_name; + std::cout << "Cannot open deviceio" << device_io_name << std::endl; + + //printf("error opening device\n"); } +// else +// { +// std::cout << "deviceio" << device_io_name << " opened successfully" << std::endl; +// +// } d_map_base = reinterpret_cast(mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, d_device_descriptor, 0)); @@ -231,7 +345,17 @@ void fpga_multicorrelator_8sc::set_channel(unsigned int channel) { LOG(WARNING) << "Cannot map the FPGA tracking module " << d_channel << "into user memory"; + std::cout << "Cannot map deviceio" << device_io_name << std::endl; + //printf("error mapping registers\n"); } +// else +// { +// std::cout << "deviceio" << device_io_name << "mapped successfully" << std::endl; +// } +// else +// { +// printf("mapping registers succes\n"); // this is for debug -- remove ! +// } // sanity check : check test register unsigned writeval = TEST_REGISTER_TRACK_WRITEVAL; @@ -240,10 +364,15 @@ void fpga_multicorrelator_8sc::set_channel(unsigned int channel) if (writeval != readval) { LOG(WARNING) << "Test register sanity check failed"; + // printf("tracking test register sanity check failed\n"); + + //printf("lslslls test sanity check reg failure\n"); } else { LOG(INFO) << "Test register sanity check success !"; + //printf("tracking test register sanity check success\n"); + //printf("lslslls test sanity check reg success\n"); } } @@ -251,11 +380,13 @@ void fpga_multicorrelator_8sc::set_channel(unsigned int channel) unsigned fpga_multicorrelator_8sc::fpga_acquisition_test_register( unsigned writeval) { - unsigned readval; + //printf("d_TEST_REG_ADDR = %d\n", d_TEST_REG_ADDR); + + unsigned readval = 0; // write value to test register - d_map_base[15] = writeval; + d_map_base[d_TEST_REG_ADDR] = writeval; // read value from test register - readval = d_map_base[15]; + readval = d_map_base[d_TEST_REG_ADDR]; // return read value return readval; } @@ -265,16 +396,29 @@ void fpga_multicorrelator_8sc::fpga_configure_tracking_gps_local_code(int PRN) { int k, s; unsigned code_chip; - unsigned select_fpga_correlator; - select_fpga_correlator = 0; + unsigned select_pilot_corelator = LOCAL_CODE_FPGA_CORRELATOR_SELECT_COUNT; +// select_fpga_correlator = 0; - for (s = 0; s < d_n_correlators; s++) - { - d_map_base[11] = LOCAL_CODE_FPGA_CLEAR_ADDRESS_COUNTER; - for (k = 0; k < d_code_length_chips; k++) + //printf("kkk d_n_correlators = %x\n", d_n_correlators); + //printf("kkk d_code_length_chips = %d\n", d_code_length_chips); + //printf("programming mems d map base %d\n", d_PROG_MEMS_ADDR); + + //FILE *fp; + //char str[80]; + //sprintf(str, "generated_code_PRN%d", PRN); + //fp = fopen(str,"w"); +// for (s = 0; s < d_n_correlators; s++) +// { + + //printf("kkk select_fpga_correlator = %x\n", select_fpga_correlator); + + d_map_base[d_PROG_MEMS_ADDR] = LOCAL_CODE_FPGA_CLEAR_ADDRESS_COUNTER; + for (k = 0; k < d_code_length_chips * d_code_samples_per_chip; k++) { //if (d_local_code_in[k] == 1) - if (d_ca_codes[((int(d_code_length)) * (PRN - 1)) + k] == 1) + //printf("kkk d_ca_codes %d = %d\n", k, d_ca_codes[((int(d_code_length)) * (PRN - 1)) + k]); + //fprintf(fp, "%d\n", d_ca_codes[((int(d_code_length_chips)) * d_code_samples_per_chip * (PRN - 1)) + k]); + if (d_ca_codes[((int(d_code_length_chips)) * d_code_samples_per_chip * (PRN - 1)) + k] == 1) { code_chip = 1; } @@ -282,13 +426,39 @@ void fpga_multicorrelator_8sc::fpga_configure_tracking_gps_local_code(int PRN) { code_chip = 0; } + // copy the local code to the FPGA memory one by one - d_map_base[11] = LOCAL_CODE_FPGA_ENABLE_WRITE_MEMORY - | code_chip | select_fpga_correlator; + d_map_base[d_PROG_MEMS_ADDR] = LOCAL_CODE_FPGA_ENABLE_WRITE_MEMORY + | code_chip; // | select_fpga_correlator; + } +// select_fpga_correlator = select_fpga_correlator +// + LOCAL_CODE_FPGA_CORRELATOR_SELECT_COUNT; +// } + //fclose(fp); + //printf("kkk d_track_pilot = %d\n", d_track_pilot); + if (d_track_pilot) + { + //printf("kkk select_fpga_correlator = %x\n", select_fpga_correlator); + + d_map_base[d_PROG_MEMS_ADDR] = LOCAL_CODE_FPGA_CLEAR_ADDRESS_COUNTER; + for (k = 0; k < d_code_length_chips * d_code_samples_per_chip; k++) + { + //if (d_local_code_in[k] == 1) + if (d_data_codes[((int(d_code_length_chips)) * d_code_samples_per_chip * (PRN - 1)) + k] == 1) + { + code_chip = 1; + } + else + { + code_chip = 0; + } + //printf("%d %d | ", d_data_codes, code_chip); + // copy the local code to the FPGA memory one by one + d_map_base[d_PROG_MEMS_ADDR] = LOCAL_CODE_FPGA_ENABLE_WRITE_MEMORY + | code_chip | select_pilot_corelator; } - select_fpga_correlator = select_fpga_correlator - + LOCAL_CODE_FPGA_CORRELATOR_SELECT_COUNT; } + printf("\n"); } @@ -297,24 +467,56 @@ void fpga_multicorrelator_8sc::fpga_compute_code_shift_parameters(void) float temp_calculation; int i; + //printf("ppp d_rem_code_phase_chips = %f\n", d_rem_code_phase_chips); for (i = 0; i < d_n_correlators; i++) { + //printf("ppp d_shifts_chips %d = %f\n", i, d_shifts_chips[i]); + //printf("ppp d_code_samples_per_chip = %d\n", d_code_samples_per_chip); temp_calculation = floor( d_shifts_chips[i] - d_rem_code_phase_chips); - + + //printf("ppp d_rem_code_phase_chips = %f\n", d_rem_code_phase_chips); + //printf("ppp temp calculation %d = %f ================================ \n", i, temp_calculation); if (temp_calculation < 0) { - temp_calculation = temp_calculation + d_code_length_chips; // % operator does not work as in Matlab with negative numbers + temp_calculation = temp_calculation + (d_code_length_chips * d_code_samples_per_chip); // % operator does not work as in Matlab with negative numbers } - d_initial_index[i] = static_cast( (static_cast(temp_calculation)) % d_code_length_chips); + //printf("ppp d_rem_code_phase_chips = %f\n", d_rem_code_phase_chips); + //printf("ppp temp calculation %d = %f ================================ \n", i, temp_calculation); + d_initial_index[i] = static_cast( (static_cast(temp_calculation)) % (d_code_length_chips * d_code_samples_per_chip)); + //printf("ppp d_initial_index %d = %d\n", i, d_initial_index[i]); temp_calculation = fmod(d_shifts_chips[i] - d_rem_code_phase_chips, 1.0); + //printf("ppp fmod %d = fmod(%f, 1) = %f\n", i, d_shifts_chips[i] - d_rem_code_phase_chips, temp_calculation); if (temp_calculation < 0) { temp_calculation = temp_calculation + 1.0; // fmod operator does not work as in Matlab with negative numbers } + d_initial_interp_counter[i] = static_cast( floor( MAX_CODE_RESAMPLER_COUNTER * temp_calculation)); + //printf("ppp d_initial_interp_counter %d = %d\n", i, d_initial_interp_counter[i]); + //printf("MAX_CODE_RESAMPLER_COUNTER = %d\n", MAX_CODE_RESAMPLER_COUNTER); } + if (d_track_pilot) + { + //printf("tracking pilot !!!!!!!!!!!!!!!!\n"); + temp_calculation = floor( + d_prompt_data_shift[0] - d_rem_code_phase_chips); + + if (temp_calculation < 0) + { + temp_calculation = temp_calculation + (d_code_length_chips * d_code_samples_per_chip); // % operator does not work as in Matlab with negative numbers + } + d_initial_index[d_n_correlators] = static_cast( (static_cast(temp_calculation)) % (d_code_length_chips * d_code_samples_per_chip)); + temp_calculation = fmod(d_prompt_data_shift[0] - d_rem_code_phase_chips, + 1.0); + if (temp_calculation < 0) + { + temp_calculation = temp_calculation + 1.0; // fmod operator does not work as in Matlab with negative numbers + } + d_initial_interp_counter[d_n_correlators] = static_cast( floor( MAX_CODE_RESAMPLER_COUNTER * temp_calculation)); + } + //while(1); } @@ -323,10 +525,23 @@ void fpga_multicorrelator_8sc::fpga_configure_code_parameters_in_fpga(void) int i; for (i = 0; i < d_n_correlators; i++) { - d_map_base[1 + i] = d_initial_index[i]; - d_map_base[1 + d_n_correlators + i] = d_initial_interp_counter[i]; + //printf("www writing d map base %d = d_initial_index %d = %d\n", d_INITIAL_INDEX_REG_BASE_ADDR + i, i, d_initial_index[i]); + d_map_base[d_INITIAL_INDEX_REG_BASE_ADDR + i] = d_initial_index[i]; + //d_map_base[1 + d_n_correlators + i] = d_initial_interp_counter[i]; + //printf("www writing d map base %d = d_initial_interp_counter %d = %d\n", d_INITIAL_INTERP_COUNTER_REG_BASE_ADDR + i, i, d_initial_interp_counter[i]); + d_map_base[d_INITIAL_INTERP_COUNTER_REG_BASE_ADDR + i] = d_initial_interp_counter[i]; } - d_map_base[8] = d_code_length_chips - 1; // number of samples - 1 + if (d_track_pilot) + { + //printf("www writing d map base %d = d_initial_index %d = %d\n", d_INITIAL_INDEX_REG_BASE_ADDR + d_n_correlators, d_n_correlators, d_initial_index[d_n_correlators]); + d_map_base[d_INITIAL_INDEX_REG_BASE_ADDR + d_n_correlators] = d_initial_index[d_n_correlators]; + //d_map_base[1 + d_n_correlators + i] = d_initial_interp_counter[i]; + //printf("www writing d map base %d = d_initial_interp_counter %d = %d\n", d_INITIAL_INTERP_COUNTER_REG_BASE_ADDR + d_n_correlators, d_n_correlators, d_initial_interp_counter[d_n_correlators]); + d_map_base[d_INITIAL_INTERP_COUNTER_REG_BASE_ADDR + d_n_correlators] = d_initial_interp_counter[d_n_correlators]; + } + + //printf("www writing d map base %d = d_code_length_chips*d_code_samples_per_chip - 1 = %d\n", d_CODE_LENGTH_MINUS_1_REG_ADDR, (d_code_length_chips*d_code_samples_per_chip) - 1); + d_map_base[d_CODE_LENGTH_MINUS_1_REG_ADDR] = (d_code_length_chips*d_code_samples_per_chip) - 1; // number of samples - 1 } @@ -335,6 +550,13 @@ void fpga_multicorrelator_8sc::fpga_compute_signal_parameters_in_fpga(void) float d_rem_carrier_phase_in_rad_temp; d_code_phase_step_chips_num = static_cast( roundf(MAX_CODE_RESAMPLER_COUNTER * d_code_phase_step_chips)); + if (d_code_phase_step_chips > 1.0) + { + printf("Warning : d_code_phase_step_chips = %d cannot be bigger than one\n", d_code_phase_step_chips); + } + + //printf("d_rem_carrier_phase_in_rad = %f\n", d_rem_carrier_phase_in_rad); + if (d_rem_carrier_phase_in_rad > M_PI) { d_rem_carrier_phase_in_rad_temp = -2 * M_PI @@ -359,19 +581,30 @@ void fpga_multicorrelator_8sc::fpga_compute_signal_parameters_in_fpga(void) d_phase_step_rad_int = static_cast( roundf( (fabs(d_phase_step_rad) / M_PI) * pow(2, PHASE_CARR_NBITS_FRAC))); // the FPGA accepts a range for the phase step between -pi and +pi + //printf("d_phase_step_rad_int = %d\n", d_phase_step_rad_int); if (d_phase_step_rad < 0) { d_phase_step_rad_int = -d_phase_step_rad_int; } + + //printf("d_phase_step_rad_int = %d\n", d_phase_step_rad_int); + } void fpga_multicorrelator_8sc::fpga_configure_signal_parameters_in_fpga(void) { - d_map_base[0] = d_code_phase_step_chips_num; - d_map_base[7] = d_correlator_length_samples - 1; - d_map_base[9] = d_rem_carr_phase_rad_int; - d_map_base[10] = d_phase_step_rad_int; + //printf("www d map base %d = d_code_phase_step_chips_num = %d\n", d_CODE_PHASE_STEP_CHIPS_NUM_REG_ADDR, d_code_phase_step_chips_num); + d_map_base[d_CODE_PHASE_STEP_CHIPS_NUM_REG_ADDR] = d_code_phase_step_chips_num; + + //printf("www d map base %d = d_correlator_length_samples - 1 = %d\n", d_NSAMPLES_MINUS_1_REG_ADDR, d_correlator_length_samples - 1); + d_map_base[d_NSAMPLES_MINUS_1_REG_ADDR] = d_correlator_length_samples - 1; + + //printf("www d map base %d = d_rem_carr_phase_rad_int = %d\n", d_REM_CARR_PHASE_RAD_REG_ADDR, d_rem_carr_phase_rad_int); + d_map_base[d_REM_CARR_PHASE_RAD_REG_ADDR] = d_rem_carr_phase_rad_int; + + //printf("www d map base %d = d_phase_step_rad_int = %d\n", d_PHASE_STEP_RAD_REG_ADDR, d_phase_step_rad_int); + d_map_base[d_PHASE_STEP_RAD_REG_ADDR] = d_phase_step_rad_int; } @@ -382,7 +615,10 @@ void fpga_multicorrelator_8sc::fpga_launch_multicorrelator_fpga(void) write(d_device_descriptor, reinterpret_cast(&reenable), sizeof(int)); // writing 1 to reg 14 launches the tracking - d_map_base[14] = 1; + //printf("www writing 1 to d map base %d = start flag\n", d_START_FLAG_ADDR); + d_map_base[d_START_FLAG_ADDR] = 1; + //while(1); + } @@ -392,28 +628,86 @@ void fpga_multicorrelator_8sc::read_tracking_gps_results(void) int readval_imag; int k; + for (k = 0; k < d_n_correlators; k++) { - readval_real = d_map_base[1 + k]; - if (readval_real >= 1048576) // 0x100000 (21 bits two's complement) + readval_real = d_map_base[d_RESULT_REG_REAL_BASE_ADDR + k]; + //printf("read real before checking d map base %d = %d\n", d_RESULT_REG_BASE_ADDR + k, readval_real); +// if (readval_real > debug_max_readval_real[k]) +// { +// debug_max_readval_real[k] = readval_real; +// } + if (readval_real >= d_result_SAT_value) // 0x100000 (21 bits two's complement) { - readval_real = -2097152 + readval_real; + readval_real = -2*d_result_SAT_value + readval_real; + } +// if (readval_real > debug_max_readval_real_after_check[k]) +// { +// debug_max_readval_real_after_check[k] = readval_real; +// } + //printf("read real d map base %d = %d\n", d_RESULT_REG_BASE_ADDR + k, readval_real); + readval_imag = d_map_base[d_RESULT_REG_IMAG_BASE_ADDR + k]; + //printf("read imag before checking d map base %d = %d\n", d_RESULT_REG_BASE_ADDR + k, readval_imag); +// if (readval_imag > debug_max_readval_imag[k]) +// { +// debug_max_readval_imag[k] = readval_imag; +// } + + if (readval_imag >= d_result_SAT_value) // 0x100000 (21 bits two's complement) + { + readval_imag = -2*d_result_SAT_value + readval_imag; + } +// if (readval_imag > debug_max_readval_imag_after_check[k]) +// { +// debug_max_readval_imag_after_check[k] = readval_real; +// } + //printf("read imag d map base %d = %d\n", d_RESULT_REG_BASE_ADDR + k, readval_imag); + d_corr_out[k] = gr_complex(readval_real,readval_imag); + + // if (printcounter > 100) + // { + // printcounter = 0; + // for (int ll=0;ll= d_result_SAT_value) // 0x100000 (21 bits two's complement) + { + readval_real = -2*d_result_SAT_value + readval_real; } - readval_imag = d_map_base[1 + d_n_correlators + k]; - if (readval_imag >= 1048576) // 0x100000 (21 bits two's complement) + readval_imag = d_map_base[d_RESULT_REG_DATA_IMAG_BASE_ADDR]; + if (readval_imag >= d_result_SAT_value) // 0x100000 (21 bits two's complement) { - readval_imag = -2097152 + readval_imag; + readval_imag = -2*d_result_SAT_value + readval_imag; } - d_corr_out[k] = gr_complex(readval_real,readval_imag); + d_Prompt_Data[0] = gr_complex(readval_real,readval_imag); } + } void fpga_multicorrelator_8sc::unlock_channel(void) { // unlock the channel to let the next samples go through - d_map_base[12] = 1; // unlock the channel + //printf("www writing 1 to d map base %d = drop samples\n", d_DROP_SAMPLES_REG_ADDR); + d_map_base[d_DROP_SAMPLES_REG_ADDR] = 1; // unlock the channel } void fpga_multicorrelator_8sc::close_device() @@ -430,19 +724,20 @@ void fpga_multicorrelator_8sc::close_device() void fpga_multicorrelator_8sc::lock_channel(void) { // lock the channel for processing - d_map_base[12] = 0; // lock the channel + //printf("www writing 0 to d map base %d = drop samples\n", d_DROP_SAMPLES_REG_ADDR); + d_map_base[d_DROP_SAMPLES_REG_ADDR] = 0; // lock the channel } -void fpga_multicorrelator_8sc::read_sample_counters(int *sample_counter, int *secondary_sample_counter, int *counter_corr_0_in, int *counter_corr_0_out) -{ - *sample_counter = d_map_base[11]; - *secondary_sample_counter = d_map_base[8]; - *counter_corr_0_in = d_map_base[10]; - *counter_corr_0_out = d_map_base[9]; - -} +//void fpga_multicorrelator_8sc::read_sample_counters(int *sample_counter, int *secondary_sample_counter, int *counter_corr_0_in, int *counter_corr_0_out) +//{ +// *sample_counter = d_map_base[11]; +// *secondary_sample_counter = d_map_base[8]; +// *counter_corr_0_in = d_map_base[10]; +// *counter_corr_0_out = d_map_base[9]; +// +//} -void fpga_multicorrelator_8sc::reset_multicorrelator(void) -{ - d_map_base[14] = 2; // writing a 2 to d_map_base[14] resets the multicorrelator -} +//void fpga_multicorrelator_8sc::reset_multicorrelator(void) +//{ +// d_map_base[14] = 2; // writing a 2 to d_map_base[14] resets the multicorrelator +//} diff --git a/src/algorithms/tracking/libs/fpga_multicorrelator.h b/src/algorithms/tracking/libs/fpga_multicorrelator.h index f054cc4d0..810eaf47d 100644 --- a/src/algorithms/tracking/libs/fpga_multicorrelator.h +++ b/src/algorithms/tracking/libs/fpga_multicorrelator.h @@ -49,7 +49,7 @@ class fpga_multicorrelator_8sc { public: fpga_multicorrelator_8sc(int n_correlators, std::string device_name, - unsigned int device_base, int *ca_codes, int *data_codes, unsigned int code_length, bool track_pilot); + unsigned int device_base, int *ca_codes, int *data_codes, unsigned int code_length_chips, bool track_pilot, unsigned int multicorr_type, unsigned int code_samples_per_chip); ~fpga_multicorrelator_8sc(); //bool set_output_vectors(gr_complex* corr_out); void set_output_vectors(gr_complex* corr_out, gr_complex* Prompt_Data); @@ -58,8 +58,8 @@ public: // float *shifts_chips, int PRN); //bool set_local_code_and_taps( void set_local_code_and_taps( - int code_length_chips, - float *shifts_chips, int PRN); +// int code_length_chips, + float *shifts_chips, float *prompt_data_shift, int PRN); //bool set_output_vectors(lv_16sc_t* corr_out); void update_local_code(float rem_code_phase_chips); //bool Carrier_wipeoff_multicorrelator_resampler( @@ -72,7 +72,7 @@ public: int read_sample_counter(); void lock_channel(void); void unlock_channel(void); - void read_sample_counters(int *sample_counter, int *secondary_sample_counter, int *counter_corr_0_in, int *counter_corr_0_out); // debug + //void read_sample_counters(int *sample_counter, int *secondary_sample_counter, int *counter_corr_0_in, int *counter_corr_0_out); // debug private: @@ -80,6 +80,7 @@ private: gr_complex * d_corr_out; gr_complex * d_Prompt_Data; float *d_shifts_chips; + float *d_prompt_data_shift; int d_code_length_chips; int d_n_correlators; @@ -110,11 +111,37 @@ private: int* d_ca_codes; + int* d_data_codes; - unsigned int d_code_length; // nominal number of chips + //unsigned int d_code_length; // nominal number of chips + unsigned int d_code_samples_per_chip; bool d_track_pilot; + unsigned int d_multicorr_type; + + // register addresses + // write-only regs + unsigned int d_CODE_PHASE_STEP_CHIPS_NUM_REG_ADDR; + unsigned int d_INITIAL_INDEX_REG_BASE_ADDR; + unsigned int d_INITIAL_INTERP_COUNTER_REG_BASE_ADDR; + unsigned int d_NSAMPLES_MINUS_1_REG_ADDR; + unsigned int d_CODE_LENGTH_MINUS_1_REG_ADDR; + unsigned int d_REM_CARR_PHASE_RAD_REG_ADDR; + unsigned int d_PHASE_STEP_RAD_REG_ADDR; + unsigned int d_PROG_MEMS_ADDR; + unsigned int d_DROP_SAMPLES_REG_ADDR; + unsigned int d_INITIAL_COUNTER_VALUE_REG_ADDR; + unsigned int d_START_FLAG_ADDR; + // read-write regs + unsigned int d_TEST_REG_ADDR; + // read-only regs + unsigned int d_RESULT_REG_REAL_BASE_ADDR; + unsigned int d_RESULT_REG_IMAG_BASE_ADDR; + unsigned int d_RESULT_REG_DATA_REAL_BASE_ADDR; + unsigned int d_RESULT_REG_DATA_IMAG_BASE_ADDR; + unsigned int d_SAMPLE_COUNTER_REG_ADDR; + // private functions unsigned fpga_acquisition_test_register(unsigned writeval); void fpga_configure_tracking_gps_local_code(int PRN); @@ -124,9 +151,17 @@ private: void fpga_configure_signal_parameters_in_fpga(void); void fpga_launch_multicorrelator_fpga(void); void read_tracking_gps_results(void); - void reset_multicorrelator(void); + //void reset_multicorrelator(void); void close_device(void); + unsigned int d_result_SAT_value; + + int debug_max_readval_real[5] = {0, 0, 0, 0, 0}; + int debug_max_readval_imag[5] = {0, 0, 0, 0, 0};; + int debug_max_readval_real_after_check[5] = {0, 0, 0, 0, 0}; + int debug_max_readval_imag_after_check[5] = {0, 0, 0, 0, 0}; + int printcounter = 0; + }; #endif /* GNSS_SDR_FPGA_MULTICORRELATOR_H_ */ diff --git a/src/core/receiver/gnss_block_factory.cc b/src/core/receiver/gnss_block_factory.cc index 7bd7a23bc..65404f829 100644 --- a/src/core/receiver/gnss_block_factory.cc +++ b/src/core/receiver/gnss_block_factory.cc @@ -106,9 +106,15 @@ #if ENABLE_FPGA #include "gps_l1_ca_pcps_acquisition_fpga.h" +#include "gps_l2_m_pcps_acquisition_fpga.h" #include "galileo_e1_pcps_ambiguous_acquisition_fpga.h" +#include "galileo_e5a_pcps_acquisition_fpga.h" +#include "gps_l5i_pcps_acquisition_fpga.h" #include "gps_l1_ca_dll_pll_tracking_fpga.h" +#include "gps_l2_m_dll_pll_tracking_fpga.h" #include "galileo_e1_dll_pll_veml_tracking_fpga.h" +#include "galileo_e5a_dll_pll_tracking_fpga.h" +#include "gps_l5_dll_pll_tracking_fpga.h" #endif #if OPENCL_BLOCKS @@ -1374,12 +1380,28 @@ std::unique_ptr GNSSBlockFactory::GetBlock( out_streams)); block = std::move(block_); } +#if ENABLE_FPGA + else if (implementation.compare("GPS_L2_M_PCPS_Acquisition_Fpga") == 0) + { + std::unique_ptr block_(new GpsL2MPcpsAcquisitionFpga(configuration.get(), role, in_streams, + out_streams)); + block = std::move(block_); + } +#endif else if (implementation.compare("GPS_L5i_PCPS_Acquisition") == 0) { std::unique_ptr block_(new GpsL5iPcpsAcquisition(configuration.get(), role, in_streams, out_streams)); block = std::move(block_); } +#if ENABLE_FPGA + else if (implementation.compare("GPS_L5i_PCPS_Acquisition_Fpga") == 0) + { + std::unique_ptr block_(new GpsL5iPcpsAcquisitionFpga(configuration.get(), role, in_streams, + out_streams)); + block = std::move(block_); + } +#endif else if (implementation.compare("Galileo_E1_PCPS_Ambiguous_Acquisition") == 0) { std::unique_ptr block_(new GalileoE1PcpsAmbiguousAcquisition(configuration.get(), role, in_streams, @@ -1424,6 +1446,14 @@ std::unique_ptr GNSSBlockFactory::GetBlock( out_streams)); block = std::move(block_); } +#if ENABLE_FPGA + else if (implementation.compare("Galileo_E5a_Pcps_Acquisition_Fpga") == 0) + { + std::unique_ptr block_(new GalileoE5aPcpsAcquisitionFpga(configuration.get(), role, in_streams, + out_streams)); + block = std::move(block_); + } +#endif else if (implementation.compare("Galileo_E1_PCPS_QuickSync_Ambiguous_Acquisition") == 0) { std::unique_ptr block_(new GalileoE1PcpsQuickSyncAmbiguousAcquisition(configuration.get(), role, in_streams, @@ -1475,12 +1505,28 @@ std::unique_ptr GNSSBlockFactory::GetBlock( out_streams)); block = std::move(block_); } +#if ENABLE_FPGA + else if (implementation.compare("GPS_L2_M_DLL_PLL_Tracking_Fpga") == 0) + { + std::unique_ptr block_(new GpsL2MDllPllTrackingFpga(configuration.get(), role, in_streams, + out_streams)); + block = std::move(block_); + } +#endif else if ((implementation.compare("GPS_L5i_DLL_PLL_Tracking") == 0) or (implementation.compare("GPS_L5_DLL_PLL_Tracking") == 0)) { std::unique_ptr block_(new GpsL5DllPllTracking(configuration.get(), role, in_streams, out_streams)); block = std::move(block_); } +#if ENABLE_FPGA + else if ((implementation.compare("GPS_L5i_DLL_PLL_Tracking_Fpga") == 0) or (implementation.compare("GPS_L5_DLL_PLL_Tracking_Fpga") == 0)) + { + std::unique_ptr block_(new GpsL5DllPllTrackingFpga(configuration.get(), role, in_streams, + out_streams)); + block = std::move(block_); + } +#endif #if CUDA_GPU_ACCEL else if (implementation.compare("GPS_L1_CA_DLL_PLL_Tracking_GPU") == 0) { @@ -1515,6 +1561,14 @@ std::unique_ptr GNSSBlockFactory::GetBlock( out_streams)); block = std::move(block_); } +#if ENABLE_FPGA + else if (implementation.compare("Galileo_E5a_DLL_PLL_Tracking_Fpga") == 0) + { + std::unique_ptr block_(new GalileoE5aDllPllTrackingFpga(configuration.get(), role, in_streams, + out_streams)); + block = std::move(block_); + } +#endif else if (implementation.compare("GLONASS_L1_CA_DLL_PLL_Tracking") == 0) { std::unique_ptr block_(new GlonassL1CaDllPllTracking(configuration.get(), role, in_streams, @@ -1683,12 +1737,28 @@ std::unique_ptr GNSSBlockFactory::GetAcqBlock( out_streams)); block = std::move(block_); } +#if ENABLE_FPGA + else if (implementation.compare("GPS_L2_M_PCPS_Acquisition_Fpga") == 0) + { + std::unique_ptr block_(new GpsL2MPcpsAcquisitionFpga(configuration.get(), role, in_streams, + out_streams)); + block = std::move(block_); + } +#endif else if (implementation.compare("GPS_L5i_PCPS_Acquisition") == 0) { std::unique_ptr block_(new GpsL5iPcpsAcquisition(configuration.get(), role, in_streams, out_streams)); block = std::move(block_); } +#if ENABLE_FPGA + else if (implementation.compare("GPS_L5i_PCPS_Acquisition_Fpga") == 0) + { + std::unique_ptr block_(new GpsL5iPcpsAcquisitionFpga(configuration.get(), role, in_streams, + out_streams)); + block = std::move(block_); + } +#endif else if (implementation.compare("Galileo_E1_PCPS_Ambiguous_Acquisition") == 0) { std::unique_ptr block_(new GalileoE1PcpsAmbiguousAcquisition(configuration.get(), role, in_streams, @@ -1740,6 +1810,14 @@ std::unique_ptr GNSSBlockFactory::GetAcqBlock( out_streams)); block = std::move(block_); } +#if ENABLE_FPGA + else if (implementation.compare("Galileo_E5a_Pcps_Acquisition_Fpga") == 0) + { + std::unique_ptr block_(new GalileoE5aPcpsAcquisitionFpga(configuration.get(), role, in_streams, + out_streams)); + block = std::move(block_); + } +#endif else if (implementation.compare("GLONASS_L1_CA_PCPS_Acquisition") == 0) { std::unique_ptr block_(new GlonassL1CaPcpsAcquisition(configuration.get(), role, in_streams, @@ -1822,18 +1900,42 @@ std::unique_ptr GNSSBlockFactory::GetTrkBlock( out_streams)); block = std::move(block_); } +#if ENABLE_FPGA + else if (implementation.compare("Galileo_E5a_DLL_PLL_Tracking_Fpga") == 0) + { + std::unique_ptr block_(new GalileoE5aDllPllTrackingFpga(configuration.get(), role, in_streams, + out_streams)); + block = std::move(block_); + } +#endif else if (implementation.compare("GPS_L2_M_DLL_PLL_Tracking") == 0) { std::unique_ptr block_(new GpsL2MDllPllTracking(configuration.get(), role, in_streams, out_streams)); block = std::move(block_); } +#if ENABLE_FPGA + else if (implementation.compare("GPS_L2_M_DLL_PLL_Tracking_Fpga") == 0) + { + std::unique_ptr block_(new GpsL2MDllPllTrackingFpga(configuration.get(), role, in_streams, + out_streams)); + block = std::move(block_); + } +#endif else if ((implementation.compare("GPS_L5i_DLL_PLL_Tracking") == 0) or (implementation.compare("GPS_L5_DLL_PLL_Tracking") == 0)) { std::unique_ptr block_(new GpsL5DllPllTracking(configuration.get(), role, in_streams, out_streams)); block = std::move(block_); } +#if ENABLE_FPGA + else if ((implementation.compare("GPS_L5i_DLL_PLL_Tracking_Fpga") == 0) or (implementation.compare("GPS_L5_DLL_PLL_Tracking_Fpga") == 0)) + { + std::unique_ptr block_(new GpsL5DllPllTrackingFpga(configuration.get(), role, in_streams, + out_streams)); + block = std::move(block_); + } +#endif #if CUDA_GPU_ACCEL else if (implementation.compare("GPS_L1_CA_DLL_PLL_Tracking_GPU") == 0) { From daedfc3e01123850378adb0d28e1fcbd9958acc3 Mon Sep 17 00:00:00 2001 From: Marc Majoral Date: Thu, 2 Aug 2018 17:32:59 +0200 Subject: [PATCH 3/7] adapted the FPGA tracking class according to the latest changes in the next branch --- ...ileo_e1_pcps_ambiguous_acquisition_fpga.cc | 8 +- .../gnuradio_blocks/pcps_acquisition_fpga.cc | 2 +- .../galileo_e1_dll_pll_veml_tracking_fpga.cc | 2 +- .../galileo_e5a_dll_pll_tracking_fpga.cc | 2 +- .../gps_l1_ca_dll_pll_tracking_fpga.cc | 2 +- .../gps_l2_m_dll_pll_tracking_fpga.cc | 2 +- .../adapters/gps_l5_dll_pll_tracking_fpga.cc | 2 +- .../dll_pll_veml_tracking_fpga.cc | 234 ++++++++++++++---- .../dll_pll_veml_tracking_fpga.h | 80 +++--- src/algorithms/tracking/libs/CMakeLists.txt | 2 +- .../tracking/libs/dll_pll_conf_fpga.cc | 91 +++++++ .../tracking/libs/dll_pll_conf_fpga.h | 97 ++++++++ 12 files changed, 423 insertions(+), 101 deletions(-) create mode 100644 src/algorithms/tracking/libs/dll_pll_conf_fpga.cc create mode 100644 src/algorithms/tracking/libs/dll_pll_conf_fpga.h diff --git a/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition_fpga.cc b/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition_fpga.cc index a605c70c1..9a75f90e4 100644 --- a/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition_fpga.cc +++ b/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition_fpga.cc @@ -208,12 +208,12 @@ GalileoE1PcpsAmbiguousAcquisitionFpga::GalileoE1PcpsAmbiguousAcquisitionFpga( // static_cast(floor(4096*fft_codes_padded[i].imag() * (pow(2, 3) - 1) / max))); // d_all_fft_codes_[i + nsamples_total * (PRN - 1)] = lv_16sc_t(static_cast(floor(1024*fft_codes_padded[i].real() * (pow(2, 5) - 1) / max)), // static_cast(floor(1024*fft_codes_padded[i].imag() * (pow(2, 5) - 1) / max))); - d_all_fft_codes_[i + nsamples_total * (PRN - 1)] = lv_16sc_t(static_cast(floor(256*fft_codes_padded[i].real() * (pow(2, 7) - 1) / max)), - static_cast(floor(256*fft_codes_padded[i].imag() * (pow(2, 7) - 1) / max))); + // d_all_fft_codes_[i + nsamples_total * (PRN - 1)] = lv_16sc_t(static_cast(floor(256*fft_codes_padded[i].real() * (pow(2, 7) - 1) / max)), + // static_cast(floor(256*fft_codes_padded[i].imag() * (pow(2, 7) - 1) / max))); // d_all_fft_codes_[i + nsamples_total * (PRN - 1)] = lv_16sc_t(static_cast(floor(16*fft_codes_padded[i].real() * (pow(2, 11) - 1) / max)), // static_cast(floor(16*fft_codes_padded[i].imag() * (pow(2, 11) - 1) / max))); -// d_all_fft_codes_[i + nsamples_total * (PRN - 1)] = lv_16sc_t(static_cast(floor(fft_codes_padded[i].real() * (pow(2, 15) - 1) / max)), -// static_cast(floor(fft_codes_padded[i].imag() * (pow(2, 15) - 1) / max))); + d_all_fft_codes_[i + nsamples_total * (PRN - 1)] = lv_16sc_t(static_cast(floor(fft_codes_padded[i].real() * (pow(2, 15) - 1) / max)), + static_cast(floor(fft_codes_padded[i].imag() * (pow(2, 15) - 1) / max))); // tmp_re = static_cast(floor(fft_codes_padded[i].real() * (pow(2, 7) - 1) / max)); // tmp_im = static_cast(floor(fft_codes_padded[i].imag() * (pow(2, 7) - 1) / max)); diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.cc b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.cc index 8df1c9fd0..9ecb22b1a 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.cc +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.cc @@ -327,7 +327,7 @@ void pcps_acquisition_fpga::set_active(bool active) printf("##### d_test_statistics = %f\n", d_test_statistics); printf("##### debug_d_max_absolute =%f\n",debug_d_max_absolute); printf("##### debug_d_input_power_absolute =%f\n",debug_d_input_power_absolute); - printf("##### debug_indext = %d\n",debug_indext); + printf("##### initial_sample = %d\n",initial_sample); printf("##### debug_doppler_index = %d\n",debug_doppler_index); send_positive_acquisition(); d_state = 0; // Positive acquisition diff --git a/src/algorithms/tracking/adapters/galileo_e1_dll_pll_veml_tracking_fpga.cc b/src/algorithms/tracking/adapters/galileo_e1_dll_pll_veml_tracking_fpga.cc index 10e1b45c9..cd4b2f84b 100644 --- a/src/algorithms/tracking/adapters/galileo_e1_dll_pll_veml_tracking_fpga.cc +++ b/src/algorithms/tracking/adapters/galileo_e1_dll_pll_veml_tracking_fpga.cc @@ -51,7 +51,7 @@ GalileoE1DllPllVemlTrackingFpga::GalileoE1DllPllVemlTrackingFpga( unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams) { //dllpllconf_t trk_param; - dllpllconf_fpga_t trk_param_fpga; + Dll_Pll_Conf_Fpga trk_param_fpga = Dll_Pll_Conf_Fpga(); DLOG(INFO) << "role " << role; //################# CONFIGURATION PARAMETERS ######################## std::string default_item_type = "gr_complex"; diff --git a/src/algorithms/tracking/adapters/galileo_e5a_dll_pll_tracking_fpga.cc b/src/algorithms/tracking/adapters/galileo_e5a_dll_pll_tracking_fpga.cc index 08ae613c6..98edf3a84 100644 --- a/src/algorithms/tracking/adapters/galileo_e5a_dll_pll_tracking_fpga.cc +++ b/src/algorithms/tracking/adapters/galileo_e5a_dll_pll_tracking_fpga.cc @@ -50,7 +50,7 @@ GalileoE5aDllPllTrackingFpga::GalileoE5aDllPllTrackingFpga( ConfigurationInterface* configuration, std::string role, unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams) { - dllpllconf_fpga_t trk_param_fpga; + Dll_Pll_Conf_Fpga trk_param_fpga = Dll_Pll_Conf_Fpga(); DLOG(INFO) << "role " << role; //################# CONFIGURATION PARAMETERS ######################## std::string default_item_type = "gr_complex"; diff --git a/src/algorithms/tracking/adapters/gps_l1_ca_dll_pll_tracking_fpga.cc b/src/algorithms/tracking/adapters/gps_l1_ca_dll_pll_tracking_fpga.cc index 70b1b290e..06d59e91f 100644 --- a/src/algorithms/tracking/adapters/gps_l1_ca_dll_pll_tracking_fpga.cc +++ b/src/algorithms/tracking/adapters/gps_l1_ca_dll_pll_tracking_fpga.cc @@ -53,7 +53,7 @@ GpsL1CaDllPllTrackingFpga::GpsL1CaDllPllTrackingFpga( unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams) { - dllpllconf_fpga_t trk_param_fpga; + Dll_Pll_Conf_Fpga trk_param_fpga = Dll_Pll_Conf_Fpga(); DLOG(INFO) << "role " << role; //################# CONFIGURATION PARAMETERS ######################## diff --git a/src/algorithms/tracking/adapters/gps_l2_m_dll_pll_tracking_fpga.cc b/src/algorithms/tracking/adapters/gps_l2_m_dll_pll_tracking_fpga.cc index 862d21590..5cdf87185 100644 --- a/src/algorithms/tracking/adapters/gps_l2_m_dll_pll_tracking_fpga.cc +++ b/src/algorithms/tracking/adapters/gps_l2_m_dll_pll_tracking_fpga.cc @@ -52,7 +52,7 @@ GpsL2MDllPllTrackingFpga::GpsL2MDllPllTrackingFpga( unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams) { //dllpllconf_t trk_param; - dllpllconf_fpga_t trk_param_fpga; + Dll_Pll_Conf_Fpga trk_param_fpga = Dll_Pll_Conf_Fpga(); DLOG(INFO) << "role " << role; //################# CONFIGURATION PARAMETERS ######################## //std::string default_item_type = "gr_complex"; diff --git a/src/algorithms/tracking/adapters/gps_l5_dll_pll_tracking_fpga.cc b/src/algorithms/tracking/adapters/gps_l5_dll_pll_tracking_fpga.cc index f9b318869..aee08cfa1 100644 --- a/src/algorithms/tracking/adapters/gps_l5_dll_pll_tracking_fpga.cc +++ b/src/algorithms/tracking/adapters/gps_l5_dll_pll_tracking_fpga.cc @@ -52,7 +52,7 @@ GpsL5DllPllTrackingFpga::GpsL5DllPllTrackingFpga( unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams) { //dllpllconf_t trk_param; - dllpllconf_fpga_t trk_param_fpga; + Dll_Pll_Conf_Fpga trk_param_fpga = Dll_Pll_Conf_Fpga(); DLOG(INFO) << "role " << role; //################# CONFIGURATION PARAMETERS ######################## //std::string default_item_type = "gr_complex"; diff --git a/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking_fpga.cc b/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking_fpga.cc index 8d54d34b6..e368ea015 100644 --- a/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking_fpga.cc +++ b/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking_fpga.cc @@ -3,6 +3,7 @@ * \brief Implementation of a code DLL + carrier PLL tracking block using an FPGA * \author Marc Majoral, 2018. marc.majoral(at)cttc.es * Antonio Ramos, 2018 antonio.ramosdet(at)gmail.com + * Javier Arribas, 2018. jarribas(at)cttc.es * * Code DLL + carrier PLL according to the algorithms described in: * [1] K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen, @@ -29,7 +30,7 @@ * 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 . + * along with GNSS-SDR. If not, see . * * ------------------------------------------------------------------------- */ @@ -60,13 +61,13 @@ using google::LogMessage; -dll_pll_veml_tracking_fpga_sptr dll_pll_veml_make_tracking_fpga(dllpllconf_fpga_t conf_) +dll_pll_veml_tracking_fpga_sptr dll_pll_veml_make_tracking_fpga(const Dll_Pll_Conf_Fpga &conf_) { return dll_pll_veml_tracking_fpga_sptr(new dll_pll_veml_tracking_fpga(conf_)); } -dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_) : +dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(const Dll_Pll_Conf_Fpga &conf_) : gr::block("dll_pll_veml_tracking_fpga", gr::io_signature::make(0, 0, sizeof(lv_16sc_t)), gr::io_signature::make(1, 1, sizeof(Gnss_Synchro))) { @@ -75,6 +76,9 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_) this->message_port_register_out(pmt::mp("events")); this->set_relative_rate(1.0 / static_cast(trk_parameters.vector_length)); + // Telemetry bit synchronization message port input (mainly for GPS L1 CA) + this->message_port_register_in(pmt::mp("preamble_samplestamp")); + // initialize internal vars d_veml = false; d_cloop = true; @@ -114,6 +118,32 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_) d_secondary = false; trk_parameters.track_pilot = false; interchange_iq = false; + + + // set the preamble + unsigned short int preambles_bits[GPS_CA_PREAMBLE_LENGTH_BITS] = GPS_PREAMBLE; + + // preamble bits to sampled symbols + d_gps_l1ca_preambles_symbols = static_cast(volk_gnsssdr_malloc(GPS_CA_PREAMBLE_LENGTH_SYMBOLS * sizeof(int), volk_gnsssdr_get_alignment())); + int n = 0; + for (int i = 0; i < GPS_CA_PREAMBLE_LENGTH_BITS; i++) + { + for (unsigned int j = 0; j < GPS_CA_TELEMETRY_SYMBOLS_PER_BIT; j++) + { + if (preambles_bits[i] == 1) + { + d_gps_l1ca_preambles_symbols[n] = 1; + } + else + { + d_gps_l1ca_preambles_symbols[n] = -1; + } + n++; + } + } + d_symbol_history.resize(GPS_CA_PREAMBLE_LENGTH_SYMBOLS); // Change fixed buffer size + d_symbol_history.clear(); // Clear all the elements in the buffer + } else if (signal_type.compare("2S") == 0) { @@ -138,21 +168,21 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_) d_correlation_length_ms = 1; //d_code_samples_per_chip = 1; //d_code_length_chips = static_cast(GPS_L5i_CODE_LENGTH_CHIPS); - // GPS L5 does not have pilot secondary code d_secondary = true; - interchange_iq = false; + // interchange_iq = false; if (trk_parameters.track_pilot) { d_secondary_code_length = static_cast(GPS_L5q_NH_CODE_LENGTH); d_secondary_code_string = const_cast(&GPS_L5q_NH_CODE_STR); signal_pretty_name = signal_pretty_name + "Q"; - //interchange_iq = true; + interchange_iq = true; } else { d_secondary_code_length = static_cast(GPS_L5i_NH_CODE_LENGTH); d_secondary_code_string = const_cast(&GPS_L5i_NH_CODE_STR); signal_pretty_name = signal_pretty_name + "I"; + interchange_iq = false; } } else @@ -206,18 +236,19 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_) //d_code_samples_per_chip = 1; //d_code_length_chips = static_cast(Galileo_E5a_CODE_LENGTH_CHIPS); d_secondary = true; - interchange_iq = false; + //interchange_iq = false; if (trk_parameters.track_pilot) { d_secondary_code_length = static_cast(Galileo_E5a_Q_SECONDARY_CODE_LENGTH); signal_pretty_name = signal_pretty_name + "Q"; - // interchange_iq = true; + interchange_iq = true; } else { d_secondary_code_length = static_cast(Galileo_E5a_I_SECONDARY_CODE_LENGTH); d_secondary_code_string = const_cast(&Galileo_E5a_I_SECONDARY_CODE); signal_pretty_name = signal_pretty_name + "I"; + interchange_iq = false; } } else @@ -272,7 +303,7 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_) d_correlator_outs = static_cast(volk_gnsssdr_malloc(d_n_correlator_taps * sizeof(gr_complex), volk_gnsssdr_get_alignment())); d_local_code_shift_chips = static_cast(volk_gnsssdr_malloc(d_n_correlator_taps * sizeof(float), volk_gnsssdr_get_alignment())); - std::fill_n(d_correlator_outs, d_n_correlator_taps, gr_complex(0.0, 0.0)); + //std::fill_n(d_correlator_outs, d_n_correlator_taps, gr_complex(0.0, 0.0)); d_code_samples_per_chip = trk_parameters.code_samples_per_chip; // number of samples per chip @@ -327,12 +358,12 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_) if (trk_parameters.track_pilot) { // Extra correlator for the data component - d_Prompt_Data = static_cast(volk_gnsssdr_malloc(sizeof(gr_complex), volk_gnsssdr_get_alignment())); - d_Prompt_Data[0] = gr_complex(0.0, 0.0); + //d_Prompt_Data = static_cast(volk_gnsssdr_malloc(sizeof(gr_complex), volk_gnsssdr_get_alignment())); + //d_Prompt_Data[0] = gr_complex(0.0, 0.0); } else { - d_Prompt_Data = nullptr; + //d_Prompt_Data = nullptr; } //--- Initializations ---// @@ -346,6 +377,7 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_) // sample synchronization d_sample_counter = 0; d_acq_sample_stamp = 0; + d_absolute_samples_offset = 0; d_current_prn_length_samples = static_cast(trk_parameters.vector_length); d_next_prn_length_samples = d_current_prn_length_samples; @@ -358,8 +390,9 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_) d_CN0_SNV_dB_Hz = 0.0; d_carrier_lock_fail_counter = 0; d_carrier_lock_threshold = trk_parameters.carrier_lock_th; + d_Prompt_Data = static_cast(volk_gnsssdr_malloc(sizeof(gr_complex), volk_gnsssdr_get_alignment())); - clear_tracking_vars(); + //clear_tracking_vars(); d_acquisition_gnss_synchro = nullptr; d_channel = 0; @@ -376,6 +409,7 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_) d_code_phase_samples = 0.0; d_last_prompt = gr_complex(0.0, 0.0); d_state = 0; // initial state: standby + clear_tracking_vars(); //printf("hhhhhhhhhhh d_n_correlator_taps = %d\n", d_n_correlator_taps); @@ -395,9 +429,7 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_) void dll_pll_veml_tracking_fpga::start_tracking() { - /* - * correct the code phase according to the delay between acq and trk - */ + // correct the code phase according to the delay between acq and trk d_acq_code_phase_samples = d_acquisition_gnss_synchro->Acq_delay_samples; d_acq_carrier_doppler_hz = d_acquisition_gnss_synchro->Acq_doppler_hz; d_acq_sample_stamp = d_acquisition_gnss_synchro->Acq_samplestamp_samples; @@ -405,7 +437,7 @@ void dll_pll_veml_tracking_fpga::start_tracking() double acq_trk_diff_seconds = 0; // when using the FPGA we don't use the global sample counter // Doppler effect Fd = (C / (C + Vr)) * F double radial_velocity = (d_signal_carrier_freq + d_acq_carrier_doppler_hz) / d_signal_carrier_freq; - // new chip and prn sequence periods based on acq Doppler + // new chip and PRN sequence periods based on acq Doppler d_code_freq_chips = radial_velocity * d_code_chip_rate; d_code_phase_step_chips = d_code_freq_chips / trk_parameters.fs_in; @@ -413,7 +445,8 @@ void dll_pll_veml_tracking_fpga::start_tracking() double T_prn_mod_seconds = T_chip_mod_seconds * static_cast(d_code_length_chips); double T_prn_mod_samples = T_prn_mod_seconds * trk_parameters.fs_in; - d_current_prn_length_samples = std::round(T_prn_mod_samples); + //d_current_prn_length_samples = std::round(T_prn_mod_samples); + d_current_prn_length_samples = std::floor(T_prn_mod_samples); d_next_prn_length_samples = d_current_prn_length_samples; double T_prn_true_seconds = static_cast(d_code_length_chips) / d_code_chip_rate; double T_prn_true_samples = T_prn_true_seconds * trk_parameters.fs_in; @@ -538,6 +571,11 @@ void dll_pll_veml_tracking_fpga::start_tracking() dll_pll_veml_tracking_fpga::~dll_pll_veml_tracking_fpga() { + if (signal_type.compare("1C") == 0) + { + volk_gnsssdr_free(d_gps_l1ca_preambles_symbols); + } + if (d_dump_file.is_open()) { try @@ -565,10 +603,11 @@ dll_pll_veml_tracking_fpga::~dll_pll_veml_tracking_fpga() { volk_gnsssdr_free(d_local_code_shift_chips); volk_gnsssdr_free(d_correlator_outs); - if (trk_parameters.track_pilot) - { - volk_gnsssdr_free(d_Prompt_Data); - } + volk_gnsssdr_free(d_Prompt_Data); +// if (trk_parameters.track_pilot) +// { +// volk_gnsssdr_free(d_Prompt_Data); +// } delete[] d_Prompt_buffer; multicorrelator_fpga->free(); } @@ -609,7 +648,9 @@ bool dll_pll_veml_tracking_fpga::acquire_secondary() } } - if (abs(corr_value) == d_secondary_code_length) +// if (abs(corr_value) == d_secondary_code_length) + if (abs(corr_value) == static_cast(d_secondary_code_length)) + { return true; } @@ -705,7 +746,8 @@ void dll_pll_veml_tracking_fpga::run_dll_pll() void dll_pll_veml_tracking_fpga::clear_tracking_vars() { std::fill_n(d_correlator_outs, d_n_correlator_taps, gr_complex(0.0, 0.0)); - if (trk_parameters.track_pilot) *d_Prompt_Data = gr_complex(0.0, 0.0); + //if (trk_parameters.track_pilot) *d_Prompt_Data = gr_complex(0.0, 0.0); + if (trk_parameters.track_pilot) d_Prompt_Data[0] = gr_complex(0.0, 0.0); d_carr_error_hz = 0.0; d_carr_error_filt_hz = 0.0; d_code_error_chips = 0.0; @@ -727,7 +769,9 @@ void dll_pll_veml_tracking_fpga::update_tracking_vars() // Compute the next buffer length based in the new period of the PRN sequence and the code phase error estimation T_prn_samples = T_prn_seconds * trk_parameters.fs_in; K_blk_samples = T_prn_samples + d_rem_code_phase_samples + code_error_filt_secs * trk_parameters.fs_in; - d_next_prn_length_samples = round(K_blk_samples); + //d_next_prn_length_samples = round(K_blk_samples); + d_next_prn_length_samples = static_cast(std::floor(K_blk_samples)); // round to a discrete number of samples + //################### PLL COMMANDS ################################################# // carrier phase step (NCO phase increment per sample) [rads/sample] d_carrier_phase_step_rad = PI_2 * d_carrier_doppler_hz / trk_parameters.fs_in; @@ -812,6 +856,7 @@ void dll_pll_veml_tracking_fpga::log_data(bool integrating) float tmp_VE, tmp_E, tmp_P, tmp_L, tmp_VL; float tmp_float; double tmp_double; + unsigned long int tmp_long_int; if (trk_parameters.track_pilot) { if (interchange_iq) @@ -878,7 +923,9 @@ void dll_pll_veml_tracking_fpga::log_data(bool integrating) d_dump_file.write(reinterpret_cast(&prompt_I), sizeof(float)); d_dump_file.write(reinterpret_cast(&prompt_Q), sizeof(float)); // PRN start sample stamp - d_dump_file.write(reinterpret_cast(&d_sample_counter), sizeof(unsigned long int)); + //d_dump_file.write(reinterpret_cast(&d_sample_counter), sizeof(unsigned long int)); + tmp_long_int = d_sample_counter + d_current_prn_length_samples; + d_dump_file.write(reinterpret_cast(&tmp_long_int), sizeof(unsigned long int)); // accumulated carrier phase tmp_float = d_acc_carrier_phase_rad; d_dump_file.write(reinterpret_cast(&tmp_float), sizeof(float)); @@ -1194,7 +1241,7 @@ int dll_pll_veml_tracking_fpga::general_work (int noutput_items __attribute__((u d_correlator_outs[n] = gr_complex(0,0); } - current_synchro_data.Tracking_sample_counter =d_sample_counter + d_current_prn_length_samples; + current_synchro_data.Tracking_sample_counter = 0; // in order to reduce computational workload do not read the sample counter until we start tracking d_sample_counter + d_current_prn_length_samples; current_synchro_data.System = {'G'}; current_synchro_data.correlation_length_ms = 1; break; @@ -1214,6 +1261,7 @@ int dll_pll_veml_tracking_fpga::general_work (int noutput_items __attribute__((u unsigned absolute_samples_offset = current_synchro_data.Acq_delay_samples + current_synchro_data.Acq_samplestamp_samples + num_frames*d_correlation_length_samples; //printf("333333 absolute_samples_offset = %d\n", absolute_samples_offset); multicorrelator_fpga->set_initial_sample(absolute_samples_offset); + d_absolute_samples_offset = absolute_samples_offset; d_sample_counter = absolute_samples_offset; current_synchro_data.Tracking_sample_counter = absolute_samples_offset; d_sample_counter_next = d_sample_counter; @@ -1276,40 +1324,116 @@ int dll_pll_veml_tracking_fpga::general_work (int noutput_items __attribute__((u } else if (d_symbols_per_bit > 1) //Signal does not have secondary code. Search a bit transition by sign change { - if (d_synchonizing) - { - if (d_Prompt->real() * d_last_prompt.real() > 0.0) - { - d_current_symbol++; - } - else if (d_current_symbol > d_symbols_per_bit) - { - d_synchonizing = false; - d_current_symbol = 1; - } - else - { - d_current_symbol = 1; - d_last_prompt = *d_Prompt; - } - } - else if (d_last_prompt.real() != 0.0) - { - d_current_symbol++; - if (d_current_symbol == d_symbols_per_bit) next_state = true; - } - else - { - d_last_prompt = *d_Prompt; - d_synchonizing = true; - d_current_symbol = 1; - } +// if (d_synchonizing) +// { +// if (d_Prompt->real() * d_last_prompt.real() > 0.0) +// { +// d_current_symbol++; +// } +// else if (d_current_symbol > d_symbols_per_bit) +// { +// d_synchonizing = false; +// d_current_symbol = 1; +// } +// else +// { +// d_current_symbol = 1; +// d_last_prompt = *d_Prompt; +// } +// } +// else if (d_last_prompt.real() != 0.0) +// { +// d_current_symbol++; +// if (d_current_symbol == d_symbols_per_bit) next_state = true; +// } +// else +// { +// d_last_prompt = *d_Prompt; +// d_synchonizing = true; +// d_current_symbol = 1; +// } +// } +//=========================================================================================================== + //float current_tracking_time_s = static_cast(d_sample_counter - d_acq_sample_stamp) / trk_parameters.fs_in; + float current_tracking_time_s = static_cast(d_sample_counter - d_absolute_samples_offset) / trk_parameters.fs_in; + if (current_tracking_time_s > 10) + { + d_symbol_history.push_back(d_Prompt->real()); + //******* preamble correlation ******** + int corr_value = 0; + if ((d_symbol_history.size() == GPS_CA_PREAMBLE_LENGTH_SYMBOLS)) // and (d_make_correlation or !d_flag_frame_sync)) + { + for (unsigned int i = 0; i < GPS_CA_PREAMBLE_LENGTH_SYMBOLS; i++) + { + if (d_symbol_history.at(i) < 0) // symbols clipping + { + corr_value -= d_gps_l1ca_preambles_symbols[i]; + } + else + { + corr_value += d_gps_l1ca_preambles_symbols[i]; + } + } + } + if (corr_value == GPS_CA_PREAMBLE_LENGTH_SYMBOLS) + { + //std::cout << "Preamble detected at tracking!" << std::endl; + next_state = true; + } + else + { + next_state = false; + } + } + else + { + next_state = false; + } + + } else { next_state = true; } + // ########### Output the tracking results to Telemetry block ########## + if (interchange_iq) + { + if (trk_parameters.track_pilot) + { + // Note that data and pilot components are in quadrature. I and Q are interchanged + current_synchro_data.Prompt_I = static_cast((*d_Prompt_Data).imag()); + current_synchro_data.Prompt_Q = static_cast((*d_Prompt_Data).real()); + } + else + { + current_synchro_data.Prompt_I = static_cast((*d_Prompt).imag()); + current_synchro_data.Prompt_Q = static_cast((*d_Prompt).real()); + } + } + else + { + if (trk_parameters.track_pilot) + { + // Note that data and pilot components are in quadrature. I and Q are interchanged + current_synchro_data.Prompt_I = static_cast((*d_Prompt_Data).real()); + current_synchro_data.Prompt_Q = static_cast((*d_Prompt_Data).imag()); + } + else + { + current_synchro_data.Prompt_I = static_cast((*d_Prompt).real()); + current_synchro_data.Prompt_Q = static_cast((*d_Prompt).imag()); + } + } + current_synchro_data.Code_phase_samples = d_rem_code_phase_samples; + current_synchro_data.Carrier_phase_rads = d_acc_carrier_phase_rad; + current_synchro_data.Carrier_Doppler_hz = d_carrier_doppler_hz; + current_synchro_data.CN0_dB_hz = d_CN0_SNV_dB_Hz; + current_synchro_data.Flag_valid_symbol_output = true; + current_synchro_data.correlation_length_ms = d_correlation_length_ms; + + if (next_state) { // reset extended correlator d_VE_accu = gr_complex(0.0, 0.0); diff --git a/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking_fpga.h b/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking_fpga.h index 1d4944bde..a58e4b04a 100644 --- a/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking_fpga.h +++ b/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking_fpga.h @@ -39,6 +39,7 @@ #ifndef GNSS_SDR_DLL_PLL_VEML_TRACKING_FPGA_H #define GNSS_SDR_DLL_PLL_VEML_TRACKING_FPGA_H +#include "dll_pll_conf_fpga.h" #include "gnss_synchro.h" #include "tracking_2nd_DLL_filter.h" #include "tracking_2nd_PLL_filter.h" @@ -47,46 +48,49 @@ #include #include #include +#include +#include #include "fpga_multicorrelator.h" -typedef struct -{ - /* DLL/PLL tracking configuration */ - double fs_in; - unsigned int vector_length; - bool dump; - std::string dump_filename; - float pll_bw_hz; - float dll_bw_hz; - float pll_bw_narrow_hz; - float dll_bw_narrow_hz; - float early_late_space_chips; - float very_early_late_space_chips; - float early_late_space_narrow_chips; - float very_early_late_space_narrow_chips; - int extend_correlation_symbols; - int cn0_samples; - int cn0_min; - int max_lock_fail; - double carrier_lock_th; - bool track_pilot; - char system; - char signal[3]; - std::string device_name; - unsigned int device_base; - unsigned int multicorr_type; - unsigned int code_length_chips; - unsigned int code_samples_per_chip; - int* ca_codes; - int* data_codes; -} dllpllconf_fpga_t; +//typedef struct +//{ +// /* DLL/PLL tracking configuration */ +// double fs_in; +// unsigned int vector_length; +// bool dump; +// std::string dump_filename; +// float pll_bw_hz; +// float dll_bw_hz; +// float pll_bw_narrow_hz; +// float dll_bw_narrow_hz; +// float early_late_space_chips; +// float very_early_late_space_chips; +// float early_late_space_narrow_chips; +// float very_early_late_space_narrow_chips; +// int extend_correlation_symbols; +// int cn0_samples; +// int cn0_min; +// int max_lock_fail; +// double carrier_lock_th; +// bool track_pilot; +// char system; +// char signal[3]; +// std::string device_name; +// unsigned int device_base; +// unsigned int multicorr_type; +// unsigned int code_length_chips; +// unsigned int code_samples_per_chip; +// int* ca_codes; +// int* data_codes; +//} dllpllconf_fpga_t; class dll_pll_veml_tracking_fpga; typedef boost::shared_ptr dll_pll_veml_tracking_fpga_sptr; -dll_pll_veml_tracking_fpga_sptr dll_pll_veml_make_tracking_fpga(dllpllconf_fpga_t conf_); +//dll_pll_veml_tracking_fpga_sptr dll_pll_veml_make_tracking_fpga(const dllpllconf_fpga_t &conf_); +dll_pll_veml_tracking_fpga_sptr dll_pll_veml_make_tracking_fpga(const Dll_Pll_Conf_Fpga &conf_); /*! @@ -107,9 +111,10 @@ public: void reset(void); private: - friend dll_pll_veml_tracking_fpga_sptr dll_pll_veml_make_tracking_fpga(dllpllconf_fpga_t conf_); + friend dll_pll_veml_tracking_fpga_sptr dll_pll_veml_make_tracking_fpga(const Dll_Pll_Conf_Fpga &conf_); - dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_); + dll_pll_veml_tracking_fpga(const Dll_Pll_Conf_Fpga &conf_); + void msg_handler_preamble_index(pmt::pmt_t msg); bool cn0_and_tracking_lock_status(double coh_integration_time_s); bool acquire_secondary(); @@ -121,7 +126,8 @@ private: int save_matfile(); // tracking configuration vars - dllpllconf_fpga_t trk_parameters; + Dll_Pll_Conf_Fpga trk_parameters; + //dllpllconf_fpga_t trk_parameters; bool d_veml; bool d_cloop; unsigned int d_channel; @@ -142,6 +148,9 @@ private: std::string *d_secondary_code_string; std::string signal_pretty_name; + int *d_gps_l1ca_preambles_symbols; + boost::circular_buffer d_symbol_history; + //tracking state machine int d_state; bool d_synchonizing; @@ -206,6 +215,7 @@ private: // processing samples counters unsigned long int d_sample_counter; unsigned long int d_acq_sample_stamp; + unsigned long int d_absolute_samples_offset; // CN0 estimation and lock detector int d_cn0_estimation_counter; diff --git a/src/algorithms/tracking/libs/CMakeLists.txt b/src/algorithms/tracking/libs/CMakeLists.txt index fdb35a4e9..593bfe55f 100644 --- a/src/algorithms/tracking/libs/CMakeLists.txt +++ b/src/algorithms/tracking/libs/CMakeLists.txt @@ -47,7 +47,7 @@ set(TRACKING_LIB_SOURCES ) if(ENABLE_FPGA) - SET(TRACKING_LIB_SOURCES ${TRACKING_LIB_SOURCES} fpga_multicorrelator.cc) + SET(TRACKING_LIB_SOURCES ${TRACKING_LIB_SOURCES} fpga_multicorrelator.cc dll_pll_conf_fpga.cc) endif(ENABLE_FPGA) include_directories( diff --git a/src/algorithms/tracking/libs/dll_pll_conf_fpga.cc b/src/algorithms/tracking/libs/dll_pll_conf_fpga.cc new file mode 100644 index 000000000..47853a35b --- /dev/null +++ b/src/algorithms/tracking/libs/dll_pll_conf_fpga.cc @@ -0,0 +1,91 @@ +/*! + * \file dll_pll_conf.cc + * \brief Class that contains all the configuration parameters for generic + * tracking block based on a DLL and a PLL. + * \author Javier Arribas, 2018. jarribas(at)cttc.es + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2018 (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 "dll_pll_conf_fpga.h" +#include + +Dll_Pll_Conf_Fpga::Dll_Pll_Conf_Fpga() +{ +// /* DLL/PLL tracking configuration */ +// fs_in = 0.0; +// vector_length = 0; +// dump = false; +// dump_filename = "./dll_pll_dump.dat"; +// pll_bw_hz = 40.0; +// dll_bw_hz = 2.0; +// pll_bw_narrow_hz = 5.0; +// dll_bw_narrow_hz = 0.75; +// early_late_space_chips = 0.5; +// very_early_late_space_chips = 0.5; +// early_late_space_narrow_chips = 0.1; +// very_early_late_space_narrow_chips = 0.1; +// extend_correlation_symbols = 5; +// cn0_samples = 20; +// carrier_lock_det_mav_samples = 20; +// cn0_min = 25; +// max_lock_fail = 50; +// carrier_lock_th = 0.85; +// track_pilot = false; +// system = 'G'; +// char sig_[3] = "1C"; +// std::memcpy(signal, sig_, 3); + + /* DLL/PLL tracking configuration */ + fs_in = 0.0; + vector_length = 0; + dump = false; + dump_filename = "./dll_pll_dump.dat"; + pll_bw_hz = 40.0; + dll_bw_hz = 2.0; + pll_bw_narrow_hz = 5.0; + dll_bw_narrow_hz = 0.75; + early_late_space_chips = 0.5; + very_early_late_space_chips = 0.5; + early_late_space_narrow_chips = 0.1; + very_early_late_space_narrow_chips = 0.1; + extend_correlation_symbols = 5; + cn0_samples = 20; + cn0_min = 25; + max_lock_fail = 50; + carrier_lock_th = 0.85; + track_pilot = false; + system = 'G'; + char sig_[3] = "1C"; + std::memcpy(signal, sig_, 3); + device_name = "/dev/uio"; + device_base = 1; + multicorr_type = 0; + code_length_chips = 0; + code_samples_per_chip = 0; + //int* ca_codes; + //int* data_codes; +} diff --git a/src/algorithms/tracking/libs/dll_pll_conf_fpga.h b/src/algorithms/tracking/libs/dll_pll_conf_fpga.h new file mode 100644 index 000000000..febd847fe --- /dev/null +++ b/src/algorithms/tracking/libs/dll_pll_conf_fpga.h @@ -0,0 +1,97 @@ +/*! + * \file dll_pll_conf.h + * \brief Class that contains all the configuration parameters for generic tracking block based on a DLL and a PLL. + * \author Javier Arribas, 2018. jarribas(at)cttc.es + * + * Class that contains all the configuration parameters for generic tracking block based on a DLL and a PLL. + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2010-2018 (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_DLL_PLL_CONF_FPGA_H_ +#define GNSS_SDR_DLL_PLL_CONF_FPGA_H_ + +#include + +class Dll_Pll_Conf_Fpga +{ +private: +public: +// /* DLL/PLL tracking configuration */ +// double fs_in; +// unsigned int vector_length; +// bool dump; +// std::string dump_filename; +// float pll_bw_hz; +// float dll_bw_hz; +// float pll_bw_narrow_hz; +// float dll_bw_narrow_hz; +// float early_late_space_chips; +// float very_early_late_space_chips; +// float early_late_space_narrow_chips; +// float very_early_late_space_narrow_chips; +// int extend_correlation_symbols; +// int cn0_samples; +// int carrier_lock_det_mav_samples; +// int cn0_min; +// int max_lock_fail; +// double carrier_lock_th; +// bool track_pilot; +// char system; +// char signal[3]; + + /* DLL/PLL tracking configuration */ + double fs_in; + unsigned int vector_length; + bool dump; + std::string dump_filename; + float pll_bw_hz; + float dll_bw_hz; + float pll_bw_narrow_hz; + float dll_bw_narrow_hz; + float early_late_space_chips; + float very_early_late_space_chips; + float early_late_space_narrow_chips; + float very_early_late_space_narrow_chips; + int extend_correlation_symbols; + int cn0_samples; + int cn0_min; + int max_lock_fail; + double carrier_lock_th; + bool track_pilot; + char system; + char signal[3]; + std::string device_name; + unsigned int device_base; + unsigned int multicorr_type; + unsigned int code_length_chips; + unsigned int code_samples_per_chip; + int* ca_codes; + int* data_codes; + + Dll_Pll_Conf_Fpga(); +}; + +#endif From b1a7031e5278519c1ca765fb792510d8e3ea07ca Mon Sep 17 00:00:00 2001 From: Marc Majoral Date: Tue, 7 Aug 2018 18:56:54 +0200 Subject: [PATCH 4/7] solved some bugs in GPS L5 removed check for sign in multicorrelator results: this is not necessary anymore did some other minor maintenances --- ...ileo_e1_pcps_ambiguous_acquisition_fpga.cc | 9 +- ...lileo_e1_pcps_ambiguous_acquisition_fpga.h | 2 +- .../galileo_e5a_pcps_acquisition_fpga.cc | 10 +- .../gps_l1_ca_pcps_acquisition_fpga.cc | 4 +- .../gps_l2_m_pcps_acquisition_fpga.cc | 4 +- .../adapters/gps_l2_m_pcps_acquisition_fpga.h | 2 +- .../adapters/gps_l5i_pcps_acquisition_fpga.cc | 32 +++- .../adapters/gps_l5i_pcps_acquisition_fpga.h | 2 +- .../gnuradio_blocks/pcps_acquisition_fpga.cc | 5 +- .../gnuradio_blocks/pcps_acquisition_fpga.h | 2 +- .../acquisition/libs/fpga_acquisition.cc | 14 +- .../acquisition/libs/fpga_acquisition.h | 4 +- .../galileo_e5a_dll_pll_tracking_fpga.cc | 10 +- .../adapters/gps_l5_dll_pll_tracking_fpga.cc | 22 ++- .../tracking/libs/fpga_multicorrelator.cc | 143 +++++++++--------- 15 files changed, 158 insertions(+), 107 deletions(-) diff --git a/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition_fpga.cc b/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition_fpga.cc index 9a75f90e4..73a38d257 100644 --- a/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition_fpga.cc +++ b/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition_fpga.cc @@ -59,8 +59,8 @@ GalileoE1PcpsAmbiguousAcquisitionFpga::GalileoE1PcpsAmbiguousAcquisitionFpga( long fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 4000000); long fs_in = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated); acq_parameters.fs_in = fs_in; - if_ = configuration_->property(role + ".if", 0); - acq_parameters.freq = if_; + //if_ = configuration_->property(role + ".if", 0); + //acq_parameters.freq = if_; // dump_ = configuration_->property(role + ".dump", false); // acq_parameters.dump = dump_; @@ -69,8 +69,11 @@ GalileoE1PcpsAmbiguousAcquisitionFpga::GalileoE1PcpsAmbiguousAcquisitionFpga( doppler_max_ = configuration_->property(role + ".doppler_max", 5000); if (FLAGS_doppler_max != 0) doppler_max_ = FLAGS_doppler_max; acq_parameters.doppler_max = doppler_max_; - unsigned int sampled_ms = 4; + //unsigned int sampled_ms = 4; + //acq_parameters.sampled_ms = sampled_ms; + unsigned int sampled_ms = configuration_->property(role + ".coherent_integration_time_ms", 4); acq_parameters.sampled_ms = sampled_ms; + // bit_transition_flag_ = configuration_->property(role + ".bit_transition_flag", false); // acq_parameters.bit_transition_flag = bit_transition_flag_; // use_CFAR_algorithm_flag_ = configuration_->property(role + ".use_CFAR_algorithm", true); //will be false in future versions diff --git a/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition_fpga.h b/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition_fpga.h index bb0c5871f..eccba3ba0 100644 --- a/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition_fpga.h +++ b/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition_fpga.h @@ -157,7 +157,7 @@ private: //unsigned int sampled_ms_; unsigned int max_dwells_; //long fs_in_; - long if_; + //long if_; bool dump_; bool blocking_; std::string dump_filename_; diff --git a/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition_fpga.cc b/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition_fpga.cc index aba5d9931..2901081ac 100644 --- a/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition_fpga.cc +++ b/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition_fpga.cc @@ -47,6 +47,7 @@ using google::LogMessage; GalileoE5aPcpsAcquisitionFpga::GalileoE5aPcpsAcquisitionFpga(ConfigurationInterface* configuration, std::string role, unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams) { + //printf("creating the E5A acquisition"); pcpsconf_fpga_t acq_parameters; configuration_ = configuration; std::string default_item_type = "gr_complex"; @@ -59,7 +60,7 @@ GalileoE5aPcpsAcquisitionFpga::GalileoE5aPcpsAcquisitionFpga(ConfigurationInterf long fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 32000000); long fs_in = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated); acq_parameters.fs_in = fs_in; - acq_parameters.freq = 0; + //acq_parameters.freq = 0; //dump_ = configuration_->property(role + ".dump", false); @@ -94,6 +95,7 @@ GalileoE5aPcpsAcquisitionFpga::GalileoE5aPcpsAcquisitionFpga(ConfigurationInterf unsigned int nsamples_total = pow(2, nbits); unsigned int vector_length = nsamples_total; unsigned int select_queue_Fpga = configuration_->property(role + ".select_queue_Fpga", 1); + //printf("select_queue_Fpga = %d\n", select_queue_Fpga); acq_parameters.select_queue_Fpga = select_queue_Fpga; std::string default_device_name = "/dev/uio0"; std::string device_name = configuration_->property(role + ".devicename", default_device_name); @@ -111,6 +113,8 @@ GalileoE5aPcpsAcquisitionFpga::GalileoE5aPcpsAcquisitionFpga(ConfigurationInterf d_all_fft_codes_ = new lv_16sc_t[nsamples_total * Galileo_E5a_NUMBER_OF_CODES]; // memory containing all the possible fft codes for PRN 0 to 32 float max; // temporary maxima search + //printf("creating the E5A acquisition CONT"); + //printf("nsamples_total = %d\n", nsamples_total); for (unsigned int PRN = 1; PRN <= Galileo_E5a_NUMBER_OF_CODES; PRN++) { @@ -130,7 +134,8 @@ GalileoE5aPcpsAcquisitionFpga::GalileoE5aPcpsAcquisitionFpga(ConfigurationInterf strcpy(signal_, "5I"); } - galileo_e5_a_code_gen_complex_sampled(code, signal_, gnss_synchro_->PRN, fs_in_, 0); + + galileo_e5_a_code_gen_complex_sampled(code, signal_, PRN, fs_in, 0); // fill in zero padding for (int s = code_length; s < nsamples_total; s++) @@ -205,6 +210,7 @@ GalileoE5aPcpsAcquisitionFpga::GalileoE5aPcpsAcquisitionFpga(ConfigurationInterf //threshold_ = 0.0; doppler_step_ = 0; gnss_synchro_ = 0; + //printf("creating the E5A acquisition end"); } 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 c456a0e98..943130a69 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 @@ -63,8 +63,8 @@ GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga( //fs_in = fs_in/2.0; // downampling filter //printf("####### DEBUG Acq: fs_in = %d\n", fs_in); acq_parameters.fs_in = fs_in; - long ifreq = configuration_->property(role + ".if", 0); - acq_parameters.freq = ifreq; + //long ifreq = configuration_->property(role + ".if", 0); + //acq_parameters.freq = ifreq; doppler_max_ = configuration_->property(role + ".doppler_max", 5000); if (FLAGS_doppler_max != 0) doppler_max_ = FLAGS_doppler_max; acq_parameters.doppler_max = doppler_max_; diff --git a/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition_fpga.cc b/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition_fpga.cc index c20916e16..733f3cea9 100644 --- a/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition_fpga.cc +++ b/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition_fpga.cc @@ -61,8 +61,8 @@ GpsL2MPcpsAcquisitionFpga::GpsL2MPcpsAcquisitionFpga( long fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 2048000); fs_in_ = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated); acq_parameters.fs_in = fs_in_; - if_ = configuration_->property(role + ".if", 0); - acq_parameters.freq = if_; + //if_ = configuration_->property(role + ".if", 0); + //acq_parameters.freq = if_; //dump_ = configuration_->property(role + ".dump", false); //acq_parameters.dump = dump_; //blocking_ = configuration_->property(role + ".blocking", true); diff --git a/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition_fpga.h b/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition_fpga.h index 47f55d10f..9f06cea42 100644 --- a/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition_fpga.h +++ b/src/algorithms/acquisition/adapters/gps_l2_m_pcps_acquisition_fpga.h @@ -153,7 +153,7 @@ private: unsigned int doppler_step_; unsigned int max_dwells_; long fs_in_; - long if_; + //long if_; bool dump_; bool blocking_; std::string dump_filename_; diff --git a/src/algorithms/acquisition/adapters/gps_l5i_pcps_acquisition_fpga.cc b/src/algorithms/acquisition/adapters/gps_l5i_pcps_acquisition_fpga.cc index 038f56567..57e986d66 100644 --- a/src/algorithms/acquisition/adapters/gps_l5i_pcps_acquisition_fpga.cc +++ b/src/algorithms/acquisition/adapters/gps_l5i_pcps_acquisition_fpga.cc @@ -47,6 +47,7 @@ GpsL5iPcpsAcquisitionFpga::GpsL5iPcpsAcquisitionFpga( ConfigurationInterface* configuration, std::string role, unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams) { + //printf("L5 ACQ CLASS CREATED\n"); pcpsconf_fpga_t acq_parameters; configuration_ = configuration; std::string default_item_type = "gr_complex"; @@ -59,8 +60,8 @@ GpsL5iPcpsAcquisitionFpga::GpsL5iPcpsAcquisitionFpga( long fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 2048000); long fs_in = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated); acq_parameters.fs_in = fs_in; - if_ = configuration_->property(role + ".if", 0); - acq_parameters.freq = if_; + //if_ = configuration_->property(role + ".if", 0); + //acq_parameters.freq = if_; //dump_ = configuration_->property(role + ".dump", false); //acq_parameters.dump = dump_; //blocking_ = configuration_->property(role + ".blocking", true); @@ -68,7 +69,12 @@ GpsL5iPcpsAcquisitionFpga::GpsL5iPcpsAcquisitionFpga( doppler_max_ = configuration->property(role + ".doppler_max", 5000); if (FLAGS_doppler_max != 0) doppler_max_ = FLAGS_doppler_max; acq_parameters.doppler_max = doppler_max_; - acq_parameters.sampled_ms = 1; + //acq_parameters.sampled_ms = 1; + unsigned int sampled_ms = configuration_->property(role + ".coherent_integration_time_ms", 1); + acq_parameters.sampled_ms = sampled_ms; + + //printf("L5 ACQ CLASS MID 0\n"); + //bit_transition_flag_ = configuration_->property(role + ".bit_transition_flag", false); //acq_parameters.bit_transition_flag = bit_transition_flag_; //use_CFAR_algorithm_flag_ = configuration_->property(role + ".use_CFAR_algorithm", true); //will be false in future versions @@ -78,32 +84,38 @@ GpsL5iPcpsAcquisitionFpga::GpsL5iPcpsAcquisitionFpga( //dump_filename_ = configuration_->property(role + ".dump_filename", default_dump_filename); //acq_parameters.dump_filename = dump_filename_; //--- Find number of samples per spreading code ------------------------- - unsigned int code_length = static_cast(std::round(static_cast(fs_in_) / (GPS_L5i_CODE_RATE_HZ / static_cast(GPS_L5i_CODE_LENGTH_CHIPS)))); + unsigned int code_length = static_cast(std::round(static_cast(fs_in) / (GPS_L5i_CODE_RATE_HZ / static_cast(GPS_L5i_CODE_LENGTH_CHIPS)))); acq_parameters.code_length = code_length; // The FPGA can only use FFT lengths that are a power of two. float nbits = ceilf(log2f((float)code_length)); unsigned int nsamples_total = pow(2, nbits); unsigned int vector_length = nsamples_total; - unsigned int select_queue_Fpga = configuration_->property(role + ".select_queue_Fpga", 0); + unsigned int select_queue_Fpga = configuration_->property(role + ".select_queue_Fpga", 1); acq_parameters.select_queue_Fpga = select_queue_Fpga; std::string default_device_name = "/dev/uio0"; std::string device_name = configuration_->property(role + ".devicename", default_device_name); acq_parameters.device_name = device_name; acq_parameters.samples_per_ms = nsamples_total; acq_parameters.samples_per_code = nsamples_total; - + //printf("L5 ACQ CLASS MID 01\n"); // compute all the GPS L5 PRN Codes (this is done only once upon the class constructor in order to avoid re-computing the PRN codes every time // a channel is assigned) gr::fft::fft_complex* fft_if = new gr::fft::fft_complex(vector_length, true); // Direct FFT - std::complex* code = new gr_complex[vector_length_]; + //printf("L5 ACQ CLASS MID 02\n"); + std::complex* code = new gr_complex[vector_length]; + //printf("L5 ACQ CLASS MID 03\n"); gr_complex* fft_codes_padded = static_cast(volk_gnsssdr_malloc(nsamples_total * sizeof(gr_complex), volk_gnsssdr_get_alignment())); + //printf("L5 ACQ CLASS MID 04\n"); d_all_fft_codes_ = new lv_16sc_t[nsamples_total * NUM_PRNs]; // memory containing all the possible fft codes for PRN 0 to 32 + //printf("L5 ACQ CLASS MID 1 vector_length = %d\n", vector_length); + float max; // temporary maxima search for (unsigned int PRN = 1; PRN <= NUM_PRNs; PRN++) { - + //printf("L5 ACQ CLASS processing PRN = %d\n", PRN); gps_l5i_code_gen_complex_sampled(code, PRN, fs_in); + //printf("L5 ACQ CLASS processing PRN = %d (cont) \n", PRN); // fill in zero padding for (int s = code_length; s < nsamples_total; s++) { @@ -141,6 +153,9 @@ GpsL5iPcpsAcquisitionFpga::GpsL5iPcpsAcquisitionFpga( } + + //printf("L5 ACQ CLASS MID 2\n"); + //acq_parameters acq_parameters.all_fft_codes = d_all_fft_codes_; @@ -191,6 +206,7 @@ GpsL5iPcpsAcquisitionFpga::GpsL5iPcpsAcquisitionFpga( // threshold_ = 0.0; doppler_step_ = 0; gnss_synchro_ = 0; + //printf("L5 ACQ CLASS FINISHED\n"); } diff --git a/src/algorithms/acquisition/adapters/gps_l5i_pcps_acquisition_fpga.h b/src/algorithms/acquisition/adapters/gps_l5i_pcps_acquisition_fpga.h index d125192dd..01b8b0845 100644 --- a/src/algorithms/acquisition/adapters/gps_l5i_pcps_acquisition_fpga.h +++ b/src/algorithms/acquisition/adapters/gps_l5i_pcps_acquisition_fpga.h @@ -153,7 +153,7 @@ private: unsigned int doppler_step_; unsigned int max_dwells_; long fs_in_; - long if_; + //long if_; bool dump_; bool blocking_; std::string dump_filename_; diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.cc b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.cc index 9ecb22b1a..deaa1a790 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.cc +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.cc @@ -88,7 +88,7 @@ pcps_acquisition_fpga::pcps_acquisition_fpga(pcpsconf_fpga_t conf_) : gr::block( // this one is the one it should be but it doesn't work acquisition_fpga = std::make_shared (acq_parameters.device_name, acq_parameters.code_length, acq_parameters.doppler_max, d_fft_size, - acq_parameters.fs_in, acq_parameters.freq, acq_parameters.sampled_ms, acq_parameters.select_queue_Fpga, acq_parameters.all_fft_codes); + acq_parameters.fs_in, acq_parameters.sampled_ms, acq_parameters.select_queue_Fpga, acq_parameters.all_fft_codes); // acquisition_fpga = std::make_shared // (acq_parameters.device_name, acq_parameters.samples_per_code, acq_parameters.doppler_max, acq_parameters.samples_per_code, @@ -269,11 +269,12 @@ void pcps_acquisition_fpga::set_active(bool active) //acquisition_fpga->block_samples(); // run loop in hw + //printf("LAUNCH ACQ\n"); acquisition_fpga->set_doppler_sweep(d_num_doppler_bins); acquisition_fpga->run_acquisition(); acquisition_fpga->read_acquisition_results(&indext, &magt, &initial_sample, &d_input_power, &d_doppler_index); - + //printf("READ ACQ RESULTS\n"); // debug //acquisition_fpga->unblock_samples(); diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.h b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.h index 6621737a6..e684b0971 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.h +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.h @@ -66,7 +66,7 @@ typedef struct /* pcps acquisition configuration */ unsigned int sampled_ms; unsigned int doppler_max; - long freq; + //long freq; long fs_in; int samples_per_ms; int samples_per_code; diff --git a/src/algorithms/acquisition/libs/fpga_acquisition.cc b/src/algorithms/acquisition/libs/fpga_acquisition.cc index 7ca39b57e..8e941fad7 100644 --- a/src/algorithms/acquisition/libs/fpga_acquisition.cc +++ b/src/algorithms/acquisition/libs/fpga_acquisition.cc @@ -92,7 +92,7 @@ bool fpga_acquisition::set_local_code(unsigned int PRN) fpga_acquisition::fpga_acquisition(std::string device_name, unsigned int nsamples, unsigned int doppler_max, - unsigned int nsamples_total, long fs_in, long freq, + unsigned int nsamples_total, long fs_in, unsigned int sampled_ms, unsigned select_queue, lv_16sc_t *all_fft_codes) { @@ -103,7 +103,7 @@ fpga_acquisition::fpga_acquisition(std::string device_name, //printf("AAA- vector_length = %d\n ", vector_length); // initial values d_device_name = device_name; - d_freq = freq; + //d_freq = freq; d_fs_in = fs_in; d_vector_length = vector_length; d_nsamples = nsamples; // number of samples not including padding @@ -237,7 +237,8 @@ void fpga_acquisition::set_doppler_sweep(unsigned int num_sweeps) int32_t phase_step_rad_int; //int doppler = static_cast(-d_doppler_max) + d_doppler_step * doppler_index; int doppler = static_cast(-d_doppler_max); - float phase_step_rad = GPS_TWO_PI * (d_freq + doppler) / static_cast(d_fs_in); + //float phase_step_rad = GPS_TWO_PI * (d_freq + doppler) / static_cast(d_fs_in); + float phase_step_rad = GPS_TWO_PI * (doppler) / static_cast(d_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) @@ -282,7 +283,8 @@ void fpga_acquisition::set_doppler_sweep_debug(unsigned int num_sweeps, unsigned int32_t phase_step_rad_int; int doppler = static_cast(-d_doppler_max) + d_doppler_step * doppler_index; //int doppler = static_cast(-d_doppler_max); - float phase_step_rad = GPS_TWO_PI * (d_freq + doppler) / static_cast(d_fs_in); + //float phase_step_rad = GPS_TWO_PI * (d_freq + doppler) / static_cast(d_fs_in); + float phase_step_rad = GPS_TWO_PI * (doppler) / static_cast(d_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) @@ -325,6 +327,7 @@ void fpga_acquisition::set_doppler_sweep_debug(unsigned int num_sweeps, unsigned void fpga_acquisition::configure_acquisition() { + //printf("AAA d_select_queue = %d\n", d_select_queue); d_map_base[0] = d_select_queue; //printf("AAA writing d_vector_length = %d to d map base 1\n ", d_vector_length); d_map_base[1] = d_vector_length; @@ -343,7 +346,8 @@ void fpga_acquisition::set_phase_step(unsigned int doppler_index) float phase_step_rad_int_temp; int32_t phase_step_rad_int; int doppler = static_cast(-d_doppler_max) + d_doppler_step * doppler_index; - float phase_step_rad = GPS_TWO_PI * (d_freq + doppler) / static_cast(d_fs_in); + //float phase_step_rad = GPS_TWO_PI * (d_freq + doppler) / static_cast(d_fs_in); + float phase_step_rad = GPS_TWO_PI * (doppler) / static_cast(d_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) diff --git a/src/algorithms/acquisition/libs/fpga_acquisition.h b/src/algorithms/acquisition/libs/fpga_acquisition.h index 80d7ddc9d..710ab4e8c 100644 --- a/src/algorithms/acquisition/libs/fpga_acquisition.h +++ b/src/algorithms/acquisition/libs/fpga_acquisition.h @@ -48,7 +48,7 @@ public: fpga_acquisition(std::string device_name, unsigned int nsamples, unsigned int doppler_max, - unsigned int nsamples_total, long fs_in, long freq, + unsigned int nsamples_total, long fs_in, unsigned int sampled_ms, unsigned select_queue, lv_16sc_t *all_fft_codes); ~fpga_acquisition(); @@ -84,7 +84,7 @@ public: } private: - long d_freq; + //long d_freq; long d_fs_in; gr::fft::fft_complex *d_fft_if; // function used to run the fft of the local codes // data related to the hardware module and the driver diff --git a/src/algorithms/tracking/adapters/galileo_e5a_dll_pll_tracking_fpga.cc b/src/algorithms/tracking/adapters/galileo_e5a_dll_pll_tracking_fpga.cc index 98edf3a84..8be397a02 100644 --- a/src/algorithms/tracking/adapters/galileo_e5a_dll_pll_tracking_fpga.cc +++ b/src/algorithms/tracking/adapters/galileo_e5a_dll_pll_tracking_fpga.cc @@ -50,6 +50,9 @@ GalileoE5aDllPllTrackingFpga::GalileoE5aDllPllTrackingFpga( ConfigurationInterface* configuration, std::string role, unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams) { + //printf("creating the E5A tracking"); + + Dll_Pll_Conf_Fpga trk_param_fpga = Dll_Pll_Conf_Fpga(); DLOG(INFO) << "role " << role; //################# CONFIGURATION PARAMETERS ######################## @@ -123,7 +126,7 @@ GalileoE5aDllPllTrackingFpga::GalileoE5aDllPllTrackingFpga( unsigned int device_base = configuration->property(role + ".device_base", 1); trk_param_fpga.device_base = device_base; //unsigned int multicorr_type = configuration->property(role + ".multicorr_type", 1); - trk_param_fpga.multicorr_type = 1; // 0 -> 3 correlators, 1 -> 5 correlators + trk_param_fpga.multicorr_type = 1; // 0 -> 3 correlators, 1 -> up to 5+1 correlators //################# PRE-COMPUTE ALL THE CODES ################# unsigned int code_samples_per_chip = 1; @@ -201,6 +204,7 @@ GalileoE5aDllPllTrackingFpga::GalileoE5aDllPllTrackingFpga( trk_param_fpga.code_length_chips = code_length_chips; trk_param_fpga.code_samples_per_chip = code_samples_per_chip; // 2 sample per chip //################# MAKE TRACKING GNURadio object ################### + tracking_fpga_sc = dll_pll_veml_make_tracking_fpga(trk_param_fpga); // if (item_type.compare("gr_complex") == 0) // { // item_size_ = sizeof(gr_complex); @@ -212,8 +216,11 @@ GalileoE5aDllPllTrackingFpga::GalileoE5aDllPllTrackingFpga( // LOG(WARNING) << item_type << " unknown tracking item type."; // } channel_ = 0; + //DLOG(INFO) << "tracking(" << tracking_->unique_id() << ")"; DLOG(INFO) << "tracking(" << tracking_fpga_sc->unique_id() << ")"; + + } @@ -240,6 +247,7 @@ void GalileoE5aDllPllTrackingFpga::start_tracking() */ void GalileoE5aDllPllTrackingFpga::set_channel(unsigned int channel) { + //printf("blabla channel = %d\n", channel); channel_ = channel; //tracking_->set_channel(channel); tracking_fpga_sc->set_channel(channel); diff --git a/src/algorithms/tracking/adapters/gps_l5_dll_pll_tracking_fpga.cc b/src/algorithms/tracking/adapters/gps_l5_dll_pll_tracking_fpga.cc index aee08cfa1..0df38771c 100644 --- a/src/algorithms/tracking/adapters/gps_l5_dll_pll_tracking_fpga.cc +++ b/src/algorithms/tracking/adapters/gps_l5_dll_pll_tracking_fpga.cc @@ -51,6 +51,7 @@ GpsL5DllPllTrackingFpga::GpsL5DllPllTrackingFpga( ConfigurationInterface* configuration, std::string role, unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams) { + //printf("L5 TRK CLASS CREATED\n"); //dllpllconf_t trk_param; Dll_Pll_Conf_Fpga trk_param_fpga = Dll_Pll_Conf_Fpga(); DLOG(INFO) << "role " << role; @@ -130,6 +131,7 @@ GpsL5DllPllTrackingFpga::GpsL5DllPllTrackingFpga( //################# PRE-COMPUTE ALL THE CODES ################# unsigned int code_samples_per_chip = 1; unsigned int code_length_chips = static_cast(GPS_L5i_CODE_LENGTH_CHIPS); + //printf("TRK code_length_chips = %d\n", code_length_chips); float *tracking_code; float *data_code; @@ -148,27 +150,30 @@ GpsL5DllPllTrackingFpga::GpsL5DllPllTrackingFpga( d_data_codes = static_cast(volk_gnsssdr_malloc((static_cast(code_length_chips)) * NUM_PRNs * sizeof(int), volk_gnsssdr_get_alignment())); } + //printf("start \n"); for (unsigned int PRN = 1; PRN <= NUM_PRNs; PRN++) { + if (track_pilot) { + gps_l5q_code_gen_float(tracking_code, PRN); gps_l5i_code_gen_float(data_code, PRN); - for (unsigned int s = 0; s < 2*code_length_chips; s++) - { - d_ca_codes[static_cast(code_length_chips)* (PRN - 1) + s] = static_cast(tracking_code[s]); - d_data_codes[static_cast(code_length_chips)* (PRN - 1) + s] = static_cast(data_code[s]); - //printf("%f %d | ", data_codes_f[s], d_data_codes[static_cast(Galileo_E1_B_CODE_LENGTH_CHIPS)* 2 * (PRN - 1) + s]); + for (unsigned int s = 0; s < code_length_chips; s++) + { + d_ca_codes[static_cast(code_length_chips)* (PRN - 1) + s] = static_cast(tracking_code[s]); + d_data_codes[static_cast(code_length_chips)* (PRN - 1) + s] = static_cast(data_code[s]); + //printf("%f %d | ", data_codes_f[s], d_data_codes[static_cast(Galileo_E1_B_CODE_LENGTH_CHIPS)* 2 * (PRN - 1) + s]); - } + } } else { - gps_l5i_code_gen_float(tracking_code, PRN); + gps_l5i_code_gen_float(tracking_code, PRN); for (unsigned int s = 0; s < code_length_chips; s++) { d_ca_codes[static_cast(code_length_chips) * (PRN - 1) + s] = static_cast(data_code[s]); @@ -176,6 +181,7 @@ GpsL5DllPllTrackingFpga::GpsL5DllPllTrackingFpga( } } } + //printf("end \n"); delete[] tracking_code; @@ -198,7 +204,9 @@ GpsL5DllPllTrackingFpga::GpsL5DllPllTrackingFpga( // item_size_ = sizeof(gr_complex); // LOG(WARNING) << item_type << " unknown tracking item type."; // } + //printf("call \n"); tracking_fpga_sc = dll_pll_veml_make_tracking_fpga(trk_param_fpga); + //printf("end2 \n"); channel_ = 0; DLOG(INFO) << "tracking(" << tracking_fpga_sc->unique_id() << ")"; } diff --git a/src/algorithms/tracking/libs/fpga_multicorrelator.cc b/src/algorithms/tracking/libs/fpga_multicorrelator.cc index f3d0752c7..ba9e65aa4 100644 --- a/src/algorithms/tracking/libs/fpga_multicorrelator.cc +++ b/src/algorithms/tracking/libs/fpga_multicorrelator.cc @@ -155,6 +155,8 @@ fpga_multicorrelator_8sc::fpga_multicorrelator_8sc(int n_correlators, std::string device_name, unsigned int device_base, int *ca_codes, int *data_codes, unsigned int code_length_chips, bool track_pilot, unsigned int multicorr_type, unsigned int code_samples_per_chip) { + + //printf("tracking fpga class created\n"); d_n_correlators = n_correlators; d_device_name = device_name; d_device_base = device_base; @@ -203,21 +205,21 @@ fpga_multicorrelator_8sc::fpga_multicorrelator_8sc(int n_correlators, // write-only registers d_CODE_PHASE_STEP_CHIPS_NUM_REG_ADDR = 0; d_INITIAL_INDEX_REG_BASE_ADDR = 1; - if (d_multicorr_type == 0) - { - // multicorrelator with 3 correlators (16 registers only) - d_INITIAL_INTERP_COUNTER_REG_BASE_ADDR = 4; - d_NSAMPLES_MINUS_1_REG_ADDR = 7; - d_CODE_LENGTH_MINUS_1_REG_ADDR = 8; - d_REM_CARR_PHASE_RAD_REG_ADDR = 9; - d_PHASE_STEP_RAD_REG_ADDR = 10; - d_PROG_MEMS_ADDR = 11; - d_DROP_SAMPLES_REG_ADDR = 12; - d_INITIAL_COUNTER_VALUE_REG_ADDR = 13; - d_START_FLAG_ADDR = 14; - } - else - { +// if (d_multicorr_type == 0) +// { +// // multicorrelator with 3 correlators (16 registers only) +// d_INITIAL_INTERP_COUNTER_REG_BASE_ADDR = 4; +// d_NSAMPLES_MINUS_1_REG_ADDR = 7; +// d_CODE_LENGTH_MINUS_1_REG_ADDR = 8; +// d_REM_CARR_PHASE_RAD_REG_ADDR = 9; +// d_PHASE_STEP_RAD_REG_ADDR = 10; +// d_PROG_MEMS_ADDR = 11; +// d_DROP_SAMPLES_REG_ADDR = 12; +// d_INITIAL_COUNTER_VALUE_REG_ADDR = 13; +// d_START_FLAG_ADDR = 14; +// } +// else +// { // other types of multicorrelators (32 registers) d_INITIAL_INTERP_COUNTER_REG_BASE_ADDR = 7; d_NSAMPLES_MINUS_1_REG_ADDR = 13; @@ -228,19 +230,21 @@ fpga_multicorrelator_8sc::fpga_multicorrelator_8sc(int n_correlators, d_DROP_SAMPLES_REG_ADDR = 18; d_INITIAL_COUNTER_VALUE_REG_ADDR = 19; d_START_FLAG_ADDR = 30; - } +// } + //printf("d_n_correlators = %d\n", d_n_correlators); + //printf("d_multicorr_type = %d\n", d_multicorr_type); // read-write registers - if (d_multicorr_type == 0) - { - // multicorrelator with 3 correlators (16 registers only) - d_TEST_REG_ADDR = 15; - } - else - { +// if (d_multicorr_type == 0) +// { +// // multicorrelator with 3 correlators (16 registers only) +// d_TEST_REG_ADDR = 15; +// } +// else +// { // other types of multicorrelators (32 registers) d_TEST_REG_ADDR = 31; - } + // } // result 2's complement saturation value if (d_multicorr_type == 0) @@ -256,24 +260,24 @@ fpga_multicorrelator_8sc::fpga_multicorrelator_8sc(int n_correlators, // read only registers d_RESULT_REG_REAL_BASE_ADDR = 1; - if (d_multicorr_type == 0) - { - // multicorrelator with 3 correlators (16 registers only) - d_RESULT_REG_IMAG_BASE_ADDR = 4; - d_RESULT_REG_DATA_REAL_BASE_ADDR = 0; // no pilot tracking - d_RESULT_REG_DATA_IMAG_BASE_ADDR = 0; - d_SAMPLE_COUNTER_REG_ADDR = 7; - - } - else - { +// if (d_multicorr_type == 0) +// { +// // multicorrelator with 3 correlators (16 registers only) +// d_RESULT_REG_IMAG_BASE_ADDR = 4; +// d_RESULT_REG_DATA_REAL_BASE_ADDR = 0; // no pilot tracking +// d_RESULT_REG_DATA_IMAG_BASE_ADDR = 0; +// d_SAMPLE_COUNTER_REG_ADDR = 7; +// +// } +// else +// { // other types of multicorrelators (32 registers) d_RESULT_REG_IMAG_BASE_ADDR = 7; d_RESULT_REG_DATA_REAL_BASE_ADDR = 6; // no pilot tracking d_RESULT_REG_DATA_IMAG_BASE_ADDR = 12; d_SAMPLE_COUNTER_REG_ADDR = 13; - } +// } //printf("d_SAMPLE_COUNTER_REG_ADDR = %d\n", d_SAMPLE_COUNTER_REG_ADDR); //printf("mmmmmmmmmmmmm d_n_correlators = %d\n", d_n_correlators); @@ -313,6 +317,7 @@ bool fpga_multicorrelator_8sc::free() void fpga_multicorrelator_8sc::set_channel(unsigned int channel) { + //printf("www trk set channel\n"); char device_io_name[MAX_LENGTH_DEVICEIO_NAME]; // driver io name d_channel = channel; @@ -354,7 +359,7 @@ void fpga_multicorrelator_8sc::set_channel(unsigned int channel) // } // else // { -// printf("mapping registers succes\n"); // this is for debug -- remove ! +// printf("trk mapping registers succes\n"); // this is for debug -- remove ! // } // sanity check : check test register @@ -364,7 +369,7 @@ void fpga_multicorrelator_8sc::set_channel(unsigned int channel) if (writeval != readval) { LOG(WARNING) << "Test register sanity check failed"; - // printf("tracking test register sanity check failed\n"); + printf("tracking test register sanity check failed\n"); //printf("lslslls test sanity check reg failure\n"); } @@ -458,7 +463,7 @@ void fpga_multicorrelator_8sc::fpga_configure_tracking_gps_local_code(int PRN) | code_chip | select_pilot_corelator; } } - printf("\n"); + //printf("\n"); } @@ -628,39 +633,39 @@ void fpga_multicorrelator_8sc::read_tracking_gps_results(void) int readval_imag; int k; - + //printf("www reading trk results\n"); for (k = 0; k < d_n_correlators; k++) { readval_real = d_map_base[d_RESULT_REG_REAL_BASE_ADDR + k]; //printf("read real before checking d map base %d = %d\n", d_RESULT_REG_BASE_ADDR + k, readval_real); -// if (readval_real > debug_max_readval_real[k]) +//// if (readval_real > debug_max_readval_real[k]) +//// { +//// debug_max_readval_real[k] = readval_real; +//// } +// if (readval_real >= d_result_SAT_value) // 0x100000 (21 bits two's complement) // { -// debug_max_readval_real[k] = readval_real; -// } - if (readval_real >= d_result_SAT_value) // 0x100000 (21 bits two's complement) - { - readval_real = -2*d_result_SAT_value + readval_real; - } -// if (readval_real > debug_max_readval_real_after_check[k]) -// { -// debug_max_readval_real_after_check[k] = readval_real; +// readval_real = -2*d_result_SAT_value + readval_real; // } +//// if (readval_real > debug_max_readval_real_after_check[k]) +//// { +//// debug_max_readval_real_after_check[k] = readval_real; +//// } //printf("read real d map base %d = %d\n", d_RESULT_REG_BASE_ADDR + k, readval_real); readval_imag = d_map_base[d_RESULT_REG_IMAG_BASE_ADDR + k]; //printf("read imag before checking d map base %d = %d\n", d_RESULT_REG_BASE_ADDR + k, readval_imag); -// if (readval_imag > debug_max_readval_imag[k]) +//// if (readval_imag > debug_max_readval_imag[k]) +//// { +//// debug_max_readval_imag[k] = readval_imag; +//// } +// +// if (readval_imag >= d_result_SAT_value) // 0x100000 (21 bits two's complement) // { -// debug_max_readval_imag[k] = readval_imag; -// } - - if (readval_imag >= d_result_SAT_value) // 0x100000 (21 bits two's complement) - { - readval_imag = -2*d_result_SAT_value + readval_imag; - } -// if (readval_imag > debug_max_readval_imag_after_check[k]) -// { -// debug_max_readval_imag_after_check[k] = readval_real; +// readval_imag = -2*d_result_SAT_value + readval_imag; // } +//// if (readval_imag > debug_max_readval_imag_after_check[k]) +//// { +//// debug_max_readval_imag_after_check[k] = readval_real; +//// } //printf("read imag d map base %d = %d\n", d_RESULT_REG_BASE_ADDR + k, readval_imag); d_corr_out[k] = gr_complex(readval_real,readval_imag); @@ -687,16 +692,16 @@ void fpga_multicorrelator_8sc::read_tracking_gps_results(void) { //printf("reading pilot !!!\n"); readval_real = d_map_base[d_RESULT_REG_DATA_REAL_BASE_ADDR]; - if (readval_real >= d_result_SAT_value) // 0x100000 (21 bits two's complement) - { - readval_real = -2*d_result_SAT_value + readval_real; - } +// if (readval_real >= d_result_SAT_value) // 0x100000 (21 bits two's complement) +// { +// readval_real = -2*d_result_SAT_value + readval_real; +// } readval_imag = d_map_base[d_RESULT_REG_DATA_IMAG_BASE_ADDR]; - if (readval_imag >= d_result_SAT_value) // 0x100000 (21 bits two's complement) - { - readval_imag = -2*d_result_SAT_value + readval_imag; - } +// if (readval_imag >= d_result_SAT_value) // 0x100000 (21 bits two's complement) +// { +// readval_imag = -2*d_result_SAT_value + readval_imag; +// } d_Prompt_Data[0] = gr_complex(readval_real,readval_imag); } From 3b154c57c2c0541e61ae8c6e34502589df9ed915 Mon Sep 17 00:00:00 2001 From: Marc Majoral Date: Fri, 10 Aug 2018 10:04:47 +0200 Subject: [PATCH 5/7] fixed some cmakefiles to allow for the correct compilation of the gnss-sdr with the FPGA option and the unit test extra options at the same time. --- src/algorithms/acquisition/CMakeLists.txt | 4 +--- src/tests/CMakeLists.txt | 10 +++++----- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/algorithms/acquisition/CMakeLists.txt b/src/algorithms/acquisition/CMakeLists.txt index 0dc31ec9b..5cf06e3e8 100644 --- a/src/algorithms/acquisition/CMakeLists.txt +++ b/src/algorithms/acquisition/CMakeLists.txt @@ -18,7 +18,5 @@ add_subdirectory(adapters) add_subdirectory(gnuradio_blocks) -if(ENABLE_FPGA) - add_subdirectory(libs) -endif(ENABLE_FPGA) +add_subdirectory(libs) diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index ac70b816e..8ea932e1b 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -211,7 +211,7 @@ if(ENABLE_UNIT_TESTING_EXTRA OR ENABLE_SYSTEM_TESTING_EXTRA OR ENABLE_FPGA) find_package(GPSTK) if(NOT GPSTK_FOUND OR ENABLE_OWN_GPSTK) message(STATUS "GPSTk v${GNSSSDR_GPSTK_LOCAL_VERSION} will be automatically downloaded and built when doing 'make'.") - if(NOT ENABLE_FPGA) +# if(NOT ENABLE_FPGA) if(CMAKE_VERSION VERSION_LESS 3.2) ExternalProject_Add( gpstk-${GNSSSDR_GPSTK_LOCAL_VERSION} @@ -245,10 +245,10 @@ if(ENABLE_UNIT_TESTING_EXTRA OR ENABLE_SYSTEM_TESTING_EXTRA OR ENABLE_FPGA) add_definitions(-DGPSTK_BINDIR="${GPSTK_BINDIR}") set(gpstk_libs gpstk) set(OWN_GPSTK True) - else(NOT ENABLE_FPGA) - message(STATUS "GPSTk has not been found, try to install it on target.") - message(STATUS "Some extra tests requiring GPSTk will not be built.") - endif(NOT ENABLE_FPGA) +# else(NOT ENABLE_FPGA) +# message(STATUS "GPSTk has not been found, try to install it on target.") +# message(STATUS "Some extra tests requiring GPSTk will not be built.") +# endif(NOT ENABLE_FPGA) else(NOT GPSTK_FOUND OR ENABLE_OWN_GPSTK) set(gpstk_libs ${GPSTK_LIBRARIES}) set(GPSTK_INCLUDE_DIRS ${GPSTK_INCLUDE_DIR}) From b1524a3afe14171e25ba1e465aa0980f8c3c11d3 Mon Sep 17 00:00:00 2001 From: Marc Majoral Date: Fri, 10 Aug 2018 13:12:06 +0200 Subject: [PATCH 6/7] implemented 64-bit global sample counter started programming the FPGA tracking unit tests --- .../gnuradio_blocks/pcps_acquisition_fpga.cc | 4 +- .../acquisition/libs/fpga_acquisition.cc | 13 +- .../acquisition/libs/fpga_acquisition.h | 2 +- .../dll_pll_veml_tracking_fpga.cc | 4 +- .../tracking/libs/fpga_multicorrelator.cc | 40 +- .../tracking/libs/fpga_multicorrelator.h | 12 +- src/tests/test_main.cc | 3 + .../tracking/tracking_pull-in_test_fpga.cc | 1018 +++++++++++++++++ 8 files changed, 1067 insertions(+), 29 deletions(-) create mode 100644 src/tests/unit-tests/signal-processing-blocks/tracking/tracking_pull-in_test_fpga.cc diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.cc b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.cc index deaa1a790..7fe87c9f6 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.cc +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.cc @@ -223,7 +223,7 @@ void pcps_acquisition_fpga::set_active(bool active) // no CFAR algorithm in the FPGA << ", use_CFAR_algorithm_flag: false"; - unsigned int initial_sample; + unsigned long int initial_sample; float input_power_all = 0.0; float input_power_computed = 0.0; @@ -328,7 +328,7 @@ void pcps_acquisition_fpga::set_active(bool active) printf("##### d_test_statistics = %f\n", d_test_statistics); printf("##### debug_d_max_absolute =%f\n",debug_d_max_absolute); printf("##### debug_d_input_power_absolute =%f\n",debug_d_input_power_absolute); - printf("##### initial_sample = %d\n",initial_sample); + printf("##### initial_sample = %lu\n",initial_sample); printf("##### debug_doppler_index = %d\n",debug_doppler_index); send_positive_acquisition(); d_state = 0; // Positive acquisition diff --git a/src/algorithms/acquisition/libs/fpga_acquisition.cc b/src/algorithms/acquisition/libs/fpga_acquisition.cc index 8e941fad7..4e74e1779 100644 --- a/src/algorithms/acquisition/libs/fpga_acquisition.cc +++ b/src/algorithms/acquisition/libs/fpga_acquisition.cc @@ -369,13 +369,20 @@ void fpga_acquisition::set_phase_step(unsigned int doppler_index) void fpga_acquisition::read_acquisition_results(uint32_t *max_index, - float *max_magnitude, unsigned *initial_sample, float *power_sum, unsigned *doppler_index) + float *max_magnitude, unsigned long int *initial_sample, float *power_sum, unsigned *doppler_index) { + unsigned long int initial_sample_tmp; + unsigned readval = 0; + unsigned long int readval_long = 0; readval = d_map_base[1]; - *initial_sample = readval; + initial_sample_tmp = readval; + //*initial_sample = readval; //printf("read initial sample dmap 1 = %d\n", readval); - readval = d_map_base[2]; + readval_long = d_map_base[2]; + initial_sample_tmp = initial_sample_tmp + (readval_long * (2^32)); + *initial_sample = initial_sample_tmp; + readval = d_map_base[6]; *max_magnitude = static_cast(readval); //printf("read max_magnitude dmap 2 = %d\n", readval); readval = d_map_base[4]; diff --git a/src/algorithms/acquisition/libs/fpga_acquisition.h b/src/algorithms/acquisition/libs/fpga_acquisition.h index 710ab4e8c..8219037a7 100644 --- a/src/algorithms/acquisition/libs/fpga_acquisition.h +++ b/src/algorithms/acquisition/libs/fpga_acquisition.h @@ -61,7 +61,7 @@ public: 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, unsigned *doppler_index); + unsigned long int *initial_sample, float *power_sum, unsigned *doppler_index); void block_samples(); void unblock_samples(); diff --git a/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking_fpga.cc b/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking_fpga.cc index e368ea015..7ea045401 100644 --- a/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking_fpga.cc +++ b/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking_fpga.cc @@ -1251,14 +1251,14 @@ int dll_pll_veml_tracking_fpga::general_work (int noutput_items __attribute__((u { d_pull_in = 0; multicorrelator_fpga->lock_channel(); - unsigned counter_value = multicorrelator_fpga->read_sample_counter(); + unsigned long int counter_value = multicorrelator_fpga->read_sample_counter(); //printf("333333 counter_value = %d\n", counter_value); //printf("333333 current_synchro_data.Acq_samplestamp_samples = %d\n", current_synchro_data.Acq_samplestamp_samples); //printf("333333 current_synchro_data.Acq_delay_samples = %f\n", current_synchro_data.Acq_delay_samples); //printf("333333 d_correlation_length_samples = %d\n", d_correlation_length_samples); unsigned num_frames = ceil((counter_value - current_synchro_data.Acq_samplestamp_samples - current_synchro_data.Acq_delay_samples)/d_correlation_length_samples); //printf("333333 num_frames = %d\n", num_frames); - unsigned absolute_samples_offset = current_synchro_data.Acq_delay_samples + current_synchro_data.Acq_samplestamp_samples + num_frames*d_correlation_length_samples; + unsigned long int absolute_samples_offset = current_synchro_data.Acq_delay_samples + current_synchro_data.Acq_samplestamp_samples + num_frames*d_correlation_length_samples; //printf("333333 absolute_samples_offset = %d\n", absolute_samples_offset); multicorrelator_fpga->set_initial_sample(absolute_samples_offset); d_absolute_samples_offset = absolute_samples_offset; diff --git a/src/algorithms/tracking/libs/fpga_multicorrelator.cc b/src/algorithms/tracking/libs/fpga_multicorrelator.cc index ba9e65aa4..5fa8f06fd 100644 --- a/src/algorithms/tracking/libs/fpga_multicorrelator.cc +++ b/src/algorithms/tracking/libs/fpga_multicorrelator.cc @@ -84,16 +84,22 @@ #define LOCAL_CODE_FPGA_ENABLE_WRITE_MEMORY 0x0C000000 #define TEST_REGISTER_TRACK_WRITEVAL 0x55AA -int fpga_multicorrelator_8sc::read_sample_counter() +unsigned long int fpga_multicorrelator_8sc::read_sample_counter() { - return d_map_base[d_SAMPLE_COUNTER_REG_ADDR]; + unsigned long int sample_counter_tmp, sample_counter_msw_tmp; + sample_counter_tmp = d_map_base[d_SAMPLE_COUNTER_REG_ADDR_LSW]; + sample_counter_msw_tmp = d_map_base[d_SAMPLE_COUNTER_REG_ADDR_MSW]; + sample_counter_tmp = sample_counter_tmp + (sample_counter_msw_tmp * (2^32)); + //return d_map_base[d_SAMPLE_COUNTER_REG_ADDR]; + return sample_counter_tmp; } -void fpga_multicorrelator_8sc::set_initial_sample(int samples_offset) +void fpga_multicorrelator_8sc::set_initial_sample(unsigned long int samples_offset) { d_initial_sample_counter = samples_offset; //printf("www writing d map base %d = d_initial_sample_counter = %d\n", d_INITIAL_COUNTER_VALUE_REG_ADDR, d_initial_sample_counter); - d_map_base[d_INITIAL_COUNTER_VALUE_REG_ADDR] = d_initial_sample_counter; + d_map_base[d_INITIAL_COUNTER_VALUE_REG_ADDR_LSW] = (d_initial_sample_counter & 0xFFFFFFFF); + d_map_base[d_INITIAL_COUNTER_VALUE_REG_ADDR_MSW] = (d_initial_sample_counter >> 32) & 0xFFFFFFFF; } //void fpga_multicorrelator_8sc::set_local_code_and_taps(int code_length_chips, @@ -228,7 +234,8 @@ fpga_multicorrelator_8sc::fpga_multicorrelator_8sc(int n_correlators, d_PHASE_STEP_RAD_REG_ADDR = 16; d_PROG_MEMS_ADDR = 17; d_DROP_SAMPLES_REG_ADDR = 18; - d_INITIAL_COUNTER_VALUE_REG_ADDR = 19; + d_INITIAL_COUNTER_VALUE_REG_ADDR_LSW = 19; + d_INITIAL_COUNTER_VALUE_REG_ADDR_MSW = 20; d_START_FLAG_ADDR = 30; // } @@ -247,16 +254,16 @@ fpga_multicorrelator_8sc::fpga_multicorrelator_8sc(int n_correlators, // } // result 2's complement saturation value - if (d_multicorr_type == 0) - { - // multicorrelator with 3 correlators (16 registers only) - d_result_SAT_value = 1048576; // 21 bits 2's complement -> 2^20 - } - else - { - // other types of multicorrelators (32 registers) - d_result_SAT_value = 4194304; // 23 bits 2's complement -> 2^22 - } +// if (d_multicorr_type == 0) +// { +// // multicorrelator with 3 correlators (16 registers only) +// d_result_SAT_value = 1048576; // 21 bits 2's complement -> 2^20 +// } +// else +// { +// // other types of multicorrelators (32 registers) +// d_result_SAT_value = 4194304; // 23 bits 2's complement -> 2^22 +// } // read only registers d_RESULT_REG_REAL_BASE_ADDR = 1; @@ -275,7 +282,8 @@ fpga_multicorrelator_8sc::fpga_multicorrelator_8sc(int n_correlators, d_RESULT_REG_IMAG_BASE_ADDR = 7; d_RESULT_REG_DATA_REAL_BASE_ADDR = 6; // no pilot tracking d_RESULT_REG_DATA_IMAG_BASE_ADDR = 12; - d_SAMPLE_COUNTER_REG_ADDR = 13; + d_SAMPLE_COUNTER_REG_ADDR_LSW = 13; + d_SAMPLE_COUNTER_REG_ADDR_MSW = 14; // } diff --git a/src/algorithms/tracking/libs/fpga_multicorrelator.h b/src/algorithms/tracking/libs/fpga_multicorrelator.h index 810eaf47d..563433297 100644 --- a/src/algorithms/tracking/libs/fpga_multicorrelator.h +++ b/src/algorithms/tracking/libs/fpga_multicorrelator.h @@ -68,8 +68,8 @@ public: float rem_code_phase_chips, float code_phase_step_chips, int signal_length_samples);bool free(); void set_channel(unsigned int channel); - void set_initial_sample(int samples_offset); - int read_sample_counter(); + void set_initial_sample(unsigned long int samples_offset); + unsigned long int read_sample_counter(); void lock_channel(void); void unlock_channel(void); //void read_sample_counters(int *sample_counter, int *secondary_sample_counter, int *counter_corr_0_in, int *counter_corr_0_out); // debug @@ -103,7 +103,7 @@ private: 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; + unsigned long int d_initial_sample_counter; // driver std::string d_device_name; @@ -131,7 +131,8 @@ private: unsigned int d_PHASE_STEP_RAD_REG_ADDR; unsigned int d_PROG_MEMS_ADDR; unsigned int d_DROP_SAMPLES_REG_ADDR; - unsigned int d_INITIAL_COUNTER_VALUE_REG_ADDR; + unsigned int d_INITIAL_COUNTER_VALUE_REG_ADDR_LSW; + unsigned int d_INITIAL_COUNTER_VALUE_REG_ADDR_MSW; unsigned int d_START_FLAG_ADDR; // read-write regs unsigned int d_TEST_REG_ADDR; @@ -140,7 +141,8 @@ private: unsigned int d_RESULT_REG_IMAG_BASE_ADDR; unsigned int d_RESULT_REG_DATA_REAL_BASE_ADDR; unsigned int d_RESULT_REG_DATA_IMAG_BASE_ADDR; - unsigned int d_SAMPLE_COUNTER_REG_ADDR; + unsigned int d_SAMPLE_COUNTER_REG_ADDR_LSW; + unsigned int d_SAMPLE_COUNTER_REG_ADDR_MSW; // private functions unsigned fpga_acquisition_test_register(unsigned writeval); diff --git a/src/tests/test_main.cc b/src/tests/test_main.cc index 536006294..6df8889be 100644 --- a/src/tests/test_main.cc +++ b/src/tests/test_main.cc @@ -149,6 +149,9 @@ DECLARE_string(log_dir); #include "unit-tests/signal-processing-blocks/tracking/gps_l2_m_dll_pll_tracking_test.cc" #include "unit-tests/signal-processing-blocks/tracking/gps_l1_ca_dll_pll_tracking_test.cc" #include "unit-tests/signal-processing-blocks/tracking/tracking_pull-in_test.cc" +#if ENABLE_FPGA +#include "unit-tests/signal-processing-blocks/tracking/tracking_pull-in_test_fpga.cc" +#endif #include "unit-tests/signal-processing-blocks/telemetry_decoder/gps_l1_ca_telemetry_decoder_test.cc" #include "unit-tests/signal-processing-blocks/observables/hybrid_observables_test.cc" #endif diff --git a/src/tests/unit-tests/signal-processing-blocks/tracking/tracking_pull-in_test_fpga.cc b/src/tests/unit-tests/signal-processing-blocks/tracking/tracking_pull-in_test_fpga.cc new file mode 100644 index 000000000..7841c1f0b --- /dev/null +++ b/src/tests/unit-tests/signal-processing-blocks/tracking/tracking_pull-in_test_fpga.cc @@ -0,0 +1,1018 @@ +/*! + * \file tracking_test.cc + * \brief This class implements a tracking Pull-In test for GPS_L1_CA_DLL_PLL_Tracking + * implementation based on some input parameters. + * \author Javier Arribas, 2018. jarribas(at)cttc.es + * + * + * ------------------------------------------------------------------------- + * + * Copyright (C) 2012-2018 (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 "GPS_L1_CA.h" +#include "gnss_block_factory.h" +#include "tracking_interface.h" +#include "gps_l2_m_pcps_acquisition.h" +#include "gps_l1_ca_pcps_acquisition.h" +#include "gps_l1_ca_pcps_acquisition_fine_doppler.h" +#include "galileo_e5a_noncoherent_iq_acquisition_caf.h" +#include "galileo_e5a_pcps_acquisition.h" +#include "gps_l5i_pcps_acquisition.h" +#include "in_memory_configuration.h" +#include "tracking_true_obs_reader.h" +#include "tracking_dump_reader.h" +#include "signal_generator_flags.h" +#include "gnuplot_i.h" +#include "test_flags.h" +#include "tracking_tests_flags.h" + + +// ######## GNURADIO ACQUISITION BLOCK MESSAGE RECEVER ######### +class Acquisition_msg_rx; + +typedef boost::shared_ptr Acquisition_msg_rx_sptr; + +Acquisition_msg_rx_sptr Acquisition_msg_rx_make(); + + +class Acquisition_msg_rx : public gr::block +{ +private: + friend Acquisition_msg_rx_sptr Acquisition_msg_rx_make(); + void msg_handler_events(pmt::pmt_t msg); + Acquisition_msg_rx(); + +public: + int rx_message; + gr::top_block_sptr top_block; + ~Acquisition_msg_rx(); //!< Default destructor +}; + + +Acquisition_msg_rx_sptr Acquisition_msg_rx_make() +{ + return Acquisition_msg_rx_sptr(new Acquisition_msg_rx()); +} + + +void Acquisition_msg_rx::msg_handler_events(pmt::pmt_t msg) +{ + try + { + long int message = pmt::to_long(msg); + rx_message = message; + top_block->stop(); //stop the flowgraph + } + catch (boost::bad_any_cast& e) + { + LOG(WARNING) << "msg_handler_acquisition Bad cast!\n"; + rx_message = 0; + } +} + + +Acquisition_msg_rx::Acquisition_msg_rx() : gr::block("Acquisition_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(&Acquisition_msg_rx::msg_handler_events, this, _1)); + rx_message = 0; +} + + +Acquisition_msg_rx::~Acquisition_msg_rx() {} +// ######## GNURADIO TRACKING BLOCK MESSAGE RECEVER ######### +class TrackingPullInTestFpga_msg_rx; + +typedef boost::shared_ptr TrackingPullInTestFpga_msg_rx_sptr; + +TrackingPullInTestFpga_msg_rx_sptr TrackingPullInTestFpga_msg_rx_make(); + +class TrackingPullInTestFpga_msg_rx : public gr::block +{ +private: + friend TrackingPullInTestFpga_msg_rx_sptr TrackingPullInTestFpga_msg_rx_make(); + void msg_handler_events(pmt::pmt_t msg); + TrackingPullInTestFpga_msg_rx(); + +public: + int rx_message; + ~TrackingPullInTestFpga_msg_rx(); //!< Default destructor +}; + + +TrackingPullInTestFpga_msg_rx_sptr TrackingPullInTestFpga_msg_rx_make() +{ + return TrackingPullInTestFpga_msg_rx_sptr(new TrackingPullInTestFpga_msg_rx()); +} + + +void TrackingPullInTestFpga_msg_rx::msg_handler_events(pmt::pmt_t msg) +{ + try + { + long int message = pmt::to_long(msg); + rx_message = message; //3 -> loss of lock + //std::cout << "Received trk message: " << rx_message << std::endl; + } + catch (boost::bad_any_cast& e) + { + LOG(WARNING) << "msg_handler_tracking Bad cast!"; + rx_message = 0; + } +} + + +TrackingPullInTestFpga_msg_rx::TrackingPullInTestFpga_msg_rx() : gr::block("TrackingPullInTestFpga_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(&TrackingPullInTestFpga_msg_rx::msg_handler_events, this, _1)); + rx_message = 0; +} + + +TrackingPullInTestFpga_msg_rx::~TrackingPullInTestFpga_msg_rx() +{ +} + + +// ########################################################### + +class TrackingPullInTestFpga : public ::testing::Test +{ +public: + std::string generator_binary; + std::string p1; + std::string p2; + std::string p3; + std::string p4; + std::string p5; + std::string p6; + std::string implementation = FLAGS_trk_test_implementation; + + const int baseband_sampling_freq = FLAGS_fs_gen_sps; + + std::string filename_rinex_obs = FLAGS_filename_rinex_obs; + std::string filename_raw_data = FLAGS_signal_file; + + std::map doppler_measurements_map; + std::map code_delay_measurements_map; + std::map acq_samplestamp_map; + + int configure_generator(double CN0_dBHz, int file_idx); + int generate_signal(); + std::vector check_results_doppler(arma::vec& true_time_s, + arma::vec& true_value, + arma::vec& meas_time_s, + arma::vec& meas_value, + double& mean_error, + double& std_dev_error); + std::vector check_results_acc_carrier_phase(arma::vec& true_time_s, + arma::vec& true_value, + arma::vec& meas_time_s, + arma::vec& meas_value, + double& mean_error, + double& std_dev_error); + std::vector check_results_codephase(arma::vec& true_time_s, + arma::vec& true_value, + arma::vec& meas_time_s, + arma::vec& meas_value, + double& mean_error, + double& std_dev_error); + + TrackingPullInTestFpga() + { + factory = std::make_shared(); + config = std::make_shared(); + item_size = sizeof(gr_complex); + gnss_synchro = Gnss_Synchro(); + } + + ~TrackingPullInTestFpga() + { + } + + void configure_receiver(double PLL_wide_bw_hz, + double DLL_wide_bw_hz, + double PLL_narrow_bw_hz, + double DLL_narrow_bw_hz, + int extend_correlation_symbols); + + bool acquire_signal(int SV_ID); + gr::top_block_sptr top_block; + std::shared_ptr factory; + std::shared_ptr config; + Gnss_Synchro gnss_synchro; + size_t item_size; +}; + + +int TrackingPullInTestFpga::configure_generator(double CN0_dBHz, int file_idx) +{ + // Configure signal generator + generator_binary = FLAGS_generator_binary; + + p1 = std::string("-rinex_nav_file=") + FLAGS_rinex_nav_file; + if (FLAGS_dynamic_position.empty()) + { + p2 = std::string("-static_position=") + FLAGS_static_position + std::string(",") + std::to_string(FLAGS_duration * 10); + } + else + { + p2 = std::string("-obs_pos_file=") + std::string(FLAGS_dynamic_position); + } + p3 = std::string("-rinex_obs_file=") + FLAGS_filename_rinex_obs; // RINEX 2.10 observation file output + p4 = std::string("-sig_out_file=") + FLAGS_signal_file + std::to_string(file_idx); // Baseband signal output file. Will be stored in int8_t IQ multiplexed samples + p5 = std::string("-sampling_freq=") + std::to_string(baseband_sampling_freq); //Baseband sampling frequency [MSps] + p6 = std::string("-CN0_dBHz=") + std::to_string(CN0_dBHz); // Signal generator CN0 + return 0; +} + + +int TrackingPullInTestFpga::generate_signal() +{ + int child_status; + + char* const parmList[] = {&generator_binary[0], &generator_binary[0], &p1[0], &p2[0], &p3[0], &p4[0], &p5[0], &p6[0], NULL}; + + int pid; + if ((pid = fork()) == -1) + perror("fork err"); + else if (pid == 0) + { + execv(&generator_binary[0], parmList); + std::cout << "Return not expected. Must be an execv err." << std::endl; + std::terminate(); + } + + waitpid(pid, &child_status, 0); + + std::cout << "Signal and Observables RINEX and RAW files created." << std::endl; + return 0; +} + + +void TrackingPullInTestFpga::configure_receiver( + double PLL_wide_bw_hz, + double DLL_wide_bw_hz, + double PLL_narrow_bw_hz, + double DLL_narrow_bw_hz, + int extend_correlation_symbols) +{ + config = std::make_shared(); + config->set_property("Tracking.dump", "true"); + config->set_property("Tracking.dump_filename", "./tracking_ch_"); + config->set_property("Tracking.implementation", implementation); + config->set_property("Tracking.item_type", "gr_complex"); + config->set_property("Tracking.pll_bw_hz", std::to_string(PLL_wide_bw_hz)); + config->set_property("Tracking.dll_bw_hz", std::to_string(DLL_wide_bw_hz)); + config->set_property("Tracking.extend_correlation_symbols", std::to_string(extend_correlation_symbols)); + config->set_property("Tracking.pll_bw_narrow_hz", std::to_string(PLL_narrow_bw_hz)); + config->set_property("Tracking.dll_bw_narrow_hz", std::to_string(DLL_narrow_bw_hz)); + gnss_synchro.PRN = FLAGS_test_satellite_PRN; + gnss_synchro.Channel_ID = 0; + config->set_property("GNSS-SDR.internal_fs_sps", std::to_string(baseband_sampling_freq)); + + std::string System_and_Signal; + if (implementation.compare("GPS_L1_CA_DLL_PLL_Tracking") == 0) + { + gnss_synchro.System = 'G'; + std::string signal = "1C"; + System_and_Signal = "GPS L1 CA"; + signal.copy(gnss_synchro.Signal, 2, 0); + config->set_property("Tracking.early_late_space_chips", "0.5"); + config->set_property("Tracking.early_late_space_narrow_chips", "0.5"); + } + else if (implementation.compare("Galileo_E1_DLL_PLL_VEML_Tracking") == 0) + { + gnss_synchro.System = 'E'; + std::string signal = "1B"; + System_and_Signal = "Galileo E1B"; + signal.copy(gnss_synchro.Signal, 2, 0); + config->set_property("Tracking.early_late_space_chips", "0.15"); + config->set_property("Tracking.very_early_late_space_chips", "0.6"); + config->set_property("Tracking.early_late_space_narrow_chips", "0.15"); + config->set_property("Tracking.very_early_late_space_narrow_chips", "0.6"); + config->set_property("Tracking.track_pilot", "true"); + } + else if (implementation.compare("GPS_L2_M_DLL_PLL_Tracking") == 0) + { + gnss_synchro.System = 'G'; + std::string signal = "2S"; + System_and_Signal = "GPS L2CM"; + signal.copy(gnss_synchro.Signal, 2, 0); + config->set_property("Tracking.early_late_space_chips", "0.5"); + config->set_property("Tracking.track_pilot", "false"); + } + else if (implementation.compare("Galileo_E5a_DLL_PLL_Tracking") == 0 or implementation.compare("Galileo_E5a_DLL_PLL_Tracking_b") == 0) + { + gnss_synchro.System = 'E'; + std::string signal = "5X"; + System_and_Signal = "Galileo E5a"; + signal.copy(gnss_synchro.Signal, 2, 0); + if (implementation.compare("Galileo_E5a_DLL_PLL_Tracking_b") == 0) + { + config->supersede_property("Tracking.implementation", std::string("Galileo_E5a_DLL_PLL_Tracking")); + } + config->set_property("Tracking.early_late_space_chips", "0.5"); + config->set_property("Tracking.track_pilot", "false"); + config->set_property("Tracking.order", "2"); + } + else if (implementation.compare("GPS_L5_DLL_PLL_Tracking") == 0) + { + gnss_synchro.System = 'G'; + std::string signal = "L5"; + System_and_Signal = "GPS L5I"; + signal.copy(gnss_synchro.Signal, 2, 0); + config->set_property("Tracking.early_late_space_chips", "0.5"); + config->set_property("Tracking.track_pilot", "false"); + config->set_property("Tracking.order", "2"); + } + else + { + std::cout << "The test can not run with the selected tracking implementation\n "; + throw(std::exception()); + } + + std::cout << "*****************************************\n"; + std::cout << "*** Tracking configuration parameters ***\n"; + std::cout << "*****************************************\n"; + std::cout << "Signal: " << System_and_Signal << "\n"; + std::cout << "implementation: " << config->property("Tracking.implementation", std::string("undefined")) << " \n"; + std::cout << "pll_bw_hz: " << config->property("Tracking.pll_bw_hz", 0.0) << " Hz\n"; + std::cout << "dll_bw_hz: " << config->property("Tracking.dll_bw_hz", 0.0) << " Hz\n"; + std::cout << "pll_bw_narrow_hz: " << config->property("Tracking.pll_bw_narrow_hz", 0.0) << " Hz\n"; + std::cout << "dll_bw_narrow_hz: " << config->property("Tracking.dll_bw_narrow_hz", 0.0) << " Hz\n"; + std::cout << "extend_correlation_symbols: " << config->property("Tracking.extend_correlation_symbols", 0) << " Symbols\n"; + std::cout << "*****************************************\n"; + std::cout << "*****************************************\n"; +} + + +bool TrackingPullInTestFpga::acquire_signal(int SV_ID) +{ + // 1. Setup GNU Radio flowgraph (file_source -> Acquisition_10m) + gr::top_block_sptr top_block; + top_block = gr::make_top_block("Acquisition test"); + + // Satellite signal definition + Gnss_Synchro tmp_gnss_synchro; + tmp_gnss_synchro.Channel_ID = 0; + config = std::make_shared(); + config->set_property("GNSS-SDR.internal_fs_sps", std::to_string(baseband_sampling_freq)); + config->set_property("Acquisition.blocking_on_standby", "true"); + config->set_property("Acquisition.blocking", "true"); + config->set_property("Acquisition.dump", "false"); + config->set_property("Acquisition.dump_filename", "./data/acquisition.dat"); + config->set_property("Acquisition.use_CFAR_algorithm", "false"); + + std::shared_ptr acquisition; + + std::string System_and_Signal; + //create the correspondign acquisition block according to the desired tracking signal + if (implementation.compare("GPS_L1_CA_DLL_PLL_Tracking") == 0) + { + tmp_gnss_synchro.System = 'G'; + std::string signal = "1C"; + const char* str = signal.c_str(); // get a C style null terminated string + std::memcpy(static_cast(tmp_gnss_synchro.Signal), str, 3); // copy string into synchro char array: 2 char + null + tmp_gnss_synchro.PRN = SV_ID; + System_and_Signal = "GPS L1 CA"; + config->set_property("Acquisition.max_dwells", std::to_string(FLAGS_external_signal_acquisition_dwells)); + //acquisition = std::make_shared(config.get(), "Acquisition", 1, 0); + acquisition = std::make_shared(config.get(), "Acquisition", 1, 0); + } + else if (implementation.compare("Galileo_E1_DLL_PLL_VEML_Tracking") == 0) + { + tmp_gnss_synchro.System = 'E'; + std::string signal = "1B"; + const char* str = signal.c_str(); // get a C style null terminated string + std::memcpy(static_cast(tmp_gnss_synchro.Signal), str, 3); // copy string into synchro char array: 2 char + null + tmp_gnss_synchro.PRN = SV_ID; + System_and_Signal = "Galileo E1B"; + config->set_property("Acquisition.max_dwells", std::to_string(FLAGS_external_signal_acquisition_dwells)); + acquisition = std::make_shared(config.get(), "Acquisition", 1, 0); + } + else if (implementation.compare("GPS_L2_M_DLL_PLL_Tracking") == 0) + { + tmp_gnss_synchro.System = 'G'; + std::string signal = "2S"; + const char* str = signal.c_str(); // get a C style null terminated string + std::memcpy(static_cast(tmp_gnss_synchro.Signal), str, 3); // copy string into synchro char array: 2 char + null + tmp_gnss_synchro.PRN = SV_ID; + System_and_Signal = "GPS L2CM"; + config->set_property("Acquisition.max_dwells", std::to_string(FLAGS_external_signal_acquisition_dwells)); + acquisition = std::make_shared(config.get(), "Acquisition", 1, 0); + } + else if (implementation.compare("Galileo_E5a_DLL_PLL_Tracking_b") == 0) + { + tmp_gnss_synchro.System = 'E'; + std::string signal = "5X"; + const char* str = signal.c_str(); // get a C style null terminated string + std::memcpy(static_cast(tmp_gnss_synchro.Signal), str, 3); // copy string into synchro char array: 2 char + null + tmp_gnss_synchro.PRN = SV_ID; + System_and_Signal = "Galileo E5a"; + config->set_property("Acquisition_5X.coherent_integration_time_ms", "1"); + config->set_property("Acquisition.max_dwells", std::to_string(FLAGS_external_signal_acquisition_dwells)); + config->set_property("Acquisition.CAF_window_hz", "0"); // **Only for E5a** Resolves doppler ambiguity averaging the specified BW in the winner code delay. If set to 0 CAF filter is desactivated. Recommended value 3000 Hz + config->set_property("Acquisition.Zero_padding", "0"); //**Only for E5a** Avoids power loss and doppler ambiguity in bit transitions by correlating one code with twice the input data length, ensuring that at least one full code is present without transitions. If set to 1 it is ON, if set to 0 it is OFF. + config->set_property("Acquisition.bit_transition_flag", "false"); + acquisition = std::make_shared(config.get(), "Acquisition", 1, 0); + } + + else if (implementation.compare("Galileo_E5a_DLL_PLL_Tracking") == 0) + { + tmp_gnss_synchro.System = 'E'; + std::string signal = "5X"; + const char* str = signal.c_str(); // get a C style null terminated string + std::memcpy(static_cast(tmp_gnss_synchro.Signal), str, 3); // copy string into synchro char array: 2 char + null + tmp_gnss_synchro.PRN = SV_ID; + System_and_Signal = "Galileo E5a"; + config->set_property("Acquisition.max_dwells", std::to_string(FLAGS_external_signal_acquisition_dwells)); + acquisition = std::make_shared(config.get(), "Acquisition", 1, 0); + } + else if (implementation.compare("GPS_L5_DLL_PLL_Tracking") == 0) + { + tmp_gnss_synchro.System = 'G'; + std::string signal = "L5"; + const char* str = signal.c_str(); // get a C style null terminated string + std::memcpy(static_cast(tmp_gnss_synchro.Signal), str, 3); // copy string into synchro char array: 2 char + null + tmp_gnss_synchro.PRN = SV_ID; + System_and_Signal = "GPS L5I"; + config->set_property("Acquisition.max_dwells", std::to_string(FLAGS_external_signal_acquisition_dwells)); + acquisition = std::make_shared(config.get(), "Acquisition", 1, 0); + } + else + { + std::cout << "The test can not run with the selected tracking implementation\n "; + throw(std::exception()); + } + + acquisition->set_gnss_synchro(&tmp_gnss_synchro); + acquisition->set_channel(0); + acquisition->set_doppler_max(config->property("Acquisition.doppler_max", FLAGS_external_signal_acquisition_doppler_max_hz)); + acquisition->set_doppler_step(config->property("Acquisition.doppler_step", FLAGS_external_signal_acquisition_doppler_step_hz)); + acquisition->set_threshold(config->property("Acquisition.threshold", FLAGS_external_signal_acquisition_threshold)); + acquisition->init(); + acquisition->set_local_code(); + acquisition->set_state(1); // Ensure that acquisition starts at the first sample + acquisition->connect(top_block); + + gr::blocks::file_source::sptr file_source; + std::string file = FLAGS_signal_file; + const char* file_name = file.c_str(); + file_source = gr::blocks::file_source::make(sizeof(int8_t), file_name, false); + file_source->seek(2 * FLAGS_skip_samples, 0); //skip head. ibyte, two bytes per complex sample + gr::blocks::interleaved_char_to_complex::sptr gr_interleaved_char_to_complex = gr::blocks::interleaved_char_to_complex::make(); + //gr::blocks::head::sptr head_samples = gr::blocks::head::make(sizeof(gr_complex), baseband_sampling_freq * FLAGS_duration); + + top_block->connect(file_source, 0, gr_interleaved_char_to_complex, 0); + top_block->connect(gr_interleaved_char_to_complex, 0, acquisition->get_left_block(), 0); + //top_block->connect(head_samples, 0, acquisition->get_left_block(), 0); + + boost::shared_ptr msg_rx; + try + { + msg_rx = Acquisition_msg_rx_make(); + } + catch (const std::exception& e) + { + std::cout << "Failure connecting the message port system: " << e.what() << std::endl; + exit(0); + } + + msg_rx->top_block = top_block; + top_block->msg_connect(acquisition->get_right_block(), pmt::mp("events"), msg_rx, pmt::mp("events")); + + // 5. Run the flowgraph + // Get visible GPS satellites (positive acquisitions with Doppler measurements) + // record startup time + std::chrono::time_point start, end; + std::chrono::duration elapsed_seconds; + start = std::chrono::system_clock::now(); + + bool start_msg = true; + + doppler_measurements_map.clear(); + code_delay_measurements_map.clear(); + acq_samplestamp_map.clear(); + + unsigned int MAX_PRN_IDX = 0; + + switch (tmp_gnss_synchro.System) + { + case 'G': + MAX_PRN_IDX = 33; + break; + case 'E': + MAX_PRN_IDX = 37; + break; + default: + MAX_PRN_IDX = 33; + } + + for (unsigned int PRN = 1; PRN < MAX_PRN_IDX; PRN++) + { + tmp_gnss_synchro.PRN = PRN; + acquisition->set_gnss_synchro(&tmp_gnss_synchro); + acquisition->init(); + acquisition->set_local_code(); + acquisition->reset(); + acquisition->set_state(1); + msg_rx->rx_message = 0; + top_block->run(); + if (start_msg == true) + { + std::cout << "Reading external signal file: " << FLAGS_signal_file << std::endl; + std::cout << "Searching for " << System_and_Signal << " Satellites..." << std::endl; + std::cout << "["; + start_msg = false; + } + while (msg_rx->rx_message == 0) + { + usleep(100000); + } + if (msg_rx->rx_message == 1) + { + std::cout << " " << PRN << " "; + doppler_measurements_map.insert(std::pair(PRN, tmp_gnss_synchro.Acq_doppler_hz)); + code_delay_measurements_map.insert(std::pair(PRN, tmp_gnss_synchro.Acq_delay_samples)); + acq_samplestamp_map.insert(std::pair(PRN, tmp_gnss_synchro.Acq_samplestamp_samples)); + } + else + { + std::cout << " . "; + } + top_block->stop(); + file_source->seek(2 * FLAGS_skip_samples, 0); //skip head. ibyte, two bytes per complex sample + std::cout.flush(); + } + std::cout << "]" << std::endl; + std::cout << "-------------------------------------------\n"; + + for (auto& x : doppler_measurements_map) + { + std::cout << "DETECTED SATELLITE " << System_and_Signal << " PRN: " << x.first << " with Doppler: " << x.second << " [Hz], code phase: " << code_delay_measurements_map.at(x.first) << " [samples] at signal SampleStamp " << acq_samplestamp_map.at(x.first) << "\n"; + } + + // report the elapsed time + end = std::chrono::system_clock::now(); + elapsed_seconds = end - start; + std::cout << "Total signal acquisition run time " + << elapsed_seconds.count() + << " [seconds]" << std::endl; + return true; +} + +TEST_F(TrackingPullInTestFpga, ValidationOfResults) +{ + //************************************************* + //***** STEP 1: Prepare the parameters sweep ****** + //************************************************* + std::vector + acq_doppler_error_hz_values; + std::vector> acq_delay_error_chips_values; //vector of vector + + for (double doppler_hz = FLAGS_acq_Doppler_error_hz_start; doppler_hz >= FLAGS_acq_Doppler_error_hz_stop; doppler_hz = doppler_hz + FLAGS_acq_Doppler_error_hz_step) + { + acq_doppler_error_hz_values.push_back(doppler_hz); + std::vector tmp_vector; + //Code Delay Sweep + for (double code_delay_chips = FLAGS_acq_Delay_error_chips_start; code_delay_chips >= FLAGS_acq_Delay_error_chips_stop; code_delay_chips = code_delay_chips + FLAGS_acq_Delay_error_chips_step) + { + tmp_vector.push_back(code_delay_chips); + } + acq_delay_error_chips_values.push_back(tmp_vector); + } + + + //*********************************************************** + //***** STEP 2: Generate the input signal (if required) ***** + //*********************************************************** + std::vector generator_CN0_values; + if (FLAGS_enable_external_signal_file) + { + generator_CN0_values.push_back(999); // an external input signal capture is selected, no CN0 information available + } + else + { + if (FLAGS_CN0_dBHz_start == FLAGS_CN0_dBHz_stop) + { + generator_CN0_values.push_back(FLAGS_CN0_dBHz_start); + } + else + { + for (double cn0 = FLAGS_CN0_dBHz_start; cn0 > FLAGS_CN0_dBHz_stop; cn0 = cn0 - FLAGS_CN0_dB_step) + { + generator_CN0_values.push_back(cn0); + } + } + } + + // use generator or use an external capture file + if (FLAGS_enable_external_signal_file) + { + //create and configure an acquisition block and perform an acquisition to obtain the synchronization parameters + ASSERT_EQ(acquire_signal(FLAGS_test_satellite_PRN), true); + bool found_satellite = doppler_measurements_map.find(FLAGS_test_satellite_PRN) != doppler_measurements_map.end(); + EXPECT_TRUE(found_satellite) << "Error: satellite SV: " << FLAGS_test_satellite_PRN << " is not acquired"; + if (!found_satellite) return; + } + else + { + for (unsigned int current_cn0_idx = 0; current_cn0_idx < generator_CN0_values.size(); current_cn0_idx++) + { + // Configure the signal generator + configure_generator(generator_CN0_values.at(current_cn0_idx), current_cn0_idx); + // Generate signal raw signal samples and observations RINEX file + if (FLAGS_disable_generator == false) + { + generate_signal(); + } + } + } + + + configure_receiver(FLAGS_PLL_bw_hz_start, + FLAGS_DLL_bw_hz_start, + FLAGS_PLL_narrow_bw_hz, + FLAGS_DLL_narrow_bw_hz, + FLAGS_extend_correlation_symbols); + + //****************************************************************************************** + //***** Obtain the initial signal sinchronization parameters (emulating an acquisition) **** + //****************************************************************************************** + int test_satellite_PRN = 0; + double true_acq_doppler_hz = 0.0; + double true_acq_delay_samples = 0.0; + unsigned long int acq_samplestamp_samples = 0; + + tracking_true_obs_reader true_obs_data; + if (!FLAGS_enable_external_signal_file) + { + test_satellite_PRN = FLAGS_test_satellite_PRN; + std::string true_obs_file = std::string("./gps_l1_ca_obs_prn"); + true_obs_file.append(std::to_string(test_satellite_PRN)); + true_obs_file.append(".dat"); + true_obs_data.close_obs_file(); + ASSERT_EQ(true_obs_data.open_obs_file(true_obs_file), true) << "Failure opening true observables file"; + // load acquisition data based on the first epoch of the true observations + ASSERT_EQ(true_obs_data.read_binary_obs(), true) + << "Failure reading true tracking dump file." << std::endl + << "Maybe sat PRN #" + std::to_string(FLAGS_test_satellite_PRN) + + " is not available?"; + std::cout << "Testing satellite PRN=" << test_satellite_PRN << std::endl; + std::cout << "True Initial Doppler " << true_obs_data.doppler_l1_hz << " [Hz], true Initial code delay [Chips]=" << true_obs_data.prn_delay_chips << "[Chips]" << std::endl; + true_acq_doppler_hz = true_obs_data.doppler_l1_hz; + true_acq_delay_samples = (GPS_L1_CA_CODE_LENGTH_CHIPS - true_obs_data.prn_delay_chips / GPS_L1_CA_CODE_LENGTH_CHIPS) * static_cast(baseband_sampling_freq) * GPS_L1_CA_CODE_PERIOD; + acq_samplestamp_samples = 0; + } + else + { + true_acq_doppler_hz = doppler_measurements_map.find(FLAGS_test_satellite_PRN)->second; + true_acq_delay_samples = code_delay_measurements_map.find(FLAGS_test_satellite_PRN)->second; + acq_samplestamp_samples = 0; + std::cout << "Estimated Initial Doppler " << true_acq_doppler_hz + << " [Hz], estimated Initial code delay " << true_acq_delay_samples << " [Samples]" + << " Acquisition SampleStamp is " << acq_samplestamp_map.find(FLAGS_test_satellite_PRN)->second << std::endl; + } + //CN0 LOOP + std::vector> pull_in_results_v_v; + + for (unsigned int current_cn0_idx = 0; current_cn0_idx < generator_CN0_values.size(); current_cn0_idx++) + { + std::vector pull_in_results_v; + for (unsigned int current_acq_doppler_error_idx = 0; current_acq_doppler_error_idx < acq_doppler_error_hz_values.size(); current_acq_doppler_error_idx++) + { + for (unsigned int current_acq_code_error_idx = 0; current_acq_code_error_idx < acq_delay_error_chips_values.at(current_acq_doppler_error_idx).size(); current_acq_code_error_idx++) + { + gnss_synchro.Acq_samplestamp_samples = acq_samplestamp_samples; + //simulate a Doppler error in acquisition + gnss_synchro.Acq_doppler_hz = true_acq_doppler_hz + acq_doppler_error_hz_values.at(current_acq_doppler_error_idx); + //simulate Code Delay error in acquisition + gnss_synchro.Acq_delay_samples = true_acq_delay_samples + (acq_delay_error_chips_values.at(current_acq_doppler_error_idx).at(current_acq_code_error_idx) / GPS_L1_CA_CODE_RATE_HZ) * static_cast(baseband_sampling_freq); + + //create flowgraph + top_block = gr::make_top_block("Tracking test"); + std::shared_ptr trk_ = factory->GetBlock(config, "Tracking", config->property("Tracking.implementation", std::string("undefined")), 1, 1); + std::shared_ptr tracking = std::dynamic_pointer_cast(trk_); + boost::shared_ptr msg_rx = TrackingPullInTestFpga_msg_rx_make(); + + + ASSERT_NO_THROW({ + tracking->set_channel(gnss_synchro.Channel_ID); + }) << "Failure setting channel."; + + ASSERT_NO_THROW({ + tracking->set_gnss_synchro(&gnss_synchro); + }) << "Failure setting gnss_synchro."; + + ASSERT_NO_THROW({ + tracking->connect(top_block); + }) << "Failure connecting tracking to the top_block."; + + std::string file; + ASSERT_NO_THROW({ + if (!FLAGS_enable_external_signal_file) + { + file = "./" + filename_raw_data + std::to_string(current_cn0_idx); + } + else + { + file = FLAGS_signal_file; + } + const char* file_name = file.c_str(); + gr::blocks::file_source::sptr file_source = gr::blocks::file_source::make(sizeof(int8_t), file_name, false); + gr::blocks::interleaved_char_to_complex::sptr gr_interleaved_char_to_complex = gr::blocks::interleaved_char_to_complex::make(); + gr::blocks::null_sink::sptr sink = gr::blocks::null_sink::make(sizeof(Gnss_Synchro)); + gr::blocks::head::sptr head_samples = gr::blocks::head::make(sizeof(gr_complex), baseband_sampling_freq * FLAGS_duration); + top_block->connect(file_source, 0, gr_interleaved_char_to_complex, 0); + top_block->connect(gr_interleaved_char_to_complex, 0, head_samples, 0); + top_block->connect(head_samples, 0, tracking->get_left_block(), 0); + top_block->connect(tracking->get_right_block(), 0, sink, 0); + top_block->msg_connect(tracking->get_right_block(), pmt::mp("events"), msg_rx, pmt::mp("events")); + file_source->seek(2 * FLAGS_skip_samples, 0); //skip head. ibyte, two bytes per complex sample + }) << "Failure connecting the blocks of tracking test."; + + + //******************************************************************** + //***** STEP 5: Perform the signal tracking and read the results ***** + //******************************************************************** + std::cout << "--- START TRACKING WITH PULL-IN ERROR: " << acq_doppler_error_hz_values.at(current_acq_doppler_error_idx) << " [Hz] and " << acq_delay_error_chips_values.at(current_acq_doppler_error_idx).at(current_acq_code_error_idx) << " [Chips] ---" << std::endl; + tracking->start_tracking(); + std::chrono::time_point start, end; + EXPECT_NO_THROW({ + start = std::chrono::system_clock::now(); + top_block->run(); // Start threads and wait + end = std::chrono::system_clock::now(); + }) << "Failure running the top_block."; + + std::chrono::duration elapsed_seconds = end - start; + std::cout << "Signal tracking completed in " << elapsed_seconds.count() << " seconds" << std::endl; + + + pull_in_results_v.push_back(msg_rx->rx_message != 3); //save last asynchronous tracking message in order to detect a loss of lock + + //******************************** + //***** STEP 7: Plot results ***** + //******************************** + if (FLAGS_plot_detail_level >= 2 and FLAGS_show_plots) + { + //load the measured values + tracking_dump_reader trk_dump; + ASSERT_EQ(trk_dump.open_obs_file(std::string("./tracking_ch_0.dat")), true) + << "Failure opening tracking dump file"; + + long int n_measured_epochs = trk_dump.num_epochs(); + //todo: use vectors instead + arma::vec trk_timestamp_s = arma::zeros(n_measured_epochs, 1); + arma::vec trk_acc_carrier_phase_cycles = arma::zeros(n_measured_epochs, 1); + arma::vec trk_Doppler_Hz = arma::zeros(n_measured_epochs, 1); + arma::vec trk_prn_delay_chips = arma::zeros(n_measured_epochs, 1); + std::vector timestamp_s; + std::vector prompt; + std::vector early; + std::vector late; + std::vector v_early; + std::vector v_late; + std::vector promptI; + std::vector promptQ; + std::vector CN0_dBHz; + std::vector Doppler; + long int epoch_counter = 0; + while (trk_dump.read_binary_obs()) + { + trk_timestamp_s(epoch_counter) = static_cast(trk_dump.PRN_start_sample_count) / static_cast(baseband_sampling_freq); + trk_acc_carrier_phase_cycles(epoch_counter) = trk_dump.acc_carrier_phase_rad / GPS_TWO_PI; + trk_Doppler_Hz(epoch_counter) = trk_dump.carrier_doppler_hz; + double delay_chips = GPS_L1_CA_CODE_LENGTH_CHIPS - GPS_L1_CA_CODE_LENGTH_CHIPS * (fmod((static_cast(trk_dump.PRN_start_sample_count) + trk_dump.aux1) / static_cast(baseband_sampling_freq), 1.0e-3) / 1.0e-3); + + trk_prn_delay_chips(epoch_counter) = delay_chips; + + timestamp_s.push_back(trk_timestamp_s(epoch_counter)); + prompt.push_back(trk_dump.abs_P); + early.push_back(trk_dump.abs_E); + late.push_back(trk_dump.abs_L); + v_early.push_back(trk_dump.abs_VE); + v_late.push_back(trk_dump.abs_VL); + promptI.push_back(trk_dump.prompt_I); + promptQ.push_back(trk_dump.prompt_Q); + CN0_dBHz.push_back(trk_dump.CN0_SNV_dB_Hz); + Doppler.push_back(trk_dump.carrier_doppler_hz); + epoch_counter++; + } + + + const std::string gnuplot_executable(FLAGS_gnuplot_executable); + if (gnuplot_executable.empty()) + { + std::cout << "WARNING: Although the flag show_plots has been set to TRUE," << std::endl; + std::cout << "gnuplot has not been found in your system." << std::endl; + std::cout << "Test results will not be plotted." << std::endl; + } + else + { + try + { + boost::filesystem::path p(gnuplot_executable); + boost::filesystem::path dir = p.parent_path(); + std::string gnuplot_path = dir.native(); + Gnuplot::set_GNUPlotPath(gnuplot_path); + unsigned int decimate = static_cast(FLAGS_plot_decimate); + + if (FLAGS_plot_detail_level >= 2 and FLAGS_show_plots) + { + Gnuplot g1("linespoints"); + g1.showonscreen(); // window output + if (!FLAGS_enable_external_signal_file) + { + g1.set_title(std::to_string(generator_CN0_values.at(current_cn0_idx)) + " dB-Hz, " + "PLL/DLL BW: " + std::to_string(FLAGS_PLL_bw_hz_start) + "," + std::to_string(FLAGS_DLL_bw_hz_start) + " [Hz], GPS L1 C/A (PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")"); + } + else + { + g1.set_title("D_e=" + std::to_string(acq_doppler_error_hz_values.at(current_acq_doppler_error_idx)) + " [Hz] " + "T_e= " + std::to_string(acq_delay_error_chips_values.at(current_acq_doppler_error_idx).at(current_acq_code_error_idx)) + " [Chips], PLL/DLL BW: " + std::to_string(FLAGS_PLL_bw_hz_start) + "," + std::to_string(FLAGS_DLL_bw_hz_start) + " [Hz], (PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")"); + } + + g1.set_grid(); + g1.set_xlabel("Time [s]"); + g1.set_ylabel("Correlators' output"); + //g1.cmd("set key box opaque"); + g1.plot_xy(trk_timestamp_s, prompt, "Prompt", decimate); + g1.plot_xy(trk_timestamp_s, early, "Early", decimate); + g1.plot_xy(trk_timestamp_s, late, "Late", decimate); + if (implementation.compare("Galileo_E1_DLL_PLL_VEML_Tracking") == 0) + { + g1.plot_xy(trk_timestamp_s, v_early, "Very Early", decimate); + g1.plot_xy(trk_timestamp_s, v_late, "Very Late", decimate); + } + g1.set_legend(); + g1.savetops("Correlators_outputs"); + + Gnuplot g2("points"); + g2.showonscreen(); // window output + if (!FLAGS_enable_external_signal_file) + { + g2.set_title(std::to_string(generator_CN0_values.at(current_cn0_idx)) + " dB-Hz Constellation " + "PLL/DLL BW: " + std::to_string(FLAGS_PLL_bw_hz_start) + "," + std::to_string(FLAGS_DLL_bw_hz_start) + " [Hz], (PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")"); + } + else + { + g2.set_title("D_e=" + std::to_string(acq_doppler_error_hz_values.at(current_acq_doppler_error_idx)) + " [Hz] " + "T_e= " + std::to_string(acq_delay_error_chips_values.at(current_acq_doppler_error_idx).at(current_acq_code_error_idx)) + " [Chips], PLL/DLL BW: " + std::to_string(FLAGS_PLL_bw_hz_start) + "," + std::to_string(FLAGS_DLL_bw_hz_start) + " [Hz], (PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")"); + } + + g2.set_grid(); + g2.set_xlabel("Inphase"); + g2.set_ylabel("Quadrature"); + //g2.cmd("set size ratio -1"); + g2.plot_xy(promptI, promptQ); + g2.savetops("Constellation"); + + Gnuplot g3("linespoints"); + if (!FLAGS_enable_external_signal_file) + { + g3.set_title(std::to_string(generator_CN0_values.at(current_cn0_idx)) + " dB-Hz, GPS L1 C/A tracking CN0 output (PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")"); + } + else + { + g3.set_title("D_e=" + std::to_string(acq_doppler_error_hz_values.at(current_acq_doppler_error_idx)) + " [Hz] " + "T_e= " + std::to_string(acq_delay_error_chips_values.at(current_acq_doppler_error_idx).at(current_acq_code_error_idx)) + " [Chips] PLL/DLL BW: " + std::to_string(FLAGS_PLL_bw_hz_start) + "," + std::to_string(FLAGS_DLL_bw_hz_start) + " [Hz], (PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")"); + } + g3.set_grid(); + g3.set_xlabel("Time [s]"); + g3.set_ylabel("Reported CN0 [dB-Hz]"); + g3.cmd("set key box opaque"); + + g3.plot_xy(trk_timestamp_s, CN0_dBHz, + std::to_string(static_cast(round(generator_CN0_values.at(current_cn0_idx)))) + "[dB-Hz]", decimate); + + g3.set_legend(); + g3.savetops("CN0_output"); + + g3.showonscreen(); // window output + + Gnuplot g4("linespoints"); + if (!FLAGS_enable_external_signal_file) + { + g4.set_title(std::to_string(generator_CN0_values.at(current_cn0_idx)) + " dB-Hz, GPS L1 C/A tracking CN0 output (PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")"); + } + else + { + g4.set_title("D_e=" + std::to_string(acq_doppler_error_hz_values.at(current_acq_doppler_error_idx)) + " [Hz] " + "T_e= " + std::to_string(acq_delay_error_chips_values.at(current_acq_doppler_error_idx).at(current_acq_code_error_idx)) + " [Chips] PLL/DLL BW: " + std::to_string(FLAGS_PLL_bw_hz_start) + "," + std::to_string(FLAGS_DLL_bw_hz_start) + " [Hz], (PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")"); + } + g4.set_grid(); + g4.set_xlabel("Time [s]"); + g4.set_ylabel("Estimated Doppler [Hz]"); + g4.cmd("set key box opaque"); + + g4.plot_xy(trk_timestamp_s, Doppler, + std::to_string(static_cast(round(generator_CN0_values.at(current_cn0_idx)))) + "[dB-Hz]", decimate); + + g4.set_legend(); + g4.savetops("Doppler"); + + g4.showonscreen(); // window output + } + } + catch (const GnuplotException& ge) + { + std::cout << ge.what() << std::endl; + } + } + } //end plot + + } //end acquisition Delay errors loop + } //end acquisition Doppler errors loop + pull_in_results_v_v.push_back(pull_in_results_v); + + + } //end CN0 LOOP + //build the mesh grid + std::vector doppler_error_mesh; + std::vector code_delay_error_mesh; + for (unsigned int current_acq_doppler_error_idx = 0; current_acq_doppler_error_idx < acq_doppler_error_hz_values.size(); current_acq_doppler_error_idx++) + { + for (unsigned int current_acq_code_error_idx = 0; current_acq_code_error_idx < acq_delay_error_chips_values.at(current_acq_doppler_error_idx).size(); current_acq_code_error_idx++) + { + doppler_error_mesh.push_back(acq_doppler_error_hz_values.at(current_acq_doppler_error_idx)); + code_delay_error_mesh.push_back(acq_delay_error_chips_values.at(current_acq_doppler_error_idx).at(current_acq_code_error_idx)); + } + } + + for (unsigned int current_cn0_idx = 0; current_cn0_idx < generator_CN0_values.size(); current_cn0_idx++) + { + std::vector pull_in_result_mesh; + pull_in_result_mesh = pull_in_results_v_v.at(current_cn0_idx); + //plot grid + Gnuplot g4("points palette pointsize 2 pointtype 7"); + if (FLAGS_show_plots) + { + g4.showonscreen(); // window output + } + else + { + g4.disablescreen(); + } + g4.cmd("set palette defined ( 0 \"black\", 1 \"green\" )"); + g4.cmd("set key off"); + g4.cmd("set view map"); + std::string title; + if (!FLAGS_enable_external_signal_file) + { + title = std::string("Tracking Pull-in result grid at CN0:" + std::to_string(static_cast(round(generator_CN0_values.at(current_cn0_idx)))) + " [dB-Hz], PLL/DLL BW: " + std::to_string(FLAGS_PLL_bw_hz_start) + "," + std::to_string(FLAGS_DLL_bw_hz_start) + " [Hz]."); + } + else + { + title = std::string("Tracking Pull-in result grid, PLL/DLL BW: " + std::to_string(FLAGS_PLL_bw_hz_start) + "," + std::to_string(FLAGS_DLL_bw_hz_start) + " [Hz], GPS L1 C/A (PRN #" + std::to_string(FLAGS_test_satellite_PRN) + ")"); + } + + g4.set_title(title); + g4.set_grid(); + g4.set_xlabel("Acquisition Doppler error [Hz]"); + g4.set_ylabel("Acquisition Code Delay error [Chips]"); + g4.cmd("set cbrange[0:1]"); + g4.plot_xyz(doppler_error_mesh, + code_delay_error_mesh, + pull_in_result_mesh); + g4.set_legend(); + if (!FLAGS_enable_external_signal_file) + { + g4.savetops("trk_pull_in_grid_" + std::to_string(static_cast(round(generator_CN0_values.at(current_cn0_idx))))); + g4.savetopdf("trk_pull_in_grid_" + std::to_string(static_cast(round(generator_CN0_values.at(current_cn0_idx)))), 12); + } + else + { + g4.savetops("trk_pull_in_grid_external_file"); + g4.savetopdf("trk_pull_in_grid_external_file", 12); + } + } +} From f14ad930d5b8861eb96a376129a4b23affd2de9b Mon Sep 17 00:00:00 2001 From: Marc Majoral Date: Fri, 10 Aug 2018 16:42:53 +0200 Subject: [PATCH 7/7] declared the 64-bit variables as long long ints instead of long ints in the FPGA related files. Variables declared as long ints are interpreted as 32-bit variables in the ARM architecture and 64-bit variables in the X86-64 architecture. --- .../gnuradio_blocks/pcps_acquisition_fpga.cc | 12 ++++++------ .../gnuradio_blocks/pcps_acquisition_fpga.h | 2 +- .../acquisition/libs/fpga_acquisition.cc | 14 ++++++++------ src/algorithms/acquisition/libs/fpga_acquisition.h | 2 +- .../gnuradio_blocks/dll_pll_veml_tracking_fpga.cc | 8 ++++---- .../gnuradio_blocks/dll_pll_veml_tracking_fpga.h | 8 ++++---- .../tracking/libs/fpga_multicorrelator.cc | 9 +++++---- .../tracking/libs/fpga_multicorrelator.h | 6 +++--- 8 files changed, 32 insertions(+), 29 deletions(-) diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.cc b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.cc index 7fe87c9f6..af36b9c4a 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.cc +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.cc @@ -223,7 +223,7 @@ void pcps_acquisition_fpga::set_active(bool active) // no CFAR algorithm in the FPGA << ", use_CFAR_algorithm_flag: false"; - unsigned long int initial_sample; + unsigned long long int initial_sample; float input_power_all = 0.0; float input_power_computed = 0.0; @@ -325,11 +325,11 @@ void pcps_acquisition_fpga::set_active(bool active) if (d_test_statistics > d_threshold) { d_active = false; - printf("##### d_test_statistics = %f\n", d_test_statistics); - printf("##### debug_d_max_absolute =%f\n",debug_d_max_absolute); - printf("##### debug_d_input_power_absolute =%f\n",debug_d_input_power_absolute); - printf("##### initial_sample = %lu\n",initial_sample); - printf("##### debug_doppler_index = %d\n",debug_doppler_index); +// printf("##### d_test_statistics = %f\n", d_test_statistics); +// printf("##### debug_d_max_absolute =%f\n",debug_d_max_absolute); +// printf("##### debug_d_input_power_absolute =%f\n",debug_d_input_power_absolute); +// printf("##### initial_sample = %llu\n",initial_sample); +// printf("##### debug_doppler_index = %d\n",debug_doppler_index); send_positive_acquisition(); d_state = 0; // Positive acquisition } diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.h b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.h index e684b0971..7775a14e8 100644 --- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.h +++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.h @@ -115,7 +115,7 @@ private: unsigned int d_doppler_step; unsigned int d_fft_size; unsigned int d_num_doppler_bins; - unsigned long int d_sample_counter; + unsigned long long int d_sample_counter; Gnss_Synchro* d_gnss_synchro; std::shared_ptr acquisition_fpga; diff --git a/src/algorithms/acquisition/libs/fpga_acquisition.cc b/src/algorithms/acquisition/libs/fpga_acquisition.cc index 4e74e1779..6bb2ff266 100644 --- a/src/algorithms/acquisition/libs/fpga_acquisition.cc +++ b/src/algorithms/acquisition/libs/fpga_acquisition.cc @@ -369,18 +369,20 @@ void fpga_acquisition::set_phase_step(unsigned int doppler_index) void fpga_acquisition::read_acquisition_results(uint32_t *max_index, - float *max_magnitude, unsigned long int *initial_sample, float *power_sum, unsigned *doppler_index) + float *max_magnitude, unsigned long long int *initial_sample, float *power_sum, unsigned *doppler_index) { - unsigned long int initial_sample_tmp; + unsigned long long int initial_sample_tmp = 0; + unsigned readval = 0; - unsigned long int readval_long = 0; + unsigned long long int readval_long = 0; + unsigned long long int readval_long_shifted = 0; readval = d_map_base[1]; initial_sample_tmp = readval; - //*initial_sample = readval; - //printf("read initial sample dmap 1 = %d\n", readval); readval_long = d_map_base[2]; - initial_sample_tmp = initial_sample_tmp + (readval_long * (2^32)); + readval_long_shifted = readval_long << 32; // 2^32 + initial_sample_tmp = initial_sample_tmp + readval_long_shifted; // 2^32 + //printf("----------------------------------------------------------------> acq initial sample TOTAL = %llu\n", initial_sample_tmp); *initial_sample = initial_sample_tmp; readval = d_map_base[6]; *max_magnitude = static_cast(readval); diff --git a/src/algorithms/acquisition/libs/fpga_acquisition.h b/src/algorithms/acquisition/libs/fpga_acquisition.h index 8219037a7..36bb4df0e 100644 --- a/src/algorithms/acquisition/libs/fpga_acquisition.h +++ b/src/algorithms/acquisition/libs/fpga_acquisition.h @@ -61,7 +61,7 @@ public: void run_acquisition(void); void set_phase_step(unsigned int doppler_index); void read_acquisition_results(uint32_t *max_index, float *max_magnitude, - unsigned long int *initial_sample, float *power_sum, unsigned *doppler_index); + unsigned long long int *initial_sample, float *power_sum, unsigned *doppler_index); void block_samples(); void unblock_samples(); diff --git a/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking_fpga.cc b/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking_fpga.cc index 7ea045401..a04d9fede 100644 --- a/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking_fpga.cc +++ b/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking_fpga.cc @@ -1251,15 +1251,15 @@ int dll_pll_veml_tracking_fpga::general_work (int noutput_items __attribute__((u { d_pull_in = 0; multicorrelator_fpga->lock_channel(); - unsigned long int counter_value = multicorrelator_fpga->read_sample_counter(); - //printf("333333 counter_value = %d\n", counter_value); + unsigned long long int counter_value = multicorrelator_fpga->read_sample_counter(); + //printf("333333 counter_value = %llu\n", counter_value); //printf("333333 current_synchro_data.Acq_samplestamp_samples = %d\n", current_synchro_data.Acq_samplestamp_samples); //printf("333333 current_synchro_data.Acq_delay_samples = %f\n", current_synchro_data.Acq_delay_samples); //printf("333333 d_correlation_length_samples = %d\n", d_correlation_length_samples); unsigned num_frames = ceil((counter_value - current_synchro_data.Acq_samplestamp_samples - current_synchro_data.Acq_delay_samples)/d_correlation_length_samples); //printf("333333 num_frames = %d\n", num_frames); - unsigned long int absolute_samples_offset = current_synchro_data.Acq_delay_samples + current_synchro_data.Acq_samplestamp_samples + num_frames*d_correlation_length_samples; - //printf("333333 absolute_samples_offset = %d\n", absolute_samples_offset); + unsigned long long int absolute_samples_offset = current_synchro_data.Acq_delay_samples + current_synchro_data.Acq_samplestamp_samples + num_frames*d_correlation_length_samples; + //printf("333333 absolute_samples_offset = %llu\n", absolute_samples_offset); multicorrelator_fpga->set_initial_sample(absolute_samples_offset); d_absolute_samples_offset = absolute_samples_offset; d_sample_counter = absolute_samples_offset; diff --git a/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking_fpga.h b/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking_fpga.h index a58e4b04a..c5419c93c 100644 --- a/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking_fpga.h +++ b/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking_fpga.h @@ -213,9 +213,9 @@ private: // PRN period in samples int d_current_prn_length_samples; // processing samples counters - unsigned long int d_sample_counter; - unsigned long int d_acq_sample_stamp; - unsigned long int d_absolute_samples_offset; + unsigned long long int d_sample_counter; + unsigned long long int d_acq_sample_stamp; + unsigned long long int d_absolute_samples_offset; // CN0 estimation and lock detector int d_cn0_estimation_counter; @@ -232,7 +232,7 @@ private: // extra int d_correlation_length_samples; int d_next_prn_length_samples; - unsigned long int d_sample_counter_next; + unsigned long long int d_sample_counter_next; unsigned int d_pull_in = 0; diff --git a/src/algorithms/tracking/libs/fpga_multicorrelator.cc b/src/algorithms/tracking/libs/fpga_multicorrelator.cc index 5fa8f06fd..a1a051d55 100644 --- a/src/algorithms/tracking/libs/fpga_multicorrelator.cc +++ b/src/algorithms/tracking/libs/fpga_multicorrelator.cc @@ -84,17 +84,18 @@ #define LOCAL_CODE_FPGA_ENABLE_WRITE_MEMORY 0x0C000000 #define TEST_REGISTER_TRACK_WRITEVAL 0x55AA -unsigned long int fpga_multicorrelator_8sc::read_sample_counter() +unsigned long long int fpga_multicorrelator_8sc::read_sample_counter() { - unsigned long int sample_counter_tmp, sample_counter_msw_tmp; + unsigned long long int sample_counter_tmp, sample_counter_msw_tmp; sample_counter_tmp = d_map_base[d_SAMPLE_COUNTER_REG_ADDR_LSW]; sample_counter_msw_tmp = d_map_base[d_SAMPLE_COUNTER_REG_ADDR_MSW]; - sample_counter_tmp = sample_counter_tmp + (sample_counter_msw_tmp * (2^32)); + sample_counter_msw_tmp = sample_counter_msw_tmp << 32; + sample_counter_tmp = sample_counter_tmp + sample_counter_msw_tmp; // 2^32 //return d_map_base[d_SAMPLE_COUNTER_REG_ADDR]; return sample_counter_tmp; } -void fpga_multicorrelator_8sc::set_initial_sample(unsigned long int samples_offset) +void fpga_multicorrelator_8sc::set_initial_sample(unsigned long long int samples_offset) { d_initial_sample_counter = samples_offset; //printf("www writing d map base %d = d_initial_sample_counter = %d\n", d_INITIAL_COUNTER_VALUE_REG_ADDR, d_initial_sample_counter); diff --git a/src/algorithms/tracking/libs/fpga_multicorrelator.h b/src/algorithms/tracking/libs/fpga_multicorrelator.h index 563433297..13c4d21f9 100644 --- a/src/algorithms/tracking/libs/fpga_multicorrelator.h +++ b/src/algorithms/tracking/libs/fpga_multicorrelator.h @@ -68,8 +68,8 @@ public: float rem_code_phase_chips, float code_phase_step_chips, int signal_length_samples);bool free(); void set_channel(unsigned int channel); - void set_initial_sample(unsigned long int samples_offset); - unsigned long int read_sample_counter(); + void set_initial_sample(unsigned long long int samples_offset); + unsigned long long int read_sample_counter(); void lock_channel(void); void unlock_channel(void); //void read_sample_counters(int *sample_counter, int *secondary_sample_counter, int *counter_corr_0_in, int *counter_corr_0_out); // debug @@ -103,7 +103,7 @@ private: unsigned d_code_phase_step_chips_num; int d_rem_carr_phase_rad_int; int d_phase_step_rad_int; - unsigned long int d_initial_sample_counter; + unsigned long long int d_initial_sample_counter; // driver std::string d_device_name;