diff --git a/src/algorithms/acquisition/CMakeLists.txt b/src/algorithms/acquisition/CMakeLists.txt
index 96259341c..5cf06e3e8 100644
--- a/src/algorithms/acquisition/CMakeLists.txt
+++ b/src/algorithms/acquisition/CMakeLists.txt
@@ -19,3 +19,4 @@
add_subdirectory(adapters)
add_subdirectory(gnuradio_blocks)
add_subdirectory(libs)
+
diff --git a/src/algorithms/acquisition/adapters/CMakeLists.txt b/src/algorithms/acquisition/adapters/CMakeLists.txt
index 82b4b33c1..8386759b0 100644
--- a/src/algorithms/acquisition/adapters/CMakeLists.txt
+++ b/src/algorithms/acquisition/adapters/CMakeLists.txt
@@ -37,9 +37,9 @@ 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 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)
set(ACQ_ADAPTER_SOURCES ${ACQ_ADAPTER_SOURCES} gps_l1_ca_pcps_opencl_acquisition.cc)
endif(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..73a38d257
--- /dev/null
+++ b/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition_fpga.cc
@@ -0,0 +1,552 @@
+/*!
+ * \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
+
+
+
+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("top acq constructor start\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;
+ 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
+ // 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;
+// }
+
+ //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";
+ 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 * 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 <= Galileo_E1_NUMBER_OF_CODES; 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)
+ {
+ //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, PRN, fs_in, 0, false);
+ }
+ else
+ {
+ 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++)
+// {
+// //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_);
+// }
+
+
+// // 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] = 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
+ 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(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_;
+
+ // 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;
+ //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.
+
+// 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_);
+ //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);
+//
+// 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;
+ // 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");
+}
+
+
+//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)
+{
+ // printf("top acq connect\n");
+// 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
+ // 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_;
+// }
+// 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;
+// }
+ // 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
new file mode 100644
index 000000000..6c975e30e
--- /dev/null
+++ b/src/algorithms/acquisition/adapters/galileo_e1_pcps_ambiguous_acquisition_fpga.h
@@ -0,0 +1,175 @@
+/*!
+ * \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
+ {
+ // printf("top acq role\n");
+ return role_;
+ }
+
+ /*!
+ * \brief Returns "Galileo_E1_PCPS_Ambiguous_Acquisition"
+ */
+ 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;
+ }
+
+ 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) override;
+
+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/galileo_e5a_pcps_acquisition_fpga.cc b/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition_fpga.cc
new file mode 100644
index 000000000..2901081ac
--- /dev/null
+++ b/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition_fpga.cc
@@ -0,0 +1,405 @@
+/*!
+ * \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)
+{
+ //printf("creating the E5A acquisition");
+ 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);
+ //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);
+ 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
+
+ //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++)
+ {
+ // 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_, 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;
+ //printf("creating the E5A acquisition end");
+}
+
+
+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..1bdca10cc
--- /dev/null
+++ b/src/algorithms/acquisition/adapters/galileo_e5a_pcps_acquisition_fpga.h
@@ -0,0 +1,175 @@
+/*!
+ * \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) override;
+
+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 f9625bae5..383e098b3 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
@@ -11,7 +11,7 @@
*
* -------------------------------------------------------------------------
*
- * Copyright (C) 2010-2018 (see AUTHORS file for a list of contributors)
+ * Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
@@ -29,20 +29,21 @@
* 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 .
*
* -------------------------------------------------------------------------
*/
-#include "gps_l1_ca_pcps_acquisition_fpga.h"
#include "configuration_interface.h"
#include "gnss_sdr_flags.h"
-#include "GPS_L1_CA.h"
+#include "gps_l1_ca_pcps_acquisition_fpga.h"
#include "gps_sdr_signal_processing.h"
+#include "GPS_L1_CA.h"
#include
#include
#include
+
#define NUM_PRNs 32
using google::LogMessage;
@@ -59,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;
acq_parameters.samples_per_code = static_cast(ceil(GPS_L1_CA_CHIP_PERIOD * static_cast(acq_parameters.fs_in)));
doppler_max_ = configuration_->property(role + ".doppler_max", 5000);
@@ -67,43 +70,56 @@ 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);
- 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
// fill in zero padding
- for (unsigned int s = code_length; s < nsamples_total; s++)
+ 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
- max = 0; // initialize maximum value
- for (unsigned int i = 0; i < nsamples_total; i++) // search for maxima
+
+
+ // // 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
{
if (std::abs(fft_codes_padded[i].real()) > max)
{
@@ -116,12 +132,31 @@ 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
+ //acq_parameters
acq_parameters.all_fft_codes = d_all_fft_codes_;
// temporary buffers that we can delete
@@ -135,14 +170,6 @@ GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga(
channel_ = 0;
doppler_step_ = 0;
gnss_synchro_ = 0;
- if (in_streams_ > 1)
- {
- LOG(ERROR) << "This implementation only supports one input stream";
- }
- if (out_streams_ > 0)
- {
- LOG(ERROR) << "This implementation does not provide an output stream";
- }
}
@@ -161,6 +188,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);
}
@@ -216,26 +245,21 @@ void GpsL1CaPcpsAcquisitionFpga::set_state(int state)
acquisition_fpga_->set_state(state);
}
-
void GpsL1CaPcpsAcquisitionFpga::connect(gr::top_block_sptr top_block)
{
- if (top_block)
- { // nothing to disconnect
- }
+ // nothing to connect
}
void GpsL1CaPcpsAcquisitionFpga::disconnect(gr::top_block_sptr top_block)
{
- if (top_block)
- { // nothing to disconnect
- }
+ // nothing to disconnect
}
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 9fac921d1..7e74f70e9 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/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..733f3cea9
--- /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..9f7912628
--- /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) override;
+
+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..57e986d66
--- /dev/null
+++ b/src/algorithms/acquisition/adapters/gps_l5i_pcps_acquisition_fpga.cc
@@ -0,0 +1,404 @@
+/*!
+ * \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)
+{
+ //printf("L5 ACQ CLASS CREATED\n");
+ 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;
+ 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
+ //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", 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
+ //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++)
+ {
+ 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)));
+ }
+
+
+ }
+
+
+ //printf("L5 ACQ CLASS MID 2\n");
+
+ //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;
+ //printf("L5 ACQ CLASS FINISHED\n");
+}
+
+
+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..f7115aaa2
--- /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) override;
+
+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/CMakeLists.txt b/src/algorithms/acquisition/gnuradio_blocks/CMakeLists.txt
index 50fc61ae9..4577c3d3b 100644
--- a/src/algorithms/acquisition/gnuradio_blocks/CMakeLists.txt
+++ b/src/algorithms/acquisition/gnuradio_blocks/CMakeLists.txt
@@ -26,12 +26,12 @@ set(ACQ_GR_BLOCKS_SOURCES
pcps_quicksync_acquisition_cc.cc
galileo_pcps_8ms_acquisition_cc.cc
galileo_e5a_noncoherent_iq_acquisition_caf_cc.cc
-)
+)
if(ENABLE_FPGA)
set(ACQ_GR_BLOCKS_SOURCES ${ACQ_GR_BLOCKS_SOURCES} pcps_acquisition_fpga.cc)
endif(ENABLE_FPGA)
-
+
if(OPENCL_FOUND)
set(ACQ_GR_BLOCKS_SOURCES ${ACQ_GR_BLOCKS_SOURCES} pcps_opencl_acquisition_cc.cc)
endif(OPENCL_FOUND)
diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.cc b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.cc
index 86a5ec969..361688faf 100644
--- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.cc
+++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.cc
@@ -15,7 +15,7 @@
*
* -------------------------------------------------------------------------
*
- * Copyright (C) 2010-2018 (see AUTHORS file for a list of contributors)
+ * Copyright (C) 2010-2017 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
@@ -33,16 +33,19 @@
* 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 .
*
* -------------------------------------------------------------------------
*/
-#include "pcps_acquisition_fpga.h"
+
#include
#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,25 +76,49 @@ pcps_acquisition_fpga::pcps_acquisition_fpga(pcpsconf_fpga_t conf_) : gr::block(
d_channel = 0;
d_gnss_synchro = 0;
- acquisition_fpga = std::make_shared(acq_parameters.device_name, d_fft_size, acq_parameters.doppler_max, acq_parameters.samples_per_ms,
+ //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, acq_parameters.code_length, acq_parameters.doppler_max, d_fft_size,
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,
+ // 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;
@@ -102,11 +131,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(int32_tstate)
+void pcps_acquisition_fpga::set_state(int32_t state)
{
+ // printf("acq set state start\n");
d_state = state;
if (d_state == 1)
{
@@ -126,11 +157,13 @@ void pcps_acquisition_fpga::set_state(int32_tstate)
{
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"
@@ -144,11 +177,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"
@@ -162,16 +197,19 @@ 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
uint32_t indext = 0;
float magt = 0.0;
+ float fft_normalization_factor = static_cast(d_fft_size) * static_cast(d_fft_size);
d_input_power = 0.0;
d_mag = 0.0;
@@ -184,24 +222,32 @@ void pcps_acquisition_fpga::set_active(bool active)
// no CFAR algorithm in the FPGA
<< ", use_CFAR_algorithm_flag: false";
- uint32_t initial_sample;
+ uint64_t initial_sample;
float input_power_all = 0.0;
float input_power_computed = 0.0;
- for (uint32_t doppler_index = 0; doppler_index < d_num_doppler_bins; doppler_index++)
+
+ 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
- int32_tdoppler = -static_cast(acq_parameters.doppler_max) + d_doppler_step * doppler_index;
+ int32_t doppler = -static_cast(acq_parameters.doppler_max) + d_doppler_step * doppler_index;
- acquisition_fpga->set_phase_step(doppler_index);
- acquisition_fpga->run_acquisition(); // runs acquisition and waits until it is finished
+ //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);
- d_sample_counter = static_cast(initial_sample);
+ &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);
@@ -210,16 +256,79 @@ void pcps_acquisition_fpga::set_active(bool active)
d_gnss_synchro->Acq_doppler_hz = static_cast(doppler);
d_gnss_synchro->Acq_samplestamp_samples = d_sample_counter;
- d_test_statistics = (d_mag / d_input_power); //* correction_factor;
+ d_test_statistics = (d_mag / d_input_power); //* correction_factor;
}
// 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
+ //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();
+
+ 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);
+ int32_t 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("##### initial_sample = %llu\n",initial_sample);
+ // printf("##### debug_doppler_index = %d\n",debug_doppler_index);
send_positive_acquisition();
d_state = 0; // Positive acquisition
}
@@ -229,12 +338,13 @@ void pcps_acquisition_fpga::set_active(bool active)
d_active = false;
send_negative_acquisition();
}
+
+ // printf("acq set active end\n");
}
int pcps_acquisition_fpga::general_work(int noutput_items __attribute__((unused)),
- gr_vector_int& ninput_items __attribute__((unused)),
- gr_vector_const_void_star& input_items __attribute__((unused)),
+ gr_vector_int& ninput_items, gr_vector_const_void_star& input_items,
gr_vector_void_star& output_items __attribute__((unused)))
{
// the general work is not used with the acquisition that uses the FPGA
diff --git a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.h b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.h
index 4dc8b6505..abf8f6b06 100644
--- a/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.h
+++ b/src/algorithms/acquisition/gnuradio_blocks/pcps_acquisition_fpga.h
@@ -66,10 +66,10 @@ typedef struct
/* pcps acquisition configuration */
uint32_t sampled_ms;
uint32_t doppler_max;
- int64_t freq;
int64_t fs_in;
- int32_tsamples_per_ms;
- int32_tsamples_per_code;
+ int32_t samples_per_ms;
+ int32_t samples_per_code;
+ int32_t code_length;
uint32_t select_queue_Fpga;
std::string device_name;
lv_16sc_t* all_fft_codes; // memory that contains all the code ffts
@@ -107,8 +107,9 @@ private:
float d_threshold;
float d_mag;
float d_input_power;
+ uint32_t d_doppler_index;
float d_test_statistics;
- int32_td_state;
+ int32_t d_state;
uint32_t d_channel;
uint32_t d_doppler_step;
uint32_t d_fft_size;
@@ -117,6 +118,12 @@ private:
Gnss_Synchro* d_gnss_synchro;
std::shared_ptr acquisition_fpga;
+ // debug
+ float debug_d_max_absolute;
+ float debug_d_input_power_absolute;
+ int32_t debug_indext;
+ int32_t debug_doppler_index;
+
public:
~pcps_acquisition_fpga();
@@ -127,7 +134,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 +144,9 @@ public:
*/
inline uint32_t mag() const
{
+ // printf("acq dmag start\n");
return d_mag;
+ // printf("acq dmag end\n");
}
/*!
@@ -154,7 +165,7 @@ public:
* first available sample.
* \param state - int=1 forces start of acquisition
*/
- void set_state(int32_tstate);
+ void set_state(int32_t state);
/*!
* \brief Starts acquisition algorithm, turning from standby mode to
@@ -179,7 +190,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 +201,10 @@ public:
*/
inline void set_doppler_max(uint32_t 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 +213,10 @@ public:
*/
inline void set_doppler_step(uint32_t 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/acq_conf.h b/src/algorithms/acquisition/libs/acq_conf.h
index 662134b2d..445fab878 100644
--- a/src/algorithms/acquisition/libs/acq_conf.h
+++ b/src/algorithms/acquisition/libs/acq_conf.h
@@ -33,20 +33,21 @@
#define GNSS_SDR_ACQ_CONF_H_
#include
+#include
#include
class Acq_Conf
{
public:
/* PCPS Acquisition configuration */
- unsigned int sampled_ms;
- unsigned int ms_per_code;
- unsigned int samples_per_chip;
- unsigned int max_dwells;
- unsigned int doppler_max;
- unsigned int num_doppler_bins_step2;
+ uint32_t sampled_ms;
+ uint32_t ms_per_code;
+ uint32_t samples_per_chip;
+ uint32_t max_dwells;
+ uint32_t doppler_max;
+ uint32_t num_doppler_bins_step2;
float doppler_step2;
- long fs_in;
+ int64_t fs_in;
float samples_per_ms;
float samples_per_code;
bool bit_transition_flag;
@@ -56,7 +57,7 @@ public:
bool blocking_on_standby; // enable it only for unit testing to avoid sample consume on idle status
bool make_2_steps;
std::string dump_filename;
- unsigned int dump_channel;
+ uint32_t dump_channel;
size_t it_size;
Acq_Conf();
diff --git a/src/algorithms/acquisition/libs/fpga_acquisition.cc b/src/algorithms/acquisition/libs/fpga_acquisition.cc
index f60be67b8..57e2a6ba2 100644
--- a/src/algorithms/acquisition/libs/fpga_acquisition.cc
+++ b/src/algorithms/acquisition/libs/fpga_acquisition.cc
@@ -37,6 +37,7 @@
#include "GPS_L1_CA.h"
#include "gps_sdr_signal_processing.h"
#include
+#include
#include // libraries used by the GIPO
#include // libraries used by the GIPO
@@ -55,6 +56,17 @@
#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(uint32_t 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,9 +96,14 @@ fpga_acquisition::fpga_acquisition(std::string device_name,
uint32_t sampled_ms, uint32_t select_queue,
lv_16sc_t *all_fft_codes)
{
- uint32_t vector_length = nsamples_total * sampled_ms;
+ //printf("AAA- sampled_ms = %d\n ", sampled_ms);
+
+ uint32_t vector_length = nsamples_total; // * sampled_ms;
+
+ //printf("AAA- vector_length = %d\n ", vector_length);
// initial values
d_device_name = device_name;
+ //d_freq = freq;
d_fs_in = fs_in;
d_vector_length = vector_length;
d_nsamples = nsamples; // number of samples not including padding
@@ -98,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));
@@ -105,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
@@ -118,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";
@@ -150,20 +174,35 @@ uint32_t fpga_acquisition::fpga_acquisition_test_register(uint32_t writeval)
void fpga_acquisition::fpga_configure_acquisition_local_code(lv_16sc_t fft_local_code[])
{
- uint16_t local_code;
+ uint32_t local_code;
uint32_t k, tmp, tmp2;
uint32_t 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);
}
@@ -173,12 +212,14 @@ void fpga_acquisition::run_acquisition(void)
int32_t reenable = 1;
write(d_fd, reinterpret_cast(&reenable), sizeof(int32_t));
// 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
int32_t 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");
@@ -187,12 +228,111 @@ void fpga_acquisition::run_acquisition(void)
}
+void fpga_acquisition::set_doppler_sweep(uint32_t num_sweeps)
+{
+ float phase_step_rad_real;
+ float phase_step_rad_int_temp;
+ int32_t phase_step_rad_int;
+ //int32_t doppler = static_cast(-d_doppler_max) + d_doppler_step * doppler_index;
+ int32_t 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 * (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 = static_cast(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 = static_cast(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(uint32_t num_sweeps, uint32_t doppler_index)
+{
+ float phase_step_rad_real;
+ float phase_step_rad_int_temp;
+ int32_t phase_step_rad_int;
+ int32_t doppler = -static_cast(d_doppler_max) + d_doppler_step * doppler_index;
+ //int32_t 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 * (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 = static_cast(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 = static_cast(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()
{
+ //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;
+ //printf("AAA writing d_nsamples = %d to d map base 2\n ", d_nsamples);
d_map_base[2] = d_nsamples;
- d_map_base[5] = static_cast(log2(static_cast(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] = static_cast(log2(static_cast(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));
}
@@ -201,8 +341,9 @@ void fpga_acquisition::set_phase_step(uint32_t doppler_index)
float phase_step_rad_real;
float phase_step_rad_int_temp;
int32_t phase_step_rad_int;
- int32_t doppler = static_cast(-d_doppler_max) + d_doppler_step * doppler_index;
- float phase_step_rad = GPS_TWO_PI * doppler / static_cast(d_fs_in);
+ int32_t 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 * (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)
@@ -210,28 +351,46 @@ void fpga_acquisition::set_phase_step(uint32_t 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;
}
- 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+ 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 = static_cast(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, uint32_t *initial_sample, float *power_sum)
+ float *max_magnitude, uint64_t *initial_sample, float *power_sum, uint32_t *doppler_index)
{
+ uint64_t initial_sample_tmp = 0;
+
uint32_t readval = 0;
+ uint64_t readval_long = 0;
+ uint64_t readval_long_shifted = 0;
readval = d_map_base[1];
- *initial_sample = readval;
- readval = d_map_base[2];
+ initial_sample_tmp = readval;
+ readval_long = d_map_base[2];
+ 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);
+ //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);
}
@@ -260,5 +419,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 17afbe361..c23e6b5d5 100644
--- a/src/algorithms/acquisition/libs/fpga_acquisition.h
+++ b/src/algorithms/acquisition/libs/fpga_acquisition.h
@@ -59,10 +59,12 @@ public:
bool init();
bool set_local_code(uint32_t PRN);
bool free();
+ void set_doppler_sweep(uint32_t num_sweeps);
+ void set_doppler_sweep_debug(uint32_t num_sweeps, uint32_t doppler_index);
void run_acquisition(void);
void set_phase_step(uint32_t doppler_index);
void read_acquisition_results(uint32_t *max_index, float *max_magnitude,
- uint32_t *initial_sample, float *power_sum);
+ uint64_t *initial_sample, float *power_sum, uint32_t *doppler_index);
void block_samples();
void unblock_samples();
diff --git a/src/algorithms/tracking/adapters/CMakeLists.txt b/src/algorithms/tracking/adapters/CMakeLists.txt
index 8a992b599..fe4b9292a 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 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
new file mode 100644
index 000000000..cd4b2f84b
--- /dev/null
+++ b/src/algorithms/tracking/adapters/galileo_e1_dll_pll_veml_tracking_fpga.cc
@@ -0,0 +1,268 @@
+/*!
+ * \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)
+{
+ //dllpllconf_t trk_param;
+ Dll_Pll_Conf_Fpga trk_param_fpga = Dll_Pll_Conf_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;
+ 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);
+ 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;
+ //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;
+
+ 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()));
+
+ 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()));
+ }
+
+ //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 < 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(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 < 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;
+ 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_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;
+ DLOG(INFO) << "tracking(" << tracking_fpga_sc->unique_id() << ")";
+}
+
+
+GalileoE1DllPllVemlTrackingFpga::~GalileoE1DllPllVemlTrackingFpga()
+{
+ delete[] d_ca_codes;
+ if (d_track_pilot)
+ {
+ 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..794e5596c
--- /dev/null
+++ b/src/algorithms/tracking/adapters/galileo_e1_dll_pll_veml_tracking_fpga.h
@@ -0,0 +1,111 @@
+/*!
+ * \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_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;
+ int* d_data_codes;
+ bool d_track_pilot;
+
+};
+
+
+#endif // GNSS_SDR_GALILEO_E1_DLL_PLL_VEML_TRACKING_FPGA_H_
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..8be397a02
--- /dev/null
+++ b/src/algorithms/tracking/adapters/galileo_e5a_dll_pll_tracking_fpga.cc
@@ -0,0 +1,293 @@
+/*!
+ * \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)
+{
+ //printf("creating the E5A tracking");
+
+
+ Dll_Pll_Conf_Fpga trk_param_fpga = Dll_Pll_Conf_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 -> up to 5+1 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 ###################
+ tracking_fpga_sc = dll_pll_veml_make_tracking_fpga(trk_param_fpga);
+// 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)
+{
+ //printf("blabla channel = %d\n", 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 f9d3aa587..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
@@ -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
@@ -13,7 +13,7 @@
*
* -------------------------------------------------------------------------
*
- * Copyright (C) 2010-2018 (see AUTHORS file for a list of contributors)
+ * Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
@@ -31,32 +31,34 @@
* 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 .
*
* -------------------------------------------------------------------------
*/
+#include
+#include "gps_sdr_signal_processing.h"
#include "gps_l1_ca_dll_pll_tracking_fpga.h"
#include "configuration_interface.h"
-#include "display.h"
-#include "gnss_sdr_flags.h"
#include "GPS_L1_CA.h"
-#include "gps_sdr_signal_processing.h"
-#include
-
+#include "gnss_sdr_flags.h"
+#include "display.h"
#define NUM_PRNs 32
using google::LogMessage;
GpsL1CaDllPllTrackingFpga::GpsL1CaDllPllTrackingFpga(
- ConfigurationInterface* configuration, std::string role,
- unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams)
+ 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";
+ //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;
@@ -127,43 +129,36 @@ 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()));
+ 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);
- }
+ {
+ 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);
channel_ = 0;
DLOG(INFO) << "tracking(" << tracking_fpga_sc->unique_id() << ")";
- if (in_streams_ > 1)
- {
- LOG(ERROR) << "This implementation only supports one input stream";
- }
- if (out_streams_ > 1)
- {
- LOG(ERROR) << "This implementation only supports one output stream";
- }
+
}
-
GpsL1CaDllPllTrackingFpga::~GpsL1CaDllPllTrackingFpga()
{
delete[] d_ca_codes;
}
-
void GpsL1CaDllPllTrackingFpga::start_tracking()
{
tracking_fpga_sc->start_tracking();
}
-
/*
* Set tracking channel unique ID
*/
@@ -173,27 +168,21 @@ void GpsL1CaDllPllTrackingFpga::set_channel(unsigned int channel)
tracking_fpga_sc->set_channel(channel);
}
-
void GpsL1CaDllPllTrackingFpga::set_gnss_synchro(Gnss_Synchro* p_gnss_synchro)
{
tracking_fpga_sc->set_gnss_synchro(p_gnss_synchro);
}
-
void GpsL1CaDllPllTrackingFpga::connect(gr::top_block_sptr top_block)
{
- if (top_block)
- { /* top_block is not null */
- };
+ if(top_block) { /* top_block is not null */};
//nothing to connect
}
void GpsL1CaDllPllTrackingFpga::disconnect(gr::top_block_sptr top_block)
{
- if (top_block)
- { /* top_block is not null */
- };
+ if(top_block) { /* top_block is not null */};
//nothing to disconnect
}
@@ -208,3 +197,5 @@ gr::basic_block_sptr GpsL1CaDllPllTrackingFpga::get_right_block()
{
return tracking_fpga_sc;
}
+
+
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 de77dff2e..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
@@ -13,7 +13,7 @@
*
* -------------------------------------------------------------------------
*
- * Copyright (C) 2010-2018 (see AUTHORS file for a list of contributors)
+ * Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
@@ -31,7 +31,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