1
0
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:
Carles Fernandez 2018-08-11 12:56:52 +02:00
commit 05a1806c8f
No known key found for this signature in database
GPG Key ID: 4C583C52B0C3877D
42 changed files with 6582 additions and 488 deletions

View File

@ -19,3 +19,4 @@
add_subdirectory(adapters)
add_subdirectory(gnuradio_blocks)
add_subdirectory(libs)

View File

@ -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)

View File

@ -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");
}

View File

@ -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_ */

View File

@ -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_;
}

View File

@ -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_ */

View File

@ -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;
}

View File

@ -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

View File

@ -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_;
}

View File

@ -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_ */

View File

@ -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_;
}

View File

@ -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_ */

View File

@ -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)

View File

@ -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

View File

@ -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");
}
/*!

View File

@ -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();

View File

@ -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
}

View File

@ -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();

View File

@ -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

View File

@ -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;
}

View File

@ -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_

View File

@ -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;
}

View File

@ -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_ */

View File

@ -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;
}

View File

@ -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_

View File

@ -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;
}

View File

@ -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_

View 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;
}

View 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_

View File

@ -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);

View File

@ -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;

View File

@ -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();
}

View File

@ -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

View File

@ -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(

View 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;
}

View 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

View File

@ -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
//}

View File

@ -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_ */

View File

@ -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)
{

View File

@ -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(

View File

@ -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