mirror of
https://github.com/gnss-sdr/gnss-sdr
synced 2024-12-15 12:40:35 +00:00
Merge branch 'fpga' of https://github.com/mmajoral/gnss-sdr into merge-marc
This commit is contained in:
commit
05a1806c8f
@ -19,3 +19,4 @@
|
||||
add_subdirectory(adapters)
|
||||
add_subdirectory(gnuradio_blocks)
|
||||
add_subdirectory(libs)
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#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 <boost/lexical_cast.hpp>
|
||||
#include <boost/math/distributions/exponential.hpp>
|
||||
#include <glog/logging.h>
|
||||
|
||||
|
||||
|
||||
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<unsigned int>(std::round(static_cast<double>(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<int>(std::round(static_cast<double>(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<float>* code = new std::complex<float>[nsamples_total]; // buffer for the local code
|
||||
gr_complex* fft_codes_padded = static_cast<gr_complex*>(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<float>* code = new std::complex<float>[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<float>(static_cast<float>(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<int>(floor(4096*fft_codes_padded[i].real() * (pow(2, 3) - 1) / max)),
|
||||
// static_cast<int>(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<int>(floor(1024*fft_codes_padded[i].real() * (pow(2, 5) - 1) / max)),
|
||||
// static_cast<int>(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<int>(floor(256*fft_codes_padded[i].real() * (pow(2, 7) - 1) / max)),
|
||||
// static_cast<int>(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<int>(floor(16*fft_codes_padded[i].real() * (pow(2, 11) - 1) / max)),
|
||||
// static_cast<int>(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<int>(floor(fft_codes_padded[i].real() * (pow(2, 15) - 1) / max)),
|
||||
static_cast<int>(floor(fft_codes_padded[i].imag() * (pow(2, 15) - 1) / max)));
|
||||
|
||||
// tmp_re = static_cast<int>(floor(fft_codes_padded[i].real() * (pow(2, 7) - 1) / max));
|
||||
// tmp_im = static_cast<int>(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<int>(tmp_re), static_cast<int>(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<std::string>(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<std::string>(channel_) + ".cboc", false);
|
||||
//
|
||||
// std::complex<float>* code = new std::complex<float>[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<int>(-doppler_max_); doppler <= static_cast<int>(doppler_max_); doppler += doppler_step_)
|
||||
// {
|
||||
// frequency_bins++;
|
||||
// }
|
||||
//
|
||||
// DLOG(INFO) << "Channel " << channel_ << " Pfa = " << pfa;
|
||||
//
|
||||
// unsigned int ncells = vector_length_ * frequency_bins;
|
||||
// double exponent = 1 / static_cast<double>(ncells);
|
||||
// double val = pow(1.0 - pfa, exponent);
|
||||
// double lambda = double(vector_length_);
|
||||
// boost::math::exponential_distribution<double> mydist(lambda);
|
||||
// float threshold = static_cast<float>(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");
|
||||
}
|
||||
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#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 <gnuradio/blocks/stream_to_vector.h>
|
||||
#include <gnuradio/blocks/float_to_complex.h>
|
||||
#include <volk_gnsssdr/volk_gnsssdr.h>
|
||||
#include <string>
|
||||
|
||||
|
||||
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<float>* 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_ */
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#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 <boost/lexical_cast.hpp>
|
||||
#include <boost/math/distributions/exponential.hpp>
|
||||
#include <glog/logging.h>
|
||||
#include <volk_gnsssdr/volk_gnsssdr_complex.h>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
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<unsigned int>(std::round(static_cast<double>(fs_in) / Galileo_E5a_CODE_CHIP_RATE_HZ * static_cast<double>(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<float>* code = new std::complex<float>[nsamples_total]; // buffer for the local code
|
||||
gr_complex* fft_codes_padded = static_cast<gr_complex*>(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<float>(static_cast<float>(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<int>(floor(fft_codes_padded[i].real() * (pow(2, 15) - 1) / max)),
|
||||
static_cast<int>(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<std::string>(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<int>(-doppler_max_); doppler <= static_cast<int>(doppler_max_); doppler += doppler_step_)
|
||||
// {
|
||||
// frequency_bins++;
|
||||
// }
|
||||
// DLOG(INFO) << "Channel " << channel_ << " Pfa = " << pfa;
|
||||
// unsigned int ncells = vector_length_ * frequency_bins;
|
||||
// double exponent = 1 / static_cast<double>(ncells);
|
||||
// double val = pow(1.0 - pfa, exponent);
|
||||
// double lambda = double(vector_length_);
|
||||
// boost::math::exponential_distribution<double> mydist(lambda);
|
||||
// float threshold = static_cast<float>(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_;
|
||||
}
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#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 <gnuradio/blocks/stream_to_vector.h>
|
||||
#include <volk_gnsssdr/volk_gnsssdr.h>
|
||||
#include <string>
|
||||
|
||||
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<float>* codeI_;
|
||||
std::complex<float>* 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_ */
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#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 <gnuradio/fft/fft.h>
|
||||
#include <glog/logging.h>
|
||||
#include <new>
|
||||
|
||||
|
||||
#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<unsigned int>(ceil(GPS_L1_CA_CHIP_PERIOD * static_cast<float>(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<unsigned int>(std::round(static_cast<double>(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<float>* code = new std::complex<float>[nsamples_total]; // buffer for the local code
|
||||
gr_complex* fft_codes_padded = static_cast<gr_complex*>(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<float>(static_cast<float>(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<int>(floor(fft_codes_padded[i].real() * (pow(2, 7) - 1) / max)),
|
||||
static_cast<int>(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<int>(floor(256*fft_codes_padded[i].real() * (pow(2, 7) - 1) / max)),
|
||||
// static_cast<int>(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<int>(16*floor(fft_codes_padded[i].real() * (pow(2, 11) - 1) / max)),
|
||||
// static_cast<int>(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<int>(floor(fft_codes_padded[i].real() * (pow(2, 15) - 1) / max)),
|
||||
// static_cast<int>(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<int>(floor(fft_codes_padded[i].real() * (pow(2, 15) - 1) / max)),
|
||||
static_cast<int>(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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 <ul>
|
||||
* <li> Javier Arribas, 2015. jarribas(at)cttc.es
|
||||
* </ul>
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#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 <boost/math/distributions/exponential.hpp>
|
||||
#include <glog/logging.h>
|
||||
|
||||
#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<double>(fs_in_) / (GPS_L2_M_CODE_RATE_HZ / static_cast<double>(GPS_L2_M_CODE_LENGTH_CHIPS)));
|
||||
|
||||
acq_parameters.sampled_ms = 20;
|
||||
unsigned code_length = std::round(static_cast<double>(fs_in_) / (GPS_L2_M_CODE_RATE_HZ / static_cast<double>(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<int>(std::round(static_cast<double>(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<float>* code = new std::complex<float>[nsamples_total]; // buffer for the local code
|
||||
gr_complex* fft_codes_padded = static_cast<gr_complex*>(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<float>(static_cast<float>(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<int>(floor(fft_codes_padded[i].real() * (pow(2, 7) - 1) / max)),
|
||||
static_cast<int>(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<int>(std::round(static_cast<double>(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<std::string>(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<int>(-doppler_max_); doppler <= static_cast<int>(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<double>(ncells);
|
||||
// double val = pow(1.0 - pfa, exponent);
|
||||
// double lambda = double(vector_length_);
|
||||
// boost::math::exponential_distribution<double> mydist(lambda);
|
||||
// float threshold = static_cast<float>(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_;
|
||||
}
|
@ -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 <ul>
|
||||
* <li> Javier Arribas, 2015. jarribas(at)cttc.es
|
||||
* </ul>
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#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 <gnuradio/blocks/stream_to_vector.h>
|
||||
#include <gnuradio/blocks/float_to_complex.h>
|
||||
#include <volk_gnsssdr/volk_gnsssdr.h>
|
||||
#include <string>
|
||||
|
||||
|
||||
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<float>* 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_ */
|
@ -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 <ul>
|
||||
* <li> Javier Arribas, 2017. jarribas(at)cttc.es
|
||||
* </ul>
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#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 <boost/math/distributions/exponential.hpp>
|
||||
#include <glog/logging.h>
|
||||
|
||||
#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<unsigned int>(std::round(static_cast<double>(fs_in) / (GPS_L5i_CODE_RATE_HZ / static_cast<double>(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<float>* code = new gr_complex[vector_length];
|
||||
//printf("L5 ACQ CLASS MID 03\n");
|
||||
gr_complex* fft_codes_padded = static_cast<gr_complex*>(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<float>(static_cast<float>(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<int>(floor(256*fft_codes_padded[i].real() * (pow(2, 7) - 1) / max)),
|
||||
// static_cast<int>(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<int>(16*floor(fft_codes_padded[i].real() * (pow(2, 11) - 1) / max)),
|
||||
// static_cast<int>(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<int>(floor(fft_codes_padded[i].real() * (pow(2, 15) - 1) / max)),
|
||||
// static_cast<int>(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<int>(floor(fft_codes_padded[i].real() * (pow(2, 15) - 1) / max)),
|
||||
static_cast<int>(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<std::string>(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<int>(-doppler_max_); doppler <= static_cast<int>(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<double>(ncells);
|
||||
// double val = pow(1.0 - pfa, exponent);
|
||||
// double lambda = double(vector_length_);
|
||||
// boost::math::exponential_distribution<double> mydist(lambda);
|
||||
// float threshold = static_cast<float>(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_;
|
||||
}
|
@ -0,0 +1,171 @@
|
||||
/*!
|
||||
* \file GPS_L5i_PCPS_Acquisition.h
|
||||
* \brief Adapts a PCPS acquisition block to an AcquisitionInterface for
|
||||
* GPS L5i signals
|
||||
* \authors <ul>
|
||||
* <li> Javier Arribas, 2017. jarribas(at)cttc.es
|
||||
* </ul>
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#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 <gnuradio/blocks/stream_to_vector.h>
|
||||
#include <gnuradio/blocks/float_to_complex.h>
|
||||
#include <volk_gnsssdr/volk_gnsssdr.h>
|
||||
#include <string>
|
||||
|
||||
|
||||
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<float>* 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_ */
|
@ -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)
|
||||
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "pcps_acquisition_fpga.h"
|
||||
|
||||
#include <glog/logging.h>
|
||||
#include <gnuradio/io_signature.h>
|
||||
#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<fpga_acquisition>(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 <fpga_acquisition>
|
||||
// (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<fpga_acquisition>(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 <fpga_acquisition>
|
||||
// (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<uint32_t>(std::ceil(static_cast<double>(static_cast<int32_t>(acq_parameters.doppler_max) - static_cast<int32_t>(-acq_parameters.doppler_max)) / static_cast<double>(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<float>(d_fft_size) * static_cast<float>(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<int32_t>(acq_parameters.doppler_max) + d_doppler_step * doppler_index;
|
||||
int32_t doppler = -static_cast<int32_t>(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<uint64_t>(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<double>(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<int32_t>(acq_parameters.doppler_max) + d_doppler_step * d_doppler_index;
|
||||
//d_gnss_synchro->Acq_delay_samples = static_cast<double>(2*(indext % (2*acq_parameters.samples_per_code)));
|
||||
d_gnss_synchro->Acq_delay_samples = static_cast<double>(indext % acq_parameters.samples_per_code);
|
||||
d_gnss_synchro->Acq_doppler_hz = static_cast<double>(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
|
||||
|
@ -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<fpga_acquisition> 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");
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -33,20 +33,21 @@
|
||||
#define GNSS_SDR_ACQ_CONF_H_
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
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();
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "GPS_L1_CA.h"
|
||||
#include "gps_sdr_signal_processing.h"
|
||||
#include <glog/logging.h>
|
||||
#include <iostream>
|
||||
#include <fcntl.h> // libraries used by the GIPO
|
||||
#include <sys/mman.h> // 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<volatile uint32_t *>(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<void *>(-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<void *>(&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<int32_t>(-d_doppler_max) + d_doppler_step * doppler_index;
|
||||
int32_t doppler = static_cast<int32_t>(-d_doppler_max);
|
||||
//float phase_step_rad = GPS_TWO_PI * (d_freq + doppler) / static_cast<float>(d_fs_in);
|
||||
float phase_step_rad = GPS_TWO_PI * (doppler) / static_cast<float>(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<int32_t>(phase_step_rad_int_temp * (POW_2_29)); // * 2^29 (in total it makes x2^31 in two steps to avoid the warnings
|
||||
//printf("AAA writing phase_step_rad_int for initial doppler = %d to d map base 3\n", phase_step_rad_int);
|
||||
d_map_base[3] = phase_step_rad_int;
|
||||
|
||||
// repeat the calculation with the doppler step
|
||||
doppler = static_cast<int32_t>(d_doppler_step);
|
||||
phase_step_rad = GPS_TWO_PI * (doppler) / static_cast<float>(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<int32_t>(phase_step_rad_int_temp * (POW_2_29)); // * 2^29 (in total it makes x2^31 in two steps to avoid the warnings
|
||||
//printf("AAA writing phase_step_rad_int for doppler step = %d to d map base 4\n", phase_step_rad_int);
|
||||
d_map_base[4] = phase_step_rad_int;
|
||||
//printf("AAA writing num sweeps to d map base 5 = %d\n", num_sweeps);
|
||||
d_map_base[5] = num_sweeps;
|
||||
}
|
||||
|
||||
void fpga_acquisition::set_doppler_sweep_debug(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<int32_t>(d_doppler_max) + d_doppler_step * doppler_index;
|
||||
//int32_t doppler = static_cast<int32_t>(-d_doppler_max);
|
||||
//float phase_step_rad = GPS_TWO_PI * (d_freq + doppler) / static_cast<float>(d_fs_in);
|
||||
float phase_step_rad = GPS_TWO_PI * (doppler) / static_cast<float>(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<int32_t>(phase_step_rad_int_temp * (POW_2_29)); // * 2^29 (in total it makes x2^31 in two steps to avoid the warnings
|
||||
//printf("AAAh writing phase_step_rad_int for initial doppler = %d to d map base 3\n", phase_step_rad_int);
|
||||
d_map_base[3] = phase_step_rad_int;
|
||||
|
||||
// repeat the calculation with the doppler step
|
||||
doppler = static_cast<int32_t>(d_doppler_step);
|
||||
phase_step_rad = GPS_TWO_PI * (doppler) / static_cast<float>(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<int32_t>(phase_step_rad_int_temp * (POW_2_29)); // * 2^29 (in total it makes x2^31 in two steps to avoid the warnings
|
||||
//printf("AAAh writing phase_step_rad_int for doppler step = %d to d map base 4\n", phase_step_rad_int);
|
||||
d_map_base[4] = phase_step_rad_int;
|
||||
//printf("AAAh writing num sweeps to d map base 5 = %d\n", num_sweeps);
|
||||
d_map_base[5] = num_sweeps;
|
||||
}
|
||||
|
||||
|
||||
void fpga_acquisition::configure_acquisition()
|
||||
{
|
||||
//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<int32_t>(log2(static_cast<float>(d_vector_length))); // log2 FFTlength
|
||||
//printf("AAA writing LOG2 d_vector_length = %d to d map base 7\n ", (int)log2((float)d_vector_length));
|
||||
d_map_base[7] = static_cast<int32_t>(log2(static_cast<float>(d_vector_length))); // log2 FFTlength
|
||||
//printf("acquisition debug vector length = %d\n", d_vector_length);
|
||||
//printf("acquisition debug vector length = %d\n", (int)log2((float)d_vector_length));
|
||||
}
|
||||
|
||||
|
||||
@ -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<int>(-d_doppler_max) + d_doppler_step * doppler_index;
|
||||
float phase_step_rad = GPS_TWO_PI * doppler / static_cast<float>(d_fs_in);
|
||||
int32_t doppler = -static_cast<int32_t>(d_doppler_max) + d_doppler_step * doppler_index;
|
||||
//float phase_step_rad = GPS_TWO_PI * (d_freq + doppler) / static_cast<float>(d_fs_in);
|
||||
float phase_step_rad = GPS_TWO_PI * (doppler) / static_cast<float>(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<int32_t>(phase_step_rad_int_temp * (POW_2_29)); // * 2^29 (in total it makes x2^31 in two steps to avoid the warnings
|
||||
//printf("writing phase_step_rad_int = %d to d_map_base 3\n", phase_step_rad_int);
|
||||
d_map_base[3] = phase_step_rad_int;
|
||||
}
|
||||
|
||||
|
||||
void fpga_acquisition::read_acquisition_results(uint32_t *max_index,
|
||||
float *max_magnitude, 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<float>(readval);
|
||||
//printf("read max_magnitude dmap 2 = %d\n", readval);
|
||||
readval = d_map_base[4];
|
||||
*power_sum = static_cast<float>(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
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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
|
||||
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#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 <glog/logging.h>
|
||||
|
||||
//#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<float>(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<float>(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<int*>(volk_gnsssdr_malloc(static_cast<int>(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<int *>(volk_gnsssdr_malloc((static_cast<unsigned int>(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<float*>(volk_gnsssdr_malloc(static_cast<int>(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<float *>(volk_gnsssdr_malloc((static_cast<unsigned int>(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<int>(Galileo_E1_B_CODE_LENGTH_CHIPS)* 2 * (PRN - 1) + s] = static_cast<int>(ca_codes_f[s]);
|
||||
d_data_codes[static_cast<int>(Galileo_E1_B_CODE_LENGTH_CHIPS)* 2 * (PRN - 1) + s] = static_cast<int>(data_codes_f[s]);
|
||||
//printf("%f %d | ", data_codes_f[s], d_data_codes[static_cast<int>(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<int>(Galileo_E1_B_CODE_LENGTH_CHIPS)* 2 * (PRN - 1) + s] = static_cast<int>(ca_codes_f[s]);
|
||||
//printf("%f %d | ", ca_codes_f[s], d_ca_codes[static_cast<int>(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;
|
||||
}
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#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 <string>
|
||||
|
||||
|
||||
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_
|
@ -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:
|
||||
* <ul>
|
||||
* <li> Javier Arribas, 2011. jarribas(at)cttc.es
|
||||
* <li> Luis Esteve, 2012. luis(at)epsilon-formacion.com
|
||||
* </ul>
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#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 <glog/logging.h>
|
||||
|
||||
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<float>(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<float>(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<unsigned int>(Galileo_E5a_CODE_LENGTH_CHIPS);
|
||||
|
||||
gr_complex *aux_code = static_cast<gr_complex *>(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<float *>(volk_gnsssdr_malloc(code_samples_per_chip * code_length_chips * sizeof(float), volk_gnsssdr_get_alignment()));
|
||||
}
|
||||
tracking_code = static_cast<float *>(volk_gnsssdr_malloc(code_samples_per_chip * code_length_chips * sizeof(float), volk_gnsssdr_get_alignment()));
|
||||
|
||||
d_ca_codes = static_cast<int*>(volk_gnsssdr_malloc(static_cast<int>(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<int *>(volk_gnsssdr_malloc((static_cast<unsigned int>(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<char *>(trk_param_fpga.signal.c_str()));
|
||||
galileo_e5_a_code_gen_complex_primary(aux_code, PRN, const_cast<char *>(sig_));
|
||||
if (trk_param_fpga.track_pilot)
|
||||
{
|
||||
//d_secondary_code_string = const_cast<std::string *>(&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<int>(code_length_chips) * (PRN - 1) + s] = static_cast<int>(tracking_code[s]);
|
||||
d_data_codes[static_cast<int>(code_length_chips) * (PRN - 1) + s] = static_cast<int>(data_code[s]);
|
||||
//printf("%f %d | ", data_codes_f[s], d_data_codes[static_cast<int>(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<int>(code_length_chips)* (PRN - 1) + s] = static_cast<int>(tracking_code[s]);
|
||||
//printf("%f %d | ", ca_codes_f[s], d_ca_codes[static_cast<int>(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;
|
||||
}
|
@ -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:
|
||||
* <ul>
|
||||
* <li> Javier Arribas, 2011. jarribas(at)cttc.es
|
||||
* <li> Luis Esteve, 2012. luis(at)epsilon-formacion.com
|
||||
* </ul>
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#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 <string>
|
||||
|
||||
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_ */
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <glog/logging.h>
|
||||
#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 <glog/logging.h>
|
||||
|
||||
#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<int*>(volk_gnsssdr_malloc(static_cast<int>(GPS_L1_CA_CODE_LENGTH_CHIPS * NUM_PRNs) * sizeof(int), volk_gnsssdr_get_alignment()));
|
||||
d_ca_codes = static_cast<int*>(volk_gnsssdr_malloc(static_cast<int>(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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
@ -39,9 +39,10 @@
|
||||
#ifndef GNSS_SDR_GPS_L1_CA_DLL_PLL_TRACKING_FPGA_H_
|
||||
#define GNSS_SDR_GPS_L1_CA_DLL_PLL_TRACKING_FPGA_H_
|
||||
|
||||
#include <string>
|
||||
#include "tracking_interface.h"
|
||||
#include "dll_pll_veml_tracking_fpga.h"
|
||||
#include <string>
|
||||
|
||||
|
||||
class ConfigurationInterface;
|
||||
|
||||
@ -52,9 +53,9 @@ class GpsL1CaDllPllTrackingFpga : public TrackingInterface
|
||||
{
|
||||
public:
|
||||
GpsL1CaDllPllTrackingFpga(ConfigurationInterface* configuration,
|
||||
std::string role,
|
||||
unsigned int in_streams,
|
||||
unsigned int out_streams);
|
||||
std::string role,
|
||||
unsigned int in_streams,
|
||||
unsigned int out_streams);
|
||||
|
||||
virtual ~GpsL1CaDllPllTrackingFpga();
|
||||
|
||||
@ -92,8 +93,10 @@ public:
|
||||
|
||||
void start_tracking() override;
|
||||
|
||||
//void reset(void);
|
||||
|
||||
private:
|
||||
dll_pll_veml_tracking_fpga_sptr tracking_fpga_sc;
|
||||
dll_pll_veml_tracking_fpga_sptr tracking_fpga_sc;
|
||||
size_t item_size_;
|
||||
unsigned int channel_;
|
||||
std::string role_;
|
||||
@ -102,4 +105,4 @@ private:
|
||||
int* d_ca_codes;
|
||||
};
|
||||
|
||||
#endif // GNSS_SDR_GPS_L1_CA_DLL_PLL_TRACKING_FPGA_H_
|
||||
#endif // GNSS_SDR_GPS_L1_CA_DLL_PLL_TRACKING_FPGA_H_
|
||||
|
@ -0,0 +1,223 @@
|
||||
/*!
|
||||
* \file gps_l2_m_dll_pll_tracking.cc
|
||||
* \brief Implementation of an adapter of a DLL+PLL tracking loop block
|
||||
* for GPS L1 C/A to a TrackingInterface
|
||||
* \author Javier Arribas, 2015. jarribas(at)cttc.es
|
||||
*
|
||||
* Code DLL + carrier PLL according to the algorithms described in:
|
||||
* K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen,
|
||||
* A Software-Defined GPS and Galileo Receiver. A Single-Frequency
|
||||
* Approach, Birkhauser, 2007
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
|
||||
*
|
||||
* GNSS-SDR is a software defined Global Navigation
|
||||
* Satellite Systems receiver
|
||||
*
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* GNSS-SDR is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GNSS-SDR is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#include "gps_l2_m_dll_pll_tracking_fpga.h"
|
||||
#include "configuration_interface.h"
|
||||
#include "GPS_L2C.h"
|
||||
#include "gps_l2c_signal.h"
|
||||
#include "gnss_sdr_flags.h"
|
||||
#include "display.h"
|
||||
#include <glog/logging.h>
|
||||
|
||||
#define NUM_PRNs 32
|
||||
|
||||
using google::LogMessage;
|
||||
|
||||
GpsL2MDllPllTrackingFpga::GpsL2MDllPllTrackingFpga(
|
||||
ConfigurationInterface* configuration, std::string role,
|
||||
unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams)
|
||||
{
|
||||
//dllpllconf_t trk_param;
|
||||
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", 2.0);
|
||||
if (FLAGS_pll_bw_hz != 0.0) pll_bw_hz = static_cast<float>(FLAGS_pll_bw_hz);
|
||||
trk_param_fpga.pll_bw_hz = pll_bw_hz;
|
||||
float dll_bw_hz = configuration->property(role + ".dll_bw_hz", 0.75);
|
||||
if (FLAGS_dll_bw_hz != 0.0) dll_bw_hz = static_cast<float>(FLAGS_dll_bw_hz);
|
||||
trk_param_fpga.dll_bw_hz = dll_bw_hz;
|
||||
float early_late_space_chips = configuration->property(role + ".early_late_space_chips", 0.5);
|
||||
trk_param_fpga.early_late_space_chips = early_late_space_chips;
|
||||
trk_param_fpga.early_late_space_narrow_chips = 0.0;
|
||||
std::string default_dump_filename = "./track_ch";
|
||||
std::string dump_filename = configuration->property(role + ".dump_filename", default_dump_filename);
|
||||
trk_param_fpga.dump_filename = dump_filename;
|
||||
int vector_length = std::round(static_cast<double>(fs_in) / (static_cast<double>(GPS_L2_M_CODE_RATE_HZ) / static_cast<double>(GPS_L2_M_CODE_LENGTH_CHIPS)));
|
||||
trk_param_fpga.vector_length = vector_length;
|
||||
int symbols_extended_correlator = configuration->property(role + ".extend_correlation_symbols", 1);
|
||||
if (symbols_extended_correlator != 1)
|
||||
{
|
||||
std::cout << TEXT_RED << "WARNING: Extended coherent integration is not allowed in GPS L2. Coherent integration has been set to 20 ms (1 symbol)" << TEXT_RESET << std::endl;
|
||||
}
|
||||
trk_param_fpga.extend_correlation_symbols = 1;
|
||||
bool track_pilot = configuration->property(role + ".track_pilot", false);
|
||||
if (track_pilot)
|
||||
{
|
||||
std::cout << TEXT_RED << "WARNING: GPS L2 does not have pilot signal. Data tracking has been enabled" << TEXT_RESET << std::endl;
|
||||
}
|
||||
trk_param_fpga.track_pilot = false;
|
||||
trk_param_fpga.very_early_late_space_chips = 0.0;
|
||||
trk_param_fpga.very_early_late_space_narrow_chips = 0.0;
|
||||
trk_param_fpga.pll_bw_narrow_hz = 0.0;
|
||||
trk_param_fpga.dll_bw_narrow_hz = 0.0;
|
||||
trk_param_fpga.system = 'G';
|
||||
char sig_[3] = "2S";
|
||||
std::memcpy(trk_param_fpga.signal, sig_, 3);
|
||||
int cn0_samples = configuration->property(role + ".cn0_samples", 20);
|
||||
if (FLAGS_cn0_samples != 20) cn0_samples = FLAGS_cn0_samples;
|
||||
trk_param_fpga.cn0_samples = cn0_samples;
|
||||
int cn0_min = configuration->property(role + ".cn0_min", 25);
|
||||
if (FLAGS_cn0_min != 25) cn0_min = FLAGS_cn0_min;
|
||||
trk_param_fpga.cn0_min = cn0_min;
|
||||
int max_lock_fail = configuration->property(role + ".max_lock_fail", 50);
|
||||
if (FLAGS_max_lock_fail != 50) max_lock_fail = FLAGS_max_lock_fail;
|
||||
trk_param_fpga.max_lock_fail = max_lock_fail;
|
||||
double carrier_lock_th = configuration->property(role + ".carrier_lock_th", 0.85);
|
||||
if (FLAGS_carrier_lock_th != 0.85) carrier_lock_th = FLAGS_carrier_lock_th;
|
||||
trk_param_fpga.carrier_lock_th = carrier_lock_th;
|
||||
|
||||
// FPGA configuration parameters
|
||||
std::string default_device_name = "/dev/uio";
|
||||
std::string device_name = configuration->property(role + ".devicename", default_device_name);
|
||||
trk_param_fpga.device_name = device_name;
|
||||
unsigned int device_base = configuration->property(role + ".device_base", 1);
|
||||
trk_param_fpga.device_base = device_base;
|
||||
//unsigned int multicorr_type = configuration->property(role + ".multicorr_type", 0);
|
||||
trk_param_fpga.multicorr_type = 0; //multicorr_type : 0 -> 3 correlators, 1 -> 5 correlators
|
||||
|
||||
//d_tracking_code = static_cast<float *>(volk_gnsssdr_malloc(2 * static_cast<unsigned int>(GPS_L2_M_CODE_LENGTH_CHIPS) * sizeof(float), volk_gnsssdr_get_alignment()));
|
||||
d_ca_codes = static_cast<int*>(volk_gnsssdr_malloc(static_cast<unsigned int>(GPS_L2_M_CODE_LENGTH_CHIPS)* NUM_PRNs * sizeof(int), volk_gnsssdr_get_alignment()));
|
||||
float* ca_codes_f = static_cast<float*>(volk_gnsssdr_malloc(static_cast<unsigned int>(GPS_L2_M_CODE_LENGTH_CHIPS)* sizeof(float), volk_gnsssdr_get_alignment()));
|
||||
|
||||
//################# PRE-COMPUTE ALL THE CODES #################
|
||||
d_ca_codes = static_cast<int*>(volk_gnsssdr_malloc(static_cast<int>(GPS_L2_M_CODE_LENGTH_CHIPS*NUM_PRNs) * sizeof(int), volk_gnsssdr_get_alignment()));
|
||||
for (unsigned int PRN = 1; PRN <= NUM_PRNs; PRN++)
|
||||
{
|
||||
//gps_l1_ca_code_gen_int(&d_ca_codes[(int(GPS_L1_CA_CODE_LENGTH_CHIPS)) * (PRN - 1)], PRN, 0);
|
||||
gps_l2c_m_code_gen_float(ca_codes_f, PRN);
|
||||
for (unsigned int s = 0; s < 2*static_cast<unsigned int>(GPS_L2_M_CODE_LENGTH_CHIPS); s++)
|
||||
{
|
||||
d_ca_codes[static_cast<int>(GPS_L2_M_CODE_LENGTH_CHIPS)* (PRN - 1) + s] = static_cast<int>(ca_codes_f[s]);
|
||||
}
|
||||
}
|
||||
|
||||
delete[] ca_codes_f;
|
||||
|
||||
trk_param_fpga.ca_codes = d_ca_codes;
|
||||
trk_param_fpga.code_length_chips = GPS_L2_M_CODE_LENGTH_CHIPS;
|
||||
trk_param_fpga.code_samples_per_chip = 1; // 1 sample per chip
|
||||
|
||||
//################# MAKE TRACKING GNURadio object ###################
|
||||
|
||||
// //################# MAKE TRACKING GNURadio object ###################
|
||||
// if (item_type.compare("gr_complex") == 0)
|
||||
// {
|
||||
// item_size_ = sizeof(gr_complex);
|
||||
// tracking_ = dll_pll_veml_make_tracking(trk_param);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// item_size_ = sizeof(gr_complex);
|
||||
// LOG(WARNING) << item_type << " unknown tracking item type.";
|
||||
// }
|
||||
|
||||
//################# MAKE TRACKING GNURadio object ###################
|
||||
tracking_fpga_sc = dll_pll_veml_make_tracking_fpga(trk_param_fpga);
|
||||
|
||||
channel_ = 0;
|
||||
DLOG(INFO) << "tracking(" << tracking_fpga_sc->unique_id() << ")";
|
||||
}
|
||||
|
||||
|
||||
GpsL2MDllPllTrackingFpga::~GpsL2MDllPllTrackingFpga()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void GpsL2MDllPllTrackingFpga::start_tracking()
|
||||
{
|
||||
//tracking_->start_tracking();
|
||||
tracking_fpga_sc->start_tracking();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set tracking channel unique ID
|
||||
*/
|
||||
void GpsL2MDllPllTrackingFpga::set_channel(unsigned int channel)
|
||||
{
|
||||
channel_ = channel;
|
||||
//tracking_->set_channel(channel);
|
||||
tracking_fpga_sc->set_channel(channel);
|
||||
}
|
||||
|
||||
|
||||
void GpsL2MDllPllTrackingFpga::set_gnss_synchro(Gnss_Synchro* p_gnss_synchro)
|
||||
{
|
||||
//tracking_->set_gnss_synchro(p_gnss_synchro);
|
||||
tracking_fpga_sc->set_gnss_synchro(p_gnss_synchro);
|
||||
}
|
||||
|
||||
|
||||
void GpsL2MDllPllTrackingFpga::connect(gr::top_block_sptr top_block)
|
||||
{
|
||||
if (top_block)
|
||||
{ /* top_block is not null */
|
||||
};
|
||||
//nothing to connect, now the tracking uses gr_sync_decimator
|
||||
}
|
||||
|
||||
|
||||
void GpsL2MDllPllTrackingFpga::disconnect(gr::top_block_sptr top_block)
|
||||
{
|
||||
if (top_block)
|
||||
{ /* top_block is not null */
|
||||
};
|
||||
//nothing to disconnect, now the tracking uses gr_sync_decimator
|
||||
}
|
||||
|
||||
|
||||
gr::basic_block_sptr GpsL2MDllPllTrackingFpga::get_left_block()
|
||||
{
|
||||
//return tracking_;
|
||||
return tracking_fpga_sc;
|
||||
}
|
||||
|
||||
|
||||
gr::basic_block_sptr GpsL2MDllPllTrackingFpga::get_right_block()
|
||||
{
|
||||
//return tracking_;
|
||||
return tracking_fpga_sc;
|
||||
}
|
@ -0,0 +1,106 @@
|
||||
/*!
|
||||
* \file gps_l2_m_dll_pll_tracking.h
|
||||
* \brief Interface of an adapter of a DLL+PLL tracking loop block
|
||||
* for GPS L1 C/A to a TrackingInterface
|
||||
* \author Carlos Aviles, 2010. carlos.avilesr(at)googlemail.com
|
||||
* Javier Arribas, 2011. jarribas(at)cttc.es
|
||||
*
|
||||
* Code DLL + carrier PLL according to the algorithms described in:
|
||||
* K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen,
|
||||
* A Software-Defined GPS and Galileo Receiver. A Single-Frequency
|
||||
* Approach, Birkhauser, 2007
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
|
||||
*
|
||||
* GNSS-SDR is a software defined Global Navigation
|
||||
* Satellite Systems receiver
|
||||
*
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* GNSS-SDR is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GNSS-SDR is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef GNSS_SDR_gps_l2_m_dll_pll_tracking_FPGA_H_
|
||||
#define GNSS_SDR_gps_l2_m_dll_pll_tracking_FPGA_H_
|
||||
|
||||
#include "tracking_interface.h"
|
||||
//#include "dll_pll_veml_tracking.h"
|
||||
#include "dll_pll_veml_tracking_fpga.h"
|
||||
#include <string>
|
||||
|
||||
class ConfigurationInterface;
|
||||
|
||||
/*!
|
||||
* \brief This class implements a code DLL + carrier PLL tracking loop
|
||||
*/
|
||||
class GpsL2MDllPllTrackingFpga : public TrackingInterface
|
||||
{
|
||||
public:
|
||||
GpsL2MDllPllTrackingFpga(ConfigurationInterface* configuration,
|
||||
std::string role,
|
||||
unsigned int in_streams,
|
||||
unsigned int out_streams);
|
||||
|
||||
virtual ~GpsL2MDllPllTrackingFpga();
|
||||
|
||||
inline std::string role() override
|
||||
{
|
||||
return role_;
|
||||
}
|
||||
|
||||
//! Returns "GPS_L2_M_DLL_PLL_Tracking"
|
||||
inline std::string implementation() override
|
||||
{
|
||||
return "GPS_L2_M_DLL_PLL_Tracking_Fpga";
|
||||
}
|
||||
|
||||
inline size_t item_size() override
|
||||
{
|
||||
return item_size_;
|
||||
}
|
||||
|
||||
void connect(gr::top_block_sptr top_block) override;
|
||||
void disconnect(gr::top_block_sptr top_block) override;
|
||||
gr::basic_block_sptr get_left_block() override;
|
||||
gr::basic_block_sptr get_right_block() override;
|
||||
|
||||
/*!
|
||||
* \brief Set tracking channel unique ID
|
||||
*/
|
||||
void set_channel(unsigned int channel) override;
|
||||
|
||||
/*!
|
||||
* \brief Set acquisition/tracking common Gnss_Synchro object pointer
|
||||
* to efficiently exchange synchronization data between acquisition and tracking blocks
|
||||
*/
|
||||
void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) override;
|
||||
|
||||
void start_tracking() override;
|
||||
|
||||
private:
|
||||
//dll_pll_veml_tracking_sptr tracking_;
|
||||
dll_pll_veml_tracking_fpga_sptr tracking_fpga_sc;
|
||||
size_t item_size_;
|
||||
unsigned int channel_;
|
||||
std::string role_;
|
||||
unsigned int in_streams_;
|
||||
unsigned int out_streams_;
|
||||
int* d_ca_codes;
|
||||
};
|
||||
|
||||
#endif // GNSS_SDR_gps_l2_m_dll_pll_tracking_FPGA_H_
|
276
src/algorithms/tracking/adapters/gps_l5_dll_pll_tracking_fpga.cc
Normal file
276
src/algorithms/tracking/adapters/gps_l5_dll_pll_tracking_fpga.cc
Normal file
@ -0,0 +1,276 @@
|
||||
/*!
|
||||
* \file gps_l5_dll_pll_tracking.cc
|
||||
* \brief Interface of an adapter of a DLL+PLL tracking loop block
|
||||
* for GPS L5 to a TrackingInterface
|
||||
* \author Javier Arribas, 2017. jarribas(at)cttc.es
|
||||
*
|
||||
* Code DLL + carrier PLL according to the algorithms described in:
|
||||
* K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen,
|
||||
* A Software-Defined GPS and Galileo Receiver. A Single-Frequency
|
||||
* Approach, Birkhauser, 2007
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
|
||||
*
|
||||
* GNSS-SDR is a software defined Global Navigation
|
||||
* Satellite Systems receiver
|
||||
*
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* GNSS-SDR is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GNSS-SDR is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#include "gps_l5_dll_pll_tracking_fpga.h"
|
||||
#include "configuration_interface.h"
|
||||
#include "GPS_L5.h"
|
||||
#include "gps_l5_signal.h"
|
||||
#include "gnss_sdr_flags.h"
|
||||
#include "display.h"
|
||||
#include <glog/logging.h>
|
||||
|
||||
#define NUM_PRNs 32
|
||||
|
||||
using google::LogMessage;
|
||||
|
||||
GpsL5DllPllTrackingFpga::GpsL5DllPllTrackingFpga(
|
||||
ConfigurationInterface* configuration, std::string role,
|
||||
unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams)
|
||||
{
|
||||
//printf("L5 TRK CLASS CREATED\n");
|
||||
//dllpllconf_t trk_param;
|
||||
Dll_Pll_Conf_Fpga trk_param_fpga = Dll_Pll_Conf_Fpga();
|
||||
DLOG(INFO) << "role " << role;
|
||||
//################# CONFIGURATION PARAMETERS ########################
|
||||
//std::string default_item_type = "gr_complex";
|
||||
//std::string item_type = configuration->property(role + ".item_type", default_item_type);
|
||||
int fs_in_deprecated = configuration->property("GNSS-SDR.internal_fs_hz", 2048000);
|
||||
int fs_in = configuration->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated);
|
||||
trk_param_fpga.fs_in = fs_in;
|
||||
bool dump = configuration->property(role + ".dump", false);
|
||||
trk_param_fpga.dump = dump;
|
||||
float pll_bw_hz = configuration->property(role + ".pll_bw_hz", 50.0);
|
||||
if (FLAGS_pll_bw_hz != 0.0) pll_bw_hz = static_cast<float>(FLAGS_pll_bw_hz);
|
||||
trk_param_fpga.pll_bw_hz = pll_bw_hz;
|
||||
float dll_bw_hz = configuration->property(role + ".dll_bw_hz", 2.0);
|
||||
if (FLAGS_dll_bw_hz != 0.0) dll_bw_hz = static_cast<float>(FLAGS_dll_bw_hz);
|
||||
trk_param_fpga.dll_bw_hz = dll_bw_hz;
|
||||
float pll_bw_narrow_hz = configuration->property(role + ".pll_bw_narrow_hz", 2.0);
|
||||
trk_param_fpga.pll_bw_narrow_hz = pll_bw_narrow_hz;
|
||||
float dll_bw_narrow_hz = configuration->property(role + ".dll_bw_narrow_hz", 0.25);
|
||||
trk_param_fpga.dll_bw_narrow_hz = dll_bw_narrow_hz;
|
||||
float early_late_space_chips = configuration->property(role + ".early_late_space_chips", 0.5);
|
||||
trk_param_fpga.early_late_space_chips = early_late_space_chips;
|
||||
std::string default_dump_filename = "./track_ch";
|
||||
std::string dump_filename = configuration->property(role + ".dump_filename", default_dump_filename);
|
||||
trk_param_fpga.dump_filename = dump_filename;
|
||||
int vector_length = std::round(static_cast<double>(fs_in) / (static_cast<double>(GPS_L5i_CODE_RATE_HZ) / static_cast<double>(GPS_L5i_CODE_LENGTH_CHIPS)));
|
||||
trk_param_fpga.vector_length = vector_length;
|
||||
int extend_correlation_symbols = configuration->property(role + ".extend_correlation_symbols", 1);
|
||||
float early_late_space_narrow_chips = configuration->property(role + ".early_late_space_narrow_chips", 0.15);
|
||||
trk_param_fpga.early_late_space_narrow_chips = early_late_space_narrow_chips;
|
||||
bool track_pilot = configuration->property(role + ".track_pilot", false);
|
||||
if (extend_correlation_symbols < 1)
|
||||
{
|
||||
extend_correlation_symbols = 1;
|
||||
std::cout << TEXT_RED << "WARNING: GPS L5. extend_correlation_symbols must be bigger than 0. Coherent integration has been set to 1 symbol (1 ms)" << TEXT_RESET << std::endl;
|
||||
}
|
||||
else if (!track_pilot and extend_correlation_symbols > GPS_L5i_NH_CODE_LENGTH)
|
||||
{
|
||||
extend_correlation_symbols = GPS_L5i_NH_CODE_LENGTH;
|
||||
std::cout << TEXT_RED << "WARNING: GPS L5. extend_correlation_symbols must be lower than 11 when tracking the data component. Coherent integration has been set to 10 symbols (10 ms)" << TEXT_RESET << std::endl;
|
||||
}
|
||||
if ((extend_correlation_symbols > 1) and (pll_bw_narrow_hz > pll_bw_hz or dll_bw_narrow_hz > dll_bw_hz))
|
||||
{
|
||||
std::cout << TEXT_RED << "WARNING: GPS L5. PLL or DLL narrow tracking bandwidth is higher than wide tracking one" << TEXT_RESET << std::endl;
|
||||
}
|
||||
trk_param_fpga.extend_correlation_symbols = extend_correlation_symbols;
|
||||
trk_param_fpga.track_pilot = track_pilot;
|
||||
d_track_pilot = track_pilot;
|
||||
trk_param_fpga.very_early_late_space_chips = 0.0;
|
||||
trk_param_fpga.very_early_late_space_narrow_chips = 0.0;
|
||||
trk_param_fpga.system = 'G';
|
||||
char sig_[3] = "L5";
|
||||
std::memcpy(trk_param_fpga.signal, sig_, 3);
|
||||
int cn0_samples = configuration->property(role + ".cn0_samples", 20);
|
||||
if (FLAGS_cn0_samples != 20) cn0_samples = FLAGS_cn0_samples;
|
||||
trk_param_fpga.cn0_samples = cn0_samples;
|
||||
int cn0_min = configuration->property(role + ".cn0_min", 25);
|
||||
if (FLAGS_cn0_min != 25) cn0_min = FLAGS_cn0_min;
|
||||
trk_param_fpga.cn0_min = cn0_min;
|
||||
int max_lock_fail = configuration->property(role + ".max_lock_fail", 50);
|
||||
if (FLAGS_max_lock_fail != 50) max_lock_fail = FLAGS_max_lock_fail;
|
||||
trk_param_fpga.max_lock_fail = max_lock_fail;
|
||||
double carrier_lock_th = configuration->property(role + ".carrier_lock_th", 0.85);
|
||||
if (FLAGS_carrier_lock_th != 0.85) carrier_lock_th = FLAGS_carrier_lock_th;
|
||||
trk_param_fpga.carrier_lock_th = carrier_lock_th;
|
||||
|
||||
// FPGA configuration parameters
|
||||
std::string default_device_name = "/dev/uio";
|
||||
std::string device_name = configuration->property(role + ".devicename", default_device_name);
|
||||
trk_param_fpga.device_name = device_name;
|
||||
unsigned int device_base = configuration->property(role + ".device_base", 1);
|
||||
trk_param_fpga.device_base = device_base;
|
||||
//unsigned int multicorr_type = configuration->property(role + ".multicorr_type", 0);
|
||||
trk_param_fpga.multicorr_type = 0; //multicorr_type : 0 -> 3 correlators, 1 -> 5 correlators
|
||||
|
||||
//################# PRE-COMPUTE ALL THE CODES #################
|
||||
unsigned int code_samples_per_chip = 1;
|
||||
unsigned int code_length_chips = static_cast<unsigned int>(GPS_L5i_CODE_LENGTH_CHIPS);
|
||||
//printf("TRK code_length_chips = %d\n", code_length_chips);
|
||||
|
||||
float *tracking_code;
|
||||
float *data_code;
|
||||
|
||||
tracking_code = static_cast<float *>(volk_gnsssdr_malloc(code_length_chips * sizeof(float), volk_gnsssdr_get_alignment()));
|
||||
|
||||
if (trk_param_fpga.track_pilot)
|
||||
{
|
||||
data_code = static_cast<float *>(volk_gnsssdr_malloc(code_length_chips * sizeof(float), volk_gnsssdr_get_alignment()));
|
||||
}
|
||||
|
||||
d_ca_codes = static_cast<int*>(volk_gnsssdr_malloc(static_cast<int>(code_length_chips*NUM_PRNs) * sizeof(int), volk_gnsssdr_get_alignment()));
|
||||
|
||||
if (trk_param_fpga.track_pilot)
|
||||
{
|
||||
d_data_codes = static_cast<int *>(volk_gnsssdr_malloc((static_cast<unsigned int>(code_length_chips)) * NUM_PRNs * sizeof(int), volk_gnsssdr_get_alignment()));
|
||||
}
|
||||
|
||||
//printf("start \n");
|
||||
for (unsigned int PRN = 1; PRN <= NUM_PRNs; PRN++)
|
||||
{
|
||||
|
||||
if (track_pilot)
|
||||
{
|
||||
|
||||
gps_l5q_code_gen_float(tracking_code, PRN);
|
||||
gps_l5i_code_gen_float(data_code, PRN);
|
||||
|
||||
|
||||
for (unsigned int s = 0; s < code_length_chips; s++)
|
||||
{
|
||||
d_ca_codes[static_cast<int>(code_length_chips)* (PRN - 1) + s] = static_cast<int>(tracking_code[s]);
|
||||
d_data_codes[static_cast<int>(code_length_chips)* (PRN - 1) + s] = static_cast<int>(data_code[s]);
|
||||
//printf("%f %d | ", data_codes_f[s], d_data_codes[static_cast<int>(Galileo_E1_B_CODE_LENGTH_CHIPS)* 2 * (PRN - 1) + s]);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
|
||||
gps_l5i_code_gen_float(tracking_code, PRN);
|
||||
for (unsigned int s = 0; s < code_length_chips; s++)
|
||||
{
|
||||
d_ca_codes[static_cast<int>(code_length_chips) * (PRN - 1) + s] = static_cast<int>(data_code[s]);
|
||||
//printf("%f %d | ", ca_codes_f[s], d_ca_codes[static_cast<int>(Galileo_E1_B_CODE_LENGTH_CHIPS)* 2 * (PRN - 1) + s]);
|
||||
}
|
||||
}
|
||||
}
|
||||
//printf("end \n");
|
||||
|
||||
|
||||
delete[] tracking_code;
|
||||
if (trk_param_fpga.track_pilot)
|
||||
{
|
||||
delete[] data_code;
|
||||
}
|
||||
trk_param_fpga.ca_codes = d_ca_codes;
|
||||
trk_param_fpga.data_codes = d_data_codes;
|
||||
trk_param_fpga.code_length_chips = code_length_chips;
|
||||
trk_param_fpga.code_samples_per_chip = code_samples_per_chip; // 2 sample per chip
|
||||
//################# MAKE TRACKING GNURadio object ###################
|
||||
// if (item_type.compare("gr_complex") == 0)
|
||||
// {
|
||||
// item_size_ = sizeof(gr_complex);
|
||||
// tracking_ = dll_pll_veml_make_tracking(trk_param_fpga);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// item_size_ = sizeof(gr_complex);
|
||||
// LOG(WARNING) << item_type << " unknown tracking item type.";
|
||||
// }
|
||||
//printf("call \n");
|
||||
tracking_fpga_sc = dll_pll_veml_make_tracking_fpga(trk_param_fpga);
|
||||
//printf("end2 \n");
|
||||
channel_ = 0;
|
||||
DLOG(INFO) << "tracking(" << tracking_fpga_sc->unique_id() << ")";
|
||||
}
|
||||
|
||||
|
||||
GpsL5DllPllTrackingFpga::~GpsL5DllPllTrackingFpga()
|
||||
{
|
||||
|
||||
delete[] d_ca_codes;
|
||||
if (d_track_pilot)
|
||||
{
|
||||
delete[] d_data_codes;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GpsL5DllPllTrackingFpga::start_tracking()
|
||||
{
|
||||
tracking_fpga_sc->start_tracking();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set tracking channel unique ID
|
||||
*/
|
||||
void GpsL5DllPllTrackingFpga::set_channel(unsigned int channel)
|
||||
{
|
||||
channel_ = channel;
|
||||
tracking_fpga_sc->set_channel(channel);
|
||||
}
|
||||
|
||||
|
||||
void GpsL5DllPllTrackingFpga::set_gnss_synchro(Gnss_Synchro* p_gnss_synchro)
|
||||
{
|
||||
tracking_fpga_sc->set_gnss_synchro(p_gnss_synchro);
|
||||
}
|
||||
|
||||
|
||||
void GpsL5DllPllTrackingFpga::connect(gr::top_block_sptr top_block)
|
||||
{
|
||||
if (top_block)
|
||||
{ /* top_block is not null */
|
||||
};
|
||||
//nothing to connect, now the tracking uses gr_sync_decimator
|
||||
}
|
||||
|
||||
|
||||
void GpsL5DllPllTrackingFpga::disconnect(gr::top_block_sptr top_block)
|
||||
{
|
||||
if (top_block)
|
||||
{ /* top_block is not null */
|
||||
};
|
||||
//nothing to disconnect, now the tracking uses gr_sync_decimator
|
||||
}
|
||||
|
||||
|
||||
gr::basic_block_sptr GpsL5DllPllTrackingFpga::get_left_block()
|
||||
{
|
||||
return tracking_fpga_sc;
|
||||
}
|
||||
|
||||
|
||||
gr::basic_block_sptr GpsL5DllPllTrackingFpga::get_right_block()
|
||||
{
|
||||
return tracking_fpga_sc;
|
||||
}
|
106
src/algorithms/tracking/adapters/gps_l5_dll_pll_tracking_fpga.h
Normal file
106
src/algorithms/tracking/adapters/gps_l5_dll_pll_tracking_fpga.h
Normal file
@ -0,0 +1,106 @@
|
||||
/*!
|
||||
* \file gps_l5_dll_pll_tracking.h
|
||||
* \brief Interface of an adapter of a DLL+PLL tracking loop block
|
||||
* for GPS L5 to a TrackingInterface
|
||||
* \author Javier Arribas, 2017. jarribas(at)cttc.es
|
||||
*
|
||||
* Code DLL + carrier PLL according to the algorithms described in:
|
||||
* K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen,
|
||||
* A Software-Defined GPS and Galileo Receiver. A Single-Frequency
|
||||
* Approach, Birkhauser, 2007
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
|
||||
*
|
||||
* GNSS-SDR is a software defined Global Navigation
|
||||
* Satellite Systems receiver
|
||||
*
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* GNSS-SDR is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GNSS-SDR is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef GNSS_SDR_GPS_L5_DLL_PLL_TRACKING_FPGA_H_
|
||||
#define GNSS_SDR_GPS_L5_DLL_PLL_TRACKING_FPGA_H_
|
||||
|
||||
#include "tracking_interface.h"
|
||||
#include "dll_pll_veml_tracking_fpga.h"
|
||||
#include <string>
|
||||
|
||||
class ConfigurationInterface;
|
||||
|
||||
/*!
|
||||
* \brief This class implements a code DLL + carrier PLL tracking loop
|
||||
*/
|
||||
class GpsL5DllPllTrackingFpga : public TrackingInterface
|
||||
{
|
||||
public:
|
||||
GpsL5DllPllTrackingFpga(ConfigurationInterface* configuration,
|
||||
std::string role,
|
||||
unsigned int in_streams,
|
||||
unsigned int out_streams);
|
||||
|
||||
virtual ~GpsL5DllPllTrackingFpga();
|
||||
|
||||
inline std::string role() override
|
||||
{
|
||||
return role_;
|
||||
}
|
||||
|
||||
//! Returns "GPS_L5_DLL_PLL_Tracking"
|
||||
inline std::string implementation() override
|
||||
{
|
||||
return "GPS_L5_DLL_PLL_Tracking";
|
||||
}
|
||||
|
||||
inline size_t item_size() override
|
||||
{
|
||||
return item_size_;
|
||||
}
|
||||
|
||||
void connect(gr::top_block_sptr top_block) override;
|
||||
void disconnect(gr::top_block_sptr top_block) override;
|
||||
gr::basic_block_sptr get_left_block() override;
|
||||
gr::basic_block_sptr get_right_block() override;
|
||||
|
||||
/*!
|
||||
* \brief Set tracking channel unique ID
|
||||
*/
|
||||
void set_channel(unsigned int channel) override;
|
||||
|
||||
/*!
|
||||
* \brief Set acquisition/tracking common Gnss_Synchro object pointer
|
||||
* to efficiently exchange synchronization data between acquisition and tracking blocks
|
||||
*/
|
||||
void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) override;
|
||||
|
||||
void start_tracking() override;
|
||||
|
||||
private:
|
||||
//dll_pll_veml_tracking_sptr tracking_;
|
||||
dll_pll_veml_tracking_fpga_sptr tracking_fpga_sc;
|
||||
size_t item_size_;
|
||||
unsigned int channel_;
|
||||
std::string role_;
|
||||
unsigned int in_streams_;
|
||||
unsigned int out_streams_;
|
||||
bool d_track_pilot;
|
||||
int* d_ca_codes;
|
||||
int* d_data_codes;
|
||||
};
|
||||
|
||||
#endif // GNSS_SDR_GPS_L5_DLL_PLL_TRACKING_FPGA_H_
|
@ -94,6 +94,7 @@ dll_pll_veml_tracking::dll_pll_veml_tracking(const Dll_Pll_Conf &conf_) : gr::bl
|
||||
d_code_chip_rate = 0.0;
|
||||
d_secondary_code_length = 0;
|
||||
d_secondary_code_string = nullptr;
|
||||
d_gps_l1ca_preambles_symbols = nullptr;
|
||||
signal_type = std::string(trk_parameters.signal);
|
||||
|
||||
std::map<std::string, std::string> map_signal_pretty_name;
|
||||
@ -118,21 +119,21 @@ dll_pll_veml_tracking::dll_pll_veml_tracking(const Dll_Pll_Conf &conf_) : gr::bl
|
||||
d_symbols_per_bit = GPS_CA_TELEMETRY_SYMBOLS_PER_BIT;
|
||||
d_correlation_length_ms = 1;
|
||||
d_code_samples_per_chip = 1;
|
||||
d_code_length_chips = static_cast<unsigned int>(GPS_L1_CA_CODE_LENGTH_CHIPS);
|
||||
d_code_length_chips = static_cast<uint32_t>(GPS_L1_CA_CODE_LENGTH_CHIPS);
|
||||
// GPS L1 C/A does not have pilot component nor secondary code
|
||||
d_secondary = false;
|
||||
trk_parameters.track_pilot = false;
|
||||
interchange_iq = false;
|
||||
|
||||
// set the preamble
|
||||
unsigned short int preambles_bits[GPS_CA_PREAMBLE_LENGTH_BITS] = GPS_PREAMBLE;
|
||||
uint16_t preambles_bits[GPS_CA_PREAMBLE_LENGTH_BITS] = GPS_PREAMBLE;
|
||||
|
||||
// preamble bits to sampled symbols
|
||||
d_gps_l1ca_preambles_symbols = static_cast<int *>(volk_gnsssdr_malloc(GPS_CA_PREAMBLE_LENGTH_SYMBOLS * sizeof(int), volk_gnsssdr_get_alignment()));
|
||||
int n = 0;
|
||||
for (int i = 0; i < GPS_CA_PREAMBLE_LENGTH_BITS; i++)
|
||||
d_gps_l1ca_preambles_symbols = static_cast<int32_t *>(volk_gnsssdr_malloc(GPS_CA_PREAMBLE_LENGTH_SYMBOLS * sizeof(int32_t), volk_gnsssdr_get_alignment()));
|
||||
int32_t n = 0;
|
||||
for (int32_t i = 0; i < GPS_CA_PREAMBLE_LENGTH_BITS; i++)
|
||||
{
|
||||
for (unsigned int j = 0; j < GPS_CA_TELEMETRY_SYMBOLS_PER_BIT; j++)
|
||||
for (uint32_t j = 0; j < GPS_CA_TELEMETRY_SYMBOLS_PER_BIT; j++)
|
||||
{
|
||||
if (preambles_bits[i] == 1)
|
||||
{
|
||||
@ -153,7 +154,7 @@ dll_pll_veml_tracking::dll_pll_veml_tracking(const Dll_Pll_Conf &conf_) : gr::bl
|
||||
d_signal_carrier_freq = GPS_L2_FREQ_HZ;
|
||||
d_code_period = GPS_L2_M_PERIOD;
|
||||
d_code_chip_rate = GPS_L2_M_CODE_RATE_HZ;
|
||||
d_code_length_chips = static_cast<unsigned int>(GPS_L2_M_CODE_LENGTH_CHIPS);
|
||||
d_code_length_chips = static_cast<uint32_t>(GPS_L2_M_CODE_LENGTH_CHIPS);
|
||||
d_symbols_per_bit = GPS_L2_SAMPLES_PER_SYMBOL;
|
||||
d_correlation_length_ms = 20;
|
||||
d_code_samples_per_chip = 1;
|
||||
@ -170,18 +171,18 @@ dll_pll_veml_tracking::dll_pll_veml_tracking(const Dll_Pll_Conf &conf_) : gr::bl
|
||||
d_symbols_per_bit = GPS_L5_SAMPLES_PER_SYMBOL;
|
||||
d_correlation_length_ms = 1;
|
||||
d_code_samples_per_chip = 1;
|
||||
d_code_length_chips = static_cast<unsigned int>(GPS_L5i_CODE_LENGTH_CHIPS);
|
||||
d_code_length_chips = static_cast<uint32_t>(GPS_L5i_CODE_LENGTH_CHIPS);
|
||||
d_secondary = true;
|
||||
if (trk_parameters.track_pilot)
|
||||
{
|
||||
d_secondary_code_length = static_cast<unsigned int>(GPS_L5q_NH_CODE_LENGTH);
|
||||
d_secondary_code_length = static_cast<uint32_t>(GPS_L5q_NH_CODE_LENGTH);
|
||||
d_secondary_code_string = const_cast<std::string *>(&GPS_L5q_NH_CODE_STR);
|
||||
signal_pretty_name = signal_pretty_name + "Q";
|
||||
interchange_iq = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
d_secondary_code_length = static_cast<unsigned int>(GPS_L5i_NH_CODE_LENGTH);
|
||||
d_secondary_code_length = static_cast<uint32_t>(GPS_L5i_NH_CODE_LENGTH);
|
||||
d_secondary_code_string = const_cast<std::string *>(&GPS_L5i_NH_CODE_STR);
|
||||
signal_pretty_name = signal_pretty_name + "I";
|
||||
interchange_iq = false;
|
||||
@ -209,7 +210,7 @@ dll_pll_veml_tracking::dll_pll_veml_tracking(const Dll_Pll_Conf &conf_) : gr::bl
|
||||
d_signal_carrier_freq = Galileo_E1_FREQ_HZ;
|
||||
d_code_period = Galileo_E1_CODE_PERIOD;
|
||||
d_code_chip_rate = Galileo_E1_CODE_CHIP_RATE_HZ;
|
||||
d_code_length_chips = static_cast<unsigned int>(Galileo_E1_B_CODE_LENGTH_CHIPS);
|
||||
d_code_length_chips = static_cast<uint32_t>(Galileo_E1_B_CODE_LENGTH_CHIPS);
|
||||
d_symbols_per_bit = 1;
|
||||
d_correlation_length_ms = 4;
|
||||
d_code_samples_per_chip = 2; // CBOC disabled: 2 samples per chip. CBOC enabled: 12 samples per chip
|
||||
@ -217,7 +218,7 @@ dll_pll_veml_tracking::dll_pll_veml_tracking(const Dll_Pll_Conf &conf_) : gr::bl
|
||||
if (trk_parameters.track_pilot)
|
||||
{
|
||||
d_secondary = true;
|
||||
d_secondary_code_length = static_cast<unsigned int>(Galileo_E1_C_SECONDARY_CODE_LENGTH);
|
||||
d_secondary_code_length = static_cast<uint32_t>(Galileo_E1_C_SECONDARY_CODE_LENGTH);
|
||||
d_secondary_code_string = const_cast<std::string *>(&Galileo_E1_C_SECONDARY_CODE);
|
||||
signal_pretty_name = signal_pretty_name + "C";
|
||||
}
|
||||
@ -236,17 +237,17 @@ dll_pll_veml_tracking::dll_pll_veml_tracking(const Dll_Pll_Conf &conf_) : gr::bl
|
||||
d_symbols_per_bit = 20;
|
||||
d_correlation_length_ms = 1;
|
||||
d_code_samples_per_chip = 1;
|
||||
d_code_length_chips = static_cast<unsigned int>(Galileo_E5a_CODE_LENGTH_CHIPS);
|
||||
d_code_length_chips = static_cast<uint32_t>(Galileo_E5a_CODE_LENGTH_CHIPS);
|
||||
d_secondary = true;
|
||||
if (trk_parameters.track_pilot)
|
||||
{
|
||||
d_secondary_code_length = static_cast<unsigned int>(Galileo_E5a_Q_SECONDARY_CODE_LENGTH);
|
||||
d_secondary_code_length = static_cast<uint32_t>(Galileo_E5a_Q_SECONDARY_CODE_LENGTH);
|
||||
signal_pretty_name = signal_pretty_name + "Q";
|
||||
interchange_iq = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
d_secondary_code_length = static_cast<unsigned int>(Galileo_E5a_I_SECONDARY_CODE_LENGTH);
|
||||
d_secondary_code_length = static_cast<uint32_t>(Galileo_E5a_I_SECONDARY_CODE_LENGTH);
|
||||
d_secondary_code_string = const_cast<std::string *>(&Galileo_E5a_I_SECONDARY_CODE);
|
||||
signal_pretty_name = signal_pretty_name + "I";
|
||||
interchange_iq = false;
|
||||
@ -494,7 +495,7 @@ void dll_pll_veml_tracking::start_tracking()
|
||||
if (trk_parameters.track_pilot)
|
||||
{
|
||||
d_secondary_code_string = const_cast<std::string *>(&Galileo_E5a_Q_SECONDARY_CODE[d_acquisition_gnss_synchro->PRN - 1]);
|
||||
for (unsigned int i = 0; i < d_code_length_chips; i++)
|
||||
for (uint32_t i = 0; i < d_code_length_chips; i++)
|
||||
{
|
||||
d_tracking_code[i] = aux_code[i].imag();
|
||||
d_data_code[i] = aux_code[i].real();
|
||||
@ -504,7 +505,7 @@ void dll_pll_veml_tracking::start_tracking()
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned int i = 0; i < d_code_length_chips; i++)
|
||||
for (uint32_t i = 0; i < d_code_length_chips; i++)
|
||||
{
|
||||
d_tracking_code[i] = aux_code[i].real();
|
||||
}
|
||||
@ -612,8 +613,8 @@ dll_pll_veml_tracking::~dll_pll_veml_tracking()
|
||||
bool dll_pll_veml_tracking::acquire_secondary()
|
||||
{
|
||||
// ******* preamble correlation ********
|
||||
int corr_value = 0;
|
||||
for (unsigned int i = 0; i < d_secondary_code_length; i++)
|
||||
int32_t corr_value = 0;
|
||||
for (uint32_t i = 0; i < d_secondary_code_length; i++)
|
||||
{
|
||||
if (d_Prompt_buffer_deque.at(i).real() < 0.0) // symbols clipping
|
||||
{
|
||||
@ -967,8 +968,8 @@ void dll_pll_veml_tracking::log_data(bool integrating)
|
||||
tmp_double = static_cast<double>(d_sample_counter + d_current_prn_length_samples);
|
||||
d_dump_file.write(reinterpret_cast<char *>(&tmp_double), sizeof(double));
|
||||
// PRN
|
||||
unsigned int prn_ = d_acquisition_gnss_synchro->PRN;
|
||||
d_dump_file.write(reinterpret_cast<char *>(&prn_), sizeof(unsigned int));
|
||||
uint32_t prn_ = d_acquisition_gnss_synchro->PRN;
|
||||
d_dump_file.write(reinterpret_cast<char *>(&prn_), sizeof(uint32_t));
|
||||
}
|
||||
catch (const std::ifstream::failure &e)
|
||||
{
|
||||
@ -978,14 +979,14 @@ void dll_pll_veml_tracking::log_data(bool integrating)
|
||||
}
|
||||
|
||||
|
||||
int dll_pll_veml_tracking::save_matfile()
|
||||
int32_t dll_pll_veml_tracking::save_matfile()
|
||||
{
|
||||
// READ DUMP FILE
|
||||
std::ifstream::pos_type size;
|
||||
int number_of_double_vars = 1;
|
||||
int number_of_float_vars = 17;
|
||||
int epoch_size_bytes = sizeof(uint64_t) + sizeof(double) * number_of_double_vars +
|
||||
sizeof(float) * number_of_float_vars + sizeof(unsigned int);
|
||||
int32_t number_of_double_vars = 1;
|
||||
int32_t number_of_float_vars = 17;
|
||||
int32_t epoch_size_bytes = sizeof(uint64_t) + sizeof(double) * number_of_double_vars +
|
||||
sizeof(float) * number_of_float_vars + sizeof(uint32_t);
|
||||
std::ifstream dump_file;
|
||||
dump_file.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
||||
try
|
||||
@ -1028,7 +1029,7 @@ int dll_pll_veml_tracking::save_matfile()
|
||||
float *carrier_lock_test = new float[num_epoch];
|
||||
float *aux1 = new float[num_epoch];
|
||||
double *aux2 = new double[num_epoch];
|
||||
unsigned int *PRN = new unsigned int[num_epoch];
|
||||
uint32_t *PRN = new uint32_t[num_epoch];
|
||||
|
||||
try
|
||||
{
|
||||
@ -1055,7 +1056,7 @@ int dll_pll_veml_tracking::save_matfile()
|
||||
dump_file.read(reinterpret_cast<char *>(&carrier_lock_test[i]), sizeof(float));
|
||||
dump_file.read(reinterpret_cast<char *>(&aux1[i]), sizeof(float));
|
||||
dump_file.read(reinterpret_cast<char *>(&aux2[i]), sizeof(double));
|
||||
dump_file.read(reinterpret_cast<char *>(&PRN[i]), sizeof(unsigned int));
|
||||
dump_file.read(reinterpret_cast<char *>(&PRN[i]), sizeof(uint32_t));
|
||||
}
|
||||
}
|
||||
dump_file.close();
|
||||
@ -1201,7 +1202,7 @@ int dll_pll_veml_tracking::save_matfile()
|
||||
}
|
||||
|
||||
|
||||
void dll_pll_veml_tracking::set_channel(unsigned int channel)
|
||||
void dll_pll_veml_tracking::set_channel(uint32_t channel)
|
||||
{
|
||||
gr::thread::scoped_lock l(d_setlock);
|
||||
d_channel = channel;
|
||||
@ -1257,7 +1258,7 @@ int dll_pll_veml_tracking::general_work(int noutput_items __attribute__((unused)
|
||||
// Signal alignment (skip samples until the incoming signal is aligned with local replica)
|
||||
uint64_t acq_to_trk_delay_samples = d_sample_counter - d_acq_sample_stamp;
|
||||
double acq_trk_shif_correction_samples = static_cast<double>(d_current_prn_length_samples) - std::fmod(static_cast<double>(acq_to_trk_delay_samples), static_cast<double>(d_current_prn_length_samples));
|
||||
int samples_offset = std::round(d_acq_code_phase_samples + acq_trk_shif_correction_samples);
|
||||
int32_t samples_offset = std::round(d_acq_code_phase_samples + acq_trk_shif_correction_samples);
|
||||
if (samples_offset < 0)
|
||||
{
|
||||
samples_offset = 0;
|
||||
@ -1319,10 +1320,10 @@ int dll_pll_veml_tracking::general_work(int noutput_items __attribute__((unused)
|
||||
{
|
||||
d_symbol_history.push_back(d_Prompt->real());
|
||||
//******* preamble correlation ********
|
||||
int corr_value = 0;
|
||||
int32_t corr_value = 0;
|
||||
if ((d_symbol_history.size() == GPS_CA_PREAMBLE_LENGTH_SYMBOLS)) // and (d_make_correlation or !d_flag_frame_sync))
|
||||
{
|
||||
for (unsigned int i = 0; i < GPS_CA_PREAMBLE_LENGTH_SYMBOLS; i++)
|
||||
for (uint32_t i = 0; i < GPS_CA_PREAMBLE_LENGTH_SYMBOLS; i++)
|
||||
{
|
||||
if (d_symbol_history.at(i) < 0) // symbols clipping
|
||||
{
|
||||
@ -1563,7 +1564,7 @@ int dll_pll_veml_tracking::general_work(int noutput_items __attribute__((unused)
|
||||
}
|
||||
}
|
||||
consume_each(d_current_prn_length_samples);
|
||||
d_sample_counter += d_current_prn_length_samples;
|
||||
d_sample_counter += static_cast<uint64_t>(d_current_prn_length_samples);
|
||||
if (current_synchro_data.Flag_valid_symbol_output)
|
||||
{
|
||||
current_synchro_data.fs = static_cast<int64_t>(trk_parameters.fs_in);
|
||||
|
@ -57,7 +57,7 @@ class dll_pll_veml_tracking : public gr::block
|
||||
public:
|
||||
~dll_pll_veml_tracking();
|
||||
|
||||
void set_channel(unsigned int channel);
|
||||
void set_channel(uint32_t channel);
|
||||
void set_gnss_synchro(Gnss_Synchro *p_gnss_synchro);
|
||||
void start_tracking();
|
||||
|
||||
@ -80,13 +80,13 @@ private:
|
||||
void clear_tracking_vars();
|
||||
void save_correlation_results();
|
||||
void log_data(bool integrating);
|
||||
int save_matfile();
|
||||
int32_t save_matfile();
|
||||
|
||||
// tracking configuration vars
|
||||
Dll_Pll_Conf trk_parameters;
|
||||
bool d_veml;
|
||||
bool d_cloop;
|
||||
unsigned int d_channel;
|
||||
uint32_t d_channel;
|
||||
Gnss_Synchro *d_acquisition_gnss_synchro;
|
||||
|
||||
//Signal parameters
|
||||
@ -95,24 +95,23 @@ private:
|
||||
double d_signal_carrier_freq;
|
||||
double d_code_period;
|
||||
double d_code_chip_rate;
|
||||
unsigned int d_secondary_code_length;
|
||||
unsigned int d_code_length_chips;
|
||||
unsigned int d_code_samples_per_chip; // All signals have 1 sample per chip code except Gal. E1 which has 2 (CBOC disabled) or 12 (CBOC enabled)
|
||||
int d_symbols_per_bit;
|
||||
uint32_t d_secondary_code_length;
|
||||
uint32_t d_code_length_chips;
|
||||
uint32_t d_code_samples_per_chip; // All signals have 1 sample per chip code except Gal. E1 which has 2 (CBOC disabled) or 12 (CBOC enabled)
|
||||
int32_t d_symbols_per_bit;
|
||||
std::string systemName;
|
||||
std::string signal_type;
|
||||
std::string *d_secondary_code_string;
|
||||
std::string signal_pretty_name;
|
||||
|
||||
uint64_t d_preamble_sample_counter;
|
||||
int *d_gps_l1ca_preambles_symbols;
|
||||
int32_t *d_gps_l1ca_preambles_symbols;
|
||||
boost::circular_buffer<float> d_symbol_history;
|
||||
|
||||
//tracking state machine
|
||||
int d_state;
|
||||
int32_t d_state;
|
||||
//Integration period in samples
|
||||
int d_correlation_length_ms;
|
||||
int d_n_correlator_taps;
|
||||
int32_t d_correlation_length_ms;
|
||||
int32_t d_n_correlator_taps;
|
||||
|
||||
float *d_tracking_code;
|
||||
float *d_data_code;
|
||||
@ -133,8 +132,8 @@ private:
|
||||
gr_complex *d_Very_Late;
|
||||
|
||||
bool d_enable_extended_integration;
|
||||
int d_extend_correlation_symbols_count;
|
||||
int d_current_symbol;
|
||||
int32_t d_extend_correlation_symbols_count;
|
||||
int32_t d_current_symbol;
|
||||
|
||||
gr_complex d_VE_accu;
|
||||
gr_complex d_E_accu;
|
||||
@ -175,14 +174,14 @@ private:
|
||||
double T_prn_samples;
|
||||
double K_blk_samples;
|
||||
// PRN period in samples
|
||||
int d_current_prn_length_samples;
|
||||
int32_t d_current_prn_length_samples;
|
||||
// processing samples counters
|
||||
uint64_t d_sample_counter;
|
||||
uint64_t d_acq_sample_stamp;
|
||||
|
||||
// CN0 estimation and lock detector
|
||||
int d_cn0_estimation_counter;
|
||||
int d_carrier_lock_fail_counter;
|
||||
int32_t d_cn0_estimation_counter;
|
||||
int32_t d_carrier_lock_fail_counter;
|
||||
std::deque<float> d_carrier_lock_detector_queue;
|
||||
double d_carrier_lock_test;
|
||||
double d_CN0_SNV_dB_Hz;
|
||||
|
@ -1,8 +1,9 @@
|
||||
/*!
|
||||
* \file dll_pll_veml_tracking.cc
|
||||
* \file dll_pll_veml_tracking_fpga.cc
|
||||
* \brief Implementation of a code DLL + carrier PLL tracking block using an FPGA
|
||||
* \author Marc Majoral, 2018. marc.majoral(at)cttc.es
|
||||
* Antonio Ramos, 2018 antonio.ramosdet(at)gmail.com
|
||||
* Javier Arribas, 2018. jarribas(at)cttc.es
|
||||
*
|
||||
* Code DLL + carrier PLL according to the algorithms described in:
|
||||
* [1] K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen,
|
||||
@ -56,22 +57,26 @@
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
|
||||
using google::LogMessage;
|
||||
|
||||
dll_pll_veml_tracking_fpga_sptr dll_pll_veml_make_tracking_fpga(dllpllconf_fpga_t conf_)
|
||||
dll_pll_veml_tracking_fpga_sptr dll_pll_veml_make_tracking_fpga(const Dll_Pll_Conf_Fpga &conf_)
|
||||
{
|
||||
return dll_pll_veml_tracking_fpga_sptr(new dll_pll_veml_tracking_fpga(conf_));
|
||||
}
|
||||
|
||||
|
||||
dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_) : gr::block("dll_pll_veml_tracking_fpga", gr::io_signature::make(0, 0, sizeof(lv_16sc_t)),
|
||||
gr::io_signature::make(1, 1, sizeof(Gnss_Synchro)))
|
||||
dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(const Dll_Pll_Conf_Fpga &conf_) : gr::block("dll_pll_veml_tracking_fpga", gr::io_signature::make(0, 0, sizeof(lv_16sc_t)),
|
||||
gr::io_signature::make(1, 1, sizeof(Gnss_Synchro)))
|
||||
{
|
||||
trk_parameters = conf_;
|
||||
// Telemetry bit synchronization message port input
|
||||
this->message_port_register_out(pmt::mp("events"));
|
||||
this->set_relative_rate(1.0 / static_cast<double>(trk_parameters.vector_length));
|
||||
|
||||
// Telemetry bit synchronization message port input (mainly for GPS L1 CA)
|
||||
this->message_port_register_in(pmt::mp("preamble_samplestamp"));
|
||||
|
||||
// initialize internal vars
|
||||
d_veml = false;
|
||||
d_cloop = true;
|
||||
@ -92,6 +97,9 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_)
|
||||
|
||||
signal_pretty_name = map_signal_pretty_name[signal_type];
|
||||
|
||||
|
||||
d_prompt_data_shift = nullptr;
|
||||
|
||||
if (trk_parameters.system == 'G')
|
||||
{
|
||||
systemName = "GPS";
|
||||
@ -102,22 +110,47 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_)
|
||||
d_code_chip_rate = GPS_L1_CA_CODE_RATE_HZ;
|
||||
d_symbols_per_bit = GPS_CA_TELEMETRY_SYMBOLS_PER_BIT;
|
||||
d_correlation_length_ms = 1;
|
||||
d_code_samples_per_chip = 1;
|
||||
d_code_length_chips = static_cast<unsigned int>(GPS_L1_CA_CODE_LENGTH_CHIPS);
|
||||
//d_code_samples_per_chip = 1;
|
||||
//d_code_length_chips = static_cast<uint32_t >(GPS_L1_CA_CODE_LENGTH_CHIPS);
|
||||
// GPS L1 C/A does not have pilot component nor secondary code
|
||||
d_secondary = false;
|
||||
trk_parameters.track_pilot = false;
|
||||
interchange_iq = false;
|
||||
|
||||
|
||||
// set the preamble
|
||||
unsigned short int preambles_bits[GPS_CA_PREAMBLE_LENGTH_BITS] = GPS_PREAMBLE;
|
||||
|
||||
// preamble bits to sampled symbols
|
||||
d_gps_l1ca_preambles_symbols = static_cast<int *>(volk_gnsssdr_malloc(GPS_CA_PREAMBLE_LENGTH_SYMBOLS * sizeof(int), volk_gnsssdr_get_alignment()));
|
||||
int n = 0;
|
||||
for (int i = 0; i < GPS_CA_PREAMBLE_LENGTH_BITS; i++)
|
||||
{
|
||||
for (uint32_t j = 0; j < GPS_CA_TELEMETRY_SYMBOLS_PER_BIT; j++)
|
||||
{
|
||||
if (preambles_bits[i] == 1)
|
||||
{
|
||||
d_gps_l1ca_preambles_symbols[n] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
d_gps_l1ca_preambles_symbols[n] = -1;
|
||||
}
|
||||
n++;
|
||||
}
|
||||
}
|
||||
d_symbol_history.resize(GPS_CA_PREAMBLE_LENGTH_SYMBOLS); // Change fixed buffer size
|
||||
d_symbol_history.clear(); // Clear all the elements in the buffer
|
||||
}
|
||||
else if (signal_type.compare("2S") == 0)
|
||||
{
|
||||
d_signal_carrier_freq = GPS_L2_FREQ_HZ;
|
||||
d_code_period = GPS_L2_M_PERIOD;
|
||||
d_code_chip_rate = GPS_L2_M_CODE_RATE_HZ;
|
||||
d_code_length_chips = static_cast<unsigned int>(GPS_L2_M_CODE_LENGTH_CHIPS);
|
||||
//d_code_length_chips = static_cast<uint32_t >(GPS_L2_M_CODE_LENGTH_CHIPS);
|
||||
d_symbols_per_bit = GPS_L2_SAMPLES_PER_SYMBOL;
|
||||
d_correlation_length_ms = 20;
|
||||
d_code_samples_per_chip = 1;
|
||||
//d_code_samples_per_chip = 1;
|
||||
// GPS L2 does not have pilot component nor secondary code
|
||||
d_secondary = false;
|
||||
trk_parameters.track_pilot = false;
|
||||
@ -130,19 +163,20 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_)
|
||||
d_code_chip_rate = GPS_L5i_CODE_RATE_HZ;
|
||||
d_symbols_per_bit = GPS_L5_SAMPLES_PER_SYMBOL;
|
||||
d_correlation_length_ms = 1;
|
||||
d_code_samples_per_chip = 1;
|
||||
d_code_length_chips = static_cast<unsigned int>(GPS_L5i_CODE_LENGTH_CHIPS);
|
||||
//d_code_samples_per_chip = 1;
|
||||
//d_code_length_chips = static_cast<uint32_t >(GPS_L5i_CODE_LENGTH_CHIPS);
|
||||
d_secondary = true;
|
||||
// interchange_iq = false;
|
||||
if (trk_parameters.track_pilot)
|
||||
{
|
||||
d_secondary_code_length = static_cast<unsigned int>(GPS_L5q_NH_CODE_LENGTH);
|
||||
d_secondary_code_length = static_cast<uint32_t>(GPS_L5q_NH_CODE_LENGTH);
|
||||
d_secondary_code_string = const_cast<std::string *>(&GPS_L5q_NH_CODE_STR);
|
||||
signal_pretty_name = signal_pretty_name + "Q";
|
||||
interchange_iq = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
d_secondary_code_length = static_cast<unsigned int>(GPS_L5i_NH_CODE_LENGTH);
|
||||
d_secondary_code_length = static_cast<uint32_t>(GPS_L5i_NH_CODE_LENGTH);
|
||||
d_secondary_code_string = const_cast<std::string *>(&GPS_L5i_NH_CODE_STR);
|
||||
signal_pretty_name = signal_pretty_name + "I";
|
||||
interchange_iq = false;
|
||||
@ -157,8 +191,8 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_)
|
||||
interchange_iq = false;
|
||||
d_signal_carrier_freq = 0.0;
|
||||
d_code_period = 0.0;
|
||||
d_code_length_chips = 0;
|
||||
d_code_samples_per_chip = 0;
|
||||
//d_code_length_chips = 0;
|
||||
//d_code_samples_per_chip = 0;
|
||||
d_symbols_per_bit = 0;
|
||||
}
|
||||
}
|
||||
@ -170,15 +204,15 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_)
|
||||
d_signal_carrier_freq = Galileo_E1_FREQ_HZ;
|
||||
d_code_period = Galileo_E1_CODE_PERIOD;
|
||||
d_code_chip_rate = Galileo_E1_CODE_CHIP_RATE_HZ;
|
||||
d_code_length_chips = static_cast<unsigned int>(Galileo_E1_B_CODE_LENGTH_CHIPS);
|
||||
//d_code_length_chips = static_cast<uint32_t >(Galileo_E1_B_CODE_LENGTH_CHIPS);
|
||||
d_symbols_per_bit = 1;
|
||||
d_correlation_length_ms = 4;
|
||||
d_code_samples_per_chip = 2; // CBOC disabled: 2 samples per chip. CBOC enabled: 12 samples per chip
|
||||
//d_code_samples_per_chip = 2; // CBOC disabled: 2 samples per chip. CBOC enabled: 12 samples per chip
|
||||
d_veml = true;
|
||||
if (trk_parameters.track_pilot)
|
||||
{
|
||||
d_secondary = true;
|
||||
d_secondary_code_length = static_cast<unsigned int>(Galileo_E1_C_SECONDARY_CODE_LENGTH);
|
||||
d_secondary_code_length = static_cast<uint32_t>(Galileo_E1_C_SECONDARY_CODE_LENGTH);
|
||||
d_secondary_code_string = const_cast<std::string *>(&Galileo_E1_C_SECONDARY_CODE);
|
||||
signal_pretty_name = signal_pretty_name + "C";
|
||||
}
|
||||
@ -196,18 +230,19 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_)
|
||||
d_code_chip_rate = Galileo_E5a_CODE_CHIP_RATE_HZ;
|
||||
d_symbols_per_bit = 20;
|
||||
d_correlation_length_ms = 1;
|
||||
d_code_samples_per_chip = 1;
|
||||
d_code_length_chips = static_cast<unsigned int>(Galileo_E5a_CODE_LENGTH_CHIPS);
|
||||
//d_code_samples_per_chip = 1;
|
||||
//d_code_length_chips = static_cast<uint32_t >(Galileo_E5a_CODE_LENGTH_CHIPS);
|
||||
d_secondary = true;
|
||||
//interchange_iq = false;
|
||||
if (trk_parameters.track_pilot)
|
||||
{
|
||||
d_secondary_code_length = static_cast<unsigned int>(Galileo_E5a_Q_SECONDARY_CODE_LENGTH);
|
||||
d_secondary_code_length = static_cast<uint32_t>(Galileo_E5a_Q_SECONDARY_CODE_LENGTH);
|
||||
signal_pretty_name = signal_pretty_name + "Q";
|
||||
interchange_iq = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
d_secondary_code_length = static_cast<unsigned int>(Galileo_E5a_I_SECONDARY_CODE_LENGTH);
|
||||
d_secondary_code_length = static_cast<uint32_t>(Galileo_E5a_I_SECONDARY_CODE_LENGTH);
|
||||
d_secondary_code_string = const_cast<std::string *>(&Galileo_E5a_I_SECONDARY_CODE);
|
||||
signal_pretty_name = signal_pretty_name + "I";
|
||||
interchange_iq = false;
|
||||
@ -222,8 +257,8 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_)
|
||||
interchange_iq = false;
|
||||
d_signal_carrier_freq = 0.0;
|
||||
d_code_period = 0.0;
|
||||
d_code_length_chips = 0;
|
||||
d_code_samples_per_chip = 0;
|
||||
//d_code_length_chips = 0;
|
||||
//d_code_samples_per_chip = 0;
|
||||
d_symbols_per_bit = 0;
|
||||
}
|
||||
}
|
||||
@ -236,8 +271,8 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_)
|
||||
interchange_iq = false;
|
||||
d_signal_carrier_freq = 0.0;
|
||||
d_code_period = 0.0;
|
||||
d_code_length_chips = 0;
|
||||
d_code_samples_per_chip = 0;
|
||||
//d_code_length_chips = 0;
|
||||
//d_code_samples_per_chip = 0;
|
||||
d_symbols_per_bit = 0;
|
||||
}
|
||||
T_chip_seconds = 0.0;
|
||||
@ -246,6 +281,7 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_)
|
||||
K_blk_samples = 0.0;
|
||||
|
||||
// Initialize tracking ==========================================
|
||||
|
||||
d_code_loop_filter = Tracking_2nd_DLL_filter(static_cast<float>(d_code_period));
|
||||
d_carrier_loop_filter = Tracking_2nd_PLL_filter(static_cast<float>(d_code_period));
|
||||
d_carrier_loop_filter.set_PLL_BW(trk_parameters.pll_bw_hz);
|
||||
@ -264,7 +300,9 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_)
|
||||
|
||||
d_correlator_outs = static_cast<gr_complex *>(volk_gnsssdr_malloc(d_n_correlator_taps * sizeof(gr_complex), volk_gnsssdr_get_alignment()));
|
||||
d_local_code_shift_chips = static_cast<float *>(volk_gnsssdr_malloc(d_n_correlator_taps * sizeof(float), volk_gnsssdr_get_alignment()));
|
||||
std::fill_n(d_correlator_outs, d_n_correlator_taps, gr_complex(0.0, 0.0));
|
||||
//std::fill_n(d_correlator_outs, d_n_correlator_taps, gr_complex(0.0, 0.0));
|
||||
|
||||
d_code_samples_per_chip = trk_parameters.code_samples_per_chip; // number of samples per chip
|
||||
|
||||
// map memory pointers of correlator outputs
|
||||
if (d_veml)
|
||||
@ -274,6 +312,11 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_)
|
||||
d_Prompt = &d_correlator_outs[2];
|
||||
d_Late = &d_correlator_outs[3];
|
||||
d_Very_Late = &d_correlator_outs[4];
|
||||
// printf("aaaa very early %f\n",-trk_parameters.very_early_late_space_chips);
|
||||
// printf("aaaa early %f\n",-trk_parameters.early_late_space_chips);
|
||||
// printf("aaaa normal %f\n",0);
|
||||
// printf("aaaa late %f\n",trk_parameters.early_late_space_chips);
|
||||
// printf("aaaa very late %f\n",trk_parameters.very_early_late_space_chips);
|
||||
d_local_code_shift_chips[0] = -trk_parameters.very_early_late_space_chips * static_cast<float>(d_code_samples_per_chip);
|
||||
d_local_code_shift_chips[1] = -trk_parameters.early_late_space_chips * static_cast<float>(d_code_samples_per_chip);
|
||||
d_local_code_shift_chips[2] = 0.0;
|
||||
@ -288,6 +331,10 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_)
|
||||
d_Prompt = &d_correlator_outs[1];
|
||||
d_Late = &d_correlator_outs[2];
|
||||
d_Very_Late = nullptr;
|
||||
// printf("aaaa early %f\n",-trk_parameters.early_late_space_chips);
|
||||
// printf("aaaa normal %f\n",0);
|
||||
// printf("aaaa late %f\n",trk_parameters.early_late_space_chips);
|
||||
|
||||
d_local_code_shift_chips[0] = -trk_parameters.early_late_space_chips * static_cast<float>(d_code_samples_per_chip);
|
||||
d_local_code_shift_chips[1] = 0.0;
|
||||
d_local_code_shift_chips[2] = trk_parameters.early_late_space_chips * static_cast<float>(d_code_samples_per_chip);
|
||||
@ -308,12 +355,12 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_)
|
||||
if (trk_parameters.track_pilot)
|
||||
{
|
||||
// Extra correlator for the data component
|
||||
d_Prompt_Data = static_cast<gr_complex *>(volk_gnsssdr_malloc(sizeof(gr_complex), volk_gnsssdr_get_alignment()));
|
||||
d_Prompt_Data[0] = gr_complex(0.0, 0.0);
|
||||
//d_Prompt_Data = static_cast<gr_complex *>(volk_gnsssdr_malloc(sizeof(gr_complex), volk_gnsssdr_get_alignment()));
|
||||
//d_Prompt_Data[0] = gr_complex(0.0, 0.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
d_Prompt_Data = nullptr;
|
||||
//d_Prompt_Data = nullptr;
|
||||
}
|
||||
|
||||
//--- Initializations ---//
|
||||
@ -327,6 +374,7 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_)
|
||||
// sample synchronization
|
||||
d_sample_counter = 0;
|
||||
d_acq_sample_stamp = 0;
|
||||
d_absolute_samples_offset = 0;
|
||||
|
||||
d_current_prn_length_samples = static_cast<int>(trk_parameters.vector_length);
|
||||
d_next_prn_length_samples = d_current_prn_length_samples;
|
||||
@ -339,8 +387,9 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_)
|
||||
d_CN0_SNV_dB_Hz = 0.0;
|
||||
d_carrier_lock_fail_counter = 0;
|
||||
d_carrier_lock_threshold = trk_parameters.carrier_lock_th;
|
||||
d_Prompt_Data = static_cast<gr_complex *>(volk_gnsssdr_malloc(sizeof(gr_complex), volk_gnsssdr_get_alignment()));
|
||||
|
||||
clear_tracking_vars();
|
||||
//clear_tracking_vars();
|
||||
|
||||
d_acquisition_gnss_synchro = nullptr;
|
||||
d_channel = 0;
|
||||
@ -357,23 +406,27 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_)
|
||||
d_code_phase_samples = 0.0;
|
||||
d_last_prompt = gr_complex(0.0, 0.0);
|
||||
d_state = 0; // initial state: standby
|
||||
clear_tracking_vars();
|
||||
|
||||
//printf("hhhhhhhhhhh d_n_correlator_taps = %d\n", d_n_correlator_taps);
|
||||
|
||||
// create multicorrelator class
|
||||
std::string device_name = trk_parameters.device_name;
|
||||
unsigned int device_base = trk_parameters.device_base;
|
||||
uint32_t device_base = trk_parameters.device_base;
|
||||
int *ca_codes = trk_parameters.ca_codes;
|
||||
unsigned int code_length = trk_parameters.code_length;
|
||||
multicorrelator_fpga = std::make_shared<fpga_multicorrelator_8sc>(d_n_correlator_taps, device_name, device_base, ca_codes, code_length);
|
||||
multicorrelator_fpga->set_output_vectors(d_correlator_outs);
|
||||
int *data_codes = trk_parameters.data_codes;
|
||||
//uint32_t code_length = trk_parameters.code_length_chips;
|
||||
d_code_length_chips = trk_parameters.code_length_chips;
|
||||
uint32_t multicorr_type = trk_parameters.multicorr_type;
|
||||
multicorrelator_fpga = std::make_shared<fpga_multicorrelator_8sc>(d_n_correlator_taps, device_name, device_base, ca_codes, data_codes, d_code_length_chips, trk_parameters.track_pilot, multicorr_type, d_code_samples_per_chip);
|
||||
multicorrelator_fpga->set_output_vectors(d_correlator_outs, d_Prompt_Data);
|
||||
|
||||
d_pull_in = 0;
|
||||
}
|
||||
|
||||
void dll_pll_veml_tracking_fpga::start_tracking()
|
||||
{
|
||||
/*
|
||||
* correct the code phase according to the delay between acq and trk
|
||||
*/
|
||||
// correct the code phase according to the delay between acq and trk
|
||||
d_acq_code_phase_samples = d_acquisition_gnss_synchro->Acq_delay_samples;
|
||||
d_acq_carrier_doppler_hz = d_acquisition_gnss_synchro->Acq_doppler_hz;
|
||||
d_acq_sample_stamp = d_acquisition_gnss_synchro->Acq_samplestamp_samples;
|
||||
@ -381,14 +434,16 @@ void dll_pll_veml_tracking_fpga::start_tracking()
|
||||
double acq_trk_diff_seconds = 0; // when using the FPGA we don't use the global sample counter
|
||||
// Doppler effect Fd = (C / (C + Vr)) * F
|
||||
double radial_velocity = (d_signal_carrier_freq + d_acq_carrier_doppler_hz) / d_signal_carrier_freq;
|
||||
// new chip and prn sequence periods based on acq Doppler
|
||||
// new chip and PRN sequence periods based on acq Doppler
|
||||
d_code_freq_chips = radial_velocity * d_code_chip_rate;
|
||||
d_code_phase_step_chips = d_code_freq_chips / trk_parameters.fs_in;
|
||||
|
||||
double T_chip_mod_seconds = 1.0 / d_code_freq_chips;
|
||||
double T_prn_mod_seconds = T_chip_mod_seconds * static_cast<double>(d_code_length_chips);
|
||||
double T_prn_mod_samples = T_prn_mod_seconds * trk_parameters.fs_in;
|
||||
|
||||
d_current_prn_length_samples = std::round(T_prn_mod_samples);
|
||||
//d_current_prn_length_samples = std::round(T_prn_mod_samples);
|
||||
d_current_prn_length_samples = std::floor(T_prn_mod_samples);
|
||||
d_next_prn_length_samples = d_current_prn_length_samples;
|
||||
double T_prn_true_seconds = static_cast<double>(d_code_length_chips) / d_code_chip_rate;
|
||||
double T_prn_true_samples = T_prn_true_seconds * trk_parameters.fs_in;
|
||||
@ -433,7 +488,9 @@ void dll_pll_veml_tracking_fpga::start_tracking()
|
||||
{
|
||||
if (trk_parameters.track_pilot)
|
||||
{
|
||||
//char pilot_signal[3] = "1C";
|
||||
d_Prompt_Data[0] = gr_complex(0.0, 0.0);
|
||||
// MISSING _: set_local_code_and_taps for the data correlator
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -445,7 +502,7 @@ void dll_pll_veml_tracking_fpga::start_tracking()
|
||||
if (trk_parameters.track_pilot)
|
||||
{
|
||||
d_secondary_code_string = const_cast<std::string *>(&Galileo_E5a_Q_SECONDARY_CODE[d_acquisition_gnss_synchro->PRN - 1]);
|
||||
for (unsigned int i = 0; i < d_code_length_chips; i++)
|
||||
for (uint32_t i = 0; i < d_code_length_chips; i++)
|
||||
{
|
||||
// nothing to compute : the local codes are pre-computed in the adapter class
|
||||
}
|
||||
@ -453,7 +510,7 @@ void dll_pll_veml_tracking_fpga::start_tracking()
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned int i = 0; i < d_code_length_chips; i++)
|
||||
for (uint32_t i = 0; i < d_code_length_chips; i++)
|
||||
{
|
||||
// nothing to compute : the local codes are pre-computed in the adapter class
|
||||
}
|
||||
@ -501,7 +558,8 @@ void dll_pll_veml_tracking_fpga::start_tracking()
|
||||
LOG(INFO) << "PULL-IN Doppler [Hz] = " << d_carrier_doppler_hz
|
||||
<< ". Code Phase correction [samples] = " << delay_correction_samples
|
||||
<< ". PULL-IN Code Phase [samples] = " << d_acq_code_phase_samples;
|
||||
multicorrelator_fpga->set_local_code_and_taps(static_cast<int>(GPS_L1_CA_CODE_LENGTH_CHIPS), d_local_code_shift_chips, d_acquisition_gnss_synchro->PRN);
|
||||
//multicorrelator_fpga->set_local_code_and_taps(d_code_length_chips, d_local_code_shift_chips, d_acquisition_gnss_synchro->PRN);
|
||||
multicorrelator_fpga->set_local_code_and_taps(d_local_code_shift_chips, d_prompt_data_shift, d_acquisition_gnss_synchro->PRN);
|
||||
d_pull_in = 1;
|
||||
// enable tracking pull-in and d_state at the end to avoid general work from starting pull-in before the start tracking function is finished
|
||||
d_state = 1;
|
||||
@ -509,6 +567,11 @@ void dll_pll_veml_tracking_fpga::start_tracking()
|
||||
|
||||
dll_pll_veml_tracking_fpga::~dll_pll_veml_tracking_fpga()
|
||||
{
|
||||
if (signal_type.compare("1C") == 0)
|
||||
{
|
||||
volk_gnsssdr_free(d_gps_l1ca_preambles_symbols);
|
||||
}
|
||||
|
||||
if (d_dump_file.is_open())
|
||||
{
|
||||
try
|
||||
@ -536,10 +599,11 @@ dll_pll_veml_tracking_fpga::~dll_pll_veml_tracking_fpga()
|
||||
{
|
||||
volk_gnsssdr_free(d_local_code_shift_chips);
|
||||
volk_gnsssdr_free(d_correlator_outs);
|
||||
if (trk_parameters.track_pilot)
|
||||
{
|
||||
volk_gnsssdr_free(d_Prompt_Data);
|
||||
}
|
||||
volk_gnsssdr_free(d_Prompt_Data);
|
||||
// if (trk_parameters.track_pilot)
|
||||
// {
|
||||
// volk_gnsssdr_free(d_Prompt_Data);
|
||||
// }
|
||||
delete[] d_Prompt_buffer;
|
||||
multicorrelator_fpga->free();
|
||||
}
|
||||
@ -554,7 +618,7 @@ bool dll_pll_veml_tracking_fpga::acquire_secondary()
|
||||
{
|
||||
// ******* preamble correlation ********
|
||||
int corr_value = 0;
|
||||
for (unsigned int i = 0; i < d_secondary_code_length; i++)
|
||||
for (uint32_t i = 0; i < d_secondary_code_length; i++)
|
||||
{
|
||||
if (d_Prompt_buffer_deque.at(i).real() < 0.0) // symbols clipping
|
||||
{
|
||||
@ -580,7 +644,9 @@ bool dll_pll_veml_tracking_fpga::acquire_secondary()
|
||||
}
|
||||
}
|
||||
|
||||
// if (abs(corr_value) == d_secondary_code_length)
|
||||
if (abs(corr_value) == static_cast<int>(d_secondary_code_length))
|
||||
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -593,6 +659,7 @@ bool dll_pll_veml_tracking_fpga::acquire_secondary()
|
||||
|
||||
bool dll_pll_veml_tracking_fpga::cn0_and_tracking_lock_status(double coh_integration_time_s)
|
||||
{
|
||||
//printf("kkkkkkkkkkkkk d_cn0_estimation_counter = %d\n", d_cn0_estimation_counter);
|
||||
// ####### CN0 ESTIMATION AND LOCK DETECTORS ######
|
||||
if (d_cn0_estimation_counter < trk_parameters.cn0_samples)
|
||||
{
|
||||
@ -603,6 +670,7 @@ bool dll_pll_veml_tracking_fpga::cn0_and_tracking_lock_status(double coh_integra
|
||||
}
|
||||
else
|
||||
{
|
||||
//printf("KKKKKKKKKKK checking count fail ...\n");
|
||||
d_cn0_estimation_counter = 0;
|
||||
// Code lock indicator
|
||||
d_CN0_SNV_dB_Hz = cn0_svn_estimator(d_Prompt_buffer, trk_parameters.cn0_samples, coh_integration_time_s);
|
||||
@ -674,7 +742,8 @@ void dll_pll_veml_tracking_fpga::run_dll_pll()
|
||||
void dll_pll_veml_tracking_fpga::clear_tracking_vars()
|
||||
{
|
||||
std::fill_n(d_correlator_outs, d_n_correlator_taps, gr_complex(0.0, 0.0));
|
||||
if (trk_parameters.track_pilot) *d_Prompt_Data = gr_complex(0.0, 0.0);
|
||||
//if (trk_parameters.track_pilot) *d_Prompt_Data = gr_complex(0.0, 0.0);
|
||||
if (trk_parameters.track_pilot) d_Prompt_Data[0] = gr_complex(0.0, 0.0);
|
||||
d_carr_error_hz = 0.0;
|
||||
d_carr_error_filt_hz = 0.0;
|
||||
d_code_error_chips = 0.0;
|
||||
@ -696,7 +765,9 @@ void dll_pll_veml_tracking_fpga::update_tracking_vars()
|
||||
// Compute the next buffer length based in the new period of the PRN sequence and the code phase error estimation
|
||||
T_prn_samples = T_prn_seconds * trk_parameters.fs_in;
|
||||
K_blk_samples = T_prn_samples + d_rem_code_phase_samples + code_error_filt_secs * trk_parameters.fs_in;
|
||||
d_next_prn_length_samples = round(K_blk_samples);
|
||||
//d_next_prn_length_samples = round(K_blk_samples);
|
||||
d_next_prn_length_samples = static_cast<int>(std::floor(K_blk_samples)); // round to a discrete number of samples
|
||||
|
||||
//################### PLL COMMANDS #################################################
|
||||
// carrier phase step (NCO phase increment per sample) [rads/sample]
|
||||
d_carrier_phase_step_rad = PI_2 * d_carrier_doppler_hz / trk_parameters.fs_in;
|
||||
@ -712,6 +783,10 @@ void dll_pll_veml_tracking_fpga::update_tracking_vars()
|
||||
// remnant code phase [chips]
|
||||
d_rem_code_phase_samples = K_blk_samples - static_cast<double>(d_current_prn_length_samples); // rounding error < 1 sample
|
||||
d_rem_code_phase_chips = d_code_freq_chips * d_rem_code_phase_samples / trk_parameters.fs_in;
|
||||
//printf("lll d_code_freq_chips = %f\n", d_code_freq_chips);
|
||||
//printf("lll d_rem_code_phase_samples = %f\n", d_rem_code_phase_samples);
|
||||
//printf("lll trk_parameters.fs_in = %f\n", trk_parameters.fs_in);
|
||||
//printf("lll d_rem_code_phase_chips = %f\n", d_rem_code_phase_chips);
|
||||
}
|
||||
|
||||
|
||||
@ -776,6 +851,7 @@ void dll_pll_veml_tracking_fpga::log_data(bool integrating)
|
||||
float tmp_VE, tmp_E, tmp_P, tmp_L, tmp_VL;
|
||||
float tmp_float;
|
||||
double tmp_double;
|
||||
unsigned long int tmp_long_int;
|
||||
if (trk_parameters.track_pilot)
|
||||
{
|
||||
if (interchange_iq)
|
||||
@ -842,7 +918,8 @@ void dll_pll_veml_tracking_fpga::log_data(bool integrating)
|
||||
d_dump_file.write(reinterpret_cast<char *>(&prompt_I), sizeof(float));
|
||||
d_dump_file.write(reinterpret_cast<char *>(&prompt_Q), sizeof(float));
|
||||
// PRN start sample stamp
|
||||
d_dump_file.write(reinterpret_cast<char *>(&d_sample_counter), sizeof(uint64_t));
|
||||
tmp_long_int = d_sample_counter + static_cast<uint64_t>(d_current_prn_length_samples);
|
||||
d_dump_file.write(reinterpret_cast<char *>(&tmp_long_int), sizeof(uint64_t));
|
||||
// accumulated carrier phase
|
||||
tmp_float = d_acc_carrier_phase_rad;
|
||||
d_dump_file.write(reinterpret_cast<char *>(&tmp_float), sizeof(float));
|
||||
@ -872,8 +949,8 @@ void dll_pll_veml_tracking_fpga::log_data(bool integrating)
|
||||
tmp_double = static_cast<double>(d_sample_counter + d_current_prn_length_samples);
|
||||
d_dump_file.write(reinterpret_cast<char *>(&tmp_double), sizeof(double));
|
||||
// PRN
|
||||
unsigned int prn_ = d_acquisition_gnss_synchro->PRN;
|
||||
d_dump_file.write(reinterpret_cast<char *>(&prn_), sizeof(unsigned int));
|
||||
uint32_t prn_ = d_acquisition_gnss_synchro->PRN;
|
||||
d_dump_file.write(reinterpret_cast<char *>(&prn_), sizeof(uint32_t));
|
||||
}
|
||||
catch (const std::ifstream::failure &e)
|
||||
{
|
||||
@ -890,7 +967,7 @@ int dll_pll_veml_tracking_fpga::save_matfile()
|
||||
int number_of_double_vars = 1;
|
||||
int number_of_float_vars = 17;
|
||||
int epoch_size_bytes = sizeof(uint64_t) + sizeof(double) * number_of_double_vars +
|
||||
sizeof(float) * number_of_float_vars + sizeof(unsigned int);
|
||||
sizeof(float) * number_of_float_vars + sizeof(uint32_t);
|
||||
std::ifstream dump_file;
|
||||
dump_file.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
||||
try
|
||||
@ -933,7 +1010,7 @@ int dll_pll_veml_tracking_fpga::save_matfile()
|
||||
float *carrier_lock_test = new float[num_epoch];
|
||||
float *aux1 = new float[num_epoch];
|
||||
double *aux2 = new double[num_epoch];
|
||||
unsigned int *PRN = new unsigned int[num_epoch];
|
||||
uint32_t *PRN = new uint32_t[num_epoch];
|
||||
|
||||
try
|
||||
{
|
||||
@ -960,7 +1037,7 @@ int dll_pll_veml_tracking_fpga::save_matfile()
|
||||
dump_file.read(reinterpret_cast<char *>(&carrier_lock_test[i]), sizeof(float));
|
||||
dump_file.read(reinterpret_cast<char *>(&aux1[i]), sizeof(float));
|
||||
dump_file.read(reinterpret_cast<char *>(&aux2[i]), sizeof(double));
|
||||
dump_file.read(reinterpret_cast<char *>(&PRN[i]), sizeof(unsigned int));
|
||||
dump_file.read(reinterpret_cast<char *>(&PRN[i]), sizeof(uint32_t));
|
||||
}
|
||||
}
|
||||
dump_file.close();
|
||||
@ -1105,7 +1182,7 @@ int dll_pll_veml_tracking_fpga::save_matfile()
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dll_pll_veml_tracking_fpga::set_channel(unsigned int channel)
|
||||
void dll_pll_veml_tracking_fpga::set_channel(uint32_t channel)
|
||||
{
|
||||
d_channel = channel;
|
||||
multicorrelator_fpga->set_channel(d_channel);
|
||||
@ -1131,21 +1208,14 @@ void dll_pll_veml_tracking_fpga::set_channel(unsigned int channel)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void dll_pll_veml_tracking_fpga::set_gnss_synchro(Gnss_Synchro *p_gnss_synchro)
|
||||
{
|
||||
d_acquisition_gnss_synchro = p_gnss_synchro;
|
||||
}
|
||||
|
||||
|
||||
void dll_pll_veml_tracking_fpga::reset(void)
|
||||
{
|
||||
multicorrelator_fpga->unlock_channel();
|
||||
}
|
||||
|
||||
|
||||
int dll_pll_veml_tracking_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_void_star &output_items)
|
||||
gr_vector_const_void_star &input_items, gr_vector_void_star &output_items)
|
||||
{
|
||||
// Block input data and block output stream pointers
|
||||
Gnss_Synchro **out = reinterpret_cast<Gnss_Synchro **>(&output_items[0]);
|
||||
@ -1165,7 +1235,7 @@ int dll_pll_veml_tracking_fpga::general_work(int noutput_items __attribute__((un
|
||||
d_correlator_outs[n] = gr_complex(0, 0);
|
||||
}
|
||||
|
||||
current_synchro_data.Tracking_sample_counter = d_sample_counter + d_current_prn_length_samples;
|
||||
current_synchro_data.Tracking_sample_counter = 0; // in order to reduce computational workload do not read the sample counter until we start tracking d_sample_counter + d_current_prn_length_samples;
|
||||
current_synchro_data.System = {'G'};
|
||||
current_synchro_data.correlation_length_ms = 1;
|
||||
break;
|
||||
@ -1174,10 +1244,17 @@ int dll_pll_veml_tracking_fpga::general_work(int noutput_items __attribute__((un
|
||||
{
|
||||
d_pull_in = 0;
|
||||
multicorrelator_fpga->lock_channel();
|
||||
unsigned counter_value = multicorrelator_fpga->read_sample_counter();
|
||||
unsigned long long int counter_value = multicorrelator_fpga->read_sample_counter();
|
||||
//printf("333333 counter_value = %llu\n", counter_value);
|
||||
//printf("333333 current_synchro_data.Acq_samplestamp_samples = %d\n", current_synchro_data.Acq_samplestamp_samples);
|
||||
//printf("333333 current_synchro_data.Acq_delay_samples = %f\n", current_synchro_data.Acq_delay_samples);
|
||||
//printf("333333 d_correlation_length_samples = %d\n", d_correlation_length_samples);
|
||||
unsigned num_frames = ceil((counter_value - current_synchro_data.Acq_samplestamp_samples - current_synchro_data.Acq_delay_samples) / d_correlation_length_samples);
|
||||
unsigned absolute_samples_offset = current_synchro_data.Acq_delay_samples + current_synchro_data.Acq_samplestamp_samples + num_frames * d_correlation_length_samples;
|
||||
//printf("333333 num_frames = %d\n", num_frames);
|
||||
unsigned long long int absolute_samples_offset = current_synchro_data.Acq_delay_samples + current_synchro_data.Acq_samplestamp_samples + num_frames * d_correlation_length_samples;
|
||||
//printf("333333 absolute_samples_offset = %llu\n", absolute_samples_offset);
|
||||
multicorrelator_fpga->set_initial_sample(absolute_samples_offset);
|
||||
d_absolute_samples_offset = absolute_samples_offset;
|
||||
d_sample_counter = absolute_samples_offset;
|
||||
current_synchro_data.Tracking_sample_counter = absolute_samples_offset;
|
||||
d_sample_counter_next = d_sample_counter;
|
||||
@ -1195,7 +1272,7 @@ int dll_pll_veml_tracking_fpga::general_work(int noutput_items __attribute__((un
|
||||
// perform carrier wipe-off and compute Early, Prompt and Late correlation
|
||||
multicorrelator_fpga->Carrier_wipeoff_multicorrelator_resampler(
|
||||
d_rem_carr_phase_rad, d_carrier_phase_step_rad,
|
||||
d_rem_code_phase_chips, d_code_phase_step_chips,
|
||||
d_rem_code_phase_chips * static_cast<float>(d_code_samples_per_chip), d_code_phase_step_chips * static_cast<float>(d_code_samples_per_chip),
|
||||
d_current_prn_length_samples);
|
||||
|
||||
// Save single correlation step variables
|
||||
@ -1240,33 +1317,70 @@ int dll_pll_veml_tracking_fpga::general_work(int noutput_items __attribute__((un
|
||||
}
|
||||
else if (d_symbols_per_bit > 1) //Signal does not have secondary code. Search a bit transition by sign change
|
||||
{
|
||||
if (d_synchonizing)
|
||||
// if (d_synchonizing)
|
||||
// {
|
||||
// if (d_Prompt->real() * d_last_prompt.real() > 0.0)
|
||||
// {
|
||||
// d_current_symbol++;
|
||||
// }
|
||||
// else if (d_current_symbol > d_symbols_per_bit)
|
||||
// {
|
||||
// d_synchonizing = false;
|
||||
// d_current_symbol = 1;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// d_current_symbol = 1;
|
||||
// d_last_prompt = *d_Prompt;
|
||||
// }
|
||||
// }
|
||||
// else if (d_last_prompt.real() != 0.0)
|
||||
// {
|
||||
// d_current_symbol++;
|
||||
// if (d_current_symbol == d_symbols_per_bit) next_state = true;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// d_last_prompt = *d_Prompt;
|
||||
// d_synchonizing = true;
|
||||
// d_current_symbol = 1;
|
||||
// }
|
||||
// }
|
||||
//===========================================================================================================
|
||||
//float current_tracking_time_s = static_cast<float>(d_sample_counter - d_acq_sample_stamp) / trk_parameters.fs_in;
|
||||
float current_tracking_time_s = static_cast<float>(d_sample_counter - d_absolute_samples_offset) / trk_parameters.fs_in;
|
||||
if (current_tracking_time_s > 10)
|
||||
{
|
||||
if (d_Prompt->real() * d_last_prompt.real() > 0.0)
|
||||
d_symbol_history.push_back(d_Prompt->real());
|
||||
//******* preamble correlation ********
|
||||
int corr_value = 0;
|
||||
if ((d_symbol_history.size() == GPS_CA_PREAMBLE_LENGTH_SYMBOLS)) // and (d_make_correlation or !d_flag_frame_sync))
|
||||
{
|
||||
d_current_symbol++;
|
||||
for (uint32_t i = 0; i < GPS_CA_PREAMBLE_LENGTH_SYMBOLS; i++)
|
||||
{
|
||||
if (d_symbol_history.at(i) < 0) // symbols clipping
|
||||
{
|
||||
corr_value -= d_gps_l1ca_preambles_symbols[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
corr_value += d_gps_l1ca_preambles_symbols[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (d_current_symbol > d_symbols_per_bit)
|
||||
if (corr_value == GPS_CA_PREAMBLE_LENGTH_SYMBOLS)
|
||||
{
|
||||
d_synchonizing = false;
|
||||
d_current_symbol = 1;
|
||||
//std::cout << "Preamble detected at tracking!" << std::endl;
|
||||
next_state = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
d_current_symbol = 1;
|
||||
d_last_prompt = *d_Prompt;
|
||||
next_state = false;
|
||||
}
|
||||
}
|
||||
else if (d_last_prompt.real() != 0.0)
|
||||
{
|
||||
d_current_symbol++;
|
||||
if (d_current_symbol == d_symbols_per_bit) next_state = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
d_last_prompt = *d_Prompt;
|
||||
d_synchonizing = true;
|
||||
d_current_symbol = 1;
|
||||
next_state = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -1274,6 +1388,43 @@ int dll_pll_veml_tracking_fpga::general_work(int noutput_items __attribute__((un
|
||||
next_state = true;
|
||||
}
|
||||
|
||||
// ########### Output the tracking results to Telemetry block ##########
|
||||
if (interchange_iq)
|
||||
{
|
||||
if (trk_parameters.track_pilot)
|
||||
{
|
||||
// Note that data and pilot components are in quadrature. I and Q are interchanged
|
||||
current_synchro_data.Prompt_I = static_cast<double>((*d_Prompt_Data).imag());
|
||||
current_synchro_data.Prompt_Q = static_cast<double>((*d_Prompt_Data).real());
|
||||
}
|
||||
else
|
||||
{
|
||||
current_synchro_data.Prompt_I = static_cast<double>((*d_Prompt).imag());
|
||||
current_synchro_data.Prompt_Q = static_cast<double>((*d_Prompt).real());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (trk_parameters.track_pilot)
|
||||
{
|
||||
// Note that data and pilot components are in quadrature. I and Q are interchanged
|
||||
current_synchro_data.Prompt_I = static_cast<double>((*d_Prompt_Data).real());
|
||||
current_synchro_data.Prompt_Q = static_cast<double>((*d_Prompt_Data).imag());
|
||||
}
|
||||
else
|
||||
{
|
||||
current_synchro_data.Prompt_I = static_cast<double>((*d_Prompt).real());
|
||||
current_synchro_data.Prompt_Q = static_cast<double>((*d_Prompt).imag());
|
||||
}
|
||||
}
|
||||
current_synchro_data.Code_phase_samples = d_rem_code_phase_samples;
|
||||
current_synchro_data.Carrier_phase_rads = d_acc_carrier_phase_rad;
|
||||
current_synchro_data.Carrier_Doppler_hz = d_carrier_doppler_hz;
|
||||
current_synchro_data.CN0_dB_hz = d_CN0_SNV_dB_Hz;
|
||||
current_synchro_data.Flag_valid_symbol_output = true;
|
||||
current_synchro_data.correlation_length_ms = d_correlation_length_ms;
|
||||
|
||||
|
||||
if (next_state)
|
||||
{ // reset extended correlator
|
||||
d_VE_accu = gr_complex(0.0, 0.0);
|
||||
@ -1336,7 +1487,7 @@ int dll_pll_veml_tracking_fpga::general_work(int noutput_items __attribute__((un
|
||||
// perform a correlation step
|
||||
multicorrelator_fpga->Carrier_wipeoff_multicorrelator_resampler(
|
||||
d_rem_carr_phase_rad, d_carrier_phase_step_rad,
|
||||
d_rem_code_phase_chips, d_code_phase_step_chips,
|
||||
d_rem_code_phase_chips * static_cast<float>(d_code_samples_per_chip), d_code_phase_step_chips * static_cast<float>(d_code_samples_per_chip),
|
||||
d_current_prn_length_samples);
|
||||
update_tracking_vars();
|
||||
save_correlation_results();
|
||||
@ -1395,7 +1546,7 @@ int dll_pll_veml_tracking_fpga::general_work(int noutput_items __attribute__((un
|
||||
//do_correlation_step(in);
|
||||
multicorrelator_fpga->Carrier_wipeoff_multicorrelator_resampler(
|
||||
d_rem_carr_phase_rad, d_carrier_phase_step_rad,
|
||||
d_rem_code_phase_chips, d_code_phase_step_chips,
|
||||
d_rem_code_phase_chips * static_cast<float>(d_code_samples_per_chip), d_code_phase_step_chips * static_cast<float>(d_code_samples_per_chip),
|
||||
d_current_prn_length_samples);
|
||||
|
||||
save_correlation_results();
|
||||
@ -1471,3 +1622,8 @@ int dll_pll_veml_tracking_fpga::general_work(int noutput_items __attribute__((un
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dll_pll_veml_tracking_fpga::reset(void)
|
||||
{
|
||||
multicorrelator_fpga->unlock_channel();
|
||||
}
|
||||
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
@ -39,51 +39,58 @@
|
||||
#ifndef GNSS_SDR_DLL_PLL_VEML_TRACKING_FPGA_H
|
||||
#define GNSS_SDR_DLL_PLL_VEML_TRACKING_FPGA_H
|
||||
|
||||
#include "fpga_multicorrelator.h"
|
||||
#include "dll_pll_conf_fpga.h"
|
||||
#include "gnss_synchro.h"
|
||||
#include "tracking_2nd_DLL_filter.h"
|
||||
#include "tracking_2nd_PLL_filter.h"
|
||||
#include "fpga_multicorrelator.h"
|
||||
#include <gnuradio/block.h>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <queue>
|
||||
#include <boost/circular_buffer.hpp>
|
||||
#include "fpga_multicorrelator.h"
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* DLL/PLL tracking configuration */
|
||||
double fs_in;
|
||||
unsigned int vector_length;
|
||||
bool dump;
|
||||
std::string dump_filename;
|
||||
float pll_bw_hz;
|
||||
float dll_bw_hz;
|
||||
float pll_bw_narrow_hz;
|
||||
float dll_bw_narrow_hz;
|
||||
float early_late_space_chips;
|
||||
float very_early_late_space_chips;
|
||||
float early_late_space_narrow_chips;
|
||||
float very_early_late_space_narrow_chips;
|
||||
int extend_correlation_symbols;
|
||||
int cn0_samples;
|
||||
int cn0_min;
|
||||
int max_lock_fail;
|
||||
double carrier_lock_th;
|
||||
bool track_pilot;
|
||||
char system;
|
||||
char signal[3];
|
||||
std::string device_name;
|
||||
unsigned int device_base;
|
||||
unsigned int code_length;
|
||||
int *ca_codes;
|
||||
} dllpllconf_fpga_t;
|
||||
//typedef struct
|
||||
//{
|
||||
// /* DLL/PLL tracking configuration */
|
||||
// double fs_in;
|
||||
// uint32_t vector_length;
|
||||
// bool dump;
|
||||
// std::string dump_filename;
|
||||
// float pll_bw_hz;
|
||||
// float dll_bw_hz;
|
||||
// float pll_bw_narrow_hz;
|
||||
// float dll_bw_narrow_hz;
|
||||
// float early_late_space_chips;
|
||||
// float very_early_late_space_chips;
|
||||
// float early_late_space_narrow_chips;
|
||||
// float very_early_late_space_narrow_chips;
|
||||
// int32_t extend_correlation_symbols;
|
||||
// int32_t cn0_samples;
|
||||
// int32_t cn0_min;
|
||||
// int32_t max_lock_fail;
|
||||
// double carrier_lock_th;
|
||||
// bool track_pilot;
|
||||
// char system;
|
||||
// char signal[3];
|
||||
// std::string device_name;
|
||||
// uint32_t device_base;
|
||||
// uint32_t multicorr_type;
|
||||
// uint32_t code_length_chips;
|
||||
// uint32_t code_samples_per_chip;
|
||||
// int* ca_codes;
|
||||
// int* data_codes;
|
||||
//} dllpllconf_fpga_t;
|
||||
|
||||
class dll_pll_veml_tracking_fpga;
|
||||
|
||||
typedef boost::shared_ptr<dll_pll_veml_tracking_fpga>
|
||||
dll_pll_veml_tracking_fpga_sptr;
|
||||
|
||||
dll_pll_veml_tracking_fpga_sptr dll_pll_veml_make_tracking_fpga(dllpllconf_fpga_t conf_);
|
||||
//dll_pll_veml_tracking_fpga_sptr dll_pll_veml_make_tracking_fpga(const dllpllconf_fpga_t &conf_);
|
||||
dll_pll_veml_tracking_fpga_sptr dll_pll_veml_make_tracking_fpga(const Dll_Pll_Conf_Fpga &conf_);
|
||||
|
||||
|
||||
/*!
|
||||
@ -94,7 +101,7 @@ class dll_pll_veml_tracking_fpga : public gr::block
|
||||
public:
|
||||
~dll_pll_veml_tracking_fpga();
|
||||
|
||||
void set_channel(unsigned int channel);
|
||||
void set_channel(uint32_t channel);
|
||||
void set_gnss_synchro(Gnss_Synchro *p_gnss_synchro);
|
||||
void start_tracking();
|
||||
|
||||
@ -104,9 +111,10 @@ public:
|
||||
void reset(void);
|
||||
|
||||
private:
|
||||
friend dll_pll_veml_tracking_fpga_sptr dll_pll_veml_make_tracking_fpga(dllpllconf_fpga_t conf_);
|
||||
friend dll_pll_veml_tracking_fpga_sptr dll_pll_veml_make_tracking_fpga(const Dll_Pll_Conf_Fpga &conf_);
|
||||
|
||||
dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_);
|
||||
dll_pll_veml_tracking_fpga(const Dll_Pll_Conf_Fpga &conf_);
|
||||
void msg_handler_preamble_index(pmt::pmt_t msg);
|
||||
|
||||
bool cn0_and_tracking_lock_status(double coh_integration_time_s);
|
||||
bool acquire_secondary();
|
||||
@ -115,13 +123,14 @@ private:
|
||||
void clear_tracking_vars();
|
||||
void save_correlation_results();
|
||||
void log_data(bool integrating);
|
||||
int save_matfile();
|
||||
int32_t save_matfile();
|
||||
|
||||
// tracking configuration vars
|
||||
dllpllconf_fpga_t trk_parameters;
|
||||
Dll_Pll_Conf_Fpga trk_parameters;
|
||||
//dllpllconf_fpga_t trk_parameters;
|
||||
bool d_veml;
|
||||
bool d_cloop;
|
||||
unsigned int d_channel;
|
||||
uint32_t d_channel;
|
||||
Gnss_Synchro *d_acquisition_gnss_synchro;
|
||||
|
||||
//Signal parameters
|
||||
@ -130,21 +139,24 @@ private:
|
||||
double d_signal_carrier_freq;
|
||||
double d_code_period;
|
||||
double d_code_chip_rate;
|
||||
unsigned int d_secondary_code_length;
|
||||
unsigned int d_code_length_chips;
|
||||
unsigned int d_code_samples_per_chip; // All signals have 1 sample per chip code except Gal. E1 which has 2 (CBOC disabled) or 12 (CBOC enabled)
|
||||
int d_symbols_per_bit;
|
||||
uint32_t d_secondary_code_length;
|
||||
uint32_t d_code_length_chips;
|
||||
uint32_t d_code_samples_per_chip; // All signals have 1 sample per chip code except Gal. E1 which has 2 (CBOC disabled) or 12 (CBOC enabled)
|
||||
int32_t d_symbols_per_bit;
|
||||
std::string systemName;
|
||||
std::string signal_type;
|
||||
std::string *d_secondary_code_string;
|
||||
std::string signal_pretty_name;
|
||||
|
||||
int32_t *d_gps_l1ca_preambles_symbols;
|
||||
boost::circular_buffer<float> d_symbol_history;
|
||||
|
||||
//tracking state machine
|
||||
int d_state;
|
||||
int32_t d_state;
|
||||
bool d_synchonizing;
|
||||
//Integration period in samples
|
||||
int d_correlation_length_ms;
|
||||
int d_n_correlator_taps;
|
||||
int32_t d_correlation_length_ms;
|
||||
int32_t d_n_correlator_taps;
|
||||
float *d_local_code_shift_chips;
|
||||
float *d_prompt_data_shift;
|
||||
std::shared_ptr<fpga_multicorrelator_8sc> multicorrelator_fpga;
|
||||
@ -157,8 +169,8 @@ private:
|
||||
gr_complex *d_Very_Late;
|
||||
|
||||
bool d_enable_extended_integration;
|
||||
int d_extend_correlation_symbols_count;
|
||||
int d_current_symbol;
|
||||
int32_t d_extend_correlation_symbols_count;
|
||||
int32_t d_current_symbol;
|
||||
|
||||
gr_complex d_VE_accu;
|
||||
gr_complex d_E_accu;
|
||||
@ -199,14 +211,15 @@ private:
|
||||
double T_prn_samples;
|
||||
double K_blk_samples;
|
||||
// PRN period in samples
|
||||
int d_current_prn_length_samples;
|
||||
int32_t d_current_prn_length_samples;
|
||||
// processing samples counters
|
||||
uint64_t d_sample_counter;
|
||||
uint64_t d_acq_sample_stamp;
|
||||
uint64_t d_absolute_samples_offset;
|
||||
|
||||
// CN0 estimation and lock detector
|
||||
int d_cn0_estimation_counter;
|
||||
int d_carrier_lock_fail_counter;
|
||||
int32_t d_cn0_estimation_counter;
|
||||
int32_t d_carrier_lock_fail_counter;
|
||||
double d_carrier_lock_test;
|
||||
double d_CN0_SNV_dB_Hz;
|
||||
double d_carrier_lock_threshold;
|
||||
@ -217,10 +230,10 @@ private:
|
||||
std::ofstream d_dump_file;
|
||||
|
||||
// extra
|
||||
int d_correlation_length_samples;
|
||||
int d_next_prn_length_samples;
|
||||
int32_t d_correlation_length_samples;
|
||||
int32_t d_next_prn_length_samples;
|
||||
uint64_t d_sample_counter_next;
|
||||
unsigned int d_pull_in = 0;
|
||||
uint32_t d_pull_in = 0;
|
||||
};
|
||||
|
||||
#endif //GNSS_SDR_DLL_PLL_VEML_TRACKING_FPGA_H
|
||||
|
@ -47,7 +47,7 @@ set(TRACKING_LIB_SOURCES
|
||||
)
|
||||
|
||||
if(ENABLE_FPGA)
|
||||
SET(TRACKING_LIB_SOURCES ${TRACKING_LIB_SOURCES} fpga_multicorrelator.cc)
|
||||
SET(TRACKING_LIB_SOURCES ${TRACKING_LIB_SOURCES} fpga_multicorrelator.cc dll_pll_conf_fpga.cc)
|
||||
endif(ENABLE_FPGA)
|
||||
|
||||
include_directories(
|
||||
|
91
src/algorithms/tracking/libs/dll_pll_conf_fpga.cc
Normal file
91
src/algorithms/tracking/libs/dll_pll_conf_fpga.cc
Normal file
@ -0,0 +1,91 @@
|
||||
/*!
|
||||
* \file dll_pll_conf.cc
|
||||
* \brief Class that contains all the configuration parameters for generic
|
||||
* tracking block based on a DLL and a PLL.
|
||||
* \author Javier Arribas, 2018. jarribas(at)cttc.es
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (C) 2010-2018 (see AUTHORS file for a list of contributors)
|
||||
*
|
||||
* GNSS-SDR is a software defined Global Navigation
|
||||
* Satellite Systems receiver
|
||||
*
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* GNSS-SDR is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GNSS-SDR is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNSS-SDR. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#include "dll_pll_conf_fpga.h"
|
||||
#include <cstring>
|
||||
|
||||
Dll_Pll_Conf_Fpga::Dll_Pll_Conf_Fpga()
|
||||
{
|
||||
// /* DLL/PLL tracking configuration */
|
||||
// fs_in = 0.0;
|
||||
// vector_length = 0;
|
||||
// dump = false;
|
||||
// dump_filename = "./dll_pll_dump.dat";
|
||||
// pll_bw_hz = 40.0;
|
||||
// dll_bw_hz = 2.0;
|
||||
// pll_bw_narrow_hz = 5.0;
|
||||
// dll_bw_narrow_hz = 0.75;
|
||||
// early_late_space_chips = 0.5;
|
||||
// very_early_late_space_chips = 0.5;
|
||||
// early_late_space_narrow_chips = 0.1;
|
||||
// very_early_late_space_narrow_chips = 0.1;
|
||||
// extend_correlation_symbols = 5;
|
||||
// cn0_samples = 20;
|
||||
// carrier_lock_det_mav_samples = 20;
|
||||
// cn0_min = 25;
|
||||
// max_lock_fail = 50;
|
||||
// carrier_lock_th = 0.85;
|
||||
// track_pilot = false;
|
||||
// system = 'G';
|
||||
// char sig_[3] = "1C";
|
||||
// std::memcpy(signal, sig_, 3);
|
||||
|
||||
/* DLL/PLL tracking configuration */
|
||||
fs_in = 0.0;
|
||||
vector_length = 0;
|
||||
dump = false;
|
||||
dump_filename = "./dll_pll_dump.dat";
|
||||
pll_bw_hz = 40.0;
|
||||
dll_bw_hz = 2.0;
|
||||
pll_bw_narrow_hz = 5.0;
|
||||
dll_bw_narrow_hz = 0.75;
|
||||
early_late_space_chips = 0.5;
|
||||
very_early_late_space_chips = 0.5;
|
||||
early_late_space_narrow_chips = 0.1;
|
||||
very_early_late_space_narrow_chips = 0.1;
|
||||
extend_correlation_symbols = 5;
|
||||
cn0_samples = 20;
|
||||
cn0_min = 25;
|
||||
max_lock_fail = 50;
|
||||
carrier_lock_th = 0.85;
|
||||
track_pilot = false;
|
||||
system = 'G';
|
||||
char sig_[3] = "1C";
|
||||
std::memcpy(signal, sig_, 3);
|
||||
device_name = "/dev/uio";
|
||||
device_base = 1;
|
||||
multicorr_type = 0;
|
||||
code_length_chips = 0;
|
||||
code_samples_per_chip = 0;
|
||||
//int32_t* ca_codes;
|
||||
//int32_t* data_codes;
|
||||
}
|
98
src/algorithms/tracking/libs/dll_pll_conf_fpga.h
Normal file
98
src/algorithms/tracking/libs/dll_pll_conf_fpga.h
Normal file
@ -0,0 +1,98 @@
|
||||
/*!
|
||||
* \file dll_pll_conf.h
|
||||
* \brief Class that contains all the configuration parameters for generic tracking block based on a DLL and a PLL.
|
||||
* \author Javier Arribas, 2018. jarribas(at)cttc.es
|
||||
*
|
||||
* Class that contains all the configuration parameters for generic tracking block based on a DLL and a PLL.
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (C) 2010-2018 (see AUTHORS file for a list of contributors)
|
||||
*
|
||||
* GNSS-SDR is a software defined Global Navigation
|
||||
* Satellite Systems receiver
|
||||
*
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* GNSS-SDR is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GNSS-SDR is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNSS-SDR. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef GNSS_SDR_DLL_PLL_CONF_FPGA_H_
|
||||
#define GNSS_SDR_DLL_PLL_CONF_FPGA_H_
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
class Dll_Pll_Conf_Fpga
|
||||
{
|
||||
private:
|
||||
public:
|
||||
// /* DLL/PLL tracking configuration */
|
||||
// double fs_in;
|
||||
// uint32_t vector_length;
|
||||
// bool dump;
|
||||
// std::string dump_filename;
|
||||
// float pll_bw_hz;
|
||||
// float dll_bw_hz;
|
||||
// float pll_bw_narrow_hz;
|
||||
// float dll_bw_narrow_hz;
|
||||
// float early_late_space_chips;
|
||||
// float very_early_late_space_chips;
|
||||
// float early_late_space_narrow_chips;
|
||||
// float very_early_late_space_narrow_chips;
|
||||
// int32_t extend_correlation_symbols;
|
||||
// int32_t cn0_samples;
|
||||
// int32_t carrier_lock_det_mav_samples;
|
||||
// int32_t cn0_min;
|
||||
// int32_t max_lock_fail;
|
||||
// double carrier_lock_th;
|
||||
// bool track_pilot;
|
||||
// char system;
|
||||
// char signal[3];
|
||||
|
||||
/* DLL/PLL tracking configuration */
|
||||
double fs_in;
|
||||
uint32_t vector_length;
|
||||
bool dump;
|
||||
std::string dump_filename;
|
||||
float pll_bw_hz;
|
||||
float dll_bw_hz;
|
||||
float pll_bw_narrow_hz;
|
||||
float dll_bw_narrow_hz;
|
||||
float early_late_space_chips;
|
||||
float very_early_late_space_chips;
|
||||
float early_late_space_narrow_chips;
|
||||
float very_early_late_space_narrow_chips;
|
||||
int32_t extend_correlation_symbols;
|
||||
int32_t cn0_samples;
|
||||
int32_t cn0_min;
|
||||
int32_t max_lock_fail;
|
||||
double carrier_lock_th;
|
||||
bool track_pilot;
|
||||
char system;
|
||||
char signal[3];
|
||||
std::string device_name;
|
||||
uint32_t device_base;
|
||||
uint32_t multicorr_type;
|
||||
uint32_t code_length_chips;
|
||||
uint32_t code_samples_per_chip;
|
||||
int32_t* ca_codes;
|
||||
int32_t* data_codes;
|
||||
|
||||
Dll_Pll_Conf_Fpga();
|
||||
};
|
||||
|
||||
#endif
|
@ -75,7 +75,7 @@
|
||||
#define CODE_RESAMPLER_NUM_BITS_PRECISION 20
|
||||
#define CODE_PHASE_STEP_CHIPS_NUM_NBITS CODE_RESAMPLER_NUM_BITS_PRECISION
|
||||
#define pwrtwo(x) (1 << (x))
|
||||
#define MAX_CODE_RESAMPLER_COUNTER pwrtwo(CODE_PHASE_STEP_CHIPS_NUM_NBITS) // 2^CODE_PHASE_STEP_CHIPS_NUM_NBITS
|
||||
#define MAX_CODE_RESAMPLER_COUNTER pwrtwo(CODE_PHASE_STEP_CHIPS_NUM_NBITS) // 2^CODE_PHASE_STEP_CHIPS_NUM_NBITS
|
||||
#define PHASE_CARR_NBITS 32
|
||||
#define PHASE_CARR_NBITS_INT 1
|
||||
#define PHASE_CARR_NBITS_FRAC PHASE_CARR_NBITS - PHASE_CARR_NBITS_INT
|
||||
@ -84,57 +84,69 @@
|
||||
#define LOCAL_CODE_FPGA_ENABLE_WRITE_MEMORY 0x0C000000
|
||||
#define TEST_REGISTER_TRACK_WRITEVAL 0x55AA
|
||||
|
||||
int fpga_multicorrelator_8sc::read_sample_counter()
|
||||
uint64_t fpga_multicorrelator_8sc::read_sample_counter()
|
||||
{
|
||||
return d_map_base[7];
|
||||
uint64_t sample_counter_tmp, sample_counter_msw_tmp;
|
||||
sample_counter_tmp = d_map_base[d_SAMPLE_COUNTER_REG_ADDR_LSW];
|
||||
sample_counter_msw_tmp = d_map_base[d_SAMPLE_COUNTER_REG_ADDR_MSW];
|
||||
sample_counter_msw_tmp = sample_counter_msw_tmp << 32;
|
||||
sample_counter_tmp = sample_counter_tmp + sample_counter_msw_tmp; // 2^32
|
||||
//return d_map_base[d_SAMPLE_COUNTER_REG_ADDR];
|
||||
return sample_counter_tmp;
|
||||
}
|
||||
|
||||
void fpga_multicorrelator_8sc::set_initial_sample(int samples_offset)
|
||||
void fpga_multicorrelator_8sc::set_initial_sample(uint64_t samples_offset)
|
||||
{
|
||||
d_initial_sample_counter = samples_offset;
|
||||
d_map_base[13] = d_initial_sample_counter;
|
||||
//printf("www writing d map base %d = d_initial_sample_counter = %d\n", d_INITIAL_COUNTER_VALUE_REG_ADDR, d_initial_sample_counter);
|
||||
d_map_base[d_INITIAL_COUNTER_VALUE_REG_ADDR_LSW] = (d_initial_sample_counter & 0xFFFFFFFF);
|
||||
d_map_base[d_INITIAL_COUNTER_VALUE_REG_ADDR_MSW] = (d_initial_sample_counter >> 32) & 0xFFFFFFFF;
|
||||
}
|
||||
|
||||
void fpga_multicorrelator_8sc::set_local_code_and_taps(int code_length_chips,
|
||||
float *shifts_chips, int PRN)
|
||||
{
|
||||
|
||||
//void fpga_multicorrelator_8sc::set_local_code_and_taps(int32_t code_length_chips,
|
||||
// float *shifts_chips, int32_t PRN)
|
||||
|
||||
void fpga_multicorrelator_8sc::set_local_code_and_taps(float *shifts_chips, float *prompt_data_shift, int32_t PRN)
|
||||
{
|
||||
d_shifts_chips = shifts_chips;
|
||||
d_code_length_chips = code_length_chips;
|
||||
d_prompt_data_shift = prompt_data_shift;
|
||||
//d_code_length_chips = code_length_chips;
|
||||
fpga_multicorrelator_8sc::fpga_configure_tracking_gps_local_code(PRN);
|
||||
}
|
||||
|
||||
void fpga_multicorrelator_8sc::set_output_vectors(gr_complex* corr_out)
|
||||
void fpga_multicorrelator_8sc::set_output_vectors(gr_complex *corr_out, gr_complex *Prompt_Data)
|
||||
{
|
||||
d_corr_out = corr_out;
|
||||
d_Prompt_Data = Prompt_Data;
|
||||
}
|
||||
|
||||
void fpga_multicorrelator_8sc::update_local_code(float rem_code_phase_chips)
|
||||
{
|
||||
d_rem_code_phase_chips = rem_code_phase_chips;
|
||||
//printf("uuuuu d_rem_code_phase_chips = %f\n", d_rem_code_phase_chips);
|
||||
fpga_multicorrelator_8sc::fpga_compute_code_shift_parameters();
|
||||
fpga_multicorrelator_8sc::fpga_configure_code_parameters_in_fpga();
|
||||
}
|
||||
|
||||
|
||||
void fpga_multicorrelator_8sc::Carrier_wipeoff_multicorrelator_resampler(
|
||||
float rem_carrier_phase_in_rad, float phase_step_rad,
|
||||
float rem_code_phase_chips, float code_phase_step_chips,
|
||||
int signal_length_samples)
|
||||
float rem_carrier_phase_in_rad, float phase_step_rad,
|
||||
float rem_code_phase_chips, float code_phase_step_chips,
|
||||
int32_t signal_length_samples)
|
||||
{
|
||||
|
||||
|
||||
update_local_code(rem_code_phase_chips);
|
||||
d_rem_carrier_phase_in_rad = rem_carrier_phase_in_rad;
|
||||
d_code_phase_step_chips = code_phase_step_chips;
|
||||
d_phase_step_rad = phase_step_rad;
|
||||
d_correlator_length_samples = signal_length_samples;
|
||||
fpga_multicorrelator_8sc::fpga_compute_signal_parameters_in_fpga();
|
||||
fpga_multicorrelator_8sc::fpga_configure_signal_parameters_in_fpga();
|
||||
fpga_multicorrelator_8sc::fpga_compute_signal_parameters_in_fpga();
|
||||
fpga_multicorrelator_8sc::fpga_configure_signal_parameters_in_fpga();
|
||||
fpga_multicorrelator_8sc::fpga_launch_multicorrelator_fpga();
|
||||
int irq_count;
|
||||
int32_t irq_count;
|
||||
ssize_t nb;
|
||||
//printf("$$$$$ waiting for interrupt ... \n");
|
||||
nb = read(d_device_descriptor, &irq_count, sizeof(irq_count));
|
||||
//printf("$$$$$ interrupt received ... \n");
|
||||
if (nb != sizeof(irq_count))
|
||||
{
|
||||
printf("Tracking_module Read failed to retrieve 4 bytes!\n");
|
||||
@ -143,23 +155,35 @@ void fpga_multicorrelator_8sc::Carrier_wipeoff_multicorrelator_resampler(
|
||||
fpga_multicorrelator_8sc::read_tracking_gps_results();
|
||||
}
|
||||
|
||||
fpga_multicorrelator_8sc::fpga_multicorrelator_8sc(int n_correlators,
|
||||
std::string device_name, unsigned int device_base, int *ca_codes, unsigned int code_length)
|
||||
fpga_multicorrelator_8sc::fpga_multicorrelator_8sc(int32_t n_correlators,
|
||||
std::string device_name, uint32_t device_base, int32_t *ca_codes, int32_t *data_codes, uint32_t code_length_chips, bool track_pilot,
|
||||
uint32_t multicorr_type, uint32_t code_samples_per_chip)
|
||||
{
|
||||
//printf("tracking fpga class created\n");
|
||||
d_n_correlators = n_correlators;
|
||||
d_device_name = device_name;
|
||||
d_device_base = device_base;
|
||||
d_track_pilot = track_pilot;
|
||||
d_device_descriptor = 0;
|
||||
d_map_base = nullptr;
|
||||
|
||||
// instantiate variable length vectors
|
||||
d_initial_index = static_cast<unsigned*>(volk_gnsssdr_malloc(
|
||||
n_correlators * sizeof(unsigned), volk_gnsssdr_get_alignment()));
|
||||
d_initial_interp_counter = static_cast<unsigned*>(volk_gnsssdr_malloc(
|
||||
n_correlators * sizeof(unsigned), volk_gnsssdr_get_alignment()));
|
||||
|
||||
//d_local_code_in = nullptr;
|
||||
if (d_track_pilot)
|
||||
{
|
||||
d_initial_index = static_cast<uint32_t *>(volk_gnsssdr_malloc(
|
||||
(n_correlators + 1) * sizeof(uint32_t), volk_gnsssdr_get_alignment()));
|
||||
d_initial_interp_counter = static_cast<uint32_t *>(volk_gnsssdr_malloc(
|
||||
(n_correlators + 1) * sizeof(uint32_t), volk_gnsssdr_get_alignment()));
|
||||
}
|
||||
else
|
||||
{
|
||||
d_initial_index = static_cast<uint32_t *>(volk_gnsssdr_malloc(
|
||||
n_correlators * sizeof(uint32_t), volk_gnsssdr_get_alignment()));
|
||||
d_initial_interp_counter = static_cast<uint32_t *>(volk_gnsssdr_malloc(
|
||||
n_correlators * sizeof(uint32_t), volk_gnsssdr_get_alignment()));
|
||||
}
|
||||
d_shifts_chips = nullptr;
|
||||
d_prompt_data_shift = nullptr;
|
||||
d_corr_out = nullptr;
|
||||
d_code_length_chips = 0;
|
||||
d_rem_code_phase_chips = 0;
|
||||
@ -171,23 +195,103 @@ fpga_multicorrelator_8sc::fpga_multicorrelator_8sc(int n_correlators,
|
||||
d_initial_sample_counter = 0;
|
||||
d_channel = 0;
|
||||
d_correlator_length_samples = 0,
|
||||
d_code_length = code_length;
|
||||
|
||||
// pre-compute all the codes
|
||||
// d_ca_codes = static_cast<int*>(volk_gnsssdr_malloc(static_cast<int>(GPS_L1_CA_CODE_LENGTH_CHIPS*NUM_PRNs) * sizeof(int), volk_gnsssdr_get_alignment()));
|
||||
// for (unsigned int PRN = 1; PRN <= NUM_PRNs; PRN++)
|
||||
// {
|
||||
// gps_l1_ca_code_gen_int(&d_ca_codes[(int(GPS_L1_CA_CODE_LENGTH_CHIPS)) * (PRN - 1)], PRN, 0);
|
||||
// }
|
||||
//d_code_length = code_length;
|
||||
d_code_length_chips = code_length_chips;
|
||||
d_ca_codes = ca_codes;
|
||||
d_data_codes = data_codes;
|
||||
d_multicorr_type = multicorr_type;
|
||||
|
||||
d_code_samples_per_chip = code_samples_per_chip;
|
||||
// set up register mapping
|
||||
|
||||
// write-only registers
|
||||
d_CODE_PHASE_STEP_CHIPS_NUM_REG_ADDR = 0;
|
||||
d_INITIAL_INDEX_REG_BASE_ADDR = 1;
|
||||
// if (d_multicorr_type == 0)
|
||||
// {
|
||||
// // multicorrelator with 3 correlators (16 registers only)
|
||||
// d_INITIAL_INTERP_COUNTER_REG_BASE_ADDR = 4;
|
||||
// d_NSAMPLES_MINUS_1_REG_ADDR = 7;
|
||||
// d_CODE_LENGTH_MINUS_1_REG_ADDR = 8;
|
||||
// d_REM_CARR_PHASE_RAD_REG_ADDR = 9;
|
||||
// d_PHASE_STEP_RAD_REG_ADDR = 10;
|
||||
// d_PROG_MEMS_ADDR = 11;
|
||||
// d_DROP_SAMPLES_REG_ADDR = 12;
|
||||
// d_INITIAL_COUNTER_VALUE_REG_ADDR = 13;
|
||||
// d_START_FLAG_ADDR = 14;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// other types of multicorrelators (32 registers)
|
||||
d_INITIAL_INTERP_COUNTER_REG_BASE_ADDR = 7;
|
||||
d_NSAMPLES_MINUS_1_REG_ADDR = 13;
|
||||
d_CODE_LENGTH_MINUS_1_REG_ADDR = 14;
|
||||
d_REM_CARR_PHASE_RAD_REG_ADDR = 15;
|
||||
d_PHASE_STEP_RAD_REG_ADDR = 16;
|
||||
d_PROG_MEMS_ADDR = 17;
|
||||
d_DROP_SAMPLES_REG_ADDR = 18;
|
||||
d_INITIAL_COUNTER_VALUE_REG_ADDR_LSW = 19;
|
||||
d_INITIAL_COUNTER_VALUE_REG_ADDR_MSW = 20;
|
||||
d_START_FLAG_ADDR = 30;
|
||||
// }
|
||||
|
||||
//printf("d_n_correlators = %d\n", d_n_correlators);
|
||||
//printf("d_multicorr_type = %d\n", d_multicorr_type);
|
||||
// read-write registers
|
||||
// if (d_multicorr_type == 0)
|
||||
// {
|
||||
// // multicorrelator with 3 correlators (16 registers only)
|
||||
// d_TEST_REG_ADDR = 15;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// other types of multicorrelators (32 registers)
|
||||
d_TEST_REG_ADDR = 31;
|
||||
// }
|
||||
|
||||
// result 2's complement saturation value
|
||||
// if (d_multicorr_type == 0)
|
||||
// {
|
||||
// // multicorrelator with 3 correlators (16 registers only)
|
||||
// d_result_SAT_value = 1048576; // 21 bits 2's complement -> 2^20
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// // other types of multicorrelators (32 registers)
|
||||
// d_result_SAT_value = 4194304; // 23 bits 2's complement -> 2^22
|
||||
// }
|
||||
|
||||
// read only registers
|
||||
d_RESULT_REG_REAL_BASE_ADDR = 1;
|
||||
// if (d_multicorr_type == 0)
|
||||
// {
|
||||
// // multicorrelator with 3 correlators (16 registers only)
|
||||
// d_RESULT_REG_IMAG_BASE_ADDR = 4;
|
||||
// d_RESULT_REG_DATA_REAL_BASE_ADDR = 0; // no pilot tracking
|
||||
// d_RESULT_REG_DATA_IMAG_BASE_ADDR = 0;
|
||||
// d_SAMPLE_COUNTER_REG_ADDR = 7;
|
||||
//
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// other types of multicorrelators (32 registers)
|
||||
d_RESULT_REG_IMAG_BASE_ADDR = 7;
|
||||
d_RESULT_REG_DATA_REAL_BASE_ADDR = 6; // no pilot tracking
|
||||
d_RESULT_REG_DATA_IMAG_BASE_ADDR = 12;
|
||||
d_SAMPLE_COUNTER_REG_ADDR_LSW = 13;
|
||||
d_SAMPLE_COUNTER_REG_ADDR_MSW = 14;
|
||||
|
||||
// }
|
||||
|
||||
//printf("d_SAMPLE_COUNTER_REG_ADDR = %d\n", d_SAMPLE_COUNTER_REG_ADDR);
|
||||
//printf("mmmmmmmmmmmmm d_n_correlators = %d\n", d_n_correlators);
|
||||
DLOG(INFO) << "TRACKING FPGA CLASS CREATED";
|
||||
|
||||
}
|
||||
|
||||
|
||||
fpga_multicorrelator_8sc::~fpga_multicorrelator_8sc()
|
||||
{
|
||||
delete[] d_ca_codes;
|
||||
//delete[] d_ca_codes;
|
||||
close_device();
|
||||
}
|
||||
|
||||
@ -195,7 +299,7 @@ fpga_multicorrelator_8sc::~fpga_multicorrelator_8sc()
|
||||
bool fpga_multicorrelator_8sc::free()
|
||||
{
|
||||
// unlock the channel
|
||||
fpga_multicorrelator_8sc::unlock_channel();
|
||||
fpga_multicorrelator_8sc::unlock_channel();
|
||||
|
||||
// free the FPGA dynamically created variables
|
||||
if (d_initial_index != nullptr)
|
||||
@ -214,73 +318,140 @@ bool fpga_multicorrelator_8sc::free()
|
||||
}
|
||||
|
||||
|
||||
void fpga_multicorrelator_8sc::set_channel(unsigned int channel)
|
||||
void fpga_multicorrelator_8sc::set_channel(uint32_t channel)
|
||||
{
|
||||
char device_io_name[MAX_LENGTH_DEVICEIO_NAME]; // driver io name
|
||||
//printf("www trk set channel\n");
|
||||
char device_io_name[MAX_LENGTH_DEVICEIO_NAME]; // driver io name
|
||||
d_channel = channel;
|
||||
|
||||
// open the device corresponding to the assigned channel
|
||||
std::string mergedname;
|
||||
std::stringstream devicebasetemp;
|
||||
int numdevice = d_device_base + d_channel;
|
||||
int32_t numdevice = d_device_base + d_channel;
|
||||
devicebasetemp << numdevice;
|
||||
mergedname = d_device_name + devicebasetemp.str();
|
||||
strcpy(device_io_name, mergedname.c_str());
|
||||
|
||||
//printf("ppps opening device %s\n", device_io_name);
|
||||
|
||||
if ((d_device_descriptor = open(device_io_name, O_RDWR | O_SYNC)) == -1)
|
||||
{
|
||||
LOG(WARNING) << "Cannot open deviceio" << device_io_name;
|
||||
}
|
||||
d_map_base = reinterpret_cast<volatile unsigned *>(mmap(NULL, PAGE_SIZE,
|
||||
PROT_READ | PROT_WRITE, MAP_SHARED, d_device_descriptor, 0));
|
||||
std::cout << "Cannot open deviceio" << device_io_name << std::endl;
|
||||
|
||||
if (d_map_base == reinterpret_cast<void*>(-1))
|
||||
//printf("error opening device\n");
|
||||
}
|
||||
// else
|
||||
// {
|
||||
// std::cout << "deviceio" << device_io_name << " opened successfully" << std::endl;
|
||||
//
|
||||
// }
|
||||
d_map_base = reinterpret_cast<volatile uint32_t *>(mmap(NULL, PAGE_SIZE,
|
||||
PROT_READ | PROT_WRITE, MAP_SHARED, d_device_descriptor, 0));
|
||||
|
||||
if (d_map_base == reinterpret_cast<void *>(-1))
|
||||
{
|
||||
LOG(WARNING) << "Cannot map the FPGA tracking module "
|
||||
<< d_channel << "into user memory";
|
||||
<< d_channel << "into user memory";
|
||||
std::cout << "Cannot map deviceio" << device_io_name << std::endl;
|
||||
//printf("error mapping registers\n");
|
||||
}
|
||||
// else
|
||||
// {
|
||||
// std::cout << "deviceio" << device_io_name << "mapped successfully" << std::endl;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// printf("trk mapping registers succes\n"); // this is for debug -- remove !
|
||||
// }
|
||||
|
||||
// sanity check : check test register
|
||||
unsigned writeval = TEST_REGISTER_TRACK_WRITEVAL;
|
||||
unsigned readval;
|
||||
uint32_t writeval = TEST_REGISTER_TRACK_WRITEVAL;
|
||||
uint32_t readval;
|
||||
readval = fpga_multicorrelator_8sc::fpga_acquisition_test_register(writeval);
|
||||
if (writeval != readval)
|
||||
{
|
||||
LOG(WARNING) << "Test register sanity check failed";
|
||||
printf("tracking test register sanity check failed\n");
|
||||
|
||||
//printf("lslslls test sanity check reg failure\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(INFO) << "Test register sanity check success !";
|
||||
//printf("tracking test register sanity check success\n");
|
||||
//printf("lslslls test sanity check reg success\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
unsigned fpga_multicorrelator_8sc::fpga_acquisition_test_register(
|
||||
unsigned writeval)
|
||||
uint32_t fpga_multicorrelator_8sc::fpga_acquisition_test_register(
|
||||
uint32_t writeval)
|
||||
{
|
||||
unsigned readval;
|
||||
//printf("d_TEST_REG_ADDR = %d\n", d_TEST_REG_ADDR);
|
||||
|
||||
uint32_t readval = 0;
|
||||
// write value to test register
|
||||
d_map_base[15] = writeval;
|
||||
d_map_base[d_TEST_REG_ADDR] = writeval;
|
||||
// read value from test register
|
||||
readval = d_map_base[15];
|
||||
readval = d_map_base[d_TEST_REG_ADDR];
|
||||
// return read value
|
||||
return readval;
|
||||
}
|
||||
|
||||
|
||||
void fpga_multicorrelator_8sc::fpga_configure_tracking_gps_local_code(int PRN)
|
||||
void fpga_multicorrelator_8sc::fpga_configure_tracking_gps_local_code(int32_t PRN)
|
||||
{
|
||||
int k, s;
|
||||
unsigned code_chip;
|
||||
unsigned select_fpga_correlator;
|
||||
select_fpga_correlator = 0;
|
||||
uint32_t k;
|
||||
uint32_t code_chip;
|
||||
uint32_t select_pilot_corelator = LOCAL_CODE_FPGA_CORRELATOR_SELECT_COUNT;
|
||||
// select_fpga_correlator = 0;
|
||||
|
||||
for (s = 0; s < d_n_correlators; s++)
|
||||
//printf("kkk d_n_correlators = %x\n", d_n_correlators);
|
||||
//printf("kkk d_code_length_chips = %d\n", d_code_length_chips);
|
||||
//printf("programming mems d map base %d\n", d_PROG_MEMS_ADDR);
|
||||
|
||||
//FILE *fp;
|
||||
//char str[80];
|
||||
//sprintf(str, "generated_code_PRN%d", PRN);
|
||||
//fp = fopen(str,"w");
|
||||
// for (s = 0; s < d_n_correlators; s++)
|
||||
// {
|
||||
|
||||
//printf("kkk select_fpga_correlator = %x\n", select_fpga_correlator);
|
||||
|
||||
d_map_base[d_PROG_MEMS_ADDR] = LOCAL_CODE_FPGA_CLEAR_ADDRESS_COUNTER;
|
||||
for (k = 0; k < d_code_length_chips * d_code_samples_per_chip; k++)
|
||||
{
|
||||
d_map_base[11] = LOCAL_CODE_FPGA_CLEAR_ADDRESS_COUNTER;
|
||||
for (k = 0; k < d_code_length_chips; k++)
|
||||
//if (d_local_code_in[k] == 1)
|
||||
//printf("kkk d_ca_codes %d = %d\n", k, d_ca_codes[((int(d_code_length)) * (PRN - 1)) + k]);
|
||||
//fprintf(fp, "%d\n", d_ca_codes[((int(d_code_length_chips)) * d_code_samples_per_chip * (PRN - 1)) + k]);
|
||||
if (d_ca_codes[((int(d_code_length_chips)) * d_code_samples_per_chip * (PRN - 1)) + k] == 1)
|
||||
{
|
||||
code_chip = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
code_chip = 0;
|
||||
}
|
||||
|
||||
// copy the local code to the FPGA memory one by one
|
||||
d_map_base[d_PROG_MEMS_ADDR] = LOCAL_CODE_FPGA_ENABLE_WRITE_MEMORY | code_chip; // | select_fpga_correlator;
|
||||
}
|
||||
// select_fpga_correlator = select_fpga_correlator
|
||||
// + LOCAL_CODE_FPGA_CORRELATOR_SELECT_COUNT;
|
||||
// }
|
||||
//fclose(fp);
|
||||
//printf("kkk d_track_pilot = %d\n", d_track_pilot);
|
||||
if (d_track_pilot)
|
||||
{
|
||||
//printf("kkk select_fpga_correlator = %x\n", select_fpga_correlator);
|
||||
|
||||
d_map_base[d_PROG_MEMS_ADDR] = LOCAL_CODE_FPGA_CLEAR_ADDRESS_COUNTER;
|
||||
for (k = 0; k < d_code_length_chips * d_code_samples_per_chip; k++)
|
||||
{
|
||||
//if (d_local_code_in[k] == 1)
|
||||
if (d_ca_codes[((int(d_code_length)) * (PRN - 1)) + k] == 1)
|
||||
if (d_data_codes[((int(d_code_length_chips)) * d_code_samples_per_chip * (PRN - 1)) + k] == 1)
|
||||
{
|
||||
code_chip = 1;
|
||||
}
|
||||
@ -288,51 +459,95 @@ void fpga_multicorrelator_8sc::fpga_configure_tracking_gps_local_code(int PRN)
|
||||
{
|
||||
code_chip = 0;
|
||||
}
|
||||
//printf("%d %d | ", d_data_codes, code_chip);
|
||||
// copy the local code to the FPGA memory one by one
|
||||
d_map_base[11] = LOCAL_CODE_FPGA_ENABLE_WRITE_MEMORY
|
||||
| code_chip | select_fpga_correlator;
|
||||
d_map_base[d_PROG_MEMS_ADDR] = LOCAL_CODE_FPGA_ENABLE_WRITE_MEMORY | code_chip | select_pilot_corelator;
|
||||
}
|
||||
select_fpga_correlator = select_fpga_correlator
|
||||
+ LOCAL_CODE_FPGA_CORRELATOR_SELECT_COUNT;
|
||||
}
|
||||
//printf("\n");
|
||||
}
|
||||
|
||||
|
||||
void fpga_multicorrelator_8sc::fpga_compute_code_shift_parameters(void)
|
||||
{
|
||||
float temp_calculation;
|
||||
int i;
|
||||
int32_t i;
|
||||
|
||||
//printf("ppp d_rem_code_phase_chips = %f\n", d_rem_code_phase_chips);
|
||||
for (i = 0; i < d_n_correlators; i++)
|
||||
{
|
||||
//printf("ppp d_shifts_chips %d = %f\n", i, d_shifts_chips[i]);
|
||||
//printf("ppp d_code_samples_per_chip = %d\n", d_code_samples_per_chip);
|
||||
temp_calculation = floor(
|
||||
d_shifts_chips[i] - d_rem_code_phase_chips);
|
||||
|
||||
d_shifts_chips[i] - d_rem_code_phase_chips);
|
||||
|
||||
//printf("ppp d_rem_code_phase_chips = %f\n", d_rem_code_phase_chips);
|
||||
//printf("ppp temp calculation %d = %f ================================ \n", i, temp_calculation);
|
||||
if (temp_calculation < 0)
|
||||
{
|
||||
temp_calculation = temp_calculation + d_code_length_chips; // % operator does not work as in Matlab with negative numbers
|
||||
temp_calculation = temp_calculation + (d_code_length_chips * d_code_samples_per_chip); // % operator does not work as in Matlab with negative numbers
|
||||
}
|
||||
d_initial_index[i] = static_cast<unsigned>( (static_cast<int>(temp_calculation)) % d_code_length_chips);
|
||||
//printf("ppp d_rem_code_phase_chips = %f\n", d_rem_code_phase_chips);
|
||||
//printf("ppp temp calculation %d = %f ================================ \n", i, temp_calculation);
|
||||
d_initial_index[i] = static_cast<uint32_t>((static_cast<int32_t>(temp_calculation)) % (d_code_length_chips * d_code_samples_per_chip));
|
||||
//printf("ppp d_initial_index %d = %d\n", i, d_initial_index[i]);
|
||||
temp_calculation = fmod(d_shifts_chips[i] - d_rem_code_phase_chips,
|
||||
1.0);
|
||||
1.0);
|
||||
//printf("ppp fmod %d = fmod(%f, 1) = %f\n", i, d_shifts_chips[i] - d_rem_code_phase_chips, temp_calculation);
|
||||
if (temp_calculation < 0)
|
||||
{
|
||||
temp_calculation = temp_calculation + 1.0; // fmod operator does not work as in Matlab with negative numbers
|
||||
temp_calculation = temp_calculation + 1.0; // fmod operator does not work as in Matlab with negative numbers
|
||||
}
|
||||
d_initial_interp_counter[i] = static_cast<unsigned>( floor( MAX_CODE_RESAMPLER_COUNTER * temp_calculation));
|
||||
|
||||
d_initial_interp_counter[i] = static_cast<uint32_t>(floor(MAX_CODE_RESAMPLER_COUNTER * temp_calculation));
|
||||
//printf("ppp d_initial_interp_counter %d = %d\n", i, d_initial_interp_counter[i]);
|
||||
//printf("MAX_CODE_RESAMPLER_COUNTER = %d\n", MAX_CODE_RESAMPLER_COUNTER);
|
||||
}
|
||||
if (d_track_pilot)
|
||||
{
|
||||
//printf("tracking pilot !!!!!!!!!!!!!!!!\n");
|
||||
temp_calculation = floor(
|
||||
d_prompt_data_shift[0] - d_rem_code_phase_chips);
|
||||
|
||||
if (temp_calculation < 0)
|
||||
{
|
||||
temp_calculation = temp_calculation + (d_code_length_chips * d_code_samples_per_chip); // % operator does not work as in Matlab with negative numbers
|
||||
}
|
||||
d_initial_index[d_n_correlators] = static_cast<uint32_t>((static_cast<int32_t>(temp_calculation)) % (d_code_length_chips * d_code_samples_per_chip));
|
||||
temp_calculation = fmod(d_prompt_data_shift[0] - d_rem_code_phase_chips,
|
||||
1.0);
|
||||
if (temp_calculation < 0)
|
||||
{
|
||||
temp_calculation = temp_calculation + 1.0; // fmod operator does not work as in Matlab with negative numbers
|
||||
}
|
||||
d_initial_interp_counter[d_n_correlators] = static_cast<uint32_t>(floor(MAX_CODE_RESAMPLER_COUNTER * temp_calculation));
|
||||
}
|
||||
//while(1);
|
||||
}
|
||||
|
||||
|
||||
void fpga_multicorrelator_8sc::fpga_configure_code_parameters_in_fpga(void)
|
||||
{
|
||||
int i;
|
||||
int32_t i;
|
||||
for (i = 0; i < d_n_correlators; i++)
|
||||
{
|
||||
d_map_base[1 + i] = d_initial_index[i];
|
||||
d_map_base[1 + d_n_correlators + i] = d_initial_interp_counter[i];
|
||||
//printf("www writing d map base %d = d_initial_index %d = %d\n", d_INITIAL_INDEX_REG_BASE_ADDR + i, i, d_initial_index[i]);
|
||||
d_map_base[d_INITIAL_INDEX_REG_BASE_ADDR + i] = d_initial_index[i];
|
||||
//d_map_base[1 + d_n_correlators + i] = d_initial_interp_counter[i];
|
||||
//printf("www writing d map base %d = d_initial_interp_counter %d = %d\n", d_INITIAL_INTERP_COUNTER_REG_BASE_ADDR + i, i, d_initial_interp_counter[i]);
|
||||
d_map_base[d_INITIAL_INTERP_COUNTER_REG_BASE_ADDR + i] = d_initial_interp_counter[i];
|
||||
}
|
||||
d_map_base[8] = d_code_length_chips - 1; // number of samples - 1
|
||||
if (d_track_pilot)
|
||||
{
|
||||
//printf("www writing d map base %d = d_initial_index %d = %d\n", d_INITIAL_INDEX_REG_BASE_ADDR + d_n_correlators, d_n_correlators, d_initial_index[d_n_correlators]);
|
||||
d_map_base[d_INITIAL_INDEX_REG_BASE_ADDR + d_n_correlators] = d_initial_index[d_n_correlators];
|
||||
//d_map_base[1 + d_n_correlators + i] = d_initial_interp_counter[i];
|
||||
//printf("www writing d map base %d = d_initial_interp_counter %d = %d\n", d_INITIAL_INTERP_COUNTER_REG_BASE_ADDR + d_n_correlators, d_n_correlators, d_initial_interp_counter[d_n_correlators]);
|
||||
d_map_base[d_INITIAL_INTERP_COUNTER_REG_BASE_ADDR + d_n_correlators] = d_initial_interp_counter[d_n_correlators];
|
||||
}
|
||||
|
||||
//printf("www writing d map base %d = d_code_length_chips*d_code_samples_per_chip - 1 = %d\n", d_CODE_LENGTH_MINUS_1_REG_ADDR, (d_code_length_chips*d_code_samples_per_chip) - 1);
|
||||
d_map_base[d_CODE_LENGTH_MINUS_1_REG_ADDR] = (d_code_length_chips * d_code_samples_per_chip) - 1; // number of samples - 1
|
||||
}
|
||||
|
||||
|
||||
@ -340,78 +555,148 @@ void fpga_multicorrelator_8sc::fpga_compute_signal_parameters_in_fpga(void)
|
||||
{
|
||||
float d_rem_carrier_phase_in_rad_temp;
|
||||
|
||||
d_code_phase_step_chips_num = static_cast<unsigned>( roundf(MAX_CODE_RESAMPLER_COUNTER * d_code_phase_step_chips));
|
||||
d_code_phase_step_chips_num = static_cast<uint32_t>(roundf(MAX_CODE_RESAMPLER_COUNTER * d_code_phase_step_chips));
|
||||
if (d_code_phase_step_chips > 1.0)
|
||||
{
|
||||
printf("Warning : d_code_phase_step_chips = %f cannot be bigger than one\n", d_code_phase_step_chips);
|
||||
}
|
||||
|
||||
//printf("d_rem_carrier_phase_in_rad = %f\n", d_rem_carrier_phase_in_rad);
|
||||
|
||||
if (d_rem_carrier_phase_in_rad > M_PI)
|
||||
{
|
||||
d_rem_carrier_phase_in_rad_temp = -2 * M_PI
|
||||
+ d_rem_carrier_phase_in_rad;
|
||||
d_rem_carrier_phase_in_rad_temp = -2 * M_PI + d_rem_carrier_phase_in_rad;
|
||||
}
|
||||
else if (d_rem_carrier_phase_in_rad < -M_PI)
|
||||
{
|
||||
d_rem_carrier_phase_in_rad_temp = 2 * M_PI
|
||||
+ d_rem_carrier_phase_in_rad;
|
||||
d_rem_carrier_phase_in_rad_temp = 2 * M_PI + d_rem_carrier_phase_in_rad;
|
||||
}
|
||||
else
|
||||
{
|
||||
d_rem_carrier_phase_in_rad_temp = d_rem_carrier_phase_in_rad;
|
||||
}
|
||||
d_rem_carr_phase_rad_int = static_cast<int>( roundf(
|
||||
(fabs(d_rem_carrier_phase_in_rad_temp) / M_PI)
|
||||
* pow(2, PHASE_CARR_NBITS_FRAC)));
|
||||
d_rem_carr_phase_rad_int = static_cast<int32_t>(roundf(
|
||||
(fabs(d_rem_carrier_phase_in_rad_temp) / M_PI) * pow(2, PHASE_CARR_NBITS_FRAC)));
|
||||
if (d_rem_carrier_phase_in_rad_temp < 0)
|
||||
{
|
||||
d_rem_carr_phase_rad_int = -d_rem_carr_phase_rad_int;
|
||||
}
|
||||
d_phase_step_rad_int = static_cast<int>( roundf(
|
||||
(fabs(d_phase_step_rad) / M_PI) * pow(2, PHASE_CARR_NBITS_FRAC))); // the FPGA accepts a range for the phase step between -pi and +pi
|
||||
d_phase_step_rad_int = static_cast<int32_t>(roundf(
|
||||
(fabs(d_phase_step_rad) / M_PI) * pow(2, PHASE_CARR_NBITS_FRAC))); // the FPGA accepts a range for the phase step between -pi and +pi
|
||||
|
||||
//printf("d_phase_step_rad_int = %d\n", d_phase_step_rad_int);
|
||||
if (d_phase_step_rad < 0)
|
||||
{
|
||||
d_phase_step_rad_int = -d_phase_step_rad_int;
|
||||
}
|
||||
|
||||
//printf("d_phase_step_rad_int = %d\n", d_phase_step_rad_int);
|
||||
}
|
||||
|
||||
|
||||
void fpga_multicorrelator_8sc::fpga_configure_signal_parameters_in_fpga(void)
|
||||
{
|
||||
d_map_base[0] = d_code_phase_step_chips_num;
|
||||
d_map_base[7] = d_correlator_length_samples - 1;
|
||||
d_map_base[9] = d_rem_carr_phase_rad_int;
|
||||
d_map_base[10] = d_phase_step_rad_int;
|
||||
//printf("www d map base %d = d_code_phase_step_chips_num = %d\n", d_CODE_PHASE_STEP_CHIPS_NUM_REG_ADDR, d_code_phase_step_chips_num);
|
||||
d_map_base[d_CODE_PHASE_STEP_CHIPS_NUM_REG_ADDR] = d_code_phase_step_chips_num;
|
||||
|
||||
//printf("www d map base %d = d_correlator_length_samples - 1 = %d\n", d_NSAMPLES_MINUS_1_REG_ADDR, d_correlator_length_samples - 1);
|
||||
d_map_base[d_NSAMPLES_MINUS_1_REG_ADDR] = d_correlator_length_samples - 1;
|
||||
|
||||
//printf("www d map base %d = d_rem_carr_phase_rad_int = %d\n", d_REM_CARR_PHASE_RAD_REG_ADDR, d_rem_carr_phase_rad_int);
|
||||
d_map_base[d_REM_CARR_PHASE_RAD_REG_ADDR] = d_rem_carr_phase_rad_int;
|
||||
|
||||
//printf("www d map base %d = d_phase_step_rad_int = %d\n", d_PHASE_STEP_RAD_REG_ADDR, d_phase_step_rad_int);
|
||||
d_map_base[d_PHASE_STEP_RAD_REG_ADDR] = d_phase_step_rad_int;
|
||||
}
|
||||
|
||||
|
||||
void fpga_multicorrelator_8sc::fpga_launch_multicorrelator_fpga(void)
|
||||
{
|
||||
// enable interrupts
|
||||
int reenable = 1;
|
||||
write(d_device_descriptor, reinterpret_cast<void*>(&reenable), sizeof(int));
|
||||
int32_t reenable = 1;
|
||||
write(d_device_descriptor, reinterpret_cast<void *>(&reenable), sizeof(int32_t));
|
||||
|
||||
// writing 1 to reg 14 launches the tracking
|
||||
d_map_base[14] = 1;
|
||||
// writing 1 to reg 14 launches the tracking
|
||||
//printf("www writing 1 to d map base %d = start flag\n", d_START_FLAG_ADDR);
|
||||
d_map_base[d_START_FLAG_ADDR] = 1;
|
||||
//while(1);
|
||||
}
|
||||
|
||||
|
||||
void fpga_multicorrelator_8sc::read_tracking_gps_results(void)
|
||||
{
|
||||
int readval_real;
|
||||
int readval_imag;
|
||||
int k;
|
||||
int32_t readval_real;
|
||||
int32_t readval_imag;
|
||||
int32_t k;
|
||||
|
||||
//printf("www reading trk results\n");
|
||||
for (k = 0; k < d_n_correlators; k++)
|
||||
{
|
||||
readval_real = d_map_base[1 + k];
|
||||
if (readval_real >= 1048576) // 0x100000 (21 bits two's complement)
|
||||
{
|
||||
readval_real = -2097152 + readval_real;
|
||||
}
|
||||
readval_real = d_map_base[d_RESULT_REG_REAL_BASE_ADDR + k];
|
||||
//printf("read real before checking d map base %d = %d\n", d_RESULT_REG_BASE_ADDR + k, readval_real);
|
||||
//// if (readval_real > debug_max_readval_real[k])
|
||||
//// {
|
||||
//// debug_max_readval_real[k] = readval_real;
|
||||
//// }
|
||||
// if (readval_real >= d_result_SAT_value) // 0x100000 (21 bits two's complement)
|
||||
// {
|
||||
// readval_real = -2*d_result_SAT_value + readval_real;
|
||||
// }
|
||||
//// if (readval_real > debug_max_readval_real_after_check[k])
|
||||
//// {
|
||||
//// debug_max_readval_real_after_check[k] = readval_real;
|
||||
//// }
|
||||
//printf("read real d map base %d = %d\n", d_RESULT_REG_BASE_ADDR + k, readval_real);
|
||||
readval_imag = d_map_base[d_RESULT_REG_IMAG_BASE_ADDR + k];
|
||||
//printf("read imag before checking d map base %d = %d\n", d_RESULT_REG_BASE_ADDR + k, readval_imag);
|
||||
//// if (readval_imag > debug_max_readval_imag[k])
|
||||
//// {
|
||||
//// debug_max_readval_imag[k] = readval_imag;
|
||||
//// }
|
||||
//
|
||||
// if (readval_imag >= d_result_SAT_value) // 0x100000 (21 bits two's complement)
|
||||
// {
|
||||
// readval_imag = -2*d_result_SAT_value + readval_imag;
|
||||
// }
|
||||
//// if (readval_imag > debug_max_readval_imag_after_check[k])
|
||||
//// {
|
||||
//// debug_max_readval_imag_after_check[k] = readval_real;
|
||||
//// }
|
||||
//printf("read imag d map base %d = %d\n", d_RESULT_REG_BASE_ADDR + k, readval_imag);
|
||||
d_corr_out[k] = gr_complex(readval_real, readval_imag);
|
||||
|
||||
readval_imag = d_map_base[1 + d_n_correlators + k];
|
||||
if (readval_imag >= 1048576) // 0x100000 (21 bits two's complement)
|
||||
{
|
||||
readval_imag = -2097152 + readval_imag;
|
||||
}
|
||||
d_corr_out[k] = gr_complex(readval_real,readval_imag);
|
||||
// if (printcounter > 100)
|
||||
// {
|
||||
// printcounter = 0;
|
||||
// for (int32_t ll=0;ll<d_n_correlators;ll++)
|
||||
// {
|
||||
// printf("debug_max_readval_real %d = %d\n", ll, debug_max_readval_real[ll]);
|
||||
// printf("debug_max_readval_imag %d = %d\n", ll, debug_max_readval_imag[ll]);
|
||||
// printf("debug_max_readval_real_%d after_check = %d\n", ll, debug_max_readval_real_after_check[ll]);
|
||||
// printf("debug_max_readval_imag_%d after_check = %d\n", ll, debug_max_readval_imag_after_check[ll]);
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// printcounter = printcounter + 1;
|
||||
// }
|
||||
}
|
||||
if (d_track_pilot)
|
||||
{
|
||||
//printf("reading pilot !!!\n");
|
||||
readval_real = d_map_base[d_RESULT_REG_DATA_REAL_BASE_ADDR];
|
||||
// if (readval_real >= d_result_SAT_value) // 0x100000 (21 bits two's complement)
|
||||
// {
|
||||
// readval_real = -2*d_result_SAT_value + readval_real;
|
||||
// }
|
||||
|
||||
readval_imag = d_map_base[d_RESULT_REG_DATA_IMAG_BASE_ADDR];
|
||||
// if (readval_imag >= d_result_SAT_value) // 0x100000 (21 bits two's complement)
|
||||
// {
|
||||
// readval_imag = -2*d_result_SAT_value + readval_imag;
|
||||
// }
|
||||
d_Prompt_Data[0] = gr_complex(readval_real, readval_imag);
|
||||
}
|
||||
}
|
||||
|
||||
@ -419,40 +704,38 @@ void fpga_multicorrelator_8sc::read_tracking_gps_results(void)
|
||||
void fpga_multicorrelator_8sc::unlock_channel(void)
|
||||
{
|
||||
// unlock the channel to let the next samples go through
|
||||
d_map_base[12] = 1; // unlock the channel
|
||||
//printf("www writing 1 to d map base %d = drop samples\n", d_DROP_SAMPLES_REG_ADDR);
|
||||
d_map_base[d_DROP_SAMPLES_REG_ADDR] = 1; // unlock the channel
|
||||
}
|
||||
|
||||
void fpga_multicorrelator_8sc::close_device()
|
||||
{
|
||||
unsigned * aux = const_cast<unsigned*>(d_map_base);
|
||||
if (munmap(static_cast<void*>(aux), PAGE_SIZE) == -1)
|
||||
uint32_t *aux = const_cast<uint32_t *>(d_map_base);
|
||||
if (munmap(static_cast<void *>(aux), PAGE_SIZE) == -1)
|
||||
{
|
||||
printf("Failed to unmap memory uio\n");
|
||||
}
|
||||
/* else
|
||||
{
|
||||
printf("memory uio unmapped\n");
|
||||
} */
|
||||
close(d_device_descriptor);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void fpga_multicorrelator_8sc::lock_channel(void)
|
||||
{
|
||||
// lock the channel for processing
|
||||
d_map_base[12] = 0; // lock the channel
|
||||
//printf("www writing 0 to d map base %d = drop samples\n", d_DROP_SAMPLES_REG_ADDR);
|
||||
d_map_base[d_DROP_SAMPLES_REG_ADDR] = 0; // lock the channel
|
||||
}
|
||||
|
||||
void fpga_multicorrelator_8sc::read_sample_counters(int *sample_counter, int *secondary_sample_counter, int *counter_corr_0_in, int *counter_corr_0_out)
|
||||
{
|
||||
*sample_counter = d_map_base[11];
|
||||
*secondary_sample_counter = d_map_base[8];
|
||||
*counter_corr_0_in = d_map_base[10];
|
||||
*counter_corr_0_out = d_map_base[9];
|
||||
|
||||
}
|
||||
//void fpga_multicorrelator_8sc::read_sample_counters(int32_t *sample_counter, int32_t *secondary_sample_counter, int32_t *counter_corr_0_in, int32_t *counter_corr_0_out)
|
||||
//{
|
||||
// *sample_counter = d_map_base[11];
|
||||
// *secondary_sample_counter = d_map_base[8];
|
||||
// *counter_corr_0_in = d_map_base[10];
|
||||
// *counter_corr_0_out = d_map_base[9];
|
||||
//
|
||||
//}
|
||||
|
||||
void fpga_multicorrelator_8sc::reset_multicorrelator(void)
|
||||
{
|
||||
d_map_base[14] = 2; // writing a 2 to d_map_base[14] resets the multicorrelator
|
||||
}
|
||||
//void fpga_multicorrelator_8sc::reset_multicorrelator(void)
|
||||
//{
|
||||
// d_map_base[14] = 2; // writing a 2 to d_map_base[14] resets the multicorrelator
|
||||
//}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*!
|
||||
* \file fpga_multicorrelator_8sc.h
|
||||
* \brief High optimized FPGA vector correlator class for lv_16sc_t (short int complex)
|
||||
* \brief High optimized FPGA vector correlator class for lv_16sc_t (short int32_t complex)
|
||||
* \authors <ul>
|
||||
* <li> Marc Majoral, 2017. mmajoral(at)cttc.cat
|
||||
* <li> Javier Arribas, 2016. jarribas(at)cttc.es
|
||||
@ -11,7 +11,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
|
||||
@ -29,7 +29,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 <https://www.gnu.org/licenses/>.
|
||||
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
@ -39,6 +39,7 @@
|
||||
|
||||
#include <gnuradio/block.h>
|
||||
#include <volk_gnsssdr/volk_gnsssdr.h>
|
||||
#include <cstdint>
|
||||
|
||||
#define MAX_LENGTH_DEVICEIO_NAME 50
|
||||
|
||||
@ -48,84 +49,121 @@
|
||||
class fpga_multicorrelator_8sc
|
||||
{
|
||||
public:
|
||||
fpga_multicorrelator_8sc(int n_correlators, std::string device_name,
|
||||
unsigned int device_base, int *ca_codes, unsigned int code_length);
|
||||
fpga_multicorrelator_8sc(int32_t n_correlators, std::string device_name,
|
||||
uint32_t device_base, int32_t *ca_codes, int32_t *data_codes, uint32_t code_length_chips, bool track_pilot, uint32_t multicorr_type, uint32_t code_samples_per_chip);
|
||||
~fpga_multicorrelator_8sc();
|
||||
//bool set_output_vectors(gr_complex* corr_out);
|
||||
void set_output_vectors(gr_complex *corr_out);
|
||||
void set_output_vectors(gr_complex *corr_out, gr_complex *Prompt_Data);
|
||||
// bool set_local_code_and_taps(
|
||||
// int code_length_chips, const int* local_code_in,
|
||||
// float *shifts_chips, int PRN);
|
||||
// int32_t code_length_chips, const int* local_code_in,
|
||||
// float *shifts_chips, int32_t PRN);
|
||||
//bool set_local_code_and_taps(
|
||||
void set_local_code_and_taps(
|
||||
int code_length_chips,
|
||||
float *shifts_chips, int PRN);
|
||||
// int32_t code_length_chips,
|
||||
float *shifts_chips, float *prompt_data_shift, int32_t PRN);
|
||||
//bool set_output_vectors(lv_16sc_t* corr_out);
|
||||
void update_local_code(float rem_code_phase_chips);
|
||||
//bool Carrier_wipeoff_multicorrelator_resampler(
|
||||
void Carrier_wipeoff_multicorrelator_resampler(
|
||||
float rem_carrier_phase_in_rad, float phase_step_rad,
|
||||
float rem_code_phase_chips, float code_phase_step_chips,
|
||||
int signal_length_samples);
|
||||
int32_t signal_length_samples);
|
||||
bool free();
|
||||
void set_channel(unsigned int channel);
|
||||
void set_initial_sample(int samples_offset);
|
||||
int read_sample_counter();
|
||||
void set_channel(uint32_t channel);
|
||||
void set_initial_sample(uint64_t samples_offset);
|
||||
uint64_t read_sample_counter();
|
||||
void lock_channel(void);
|
||||
void unlock_channel(void);
|
||||
void read_sample_counters(int *sample_counter, int *secondary_sample_counter, int *counter_corr_0_in, int *counter_corr_0_out); // debug
|
||||
|
||||
//void read_sample_counters(int32_t *sample_counter, int32_t *secondary_sample_counter, int32_t *counter_corr_0_in, int32_t *counter_corr_0_out); // debug
|
||||
|
||||
private:
|
||||
//const int *d_local_code_in;
|
||||
//const int32_t *d_local_code_in;
|
||||
gr_complex *d_corr_out;
|
||||
gr_complex *d_Prompt_Data;
|
||||
float *d_shifts_chips;
|
||||
int d_code_length_chips;
|
||||
int d_n_correlators;
|
||||
float *d_prompt_data_shift;
|
||||
int32_t d_code_length_chips;
|
||||
int32_t d_n_correlators;
|
||||
|
||||
// data related to the hardware module and the driver
|
||||
int d_device_descriptor; // driver descriptor
|
||||
volatile unsigned *d_map_base; // driver memory map
|
||||
int32_t d_device_descriptor; // driver descriptor
|
||||
volatile uint32_t *d_map_base; // driver memory map
|
||||
|
||||
// configuration data received from the interface
|
||||
unsigned int d_channel; // channel number
|
||||
unsigned d_correlator_length_samples;
|
||||
uint32_t d_channel; // channel number
|
||||
uint32_t d_ncorrelators; // number of correlators
|
||||
uint32_t d_correlator_length_samples;
|
||||
float d_rem_code_phase_chips;
|
||||
float d_code_phase_step_chips;
|
||||
float d_rem_carrier_phase_in_rad;
|
||||
float d_phase_step_rad;
|
||||
|
||||
// configuration data computed in the format that the FPGA expects
|
||||
unsigned *d_initial_index;
|
||||
unsigned *d_initial_interp_counter;
|
||||
unsigned d_code_phase_step_chips_num;
|
||||
int d_rem_carr_phase_rad_int;
|
||||
int d_phase_step_rad_int;
|
||||
unsigned d_initial_sample_counter;
|
||||
uint32_t *d_initial_index;
|
||||
uint32_t *d_initial_interp_counter;
|
||||
uint32_t d_code_phase_step_chips_num;
|
||||
int32_t d_rem_carr_phase_rad_int;
|
||||
int32_t d_phase_step_rad_int;
|
||||
uint64_t d_initial_sample_counter;
|
||||
|
||||
// driver
|
||||
std::string d_device_name;
|
||||
unsigned int d_device_base;
|
||||
uint32_t d_device_base;
|
||||
|
||||
int32_t *d_ca_codes;
|
||||
int32_t *d_data_codes;
|
||||
|
||||
int *d_ca_codes;
|
||||
//uint32_t d_code_length; // nominal number of chips
|
||||
|
||||
unsigned int d_code_length; // nominal number of chips
|
||||
uint32_t d_code_samples_per_chip;
|
||||
bool d_track_pilot;
|
||||
|
||||
uint32_t d_multicorr_type;
|
||||
|
||||
// register addresses
|
||||
// write-only regs
|
||||
uint32_t d_CODE_PHASE_STEP_CHIPS_NUM_REG_ADDR;
|
||||
uint32_t d_INITIAL_INDEX_REG_BASE_ADDR;
|
||||
uint32_t d_INITIAL_INTERP_COUNTER_REG_BASE_ADDR;
|
||||
uint32_t d_NSAMPLES_MINUS_1_REG_ADDR;
|
||||
uint32_t d_CODE_LENGTH_MINUS_1_REG_ADDR;
|
||||
uint32_t d_REM_CARR_PHASE_RAD_REG_ADDR;
|
||||
uint32_t d_PHASE_STEP_RAD_REG_ADDR;
|
||||
uint32_t d_PROG_MEMS_ADDR;
|
||||
uint32_t d_DROP_SAMPLES_REG_ADDR;
|
||||
uint32_t d_INITIAL_COUNTER_VALUE_REG_ADDR_LSW;
|
||||
uint32_t d_INITIAL_COUNTER_VALUE_REG_ADDR_MSW;
|
||||
uint32_t d_START_FLAG_ADDR;
|
||||
// read-write regs
|
||||
uint32_t d_TEST_REG_ADDR;
|
||||
// read-only regs
|
||||
uint32_t d_RESULT_REG_REAL_BASE_ADDR;
|
||||
uint32_t d_RESULT_REG_IMAG_BASE_ADDR;
|
||||
uint32_t d_RESULT_REG_DATA_REAL_BASE_ADDR;
|
||||
uint32_t d_RESULT_REG_DATA_IMAG_BASE_ADDR;
|
||||
uint32_t d_SAMPLE_COUNTER_REG_ADDR_LSW;
|
||||
uint32_t d_SAMPLE_COUNTER_REG_ADDR_MSW;
|
||||
|
||||
// private functions
|
||||
unsigned fpga_acquisition_test_register(unsigned writeval);
|
||||
void fpga_configure_tracking_gps_local_code(int PRN);
|
||||
uint32_t fpga_acquisition_test_register(uint32_t writeval);
|
||||
void fpga_configure_tracking_gps_local_code(int32_t PRN);
|
||||
void fpga_compute_code_shift_parameters(void);
|
||||
void fpga_configure_code_parameters_in_fpga(void);
|
||||
void fpga_compute_signal_parameters_in_fpga(void);
|
||||
void fpga_configure_signal_parameters_in_fpga(void);
|
||||
void fpga_launch_multicorrelator_fpga(void);
|
||||
void read_tracking_gps_results(void);
|
||||
void reset_multicorrelator(void);
|
||||
//void reset_multicorrelator(void);
|
||||
void close_device(void);
|
||||
|
||||
// debug
|
||||
//unsigned int first_time = 1;
|
||||
uint32_t d_result_SAT_value;
|
||||
|
||||
int32_t debug_max_readval_real[5] = {0, 0, 0, 0, 0};
|
||||
int32_t debug_max_readval_imag[5] = {0, 0, 0, 0, 0};
|
||||
|
||||
int32_t debug_max_readval_real_after_check[5] = {0, 0, 0, 0, 0};
|
||||
int32_t debug_max_readval_imag_after_check[5] = {0, 0, 0, 0, 0};
|
||||
int32_t printcounter = 0;
|
||||
};
|
||||
|
||||
#endif /* GNSS_SDR_FPGA_MULTICORRELATOR_H_ */
|
||||
|
@ -4,6 +4,7 @@
|
||||
* \author Carlos Aviles, 2010. carlos.avilesr(at)googlemail.com
|
||||
* Luis Esteve, 2012. luis(at)epsilon-formacion.com
|
||||
* Javier Arribas, 2011. jarribas(at)cttc.es
|
||||
* Marc Majoral, 2018. mmajoral(at)cttc.es
|
||||
*
|
||||
* This class encapsulates the complexity behind the instantiation
|
||||
* of GNSS blocks.
|
||||
@ -110,7 +111,15 @@
|
||||
|
||||
#if ENABLE_FPGA
|
||||
#include "gps_l1_ca_pcps_acquisition_fpga.h"
|
||||
#include "gps_l2_m_pcps_acquisition_fpga.h"
|
||||
#include "galileo_e1_pcps_ambiguous_acquisition_fpga.h"
|
||||
#include "galileo_e5a_pcps_acquisition_fpga.h"
|
||||
#include "gps_l5i_pcps_acquisition_fpga.h"
|
||||
#include "gps_l1_ca_dll_pll_tracking_fpga.h"
|
||||
#include "gps_l2_m_dll_pll_tracking_fpga.h"
|
||||
#include "galileo_e1_dll_pll_veml_tracking_fpga.h"
|
||||
#include "galileo_e5a_dll_pll_tracking_fpga.h"
|
||||
#include "gps_l5_dll_pll_tracking_fpga.h"
|
||||
#endif
|
||||
|
||||
#if OPENCL_BLOCKS
|
||||
@ -163,7 +172,11 @@ using google::LogMessage;
|
||||
|
||||
|
||||
GNSSBlockFactory::GNSSBlockFactory() {}
|
||||
|
||||
|
||||
GNSSBlockFactory::~GNSSBlockFactory() {}
|
||||
|
||||
|
||||
std::unique_ptr<GNSSBlockInterface> GNSSBlockFactory::GetSignalSource(
|
||||
std::shared_ptr<ConfigurationInterface> configuration, gr::msg_queue::sptr queue, int ID)
|
||||
{
|
||||
@ -1389,18 +1402,42 @@ std::unique_ptr<GNSSBlockInterface> GNSSBlockFactory::GetBlock(
|
||||
out_streams));
|
||||
block = std::move(block_);
|
||||
}
|
||||
#if ENABLE_FPGA
|
||||
else if (implementation.compare("GPS_L2_M_PCPS_Acquisition_Fpga") == 0)
|
||||
{
|
||||
std::unique_ptr<GNSSBlockInterface> block_(new GpsL2MPcpsAcquisitionFpga(configuration.get(), role, in_streams,
|
||||
out_streams));
|
||||
block = std::move(block_);
|
||||
}
|
||||
#endif
|
||||
else if (implementation.compare("GPS_L5i_PCPS_Acquisition") == 0)
|
||||
{
|
||||
std::unique_ptr<AcquisitionInterface> block_(new GpsL5iPcpsAcquisition(configuration.get(), role, in_streams,
|
||||
out_streams));
|
||||
block = std::move(block_);
|
||||
}
|
||||
#if ENABLE_FPGA
|
||||
else if (implementation.compare("GPS_L5i_PCPS_Acquisition_Fpga") == 0)
|
||||
{
|
||||
std::unique_ptr<AcquisitionInterface> block_(new GpsL5iPcpsAcquisitionFpga(configuration.get(), role, in_streams,
|
||||
out_streams));
|
||||
block = std::move(block_);
|
||||
}
|
||||
#endif
|
||||
else if (implementation.compare("Galileo_E1_PCPS_Ambiguous_Acquisition") == 0)
|
||||
{
|
||||
std::unique_ptr<GNSSBlockInterface> block_(new GalileoE1PcpsAmbiguousAcquisition(configuration.get(), role, in_streams,
|
||||
out_streams));
|
||||
block = std::move(block_);
|
||||
}
|
||||
#if ENABLE_FPGA
|
||||
else if (implementation.compare("Galileo_E1_PCPS_Ambiguous_Acquisition_Fpga") == 0)
|
||||
{
|
||||
std::unique_ptr<GNSSBlockInterface> block_(new GalileoE1PcpsAmbiguousAcquisitionFpga(configuration.get(), role, in_streams,
|
||||
out_streams));
|
||||
block = std::move(block_);
|
||||
}
|
||||
#endif
|
||||
else if (implementation.compare("Galileo_E1_PCPS_8ms_Ambiguous_Acquisition") == 0)
|
||||
{
|
||||
std::unique_ptr<GNSSBlockInterface> block_(new GalileoE1Pcps8msAmbiguousAcquisition(configuration.get(), role, in_streams,
|
||||
@ -1431,6 +1468,14 @@ std::unique_ptr<GNSSBlockInterface> GNSSBlockFactory::GetBlock(
|
||||
out_streams));
|
||||
block = std::move(block_);
|
||||
}
|
||||
#if ENABLE_FPGA
|
||||
else if (implementation.compare("Galileo_E5a_Pcps_Acquisition_Fpga") == 0)
|
||||
{
|
||||
std::unique_ptr<GNSSBlockInterface> block_(new GalileoE5aPcpsAcquisitionFpga(configuration.get(), role, in_streams,
|
||||
out_streams));
|
||||
block = std::move(block_);
|
||||
}
|
||||
#endif
|
||||
else if (implementation.compare("Galileo_E1_PCPS_QuickSync_Ambiguous_Acquisition") == 0)
|
||||
{
|
||||
std::unique_ptr<GNSSBlockInterface> block_(new GalileoE1PcpsQuickSyncAmbiguousAcquisition(configuration.get(), role, in_streams,
|
||||
@ -1482,12 +1527,28 @@ std::unique_ptr<GNSSBlockInterface> GNSSBlockFactory::GetBlock(
|
||||
out_streams));
|
||||
block = std::move(block_);
|
||||
}
|
||||
#if ENABLE_FPGA
|
||||
else if (implementation.compare("GPS_L2_M_DLL_PLL_Tracking_Fpga") == 0)
|
||||
{
|
||||
std::unique_ptr<GNSSBlockInterface> block_(new GpsL2MDllPllTrackingFpga(configuration.get(), role, in_streams,
|
||||
out_streams));
|
||||
block = std::move(block_);
|
||||
}
|
||||
#endif
|
||||
else if ((implementation.compare("GPS_L5i_DLL_PLL_Tracking") == 0) or (implementation.compare("GPS_L5_DLL_PLL_Tracking") == 0))
|
||||
{
|
||||
std::unique_ptr<GNSSBlockInterface> block_(new GpsL5DllPllTracking(configuration.get(), role, in_streams,
|
||||
out_streams));
|
||||
block = std::move(block_);
|
||||
}
|
||||
#if ENABLE_FPGA
|
||||
else if ((implementation.compare("GPS_L5i_DLL_PLL_Tracking_Fpga") == 0) or (implementation.compare("GPS_L5_DLL_PLL_Tracking_Fpga") == 0))
|
||||
{
|
||||
std::unique_ptr<GNSSBlockInterface> block_(new GpsL5DllPllTrackingFpga(configuration.get(), role, in_streams,
|
||||
out_streams));
|
||||
block = std::move(block_);
|
||||
}
|
||||
#endif
|
||||
#if CUDA_GPU_ACCEL
|
||||
else if (implementation.compare("GPS_L1_CA_DLL_PLL_Tracking_GPU") == 0)
|
||||
{
|
||||
@ -1502,6 +1563,14 @@ std::unique_ptr<GNSSBlockInterface> GNSSBlockFactory::GetBlock(
|
||||
out_streams));
|
||||
block = std::move(block_);
|
||||
}
|
||||
#if ENABLE_FPGA
|
||||
else if (implementation.compare("Galileo_E1_DLL_PLL_VEML_Tracking_Fpga") == 0)
|
||||
{
|
||||
std::unique_ptr<TrackingInterface> block_(new GalileoE1DllPllVemlTrackingFpga(configuration.get(), role, in_streams,
|
||||
out_streams));
|
||||
block = std::move(block_);
|
||||
}
|
||||
#endif
|
||||
else if (implementation.compare("Galileo_E1_TCP_CONNECTOR_Tracking") == 0)
|
||||
{
|
||||
std::unique_ptr<GNSSBlockInterface> block_(new GalileoE1TcpConnectorTracking(configuration.get(), role, in_streams,
|
||||
@ -1514,6 +1583,14 @@ std::unique_ptr<GNSSBlockInterface> GNSSBlockFactory::GetBlock(
|
||||
out_streams));
|
||||
block = std::move(block_);
|
||||
}
|
||||
#if ENABLE_FPGA
|
||||
else if (implementation.compare("Galileo_E5a_DLL_PLL_Tracking_Fpga") == 0)
|
||||
{
|
||||
std::unique_ptr<GNSSBlockInterface> block_(new GalileoE5aDllPllTrackingFpga(configuration.get(), role, in_streams,
|
||||
out_streams));
|
||||
block = std::move(block_);
|
||||
}
|
||||
#endif
|
||||
else if (implementation.compare("GLONASS_L1_CA_DLL_PLL_Tracking") == 0)
|
||||
{
|
||||
std::unique_ptr<GNSSBlockInterface> block_(new GlonassL1CaDllPllTracking(configuration.get(), role, in_streams,
|
||||
@ -1682,18 +1759,42 @@ std::unique_ptr<AcquisitionInterface> GNSSBlockFactory::GetAcqBlock(
|
||||
out_streams));
|
||||
block = std::move(block_);
|
||||
}
|
||||
#if ENABLE_FPGA
|
||||
else if (implementation.compare("GPS_L2_M_PCPS_Acquisition_Fpga") == 0)
|
||||
{
|
||||
std::unique_ptr<AcquisitionInterface> block_(new GpsL2MPcpsAcquisitionFpga(configuration.get(), role, in_streams,
|
||||
out_streams));
|
||||
block = std::move(block_);
|
||||
}
|
||||
#endif
|
||||
else if (implementation.compare("GPS_L5i_PCPS_Acquisition") == 0)
|
||||
{
|
||||
std::unique_ptr<AcquisitionInterface> block_(new GpsL5iPcpsAcquisition(configuration.get(), role, in_streams,
|
||||
out_streams));
|
||||
block = std::move(block_);
|
||||
}
|
||||
#if ENABLE_FPGA
|
||||
else if (implementation.compare("GPS_L5i_PCPS_Acquisition_Fpga") == 0)
|
||||
{
|
||||
std::unique_ptr<AcquisitionInterface> block_(new GpsL5iPcpsAcquisitionFpga(configuration.get(), role, in_streams,
|
||||
out_streams));
|
||||
block = std::move(block_);
|
||||
}
|
||||
#endif
|
||||
else if (implementation.compare("Galileo_E1_PCPS_Ambiguous_Acquisition") == 0)
|
||||
{
|
||||
std::unique_ptr<AcquisitionInterface> block_(new GalileoE1PcpsAmbiguousAcquisition(configuration.get(), role, in_streams,
|
||||
out_streams));
|
||||
block = std::move(block_);
|
||||
}
|
||||
#if ENABLE_FPGA
|
||||
else if (implementation.compare("Galileo_E1_PCPS_Ambiguous_Acquisition_Fpga") == 0)
|
||||
{
|
||||
std::unique_ptr<AcquisitionInterface> block_(new GalileoE1PcpsAmbiguousAcquisitionFpga(configuration.get(), role, in_streams,
|
||||
out_streams));
|
||||
block = std::move(block_);
|
||||
}
|
||||
#endif
|
||||
else if (implementation.compare("Galileo_E1_PCPS_8ms_Ambiguous_Acquisition") == 0)
|
||||
{
|
||||
std::unique_ptr<AcquisitionInterface> block_(new GalileoE1Pcps8msAmbiguousAcquisition(configuration.get(), role, in_streams,
|
||||
@ -1731,6 +1832,14 @@ std::unique_ptr<AcquisitionInterface> GNSSBlockFactory::GetAcqBlock(
|
||||
out_streams));
|
||||
block = std::move(block_);
|
||||
}
|
||||
#if ENABLE_FPGA
|
||||
else if (implementation.compare("Galileo_E5a_Pcps_Acquisition_Fpga") == 0)
|
||||
{
|
||||
std::unique_ptr<AcquisitionInterface> block_(new GalileoE5aPcpsAcquisitionFpga(configuration.get(), role, in_streams,
|
||||
out_streams));
|
||||
block = std::move(block_);
|
||||
}
|
||||
#endif
|
||||
else if (implementation.compare("GLONASS_L1_CA_PCPS_Acquisition") == 0)
|
||||
{
|
||||
std::unique_ptr<AcquisitionInterface> block_(new GlonassL1CaPcpsAcquisition(configuration.get(), role, in_streams,
|
||||
@ -1793,6 +1902,14 @@ std::unique_ptr<TrackingInterface> GNSSBlockFactory::GetTrkBlock(
|
||||
out_streams));
|
||||
block = std::move(block_);
|
||||
}
|
||||
#if ENABLE_FPGA
|
||||
else if (implementation.compare("Galileo_E1_DLL_PLL_VEML_Tracking_Fpga") == 0)
|
||||
{
|
||||
std::unique_ptr<TrackingInterface> block_(new GalileoE1DllPllVemlTrackingFpga(configuration.get(), role, in_streams,
|
||||
out_streams));
|
||||
block = std::move(block_);
|
||||
}
|
||||
#endif
|
||||
else if (implementation.compare("Galileo_E1_TCP_CONNECTOR_Tracking") == 0)
|
||||
{
|
||||
std::unique_ptr<TrackingInterface> block_(new GalileoE1TcpConnectorTracking(configuration.get(), role, in_streams,
|
||||
@ -1805,18 +1922,42 @@ std::unique_ptr<TrackingInterface> GNSSBlockFactory::GetTrkBlock(
|
||||
out_streams));
|
||||
block = std::move(block_);
|
||||
}
|
||||
#if ENABLE_FPGA
|
||||
else if (implementation.compare("Galileo_E5a_DLL_PLL_Tracking_Fpga") == 0)
|
||||
{
|
||||
std::unique_ptr<TrackingInterface> block_(new GalileoE5aDllPllTrackingFpga(configuration.get(), role, in_streams,
|
||||
out_streams));
|
||||
block = std::move(block_);
|
||||
}
|
||||
#endif
|
||||
else if (implementation.compare("GPS_L2_M_DLL_PLL_Tracking") == 0)
|
||||
{
|
||||
std::unique_ptr<TrackingInterface> block_(new GpsL2MDllPllTracking(configuration.get(), role, in_streams,
|
||||
out_streams));
|
||||
block = std::move(block_);
|
||||
}
|
||||
#if ENABLE_FPGA
|
||||
else if (implementation.compare("GPS_L2_M_DLL_PLL_Tracking_Fpga") == 0)
|
||||
{
|
||||
std::unique_ptr<TrackingInterface> block_(new GpsL2MDllPllTrackingFpga(configuration.get(), role, in_streams,
|
||||
out_streams));
|
||||
block = std::move(block_);
|
||||
}
|
||||
#endif
|
||||
else if ((implementation.compare("GPS_L5i_DLL_PLL_Tracking") == 0) or (implementation.compare("GPS_L5_DLL_PLL_Tracking") == 0))
|
||||
{
|
||||
std::unique_ptr<TrackingInterface> block_(new GpsL5DllPllTracking(configuration.get(), role, in_streams,
|
||||
out_streams));
|
||||
block = std::move(block_);
|
||||
}
|
||||
#if ENABLE_FPGA
|
||||
else if ((implementation.compare("GPS_L5i_DLL_PLL_Tracking_Fpga") == 0) or (implementation.compare("GPS_L5_DLL_PLL_Tracking_Fpga") == 0))
|
||||
{
|
||||
std::unique_ptr<TrackingInterface> block_(new GpsL5DllPllTrackingFpga(configuration.get(), role, in_streams,
|
||||
out_streams));
|
||||
block = std::move(block_);
|
||||
}
|
||||
#endif
|
||||
#if CUDA_GPU_ACCEL
|
||||
else if (implementation.compare("GPS_L1_CA_DLL_PLL_Tracking_GPU") == 0)
|
||||
{
|
||||
|
@ -211,6 +211,7 @@ if(ENABLE_UNIT_TESTING_EXTRA OR ENABLE_SYSTEM_TESTING_EXTRA OR ENABLE_FPGA)
|
||||
find_package(GPSTK)
|
||||
if(NOT GPSTK_FOUND OR ENABLE_OWN_GPSTK)
|
||||
message(STATUS "GPSTk v${GNSSSDR_GPSTK_LOCAL_VERSION} will be automatically downloaded and built when doing 'make'.")
|
||||
|
||||
# if(NOT ENABLE_FPGA)
|
||||
if(CMAKE_VERSION VERSION_LESS 3.2)
|
||||
ExternalProject_Add(
|
||||
|
@ -149,6 +149,9 @@ DECLARE_string(log_dir);
|
||||
#include "unit-tests/signal-processing-blocks/tracking/gps_l2_m_dll_pll_tracking_test.cc"
|
||||
#include "unit-tests/signal-processing-blocks/tracking/gps_l1_ca_dll_pll_tracking_test.cc"
|
||||
#include "unit-tests/signal-processing-blocks/tracking/tracking_pull-in_test.cc"
|
||||
#if ENABLE_FPGA
|
||||
#include "unit-tests/signal-processing-blocks/tracking/tracking_pull-in_test_fpga.cc"
|
||||
#endif
|
||||
#include "unit-tests/signal-processing-blocks/telemetry_decoder/gps_l1_ca_telemetry_decoder_test.cc"
|
||||
#include "unit-tests/signal-processing-blocks/observables/hybrid_observables_test.cc"
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user