mirror of
https://github.com/gnss-sdr/gnss-sdr
synced 2024-12-15 04:30:33 +00:00
improved existing code
started the GPS L2 FPGA class implementation (not finished yet) implemented the GPS L5 FPGA class (not tested yet) implemented the Galileo E5 FPGA class (not tested yet) The code is still "dirty": it is yet to be cleaned of debug comments/code and any possible redundant code and not used variables.
This commit is contained in:
parent
75cbc3fcdd
commit
bb33faea21
@ -37,7 +37,7 @@ set(ACQ_ADAPTER_SOURCES
|
||||
)
|
||||
|
||||
if(ENABLE_FPGA)
|
||||
set(ACQ_ADAPTER_SOURCES ${ACQ_ADAPTER_SOURCES} gps_l1_ca_pcps_acquisition_fpga.cc galileo_e1_pcps_ambiguous_acquisition_fpga.cc)
|
||||
set(ACQ_ADAPTER_SOURCES ${ACQ_ADAPTER_SOURCES} gps_l1_ca_pcps_acquisition_fpga.cc gps_l2_m_pcps_acquisition_fpga.cc galileo_e1_pcps_ambiguous_acquisition_fpga.cc galileo_e5a_pcps_acquisition_fpga.cc gps_l5i_pcps_acquisition_fpga.cc)
|
||||
endif(ENABLE_FPGA)
|
||||
|
||||
if(OPENCL_FOUND)
|
||||
|
@ -38,7 +38,7 @@
|
||||
#include <boost/math/distributions/exponential.hpp>
|
||||
#include <glog/logging.h>
|
||||
|
||||
#define NUM_PRNs_GALILEO_E1 50
|
||||
|
||||
|
||||
using google::LogMessage;
|
||||
|
||||
@ -46,7 +46,7 @@ GalileoE1PcpsAmbiguousAcquisitionFpga::GalileoE1PcpsAmbiguousAcquisitionFpga(
|
||||
ConfigurationInterface* configuration, std::string role,
|
||||
unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams)
|
||||
{
|
||||
printf("galileo e1 fpga constructor called\n");
|
||||
//printf("top acq constructor start\n");
|
||||
pcpsconf_fpga_t acq_parameters;
|
||||
configuration_ = configuration;
|
||||
std::string default_item_type = "gr_complex";
|
||||
@ -61,16 +61,17 @@ GalileoE1PcpsAmbiguousAcquisitionFpga::GalileoE1PcpsAmbiguousAcquisitionFpga(
|
||||
acq_parameters.fs_in = fs_in;
|
||||
if_ = configuration_->property(role + ".if", 0);
|
||||
acq_parameters.freq = if_;
|
||||
dump_ = configuration_->property(role + ".dump", false);
|
||||
|
||||
// dump_ = configuration_->property(role + ".dump", false);
|
||||
// acq_parameters.dump = dump_;
|
||||
blocking_ = configuration_->property(role + ".blocking", true);
|
||||
// blocking_ = configuration_->property(role + ".blocking", true);
|
||||
// acq_parameters.blocking = blocking_;
|
||||
doppler_max_ = configuration_->property(role + ".doppler_max", 5000);
|
||||
if (FLAGS_doppler_max != 0) doppler_max_ = FLAGS_doppler_max;
|
||||
acq_parameters.doppler_max = doppler_max_;
|
||||
unsigned int sampled_ms = 4;
|
||||
acq_parameters.sampled_ms = sampled_ms;
|
||||
bit_transition_flag_ = configuration_->property(role + ".bit_transition_flag", false);
|
||||
// bit_transition_flag_ = configuration_->property(role + ".bit_transition_flag", false);
|
||||
// acq_parameters.bit_transition_flag = bit_transition_flag_;
|
||||
// use_CFAR_algorithm_flag_ = configuration_->property(role + ".use_CFAR_algorithm", true); //will be false in future versions
|
||||
// acq_parameters.use_CFAR_algorithm_flag = use_CFAR_algorithm_flag_;
|
||||
@ -78,7 +79,7 @@ GalileoE1PcpsAmbiguousAcquisitionFpga::GalileoE1PcpsAmbiguousAcquisitionFpga(
|
||||
|
||||
// max_dwells_ = configuration_->property(role + ".max_dwells", 1);
|
||||
// acq_parameters.max_dwells = max_dwells_;
|
||||
dump_filename_ = configuration_->property(role + ".dump_filename", default_dump_filename);
|
||||
// dump_filename_ = configuration_->property(role + ".dump_filename", default_dump_filename);
|
||||
// acq_parameters.dump_filename = dump_filename_;
|
||||
//--- Find number of samples per spreading code (4 ms) -----------------
|
||||
unsigned int code_length = static_cast<unsigned int>(std::round(static_cast<double>(fs_in) / (Galileo_E1_CODE_CHIP_RATE_HZ / Galileo_E1_B_CODE_LENGTH_CHIPS)));
|
||||
@ -92,12 +93,16 @@ GalileoE1PcpsAmbiguousAcquisitionFpga::GalileoE1PcpsAmbiguousAcquisitionFpga(
|
||||
// vector_length_ *= 2;
|
||||
// }
|
||||
|
||||
|
||||
|
||||
//printf("fs_in = %d\n", fs_in);
|
||||
//printf("Galileo_E1_B_CODE_LENGTH_CHIPS = %f\n", Galileo_E1_B_CODE_LENGTH_CHIPS);
|
||||
//printf("Galileo_E1_CODE_CHIP_RATE_HZ = %f\n", Galileo_E1_CODE_CHIP_RATE_HZ);
|
||||
//printf("acq adapter code_length = %d\n", code_length);
|
||||
acq_parameters.code_length = code_length;
|
||||
// The FPGA can only use FFT lengths that are a power of two.
|
||||
float nbits = ceilf(log2f((float)code_length));
|
||||
unsigned int nsamples_total = pow(2, nbits);
|
||||
unsigned int vector_length = nsamples_total;
|
||||
//printf("acq adapter nsamples_total (= vector_length) = %d\n", vector_length);
|
||||
unsigned int select_queue_Fpga = configuration_->property(role + ".select_queue_Fpga", 0);
|
||||
acq_parameters.select_queue_Fpga = select_queue_Fpga;
|
||||
std::string default_device_name = "/dev/uio0";
|
||||
@ -106,18 +111,17 @@ GalileoE1PcpsAmbiguousAcquisitionFpga::GalileoE1PcpsAmbiguousAcquisitionFpga(
|
||||
acq_parameters.samples_per_ms = nsamples_total/sampled_ms;
|
||||
acq_parameters.samples_per_code = nsamples_total;
|
||||
|
||||
|
||||
|
||||
// compute all the GALILEO E1 PRN Codes (this is done only once upon the class constructor in order to avoid re-computing the PRN codes every time
|
||||
// a channel is assigned)
|
||||
gr::fft::fft_complex* fft_if = new gr::fft::fft_complex(nsamples_total, true); // Direct FFT
|
||||
std::complex<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_GALILEO_E1]; // memory containing all the possible fft codes for PRN 0 to 32
|
||||
d_all_fft_codes_ = new lv_16sc_t[nsamples_total * Galileo_E1_NUMBER_OF_CODES]; // memory containing all the possible fft codes for PRN 0 to 32
|
||||
float max; // temporary maxima search
|
||||
|
||||
//int tmp_re, tmp_im;
|
||||
|
||||
for (unsigned int PRN = 1; PRN <= NUM_PRNs_GALILEO_E1; PRN++)
|
||||
for (unsigned int PRN = 1; PRN <= Galileo_E1_NUMBER_OF_CODES; PRN++)
|
||||
{
|
||||
|
||||
//code_ = new gr_complex[vector_length_];
|
||||
@ -128,15 +132,17 @@ GalileoE1PcpsAmbiguousAcquisitionFpga::GalileoE1PcpsAmbiguousAcquisitionFpga(
|
||||
|
||||
if (acquire_pilot_ == true)
|
||||
{
|
||||
//printf("yes acquiring pilot!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1\n");
|
||||
//set local signal generator to Galileo E1 pilot component (1C)
|
||||
char pilot_signal[3] = "1C";
|
||||
galileo_e1_code_gen_complex_sampled(code, pilot_signal,
|
||||
cboc, gnss_synchro_->PRN, fs_in, 0, false);
|
||||
cboc, PRN, fs_in, 0, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
galileo_e1_code_gen_complex_sampled(code, gnss_synchro_->Signal,
|
||||
cboc, gnss_synchro_->PRN, fs_in, 0, false);
|
||||
char data_signal[3] = "1B";
|
||||
galileo_e1_code_gen_complex_sampled(code, data_signal,
|
||||
cboc, PRN, fs_in, 0, false);
|
||||
}
|
||||
|
||||
// for (unsigned int i = 0; i < sampled_ms / 4; i++)
|
||||
@ -145,16 +151,43 @@ GalileoE1PcpsAmbiguousAcquisitionFpga::GalileoE1PcpsAmbiguousAcquisitionFpga(
|
||||
// memcpy(&(d_all_fft_codes_[i * code_length_]), code, sizeof(gr_complex) * code_length_);
|
||||
// }
|
||||
|
||||
|
||||
// // debug
|
||||
// char filename[25];
|
||||
// FILE *fid;
|
||||
// sprintf(filename,"gal_prn%d.txt", PRN);
|
||||
// fid = fopen(filename, "w");
|
||||
// for (unsigned int kk=0;kk< nsamples_total; kk++)
|
||||
// {
|
||||
// fprintf(fid, "%f\n", code[kk].real());
|
||||
// fprintf(fid, "%f\n", code[kk].imag());
|
||||
// }
|
||||
// fclose(fid);
|
||||
|
||||
|
||||
// // fill in zero padding
|
||||
for (int s = code_length; s < nsamples_total; s++)
|
||||
{
|
||||
code[s] = 0;
|
||||
code[s] = std::complex<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
|
||||
@ -171,13 +204,71 @@ GalileoE1PcpsAmbiguousAcquisitionFpga::GalileoE1PcpsAmbiguousAcquisitionFpga(
|
||||
}
|
||||
for (unsigned int i = 0; i < nsamples_total; i++) // map the FFT to the dynamic range of the fixed point values an copy to buffer containing all FFTs
|
||||
{
|
||||
d_all_fft_codes_[i + nsamples_total * (PRN - 1)] = lv_16sc_t(static_cast<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(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_;
|
||||
@ -203,25 +294,31 @@ GalileoE1PcpsAmbiguousAcquisitionFpga::GalileoE1PcpsAmbiguousAcquisitionFpga(
|
||||
//threshold_ = 0.0;
|
||||
doppler_step_ = 0;
|
||||
gnss_synchro_ = 0;
|
||||
//printf("top acq constructor end\n");
|
||||
}
|
||||
|
||||
|
||||
GalileoE1PcpsAmbiguousAcquisitionFpga::~GalileoE1PcpsAmbiguousAcquisitionFpga()
|
||||
{
|
||||
//printf("top acq destructor start\n");
|
||||
//delete[] code_;
|
||||
delete[] d_all_fft_codes_;
|
||||
//printf("top acq destructor end\n");
|
||||
}
|
||||
|
||||
|
||||
void GalileoE1PcpsAmbiguousAcquisitionFpga::set_channel(unsigned int channel)
|
||||
{
|
||||
//printf("top acq set channel start\n");
|
||||
channel_ = channel;
|
||||
acquisition_fpga_->set_channel(channel_);
|
||||
//printf("top acq set channel end\n");
|
||||
}
|
||||
|
||||
|
||||
void GalileoE1PcpsAmbiguousAcquisitionFpga::set_threshold(float threshold)
|
||||
{
|
||||
//printf("top acq set threshold start\n");
|
||||
// the .pfa parameter and the threshold calculation is only used for the CFAR algorithm.
|
||||
// We don't use the CFAR algorithm in the FPGA. Therefore the threshold is set as such.
|
||||
|
||||
@ -241,48 +338,60 @@ void GalileoE1PcpsAmbiguousAcquisitionFpga::set_threshold(float threshold)
|
||||
DLOG(INFO) << "Channel " << channel_ << " Threshold = " << threshold;
|
||||
acquisition_fpga_->set_threshold(threshold);
|
||||
// acquisition_fpga_->set_threshold(threshold_);
|
||||
//printf("top acq set threshold end\n");
|
||||
}
|
||||
|
||||
|
||||
void GalileoE1PcpsAmbiguousAcquisitionFpga::set_doppler_max(unsigned int doppler_max)
|
||||
{
|
||||
//printf("top acq set doppler max start\n");
|
||||
doppler_max_ = doppler_max;
|
||||
|
||||
acquisition_fpga_->set_doppler_max(doppler_max_);
|
||||
//printf("top acq set doppler max end\n");
|
||||
}
|
||||
|
||||
|
||||
void GalileoE1PcpsAmbiguousAcquisitionFpga::set_doppler_step(unsigned int doppler_step)
|
||||
{
|
||||
//printf("top acq set doppler step start\n");
|
||||
doppler_step_ = doppler_step;
|
||||
|
||||
acquisition_fpga_->set_doppler_step(doppler_step_);
|
||||
//printf("top acq set doppler step end\n");
|
||||
}
|
||||
|
||||
|
||||
void GalileoE1PcpsAmbiguousAcquisitionFpga::set_gnss_synchro(Gnss_Synchro* gnss_synchro)
|
||||
{
|
||||
//printf("top acq set gnss synchro start\n");
|
||||
gnss_synchro_ = gnss_synchro;
|
||||
|
||||
acquisition_fpga_->set_gnss_synchro(gnss_synchro_);
|
||||
//printf("top acq set gnss synchro end\n");
|
||||
}
|
||||
|
||||
|
||||
signed int GalileoE1PcpsAmbiguousAcquisitionFpga::mag()
|
||||
{
|
||||
// printf("top acq mag start\n");
|
||||
return acquisition_fpga_->mag();
|
||||
//printf("top acq mag end\n");
|
||||
}
|
||||
|
||||
|
||||
void GalileoE1PcpsAmbiguousAcquisitionFpga::init()
|
||||
{
|
||||
// printf("top acq init start\n");
|
||||
acquisition_fpga_->init();
|
||||
// printf("top acq init end\n");
|
||||
//set_local_code();
|
||||
}
|
||||
|
||||
|
||||
void GalileoE1PcpsAmbiguousAcquisitionFpga::set_local_code()
|
||||
{
|
||||
// printf("top acq set local code start\n");
|
||||
// bool cboc = configuration_->property(
|
||||
// "Acquisition" + boost::lexical_cast<std::string>(channel_) + ".cboc", false);
|
||||
//
|
||||
@ -310,18 +419,23 @@ void GalileoE1PcpsAmbiguousAcquisitionFpga::set_local_code()
|
||||
//acquisition_fpga_->set_local_code(code_);
|
||||
acquisition_fpga_->set_local_code();
|
||||
// delete[] code;
|
||||
// printf("top acq set local code end\n");
|
||||
}
|
||||
|
||||
|
||||
void GalileoE1PcpsAmbiguousAcquisitionFpga::reset()
|
||||
{
|
||||
// printf("top acq reset start\n");
|
||||
acquisition_fpga_->set_active(true);
|
||||
// printf("top acq reset end\n");
|
||||
}
|
||||
|
||||
|
||||
void GalileoE1PcpsAmbiguousAcquisitionFpga::set_state(int state)
|
||||
{
|
||||
// printf("top acq set state start\n");
|
||||
acquisition_fpga_->set_state(state);
|
||||
// printf("top acq set state end\n");
|
||||
}
|
||||
|
||||
|
||||
@ -348,6 +462,7 @@ void GalileoE1PcpsAmbiguousAcquisitionFpga::set_state(int state)
|
||||
|
||||
void GalileoE1PcpsAmbiguousAcquisitionFpga::connect(gr::top_block_sptr top_block)
|
||||
{
|
||||
// printf("top acq connect\n");
|
||||
// if (item_type_.compare("gr_complex") == 0)
|
||||
// {
|
||||
// top_block->connect(stream_to_vector_, 0, acquisition_fpga_, 0);
|
||||
@ -397,11 +512,13 @@ void GalileoE1PcpsAmbiguousAcquisitionFpga::disconnect(gr::top_block_sptr top_bl
|
||||
// }
|
||||
|
||||
// nothing to disconnect
|
||||
// printf("top acq disconnect\n");
|
||||
}
|
||||
|
||||
|
||||
gr::basic_block_sptr GalileoE1PcpsAmbiguousAcquisitionFpga::get_left_block()
|
||||
{
|
||||
// printf("top acq get left block start\n");
|
||||
// if (item_type_.compare("gr_complex") == 0)
|
||||
// {
|
||||
// return stream_to_vector_;
|
||||
@ -419,10 +536,14 @@ gr::basic_block_sptr GalileoE1PcpsAmbiguousAcquisitionFpga::get_left_block()
|
||||
// LOG(WARNING) << item_type_ << " unknown acquisition item type";
|
||||
return nullptr;
|
||||
// }
|
||||
// printf("top acq get left block end\n");
|
||||
}
|
||||
|
||||
|
||||
gr::basic_block_sptr GalileoE1PcpsAmbiguousAcquisitionFpga::get_right_block()
|
||||
{
|
||||
// printf("top acq get right block start\n");
|
||||
return acquisition_fpga_;
|
||||
// printf("top acq get right block end\n");
|
||||
}
|
||||
|
||||
|
@ -59,6 +59,7 @@ public:
|
||||
|
||||
inline std::string role() override
|
||||
{
|
||||
// printf("top acq role\n");
|
||||
return role_;
|
||||
}
|
||||
|
||||
@ -67,11 +68,13 @@ public:
|
||||
*/
|
||||
inline std::string implementation() override
|
||||
{
|
||||
// printf("top acq implementation\n");
|
||||
return "Galileo_E1_PCPS_Ambiguous_Acquisition_Fpga";
|
||||
}
|
||||
|
||||
size_t item_size() override
|
||||
{
|
||||
// printf("top acq item size\n");
|
||||
size_t item_size = sizeof(lv_16sc_t);
|
||||
return item_size;
|
||||
}
|
||||
|
@ -0,0 +1,399 @@
|
||||
/*!
|
||||
* \file galileo_e5a_pcps_acquisition.cc
|
||||
* \brief Adapts a PCPS acquisition block to an AcquisitionInterface for
|
||||
* Galileo E5a data and pilot Signals
|
||||
* \author Antonio Ramos, 2018. antonio.ramos(at)cttc.es
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (C) 2010-2018 (see AUTHORS file for a list of contributors)
|
||||
*
|
||||
* GNSS-SDR is a software defined Global Navigation
|
||||
* Satellite Systems receiver
|
||||
*
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* GNSS-SDR is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GNSS-SDR is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNSS-SDR. If not, see <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)
|
||||
{
|
||||
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);
|
||||
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
|
||||
|
||||
|
||||
for (unsigned int PRN = 1; PRN <= Galileo_E5a_NUMBER_OF_CODES; PRN++)
|
||||
{
|
||||
// gr_complex* code = new gr_complex[code_length_];
|
||||
char signal_[3];
|
||||
|
||||
if (acq_iq_)
|
||||
{
|
||||
strcpy(signal_, "5X");
|
||||
}
|
||||
else if (acq_pilot_)
|
||||
{
|
||||
strcpy(signal_, "5Q");
|
||||
}
|
||||
else
|
||||
{
|
||||
strcpy(signal_, "5I");
|
||||
}
|
||||
|
||||
galileo_e5_a_code_gen_complex_sampled(code, signal_, gnss_synchro_->PRN, fs_in_, 0);
|
||||
|
||||
// fill in zero padding
|
||||
for (int s = code_length; s < nsamples_total; s++)
|
||||
{
|
||||
code[s] = std::complex<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;
|
||||
}
|
||||
|
||||
|
||||
GalileoE5aPcpsAcquisitionFpga::~GalileoE5aPcpsAcquisitionFpga()
|
||||
{
|
||||
//delete[] code_;
|
||||
delete[] d_all_fft_codes_;
|
||||
}
|
||||
|
||||
|
||||
void GalileoE5aPcpsAcquisitionFpga::set_channel(unsigned int channel)
|
||||
{
|
||||
channel_ = channel;
|
||||
//acquisition_->set_channel(channel_);
|
||||
acquisition_fpga_->set_channel(channel_);
|
||||
}
|
||||
|
||||
|
||||
void GalileoE5aPcpsAcquisitionFpga::set_threshold(float threshold)
|
||||
{
|
||||
// float pfa = configuration_->property(role_ + boost::lexical_cast<std::string>(channel_) + ".pfa", 0.0);
|
||||
//
|
||||
// if (pfa == 0.0)
|
||||
// {
|
||||
// pfa = configuration_->property(role_ + ".pfa", 0.0);
|
||||
// }
|
||||
//
|
||||
// if (pfa == 0.0)
|
||||
// {
|
||||
// threshold_ = threshold;
|
||||
// }
|
||||
//
|
||||
// else
|
||||
// {
|
||||
// threshold_ = calculate_threshold(pfa);
|
||||
// }
|
||||
|
||||
DLOG(INFO) << "Channel " << channel_ << " Threshold = " << threshold;
|
||||
|
||||
//acquisition_->set_threshold(threshold_);
|
||||
acquisition_fpga_->set_threshold(threshold);
|
||||
}
|
||||
|
||||
|
||||
void GalileoE5aPcpsAcquisitionFpga::set_doppler_max(unsigned int doppler_max)
|
||||
{
|
||||
doppler_max_ = doppler_max;
|
||||
//acquisition_->set_doppler_max(doppler_max_);
|
||||
acquisition_fpga_->set_doppler_max(doppler_max_);
|
||||
}
|
||||
|
||||
|
||||
void GalileoE5aPcpsAcquisitionFpga::set_doppler_step(unsigned int doppler_step)
|
||||
{
|
||||
doppler_step_ = doppler_step;
|
||||
//acquisition_->set_doppler_step(doppler_step_);
|
||||
acquisition_fpga_->set_doppler_step(doppler_step_);
|
||||
}
|
||||
|
||||
|
||||
void GalileoE5aPcpsAcquisitionFpga::set_gnss_synchro(Gnss_Synchro* gnss_synchro)
|
||||
{
|
||||
gnss_synchro_ = gnss_synchro;
|
||||
//acquisition_->set_gnss_synchro(gnss_synchro_);
|
||||
acquisition_fpga_->set_gnss_synchro(gnss_synchro_);
|
||||
}
|
||||
|
||||
|
||||
signed int GalileoE5aPcpsAcquisitionFpga::mag()
|
||||
{
|
||||
//return acquisition_->mag();
|
||||
return acquisition_fpga_->mag();
|
||||
}
|
||||
|
||||
|
||||
void GalileoE5aPcpsAcquisitionFpga::init()
|
||||
{
|
||||
//acquisition_->init();
|
||||
acquisition_fpga_->init();
|
||||
}
|
||||
|
||||
|
||||
void GalileoE5aPcpsAcquisitionFpga::set_local_code()
|
||||
{
|
||||
// gr_complex* code = new gr_complex[code_length_];
|
||||
// char signal_[3];
|
||||
//
|
||||
// if (acq_iq_)
|
||||
// {
|
||||
// strcpy(signal_, "5X");
|
||||
// }
|
||||
// else if (acq_pilot_)
|
||||
// {
|
||||
// strcpy(signal_, "5Q");
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// strcpy(signal_, "5I");
|
||||
// }
|
||||
//
|
||||
// galileo_e5_a_code_gen_complex_sampled(code, signal_, gnss_synchro_->PRN, fs_in_, 0);
|
||||
//
|
||||
// for (unsigned int i = 0; i < sampled_ms_; i++)
|
||||
// {
|
||||
// memcpy(code_ + (i * code_length_), code, sizeof(gr_complex) * code_length_);
|
||||
// }
|
||||
|
||||
//acquisition_->set_local_code(code_);
|
||||
acquisition_fpga_->set_local_code();
|
||||
// delete[] code;
|
||||
}
|
||||
|
||||
|
||||
void GalileoE5aPcpsAcquisitionFpga::reset()
|
||||
{
|
||||
//acquisition_->set_active(true);
|
||||
acquisition_fpga_->set_active(true);
|
||||
}
|
||||
|
||||
|
||||
//float GalileoE5aPcpsAcquisitionFpga::calculate_threshold(float pfa)
|
||||
//{
|
||||
// unsigned int frequency_bins = 0;
|
||||
// for (int doppler = static_cast<int>(-doppler_max_); doppler <= static_cast<int>(doppler_max_); doppler += doppler_step_)
|
||||
// {
|
||||
// frequency_bins++;
|
||||
// }
|
||||
// DLOG(INFO) << "Channel " << channel_ << " Pfa = " << pfa;
|
||||
// unsigned int ncells = vector_length_ * frequency_bins;
|
||||
// double exponent = 1 / static_cast<double>(ncells);
|
||||
// double val = pow(1.0 - pfa, exponent);
|
||||
// double lambda = double(vector_length_);
|
||||
// boost::math::exponential_distribution<double> mydist(lambda);
|
||||
// float threshold = static_cast<float>(quantile(mydist, val));
|
||||
//
|
||||
// return threshold;
|
||||
//}
|
||||
|
||||
|
||||
void GalileoE5aPcpsAcquisitionFpga::set_state(int state)
|
||||
{
|
||||
//acquisition_->set_state(state);
|
||||
acquisition_fpga_->set_state(state);
|
||||
}
|
||||
|
||||
|
||||
void GalileoE5aPcpsAcquisitionFpga::connect(gr::top_block_sptr top_block)
|
||||
{
|
||||
// if (item_type_.compare("gr_complex") == 0)
|
||||
// {
|
||||
// top_block->connect(stream_to_vector_, 0, acquisition_, 0);
|
||||
// }
|
||||
// else if (item_type_.compare("cshort") == 0)
|
||||
// {
|
||||
// top_block->connect(stream_to_vector_, 0, acquisition_, 0);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// LOG(WARNING) << item_type_ << " unknown acquisition item type";
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
void GalileoE5aPcpsAcquisitionFpga::disconnect(gr::top_block_sptr top_block)
|
||||
{
|
||||
// if (item_type_.compare("gr_complex") == 0)
|
||||
// {
|
||||
// top_block->disconnect(stream_to_vector_, 0, acquisition_, 0);
|
||||
// }
|
||||
// else if (item_type_.compare("cshort") == 0)
|
||||
// {
|
||||
// top_block->disconnect(stream_to_vector_, 0, acquisition_, 0);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// LOG(WARNING) << item_type_ << " unknown acquisition item type";
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
gr::basic_block_sptr GalileoE5aPcpsAcquisitionFpga::get_left_block()
|
||||
{
|
||||
//return stream_to_vector_;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
gr::basic_block_sptr GalileoE5aPcpsAcquisitionFpga::get_right_block()
|
||||
{
|
||||
//return acquisition_;
|
||||
return acquisition_fpga_;
|
||||
}
|
@ -0,0 +1,176 @@
|
||||
/*!
|
||||
* \file galileo_e5a_pcps_acquisition.h
|
||||
* \brief Adapts a PCPS acquisition block to an AcquisitionInterface for
|
||||
* Galileo E5a data and pilot Signals
|
||||
* \author Antonio Ramos, 2018. antonio.ramos(at)cttc.es
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (C) 2010-2018 (see AUTHORS file for a list of contributors)
|
||||
*
|
||||
* GNSS-SDR is a software defined Global Navigation
|
||||
* Satellite Systems receiver
|
||||
*
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* GNSS-SDR is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GNSS-SDR is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNSS-SDR. If not, see <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);
|
||||
|
||||
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_ */
|
@ -60,6 +60,8 @@ GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga(
|
||||
|
||||
long fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 2048000);
|
||||
long fs_in = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated);
|
||||
//fs_in = fs_in/2.0; // downampling filter
|
||||
//printf("####### DEBUG Acq: fs_in = %d\n", fs_in);
|
||||
acq_parameters.fs_in = fs_in;
|
||||
long ifreq = configuration_->property(role + ".if", 0);
|
||||
acq_parameters.freq = ifreq;
|
||||
@ -69,7 +71,7 @@ GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga(
|
||||
unsigned int sampled_ms = configuration_->property(role + ".coherent_integration_time_ms", 1);
|
||||
acq_parameters.sampled_ms = sampled_ms;
|
||||
unsigned int code_length = static_cast<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);
|
||||
@ -96,12 +98,29 @@ GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga(
|
||||
// fill in zero padding
|
||||
for (int s = code_length; s < nsamples_total; s++)
|
||||
{
|
||||
code[s] = 0;
|
||||
code[s] = std::complex<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
|
||||
|
||||
|
||||
// // debug
|
||||
// char filename[25];
|
||||
// FILE *fid;
|
||||
// sprintf(filename,"fft_gps_prn%d.txt", PRN);
|
||||
// fid = fopen(filename, "w");
|
||||
// for (unsigned int kk=0;kk< nsamples_total; kk++)
|
||||
// {
|
||||
// fprintf(fid, "%f\n", fft_codes_padded[kk].real());
|
||||
// fprintf(fid, "%f\n", fft_codes_padded[kk].imag());
|
||||
// }
|
||||
// fclose(fid);
|
||||
|
||||
|
||||
|
||||
max = 0; // initialize maximum value
|
||||
for (unsigned int i = 0; i < nsamples_total; i++) // search for maxima
|
||||
{
|
||||
@ -116,9 +135,30 @@ GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga(
|
||||
}
|
||||
for (unsigned int i = 0; i < nsamples_total; i++) // map the FFT to the dynamic range of the fixed point values an copy to buffer containing all FFTs
|
||||
{
|
||||
d_all_fft_codes_[i + nsamples_total * (PRN - 1)] = lv_16sc_t(static_cast<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
|
||||
|
@ -0,0 +1,398 @@
|
||||
/*!
|
||||
* \file gps_l2_m_pcps_acquisition.cc
|
||||
* \brief Adapts a PCPS acquisition block to an AcquisitionInterface for
|
||||
* GPS L2 M signals
|
||||
* \authors <ul>
|
||||
* <li> Javier Arribas, 2015. jarribas(at)cttc.es
|
||||
* </ul>
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
|
||||
*
|
||||
* GNSS-SDR is a software defined Global Navigation
|
||||
* Satellite Systems receiver
|
||||
*
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* GNSS-SDR is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GNSS-SDR is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "gps_l2_m_pcps_acquisition_fpga.h"
|
||||
#include "configuration_interface.h"
|
||||
#include "gps_l2c_signal.h"
|
||||
#include "GPS_L2C.h"
|
||||
#include "gnss_sdr_flags.h"
|
||||
#include <boost/math/distributions/exponential.hpp>
|
||||
#include <glog/logging.h>
|
||||
|
||||
#define NUM_PRNs 32
|
||||
|
||||
using google::LogMessage;
|
||||
|
||||
GpsL2MPcpsAcquisitionFpga::GpsL2MPcpsAcquisitionFpga(
|
||||
ConfigurationInterface* configuration, std::string role,
|
||||
unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams)
|
||||
{
|
||||
//pcpsconf_t acq_parameters;
|
||||
pcpsconf_fpga_t acq_parameters;
|
||||
configuration_ = configuration;
|
||||
std::string default_item_type = "gr_complex";
|
||||
std::string default_dump_filename = "./data/acquisition.dat";
|
||||
|
||||
LOG(INFO) << "role " << role;
|
||||
|
||||
item_type_ = configuration_->property(role + ".item_type", default_item_type);
|
||||
//float pfa = configuration_->property(role + ".pfa", 0.0);
|
||||
|
||||
long fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 2048000);
|
||||
fs_in_ = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated);
|
||||
acq_parameters.fs_in = fs_in_;
|
||||
if_ = configuration_->property(role + ".if", 0);
|
||||
acq_parameters.freq = if_;
|
||||
//dump_ = configuration_->property(role + ".dump", false);
|
||||
//acq_parameters.dump = dump_;
|
||||
//blocking_ = configuration_->property(role + ".blocking", true);
|
||||
//acq_parameters.blocking = blocking_;
|
||||
doppler_max_ = configuration->property(role + ".doppler_max", 5000);
|
||||
if (FLAGS_doppler_max != 0) doppler_max_ = FLAGS_doppler_max;
|
||||
acq_parameters.doppler_max = doppler_max_;
|
||||
//bit_transition_flag_ = configuration_->property(role + ".bit_transition_flag", false);
|
||||
//acq_parameters.bit_transition_flag = bit_transition_flag_;
|
||||
//use_CFAR_algorithm_flag_ = configuration_->property(role + ".use_CFAR_algorithm", true); //will be false in future versions
|
||||
//acq_parameters.use_CFAR_algorithm_flag = use_CFAR_algorithm_flag_;
|
||||
//max_dwells_ = configuration_->property(role + ".max_dwells", 1);
|
||||
//acq_parameters.max_dwells = max_dwells_;
|
||||
//dump_filename_ = configuration_->property(role + ".dump_filename", default_dump_filename);
|
||||
//acq_parameters.dump_filename = dump_filename_;
|
||||
//--- Find number of samples per spreading code -------------------------
|
||||
//code_length_ = std::round(static_cast<double>(fs_in_) / (GPS_L2_M_CODE_RATE_HZ / static_cast<double>(GPS_L2_M_CODE_LENGTH_CHIPS)));
|
||||
|
||||
acq_parameters.sampled_ms = 20;
|
||||
unsigned code_length = std::round(static_cast<double>(fs_in_) / (GPS_L2_M_CODE_RATE_HZ / static_cast<double>(GPS_L2_M_CODE_LENGTH_CHIPS)));
|
||||
acq_parameters.code_length = code_length;
|
||||
// The FPGA can only use FFT lengths that are a power of two.
|
||||
float nbits = ceilf(log2f((float)code_length));
|
||||
unsigned int nsamples_total = pow(2, nbits);
|
||||
unsigned int vector_length = nsamples_total;
|
||||
unsigned int select_queue_Fpga = configuration_->property(role + ".select_queue_Fpga", 0);
|
||||
acq_parameters.select_queue_Fpga = select_queue_Fpga;
|
||||
std::string default_device_name = "/dev/uio0";
|
||||
std::string device_name = configuration_->property(role + ".devicename", default_device_name);
|
||||
acq_parameters.device_name = device_name;
|
||||
acq_parameters.samples_per_ms = nsamples_total/acq_parameters.sampled_ms;
|
||||
//acq_parameters.samples_per_ms = static_cast<int>(std::round(static_cast<double>(fs_in_) * 0.001));
|
||||
acq_parameters.samples_per_code = nsamples_total;
|
||||
|
||||
// compute all the GPS L1 PRN Codes (this is done only once upon the class constructor in order to avoid re-computing the PRN codes every time
|
||||
// a channel is assigned)
|
||||
gr::fft::fft_complex* fft_if = new gr::fft::fft_complex(vector_length, true); // Direct FFT
|
||||
// allocate memory to compute all the PRNs and compute all the possible codes
|
||||
std::complex<float>* code = new std::complex<float>[nsamples_total]; // buffer for the local code
|
||||
gr_complex* fft_codes_padded = static_cast<gr_complex*>(volk_gnsssdr_malloc(nsamples_total * sizeof(gr_complex), volk_gnsssdr_get_alignment()));
|
||||
d_all_fft_codes_ = new lv_16sc_t[nsamples_total * NUM_PRNs]; // memory containing all the possible fft codes for PRN 0 to 32
|
||||
float max; // temporary maxima search
|
||||
for (unsigned int PRN = 1; PRN <= NUM_PRNs; PRN++)
|
||||
{
|
||||
gps_l2c_m_code_gen_complex_sampled(code, PRN, fs_in_);
|
||||
// fill in zero padding
|
||||
for (int s = code_length; s < nsamples_total; s++)
|
||||
{
|
||||
code[s] = std::complex<float>(static_cast<float>(0,0));
|
||||
//code[s] = 0;
|
||||
}
|
||||
memcpy(fft_if->get_inbuf(), code, sizeof(gr_complex) * nsamples_total); // copy to FFT buffer
|
||||
fft_if->execute(); // Run the FFT of local code
|
||||
volk_32fc_conjugate_32fc(fft_codes_padded, fft_if->get_outbuf(), nsamples_total); // conjugate values
|
||||
max = 0; // initialize maximum value
|
||||
for (unsigned int i = 0; i < nsamples_total; i++) // search for maxima
|
||||
{
|
||||
if (std::abs(fft_codes_padded[i].real()) > max)
|
||||
{
|
||||
max = std::abs(fft_codes_padded[i].real());
|
||||
}
|
||||
if (std::abs(fft_codes_padded[i].imag()) > max)
|
||||
{
|
||||
max = std::abs(fft_codes_padded[i].imag());
|
||||
}
|
||||
}
|
||||
for (unsigned int i = 0; i < nsamples_total; i++) // map the FFT to the dynamic range of the fixed point values an copy to buffer containing all FFTs
|
||||
{
|
||||
d_all_fft_codes_[i + nsamples_total * (PRN - 1)] = lv_16sc_t(static_cast<int>(floor(fft_codes_padded[i].real() * (pow(2, 7) - 1) / max)),
|
||||
static_cast<int>(floor(fft_codes_padded[i].imag() * (pow(2, 7) - 1) / max)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//acq_parameters
|
||||
acq_parameters.all_fft_codes = d_all_fft_codes_;
|
||||
|
||||
// temporary buffers that we can delete
|
||||
delete[] code;
|
||||
delete fft_if;
|
||||
delete[] fft_codes_padded;
|
||||
|
||||
acquisition_fpga_ = pcps_make_acquisition_fpga(acq_parameters);
|
||||
DLOG(INFO) << "acquisition(" << acquisition_fpga_->unique_id() << ")";
|
||||
|
||||
channel_ = 0;
|
||||
doppler_step_ = 0;
|
||||
gnss_synchro_ = 0;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// vector_length_ = code_length_;
|
||||
//
|
||||
// if (bit_transition_flag_)
|
||||
// {
|
||||
// vector_length_ *= 2;
|
||||
// }
|
||||
|
||||
// code_ = new gr_complex[vector_length_];
|
||||
//
|
||||
// if (item_type_.compare("cshort") == 0)
|
||||
// {
|
||||
// item_size_ = sizeof(lv_16sc_t);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// item_size_ = sizeof(gr_complex);
|
||||
// }
|
||||
//acq_parameters.samples_per_ms = static_cast<int>(std::round(static_cast<double>(fs_in_) * 0.001));
|
||||
//acq_parameters.samples_per_code = code_length_;
|
||||
//acq_parameters.it_size = item_size_;
|
||||
//acq_parameters.sampled_ms = 20;
|
||||
//acq_parameters.num_doppler_bins_step2 = configuration_->property(role + ".second_nbins", 4);
|
||||
//acq_parameters.doppler_step2 = configuration_->property(role + ".second_doppler_step", 125.0);
|
||||
//acq_parameters.make_2_steps = configuration_->property(role + ".make_two_steps", true);
|
||||
//acquisition_ = pcps_make_acquisition(acq_parameters);
|
||||
DLOG(INFO) << "acquisition(" << acquisition_fpga_->unique_id() << ")";
|
||||
|
||||
// stream_to_vector_ = gr::blocks::stream_to_vector::make(item_size_, vector_length_);
|
||||
// DLOG(INFO) << "stream_to_vector(" << stream_to_vector_->unique_id() << ")";
|
||||
//
|
||||
// if (item_type_.compare("cbyte") == 0)
|
||||
// {
|
||||
// cbyte_to_float_x2_ = make_complex_byte_to_float_x2();
|
||||
// float_to_complex_ = gr::blocks::float_to_complex::make();
|
||||
// }
|
||||
|
||||
// channel_ = 0;
|
||||
threshold_ = 0.0;
|
||||
// doppler_step_ = 0;
|
||||
// gnss_synchro_ = 0;
|
||||
}
|
||||
|
||||
|
||||
GpsL2MPcpsAcquisitionFpga::~GpsL2MPcpsAcquisitionFpga()
|
||||
{
|
||||
//delete[] code_;
|
||||
delete[] d_all_fft_codes_;
|
||||
}
|
||||
|
||||
|
||||
void GpsL2MPcpsAcquisitionFpga::set_channel(unsigned int channel)
|
||||
{
|
||||
channel_ = channel;
|
||||
acquisition_fpga_->set_channel(channel_);
|
||||
}
|
||||
|
||||
|
||||
void GpsL2MPcpsAcquisitionFpga::set_threshold(float threshold)
|
||||
{
|
||||
// float pfa = configuration_->property(role_ + boost::lexical_cast<std::string>(channel_) + ".pfa", 0.0);
|
||||
//
|
||||
// if (pfa == 0.0)
|
||||
// {
|
||||
// pfa = configuration_->property(role_ + ".pfa", 0.0);
|
||||
// }
|
||||
// if (pfa == 0.0)
|
||||
// {
|
||||
// threshold_ = threshold;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// threshold_ = calculate_threshold(pfa);
|
||||
// }
|
||||
|
||||
DLOG(INFO) << "Channel " << channel_ << " Threshold = " << threshold_;
|
||||
|
||||
acquisition_fpga_->set_threshold(threshold_);
|
||||
}
|
||||
|
||||
|
||||
void GpsL2MPcpsAcquisitionFpga::set_doppler_max(unsigned int doppler_max)
|
||||
{
|
||||
doppler_max_ = doppler_max;
|
||||
|
||||
acquisition_fpga_->set_doppler_max(doppler_max_);
|
||||
}
|
||||
|
||||
|
||||
// Be aware that Doppler step should be set to 2/(3T) Hz, where T is the coherent integration time (GPS L2 period is 0.02s)
|
||||
// Doppler bin minimum size= 33 Hz
|
||||
void GpsL2MPcpsAcquisitionFpga::set_doppler_step(unsigned int doppler_step)
|
||||
{
|
||||
doppler_step_ = doppler_step;
|
||||
|
||||
acquisition_fpga_->set_doppler_step(doppler_step_);
|
||||
}
|
||||
|
||||
|
||||
void GpsL2MPcpsAcquisitionFpga::set_gnss_synchro(Gnss_Synchro* gnss_synchro)
|
||||
{
|
||||
gnss_synchro_ = gnss_synchro;
|
||||
|
||||
acquisition_fpga_->set_gnss_synchro(gnss_synchro_);
|
||||
}
|
||||
|
||||
|
||||
signed int GpsL2MPcpsAcquisitionFpga::mag()
|
||||
{
|
||||
return acquisition_fpga_->mag();
|
||||
}
|
||||
|
||||
|
||||
void GpsL2MPcpsAcquisitionFpga::init()
|
||||
{
|
||||
acquisition_fpga_->init();
|
||||
//set_local_code();
|
||||
}
|
||||
|
||||
|
||||
void GpsL2MPcpsAcquisitionFpga::set_local_code()
|
||||
{
|
||||
//gps_l2c_m_code_gen_complex_sampled(code_, gnss_synchro_->PRN, fs_in_);
|
||||
|
||||
//acquisition_fpga_->set_local_code(code_);
|
||||
acquisition_fpga_->set_local_code();
|
||||
}
|
||||
|
||||
|
||||
void GpsL2MPcpsAcquisitionFpga::reset()
|
||||
{
|
||||
acquisition_fpga_->set_active(true);
|
||||
}
|
||||
|
||||
void GpsL2MPcpsAcquisitionFpga::set_state(int state)
|
||||
{
|
||||
acquisition_fpga_->set_state(state);
|
||||
}
|
||||
|
||||
|
||||
//float GpsL2MPcpsAcquisitionFpga::calculate_threshold(float pfa)
|
||||
//{
|
||||
// //Calculate the threshold
|
||||
// unsigned int frequency_bins = 0;
|
||||
// for (int doppler = static_cast<int>(-doppler_max_); doppler <= static_cast<int>(doppler_max_); doppler += doppler_step_)
|
||||
// {
|
||||
// frequency_bins++;
|
||||
// }
|
||||
// DLOG(INFO) << "Channel " << channel_ << " Pfa = " << pfa;
|
||||
// unsigned int ncells = vector_length_ * frequency_bins;
|
||||
// double exponent = 1.0 / static_cast<double>(ncells);
|
||||
// double val = pow(1.0 - pfa, exponent);
|
||||
// double lambda = double(vector_length_);
|
||||
// boost::math::exponential_distribution<double> mydist(lambda);
|
||||
// float threshold = static_cast<float>(quantile(mydist, val));
|
||||
//
|
||||
// return threshold;
|
||||
//}
|
||||
|
||||
|
||||
void GpsL2MPcpsAcquisitionFpga::connect(gr::top_block_sptr top_block)
|
||||
{
|
||||
// if (item_type_.compare("gr_complex") == 0)
|
||||
// {
|
||||
// top_block->connect(stream_to_vector_, 0, acquisition_, 0);
|
||||
// }
|
||||
// else if (item_type_.compare("cshort") == 0)
|
||||
// {
|
||||
// top_block->connect(stream_to_vector_, 0, acquisition_, 0);
|
||||
// }
|
||||
// else if (item_type_.compare("cbyte") == 0)
|
||||
// {
|
||||
// top_block->connect(cbyte_to_float_x2_, 0, float_to_complex_, 0);
|
||||
// top_block->connect(cbyte_to_float_x2_, 1, float_to_complex_, 1);
|
||||
// top_block->connect(float_to_complex_, 0, stream_to_vector_, 0);
|
||||
// top_block->connect(stream_to_vector_, 0, acquisition_, 0);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// LOG(WARNING) << item_type_ << " unknown acquisition item type";
|
||||
// }
|
||||
|
||||
// nothing to connect
|
||||
}
|
||||
|
||||
|
||||
void GpsL2MPcpsAcquisitionFpga::disconnect(gr::top_block_sptr top_block)
|
||||
{
|
||||
// if (item_type_.compare("gr_complex") == 0)
|
||||
// {
|
||||
// top_block->disconnect(stream_to_vector_, 0, acquisition_, 0);
|
||||
// }
|
||||
// else if (item_type_.compare("cshort") == 0)
|
||||
// {
|
||||
// top_block->disconnect(stream_to_vector_, 0, acquisition_, 0);
|
||||
// }
|
||||
// else if (item_type_.compare("cbyte") == 0)
|
||||
// {
|
||||
// // Since a byte-based acq implementation is not available,
|
||||
// // we just convert cshorts to gr_complex
|
||||
// top_block->disconnect(cbyte_to_float_x2_, 0, float_to_complex_, 0);
|
||||
// top_block->disconnect(cbyte_to_float_x2_, 1, float_to_complex_, 1);
|
||||
// top_block->disconnect(float_to_complex_, 0, stream_to_vector_, 0);
|
||||
// top_block->disconnect(stream_to_vector_, 0, acquisition_, 0);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// LOG(WARNING) << item_type_ << " unknown acquisition item type";
|
||||
// }
|
||||
|
||||
// nothing to disconnect
|
||||
}
|
||||
|
||||
|
||||
gr::basic_block_sptr GpsL2MPcpsAcquisitionFpga::get_left_block()
|
||||
{
|
||||
// if (item_type_.compare("gr_complex") == 0)
|
||||
// {
|
||||
// return stream_to_vector_;
|
||||
// }
|
||||
// else if (item_type_.compare("cshort") == 0)
|
||||
// {
|
||||
// return stream_to_vector_;
|
||||
// }
|
||||
// else if (item_type_.compare("cbyte") == 0)
|
||||
// {
|
||||
// return cbyte_to_float_x2_;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// LOG(WARNING) << item_type_ << " unknown acquisition item type";
|
||||
// return nullptr;
|
||||
// }
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
gr::basic_block_sptr GpsL2MPcpsAcquisitionFpga::get_right_block()
|
||||
{
|
||||
return acquisition_fpga_;
|
||||
}
|
@ -0,0 +1,171 @@
|
||||
/*!
|
||||
* \file gps_l2_m_pcps_acquisition.h
|
||||
* \brief Adapts a PCPS acquisition block to an AcquisitionInterface for
|
||||
* GPS L2 M signals
|
||||
* \authors <ul>
|
||||
* <li> Javier Arribas, 2015. jarribas(at)cttc.es
|
||||
* </ul>
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
|
||||
*
|
||||
* GNSS-SDR is a software defined Global Navigation
|
||||
* Satellite Systems receiver
|
||||
*
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* GNSS-SDR is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GNSS-SDR is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef GNSS_SDR_GPS_L2_M_PCPS_ACQUISITION_FPGA_H_
|
||||
#define GNSS_SDR_GPS_L2_M_PCPS_ACQUISITION_FPGA_H_
|
||||
|
||||
#include "acquisition_interface.h"
|
||||
#include "gnss_synchro.h"
|
||||
#include "pcps_acquisition_fpga.h"
|
||||
#include "complex_byte_to_float_x2.h"
|
||||
#include <gnuradio/blocks/stream_to_vector.h>
|
||||
#include <gnuradio/blocks/float_to_complex.h>
|
||||
#include <volk_gnsssdr/volk_gnsssdr.h>
|
||||
#include <string>
|
||||
|
||||
|
||||
class ConfigurationInterface;
|
||||
|
||||
/*!
|
||||
* \brief This class adapts a PCPS acquisition block to an AcquisitionInterface
|
||||
* for GPS L2 M signals
|
||||
*/
|
||||
class GpsL2MPcpsAcquisitionFpga : public AcquisitionInterface
|
||||
{
|
||||
public:
|
||||
GpsL2MPcpsAcquisitionFpga(ConfigurationInterface* configuration,
|
||||
std::string role, unsigned int in_streams,
|
||||
unsigned int out_streams);
|
||||
|
||||
virtual ~GpsL2MPcpsAcquisitionFpga();
|
||||
|
||||
inline std::string role() override
|
||||
{
|
||||
return role_;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns "GPS_L2_M_PCPS_Acquisition"
|
||||
*/
|
||||
inline std::string implementation() override
|
||||
{
|
||||
return "GPS_L2_M_PCPS_Acquisition";
|
||||
}
|
||||
|
||||
inline size_t item_size() override
|
||||
{
|
||||
return item_size_;
|
||||
}
|
||||
|
||||
void connect(gr::top_block_sptr top_block) override;
|
||||
void disconnect(gr::top_block_sptr top_block) override;
|
||||
gr::basic_block_sptr get_left_block() override;
|
||||
gr::basic_block_sptr get_right_block() override;
|
||||
|
||||
/*!
|
||||
* \brief Set acquisition/tracking common Gnss_Synchro object pointer
|
||||
* to efficiently exchange synchronization data between acquisition and
|
||||
* tracking blocks
|
||||
*/
|
||||
void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) override;
|
||||
|
||||
/*!
|
||||
* \brief Set acquisition channel unique ID
|
||||
*/
|
||||
void set_channel(unsigned int channel) override;
|
||||
|
||||
/*!
|
||||
* \brief Set statistics threshold of PCPS algorithm
|
||||
*/
|
||||
void set_threshold(float threshold) override;
|
||||
|
||||
/*!
|
||||
* \brief Set maximum Doppler off grid search
|
||||
*/
|
||||
void set_doppler_max(unsigned int doppler_max) override;
|
||||
|
||||
/*!
|
||||
* \brief Set Doppler steps for the grid search
|
||||
*/
|
||||
void set_doppler_step(unsigned int doppler_step) override;
|
||||
|
||||
/*!
|
||||
* \brief Initializes acquisition algorithm.
|
||||
*/
|
||||
void init() override;
|
||||
|
||||
/*!
|
||||
* \brief Sets local code for GPS L2/M PCPS acquisition algorithm.
|
||||
*/
|
||||
void set_local_code() override;
|
||||
|
||||
/*!
|
||||
* \brief Returns the maximum peak of grid search
|
||||
*/
|
||||
signed int mag() override;
|
||||
|
||||
/*!
|
||||
* \brief Restart acquisition algorithm
|
||||
*/
|
||||
void reset() override;
|
||||
|
||||
/*!
|
||||
* \brief If state = 1, it forces the block to start acquiring from the first sample
|
||||
*/
|
||||
void set_state(int state);
|
||||
|
||||
private:
|
||||
ConfigurationInterface* configuration_;
|
||||
//pcps_acquisition_sptr acquisition_;
|
||||
pcps_acquisition_fpga_sptr acquisition_fpga_;
|
||||
gr::blocks::stream_to_vector::sptr stream_to_vector_;
|
||||
gr::blocks::float_to_complex::sptr float_to_complex_;
|
||||
complex_byte_to_float_x2_sptr cbyte_to_float_x2_;
|
||||
size_t item_size_;
|
||||
std::string item_type_;
|
||||
unsigned int vector_length_;
|
||||
unsigned int code_length_;
|
||||
bool bit_transition_flag_;
|
||||
bool use_CFAR_algorithm_flag_;
|
||||
unsigned int channel_;
|
||||
float threshold_;
|
||||
unsigned int doppler_max_;
|
||||
unsigned int doppler_step_;
|
||||
unsigned int max_dwells_;
|
||||
long fs_in_;
|
||||
long if_;
|
||||
bool dump_;
|
||||
bool blocking_;
|
||||
std::string dump_filename_;
|
||||
std::complex<float>* code_;
|
||||
Gnss_Synchro* gnss_synchro_;
|
||||
std::string role_;
|
||||
unsigned int in_streams_;
|
||||
unsigned int out_streams_;
|
||||
|
||||
lv_16sc_t* d_all_fft_codes_; // memory that contains all the code ffts
|
||||
|
||||
//float calculate_threshold(float pfa);
|
||||
};
|
||||
|
||||
#endif /* GNSS_SDR_GPS_L2_M_PCPS_ACQUISITION_FPGA_H_ */
|
@ -0,0 +1,388 @@
|
||||
/*!
|
||||
* \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)
|
||||
{
|
||||
pcpsconf_fpga_t acq_parameters;
|
||||
configuration_ = configuration;
|
||||
std::string default_item_type = "gr_complex";
|
||||
std::string default_dump_filename = "./data/acquisition.dat";
|
||||
|
||||
LOG(INFO) << "role " << role;
|
||||
|
||||
//item_type_ = configuration_->property(role + ".item_type", default_item_type);
|
||||
|
||||
long fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 2048000);
|
||||
long fs_in = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated);
|
||||
acq_parameters.fs_in = fs_in;
|
||||
if_ = configuration_->property(role + ".if", 0);
|
||||
acq_parameters.freq = if_;
|
||||
//dump_ = configuration_->property(role + ".dump", false);
|
||||
//acq_parameters.dump = dump_;
|
||||
//blocking_ = configuration_->property(role + ".blocking", true);
|
||||
//acq_parameters.blocking = blocking_;
|
||||
doppler_max_ = configuration->property(role + ".doppler_max", 5000);
|
||||
if (FLAGS_doppler_max != 0) doppler_max_ = FLAGS_doppler_max;
|
||||
acq_parameters.doppler_max = doppler_max_;
|
||||
acq_parameters.sampled_ms = 1;
|
||||
//bit_transition_flag_ = configuration_->property(role + ".bit_transition_flag", false);
|
||||
//acq_parameters.bit_transition_flag = bit_transition_flag_;
|
||||
//use_CFAR_algorithm_flag_ = configuration_->property(role + ".use_CFAR_algorithm", true); //will be false in future versions
|
||||
//acq_parameters.use_CFAR_algorithm_flag = use_CFAR_algorithm_flag_;
|
||||
//max_dwells_ = configuration_->property(role + ".max_dwells", 1);
|
||||
//acq_parameters.max_dwells = max_dwells_;
|
||||
//dump_filename_ = configuration_->property(role + ".dump_filename", default_dump_filename);
|
||||
//acq_parameters.dump_filename = dump_filename_;
|
||||
//--- Find number of samples per spreading code -------------------------
|
||||
unsigned int code_length = static_cast<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", 0);
|
||||
acq_parameters.select_queue_Fpga = select_queue_Fpga;
|
||||
std::string default_device_name = "/dev/uio0";
|
||||
std::string device_name = configuration_->property(role + ".devicename", default_device_name);
|
||||
acq_parameters.device_name = device_name;
|
||||
acq_parameters.samples_per_ms = nsamples_total;
|
||||
acq_parameters.samples_per_code = nsamples_total;
|
||||
|
||||
// compute all the GPS L5 PRN Codes (this is done only once upon the class constructor in order to avoid re-computing the PRN codes every time
|
||||
// a channel is assigned)
|
||||
gr::fft::fft_complex* fft_if = new gr::fft::fft_complex(vector_length, true); // Direct FFT
|
||||
std::complex<float>* code = new gr_complex[vector_length_];
|
||||
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_l5i_code_gen_complex_sampled(code, PRN, fs_in);
|
||||
// fill in zero padding
|
||||
for (int s = code_length; s < nsamples_total; s++)
|
||||
{
|
||||
code[s] = std::complex<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)));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
//acq_parameters
|
||||
acq_parameters.all_fft_codes = d_all_fft_codes_;
|
||||
|
||||
// temporary buffers that we can delete
|
||||
delete[] code;
|
||||
delete fft_if;
|
||||
delete[] fft_codes_padded;
|
||||
// vector_length_ = code_length_;
|
||||
//
|
||||
// if (bit_transition_flag_)
|
||||
// {
|
||||
// vector_length_ *= 2;
|
||||
// }
|
||||
//
|
||||
// code_ = new gr_complex[vector_length_];
|
||||
//
|
||||
// if (item_type_.compare("cshort") == 0)
|
||||
// {
|
||||
// item_size_ = sizeof(lv_16sc_t);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// item_size_ = sizeof(gr_complex);
|
||||
// }
|
||||
// acq_parameters.samples_per_code = code_length_;
|
||||
// acq_parameters.samples_per_ms = code_length_;
|
||||
// acq_parameters.it_size = item_size_;
|
||||
//acq_parameters.sampled_ms = 1;
|
||||
// acq_parameters.num_doppler_bins_step2 = configuration_->property(role + ".second_nbins", 4);
|
||||
// acq_parameters.doppler_step2 = configuration_->property(role + ".second_doppler_step", 125.0);
|
||||
// acq_parameters.make_2_steps = configuration_->property(role + ".make_two_steps", false);
|
||||
// acquisition_fpga_ = pcps_make_acquisition(acq_parameters);
|
||||
// DLOG(INFO) << "acquisition(" << acquisition_fpga_->unique_id() << ")";
|
||||
|
||||
acquisition_fpga_ = pcps_make_acquisition_fpga(acq_parameters);
|
||||
DLOG(INFO) << "acquisition(" << acquisition_fpga_->unique_id() << ")";
|
||||
|
||||
// stream_to_vector_ = gr::blocks::stream_to_vector::make(item_size_, vector_length_);
|
||||
// DLOG(INFO) << "stream_to_vector(" << stream_to_vector_->unique_id() << ")";
|
||||
//
|
||||
// if (item_type_.compare("cbyte") == 0)
|
||||
// {
|
||||
// cbyte_to_float_x2_ = make_complex_byte_to_float_x2();
|
||||
// float_to_complex_ = gr::blocks::float_to_complex::make();
|
||||
// }
|
||||
|
||||
channel_ = 0;
|
||||
// threshold_ = 0.0;
|
||||
doppler_step_ = 0;
|
||||
gnss_synchro_ = 0;
|
||||
}
|
||||
|
||||
|
||||
GpsL5iPcpsAcquisitionFpga::~GpsL5iPcpsAcquisitionFpga()
|
||||
{
|
||||
//delete[] code_;
|
||||
delete[] d_all_fft_codes_;
|
||||
}
|
||||
|
||||
|
||||
void GpsL5iPcpsAcquisitionFpga::set_channel(unsigned int channel)
|
||||
{
|
||||
channel_ = channel;
|
||||
acquisition_fpga_->set_channel(channel_);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void GpsL5iPcpsAcquisitionFpga::set_threshold(float threshold)
|
||||
{
|
||||
// float pfa = configuration_->property(role_ + boost::lexical_cast<std::string>(channel_) + ".pfa", 0.0);
|
||||
//
|
||||
// if (pfa == 0.0)
|
||||
// {
|
||||
// pfa = configuration_->property(role_ + ".pfa", 0.0);
|
||||
// }
|
||||
// if (pfa == 0.0)
|
||||
// {
|
||||
// threshold_ = threshold;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// threshold_ = calculate_threshold(pfa);
|
||||
// }
|
||||
|
||||
// DLOG(INFO) << "Channel " << channel_ << " Threshold = " << threshold_;
|
||||
|
||||
// the .pfa parameter and the threshold calculation is only used for the CFAR algorithm.
|
||||
// We don't use the CFAR algorithm in the FPGA. Therefore the threshold is set as such.
|
||||
DLOG(INFO) << "Channel " << channel_ << " Threshold = " << threshold;
|
||||
acquisition_fpga_->set_threshold(threshold);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void GpsL5iPcpsAcquisitionFpga::set_doppler_max(unsigned int doppler_max)
|
||||
{
|
||||
doppler_max_ = doppler_max;
|
||||
acquisition_fpga_->set_doppler_max(doppler_max_);
|
||||
}
|
||||
|
||||
|
||||
// Be aware that Doppler step should be set to 2/(3T) Hz, where T is the coherent integration time (GPS L2 period is 0.02s)
|
||||
// Doppler bin minimum size= 33 Hz
|
||||
void GpsL5iPcpsAcquisitionFpga::set_doppler_step(unsigned int doppler_step)
|
||||
{
|
||||
doppler_step_ = doppler_step;
|
||||
acquisition_fpga_->set_doppler_step(doppler_step_);
|
||||
}
|
||||
|
||||
|
||||
void GpsL5iPcpsAcquisitionFpga::set_gnss_synchro(Gnss_Synchro* gnss_synchro)
|
||||
{
|
||||
gnss_synchro_ = gnss_synchro;
|
||||
acquisition_fpga_->set_gnss_synchro(gnss_synchro_);
|
||||
}
|
||||
|
||||
|
||||
signed int GpsL5iPcpsAcquisitionFpga::mag()
|
||||
{
|
||||
return acquisition_fpga_->mag();
|
||||
}
|
||||
|
||||
|
||||
void GpsL5iPcpsAcquisitionFpga::init()
|
||||
{
|
||||
acquisition_fpga_->init();
|
||||
}
|
||||
|
||||
void GpsL5iPcpsAcquisitionFpga::set_local_code()
|
||||
{
|
||||
acquisition_fpga_->set_local_code();
|
||||
}
|
||||
|
||||
|
||||
void GpsL5iPcpsAcquisitionFpga::reset()
|
||||
{
|
||||
acquisition_fpga_->set_active(true);
|
||||
}
|
||||
|
||||
void GpsL5iPcpsAcquisitionFpga::set_state(int state)
|
||||
{
|
||||
acquisition_fpga_->set_state(state);
|
||||
}
|
||||
|
||||
|
||||
//float GpsL5iPcpsAcquisitionFpga::calculate_threshold(float pfa)
|
||||
//{
|
||||
// //Calculate the threshold
|
||||
// unsigned int frequency_bins = 0;
|
||||
// for (int doppler = static_cast<int>(-doppler_max_); doppler <= static_cast<int>(doppler_max_); doppler += doppler_step_)
|
||||
// {
|
||||
// frequency_bins++;
|
||||
// }
|
||||
// DLOG(INFO) << "Channel " << channel_ << " Pfa = " << pfa;
|
||||
// unsigned int ncells = vector_length_ * frequency_bins;
|
||||
// double exponent = 1.0 / static_cast<double>(ncells);
|
||||
// double val = pow(1.0 - pfa, exponent);
|
||||
// double lambda = double(vector_length_);
|
||||
// boost::math::exponential_distribution<double> mydist(lambda);
|
||||
// float threshold = static_cast<float>(quantile(mydist, val));
|
||||
//
|
||||
// return threshold;
|
||||
//}
|
||||
|
||||
|
||||
void GpsL5iPcpsAcquisitionFpga::connect(gr::top_block_sptr top_block)
|
||||
{
|
||||
// if (item_type_.compare("gr_complex") == 0)
|
||||
// {
|
||||
// top_block->connect(stream_to_vector_, 0, acquisition_fpga_, 0);
|
||||
// }
|
||||
// else if (item_type_.compare("cshort") == 0)
|
||||
// {
|
||||
// top_block->connect(stream_to_vector_, 0, acquisition_fpga_, 0);
|
||||
// }
|
||||
// else if (item_type_.compare("cbyte") == 0)
|
||||
// {
|
||||
// top_block->connect(cbyte_to_float_x2_, 0, float_to_complex_, 0);
|
||||
// top_block->connect(cbyte_to_float_x2_, 1, float_to_complex_, 1);
|
||||
// top_block->connect(float_to_complex_, 0, stream_to_vector_, 0);
|
||||
// top_block->connect(stream_to_vector_, 0, acquisition_fpga_, 0);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// LOG(WARNING) << item_type_ << " unknown acquisition item type";
|
||||
// }
|
||||
// nothing to connect
|
||||
}
|
||||
|
||||
|
||||
void GpsL5iPcpsAcquisitionFpga::disconnect(gr::top_block_sptr top_block)
|
||||
{
|
||||
// if (item_type_.compare("gr_complex") == 0)
|
||||
// {
|
||||
// top_block->disconnect(stream_to_vector_, 0, acquisition_fpga_, 0);
|
||||
// }
|
||||
// else if (item_type_.compare("cshort") == 0)
|
||||
// {
|
||||
// top_block->disconnect(stream_to_vector_, 0, acquisition_fpga_, 0);
|
||||
// }
|
||||
// else if (item_type_.compare("cbyte") == 0)
|
||||
// {
|
||||
// // Since a byte-based acq implementation is not available,
|
||||
// // we just convert cshorts to gr_complex
|
||||
// top_block->disconnect(cbyte_to_float_x2_, 0, float_to_complex_, 0);
|
||||
// top_block->disconnect(cbyte_to_float_x2_, 1, float_to_complex_, 1);
|
||||
// top_block->disconnect(float_to_complex_, 0, stream_to_vector_, 0);
|
||||
// top_block->disconnect(stream_to_vector_, 0, acquisition_fpga_, 0);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// LOG(WARNING) << item_type_ << " unknown acquisition item type";
|
||||
// }
|
||||
// nothing to disconnect
|
||||
}
|
||||
|
||||
|
||||
gr::basic_block_sptr GpsL5iPcpsAcquisitionFpga::get_left_block()
|
||||
{
|
||||
// if (item_type_.compare("gr_complex") == 0)
|
||||
// {
|
||||
// return stream_to_vector_;
|
||||
// }
|
||||
// else if (item_type_.compare("cshort") == 0)
|
||||
// {
|
||||
// return stream_to_vector_;
|
||||
// }
|
||||
// else if (item_type_.compare("cbyte") == 0)
|
||||
// {
|
||||
// return cbyte_to_float_x2_;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// LOG(WARNING) << item_type_ << " unknown acquisition item type";
|
||||
// return nullptr;
|
||||
// }
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
gr::basic_block_sptr GpsL5iPcpsAcquisitionFpga::get_right_block()
|
||||
{
|
||||
return acquisition_fpga_;
|
||||
}
|
@ -0,0 +1,171 @@
|
||||
/*!
|
||||
* \file GPS_L5i_PCPS_Acquisition.h
|
||||
* \brief Adapts a PCPS acquisition block to an AcquisitionInterface for
|
||||
* GPS L5i signals
|
||||
* \authors <ul>
|
||||
* <li> Javier Arribas, 2017. jarribas(at)cttc.es
|
||||
* </ul>
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (C) 2010-2017 (see AUTHORS file for a list of contributors)
|
||||
*
|
||||
* GNSS-SDR is a software defined Global Navigation
|
||||
* Satellite Systems receiver
|
||||
*
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* GNSS-SDR is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GNSS-SDR is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef GNSS_SDR_GPS_L5i_PCPS_ACQUISITION_FPGA_H_
|
||||
#define GNSS_SDR_GPS_L5i_PCPS_ACQUISITION_FPGA_H_
|
||||
|
||||
#include "acquisition_interface.h"
|
||||
#include "gnss_synchro.h"
|
||||
#include "pcps_acquisition_fpga.h"
|
||||
#include "complex_byte_to_float_x2.h"
|
||||
#include <gnuradio/blocks/stream_to_vector.h>
|
||||
#include <gnuradio/blocks/float_to_complex.h>
|
||||
#include <volk_gnsssdr/volk_gnsssdr.h>
|
||||
#include <string>
|
||||
|
||||
|
||||
class ConfigurationInterface;
|
||||
|
||||
/*!
|
||||
* \brief This class adapts a PCPS acquisition block to an AcquisitionInterface
|
||||
* for GPS L5i signals
|
||||
*/
|
||||
class GpsL5iPcpsAcquisitionFpga : public AcquisitionInterface
|
||||
{
|
||||
public:
|
||||
GpsL5iPcpsAcquisitionFpga(ConfigurationInterface* configuration,
|
||||
std::string role, unsigned int in_streams,
|
||||
unsigned int out_streams);
|
||||
|
||||
virtual ~GpsL5iPcpsAcquisitionFpga();
|
||||
|
||||
inline std::string role() override
|
||||
{
|
||||
return role_;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Returns "GPS_L5i_PCPS_Acquisition"
|
||||
*/
|
||||
inline std::string implementation() override
|
||||
{
|
||||
return "GPS_L5i_PCPS_Acquisition";
|
||||
}
|
||||
|
||||
inline size_t item_size() override
|
||||
{
|
||||
return item_size_;
|
||||
}
|
||||
|
||||
void connect(gr::top_block_sptr top_block) override;
|
||||
void disconnect(gr::top_block_sptr top_block) override;
|
||||
gr::basic_block_sptr get_left_block() override;
|
||||
gr::basic_block_sptr get_right_block() override;
|
||||
|
||||
/*!
|
||||
* \brief Set acquisition/tracking common Gnss_Synchro object pointer
|
||||
* to efficiently exchange synchronization data between acquisition and
|
||||
* tracking blocks
|
||||
*/
|
||||
void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) override;
|
||||
|
||||
/*!
|
||||
* \brief Set acquisition channel unique ID
|
||||
*/
|
||||
void set_channel(unsigned int channel) override;
|
||||
|
||||
/*!
|
||||
* \brief Set statistics threshold of PCPS algorithm
|
||||
*/
|
||||
void set_threshold(float threshold) override;
|
||||
|
||||
/*!
|
||||
* \brief Set maximum Doppler off grid search
|
||||
*/
|
||||
void set_doppler_max(unsigned int doppler_max) override;
|
||||
|
||||
/*!
|
||||
* \brief Set Doppler steps for the grid search
|
||||
*/
|
||||
void set_doppler_step(unsigned int doppler_step) override;
|
||||
|
||||
/*!
|
||||
* \brief Initializes acquisition algorithm.
|
||||
*/
|
||||
void init() override;
|
||||
|
||||
/*!
|
||||
* \brief Sets local code for GPS L2/M PCPS acquisition algorithm.
|
||||
*/
|
||||
void set_local_code() override;
|
||||
|
||||
/*!
|
||||
* \brief Returns the maximum peak of grid search
|
||||
*/
|
||||
signed int mag() override;
|
||||
|
||||
/*!
|
||||
* \brief Restart acquisition algorithm
|
||||
*/
|
||||
void reset() override;
|
||||
|
||||
/*!
|
||||
* \brief If state = 1, it forces the block to start acquiring from the first sample
|
||||
*/
|
||||
void set_state(int state);
|
||||
|
||||
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_ */
|
@ -43,6 +43,9 @@
|
||||
#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,27 +76,50 @@ pcps_acquisition_fpga::pcps_acquisition_fpga(pcpsconf_fpga_t conf_) : gr::block(
|
||||
d_channel = 0;
|
||||
d_gnss_synchro = 0;
|
||||
|
||||
//printf("zzzz acq_parameters.code_length = %d\n", acq_parameters.code_length);
|
||||
//printf("zzzz acq_parameters.samples_per_ms = %d\n", acq_parameters.samples_per_ms);
|
||||
//printf("zzzz d_fft_size = %d\n", d_fft_size);
|
||||
|
||||
// this one works we don't know why
|
||||
// acquisition_fpga = std::make_shared <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, d_fft_size, acq_parameters.doppler_max, acq_parameters.samples_per_ms,
|
||||
(acq_parameters.device_name, acq_parameters.code_length, acq_parameters.doppler_max, d_fft_size,
|
||||
acq_parameters.fs_in, acq_parameters.freq, acq_parameters.sampled_ms, acq_parameters.select_queue_Fpga, acq_parameters.all_fft_codes);
|
||||
|
||||
// acquisition_fpga = std::make_shared <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;
|
||||
@ -104,11 +132,13 @@ void pcps_acquisition_fpga::init()
|
||||
d_num_doppler_bins = static_cast<unsigned int>(std::ceil(static_cast<double>(static_cast<int>(acq_parameters.doppler_max) - static_cast<int>(-acq_parameters.doppler_max)) / static_cast<double>(d_doppler_step)));
|
||||
|
||||
acquisition_fpga->init();
|
||||
// printf("acq init end\n");
|
||||
}
|
||||
|
||||
|
||||
void pcps_acquisition_fpga::set_state(int state)
|
||||
{
|
||||
// printf("acq set state start\n");
|
||||
d_state = state;
|
||||
if (d_state == 1)
|
||||
{
|
||||
@ -128,11 +158,13 @@ void pcps_acquisition_fpga::set_state(int state)
|
||||
{
|
||||
LOG(ERROR) << "State can only be set to 0 or 1";
|
||||
}
|
||||
// printf("acq set state end\n");
|
||||
}
|
||||
|
||||
|
||||
void pcps_acquisition_fpga::send_positive_acquisition()
|
||||
{
|
||||
// printf("acq send positive acquisition start\n");
|
||||
// 6.1- Declare positive acquisition using a message port
|
||||
//0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL
|
||||
DLOG(INFO) << "positive acquisition"
|
||||
@ -146,11 +178,13 @@ void pcps_acquisition_fpga::send_positive_acquisition()
|
||||
<< ", input signal power " << d_input_power;
|
||||
|
||||
this->message_port_pub(pmt::mp("events"), pmt::from_long(1));
|
||||
// printf("acq send positive acquisition end\n");
|
||||
}
|
||||
|
||||
|
||||
void pcps_acquisition_fpga::send_negative_acquisition()
|
||||
{
|
||||
// printf("acq send negative acquisition start\n");
|
||||
// 6.2- Declare negative acquisition using a message port
|
||||
//0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL
|
||||
DLOG(INFO) << "negative acquisition"
|
||||
@ -164,11 +198,13 @@ void pcps_acquisition_fpga::send_negative_acquisition()
|
||||
<< ", input signal power " << d_input_power;
|
||||
|
||||
this->message_port_pub(pmt::mp("events"), pmt::from_long(2));
|
||||
// printf("acq send negative acquisition end\n");
|
||||
}
|
||||
|
||||
|
||||
void pcps_acquisition_fpga::set_active(bool active)
|
||||
{
|
||||
// printf("acq set active start\n");
|
||||
d_active = active;
|
||||
|
||||
// initialize acquisition algorithm
|
||||
@ -190,21 +226,29 @@ void pcps_acquisition_fpga::set_active(bool active)
|
||||
unsigned int initial_sample;
|
||||
float input_power_all = 0.0;
|
||||
float input_power_computed = 0.0;
|
||||
|
||||
float temp_d_input_power;
|
||||
|
||||
// loop through acquisition
|
||||
/*
|
||||
for (unsigned int doppler_index = 0; doppler_index < d_num_doppler_bins; doppler_index++)
|
||||
{
|
||||
// doppler search steps
|
||||
int doppler = -static_cast<int>(acq_parameters.doppler_max) + d_doppler_step * doppler_index;
|
||||
|
||||
acquisition_fpga->set_phase_step(doppler_index);
|
||||
//acquisition_fpga->set_phase_step(doppler_index);
|
||||
acquisition_fpga->set_doppler_sweep_debug(1, doppler_index);
|
||||
acquisition_fpga->run_acquisition(); // runs acquisition and waits until it is finished
|
||||
acquisition_fpga->read_acquisition_results(&indext, &magt,
|
||||
&initial_sample, &d_input_power);
|
||||
&initial_sample, &d_input_power, &d_doppler_index);
|
||||
d_sample_counter = initial_sample;
|
||||
|
||||
if (d_mag < magt)
|
||||
{
|
||||
d_mag = magt;
|
||||
|
||||
temp_d_input_power = d_input_power;
|
||||
|
||||
input_power_all = d_input_power / (d_fft_size - 1);
|
||||
input_power_computed = (d_input_power - d_mag) / (d_fft_size - 1);
|
||||
d_input_power = (d_input_power - d_mag) / (d_fft_size - 1);
|
||||
@ -219,10 +263,72 @@ void pcps_acquisition_fpga::set_active(bool active)
|
||||
// In the case of the FPGA the option of dumping the results of the acquisition to a file is not available
|
||||
// because the IFFT vector is not available
|
||||
}
|
||||
*/
|
||||
|
||||
// debug
|
||||
//acquisition_fpga->block_samples();
|
||||
|
||||
// run loop in hw
|
||||
acquisition_fpga->set_doppler_sweep(d_num_doppler_bins);
|
||||
acquisition_fpga->run_acquisition();
|
||||
acquisition_fpga->read_acquisition_results(&indext, &magt,
|
||||
&initial_sample, &d_input_power, &d_doppler_index);
|
||||
|
||||
|
||||
// debug
|
||||
//acquisition_fpga->unblock_samples();
|
||||
|
||||
d_mag = magt;
|
||||
|
||||
|
||||
// debug
|
||||
debug_d_max_absolute = magt;
|
||||
debug_d_input_power_absolute = d_input_power;
|
||||
debug_indext = indext;
|
||||
debug_doppler_index = d_doppler_index;
|
||||
|
||||
// temp_d_input_power = d_input_power;
|
||||
|
||||
d_input_power = (d_input_power - d_mag) / (d_fft_size - 1);
|
||||
int doppler = -static_cast<int>(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("##### debug_indext = %d\n",debug_indext);
|
||||
printf("##### debug_doppler_index = %d\n",debug_doppler_index);
|
||||
send_positive_acquisition();
|
||||
d_state = 0; // Positive acquisition
|
||||
}
|
||||
@ -232,6 +338,9 @@ void pcps_acquisition_fpga::set_active(bool active)
|
||||
d_active = false;
|
||||
send_negative_acquisition();
|
||||
}
|
||||
|
||||
// printf("acq set active end\n");
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -70,6 +70,7 @@ typedef struct
|
||||
long fs_in;
|
||||
int samples_per_ms;
|
||||
int samples_per_code;
|
||||
int code_length;
|
||||
unsigned int select_queue_Fpga;
|
||||
std::string device_name;
|
||||
lv_16sc_t* all_fft_codes; // memory that contains all the code ffts
|
||||
@ -107,6 +108,7 @@ private:
|
||||
float d_threshold;
|
||||
float d_mag;
|
||||
float d_input_power;
|
||||
unsigned d_doppler_index;
|
||||
float d_test_statistics;
|
||||
int d_state;
|
||||
unsigned int d_channel;
|
||||
@ -117,6 +119,12 @@ private:
|
||||
Gnss_Synchro* d_gnss_synchro;
|
||||
std::shared_ptr<fpga_acquisition> acquisition_fpga;
|
||||
|
||||
// debug
|
||||
float debug_d_max_absolute;
|
||||
float debug_d_input_power_absolute;
|
||||
int debug_indext;
|
||||
int debug_doppler_index;
|
||||
|
||||
public:
|
||||
~pcps_acquisition_fpga();
|
||||
|
||||
@ -127,7 +135,9 @@ public:
|
||||
*/
|
||||
inline void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro)
|
||||
{
|
||||
// printf("acq set gnss synchro start\n");
|
||||
d_gnss_synchro = p_gnss_synchro;
|
||||
// printf("acq set gnss synchro end\n");
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -135,7 +145,9 @@ public:
|
||||
*/
|
||||
inline unsigned int mag() const
|
||||
{
|
||||
// printf("acq dmag start\n");
|
||||
return d_mag;
|
||||
// printf("acq dmag end\n");
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -179,7 +191,9 @@ public:
|
||||
*/
|
||||
inline void set_threshold(float threshold)
|
||||
{
|
||||
// printf("acq set threshold start\n");
|
||||
d_threshold = threshold;
|
||||
// printf("acq set threshold end\n");
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -188,8 +202,10 @@ public:
|
||||
*/
|
||||
inline void set_doppler_max(unsigned int doppler_max)
|
||||
{
|
||||
// printf("acq set doppler max start\n");
|
||||
acq_parameters.doppler_max = doppler_max;
|
||||
acquisition_fpga->set_doppler_max(doppler_max);
|
||||
// printf("acq set doppler max end\n");
|
||||
}
|
||||
|
||||
/*!
|
||||
@ -198,8 +214,10 @@ public:
|
||||
*/
|
||||
inline void set_doppler_step(unsigned int doppler_step)
|
||||
{
|
||||
// printf("acq set doppler step start\n");
|
||||
d_doppler_step = doppler_step;
|
||||
acquisition_fpga->set_doppler_step(doppler_step);
|
||||
// printf("acq set doppler step end\n");
|
||||
}
|
||||
|
||||
/*!
|
||||
|
@ -55,6 +55,18 @@
|
||||
#define SELECT_16_BITS 0xFFFF // value to select 16 bits
|
||||
#define SHL_8_BITS 256 // value used to shift a value 8 bits to the left
|
||||
|
||||
// 12-bits
|
||||
//#define SELECT_LSBits 0x0FFF
|
||||
//#define SELECT_MSBbits 0x00FFF000
|
||||
//#define SELECT_24_BITS 0x00FFFFFF
|
||||
//#define SHL_12_BITS 4096
|
||||
// 16-bits
|
||||
#define SELECT_LSBits 0x0FFFF
|
||||
#define SELECT_MSBbits 0xFFFF0000
|
||||
#define SELECT_32_BITS 0xFFFFFFFF
|
||||
#define SHL_16_BITS 65536
|
||||
|
||||
|
||||
|
||||
bool fpga_acquisition::init()
|
||||
{
|
||||
@ -69,6 +81,10 @@ bool fpga_acquisition::set_local_code(unsigned int PRN)
|
||||
// select the code with the chosen PRN
|
||||
fpga_acquisition::fpga_configure_acquisition_local_code(
|
||||
&d_all_fft_codes[d_nsamples_total * (PRN - 1)]);
|
||||
|
||||
//fpga_acquisition::fpga_configure_acquisition_local_code(
|
||||
// &d_all_fft_codes[0]);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -80,7 +96,11 @@ fpga_acquisition::fpga_acquisition(std::string device_name,
|
||||
unsigned int sampled_ms, unsigned select_queue,
|
||||
lv_16sc_t *all_fft_codes)
|
||||
{
|
||||
unsigned int vector_length = nsamples_total * sampled_ms;
|
||||
//printf("AAA- sampled_ms = %d\n ", sampled_ms);
|
||||
|
||||
unsigned int vector_length = nsamples_total; // * sampled_ms;
|
||||
|
||||
//printf("AAA- vector_length = %d\n ", vector_length);
|
||||
// initial values
|
||||
d_device_name = device_name;
|
||||
d_freq = freq;
|
||||
@ -99,6 +119,7 @@ fpga_acquisition::fpga_acquisition(std::string device_name,
|
||||
if ((d_fd = open(d_device_name.c_str(), O_RDWR | O_SYNC)) == -1)
|
||||
{
|
||||
LOG(WARNING) << "Cannot open deviceio" << d_device_name;
|
||||
std::cout << "Acq: cannot open deviceio" << d_device_name << std::endl;
|
||||
}
|
||||
d_map_base = reinterpret_cast<volatile unsigned *>(mmap(NULL, PAGE_SIZE,
|
||||
PROT_READ | PROT_WRITE, MAP_SHARED, d_fd, 0));
|
||||
@ -106,6 +127,7 @@ fpga_acquisition::fpga_acquisition(std::string device_name,
|
||||
if (d_map_base == reinterpret_cast<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
|
||||
@ -119,6 +141,7 @@ fpga_acquisition::fpga_acquisition(std::string device_name,
|
||||
else
|
||||
{
|
||||
LOG(INFO) << "Acquisition test register sanity check success!";
|
||||
//std::cout << "Acquisition test register sanity check success!" << std::endl;
|
||||
}
|
||||
fpga_acquisition::reset_acquisition();
|
||||
DLOG(INFO) << "Acquisition FPGA class created";
|
||||
@ -151,35 +174,53 @@ unsigned fpga_acquisition::fpga_acquisition_test_register(unsigned writeval)
|
||||
|
||||
void fpga_acquisition::fpga_configure_acquisition_local_code(lv_16sc_t fft_local_code[])
|
||||
{
|
||||
unsigned short local_code;
|
||||
//unsigned short local_code;
|
||||
unsigned int local_code;
|
||||
unsigned int k, tmp, tmp2;
|
||||
unsigned int fft_data;
|
||||
// clear memory address counter
|
||||
d_map_base[4] = LOCAL_CODE_CLEAR_MEM;
|
||||
//d_map_base[6] = LOCAL_CODE_CLEAR_MEM;
|
||||
d_map_base[9] = LOCAL_CODE_CLEAR_MEM;
|
||||
// write local code
|
||||
for (k = 0; k < d_vector_length; k++)
|
||||
{
|
||||
tmp = fft_local_code[k].real();
|
||||
tmp2 = fft_local_code[k].imag();
|
||||
local_code = (tmp & SELECT_LSB) | ((tmp2 * SHL_8_BITS) & SELECT_MSB); // put together the real part and the imaginary part
|
||||
fft_data = MEM_LOCAL_CODE_WR_ENABLE | (local_code & SELECT_16_BITS);
|
||||
d_map_base[4] = fft_data;
|
||||
//tmp = k;
|
||||
//tmp2 = k;
|
||||
|
||||
//local_code = (tmp & SELECT_LSB) | ((tmp2 * SHL_8_BITS) & SELECT_MSB); // put together the real part and the imaginary part
|
||||
//fft_data = MEM_LOCAL_CODE_WR_ENABLE | (local_code & SELECT_16_BITS);
|
||||
//local_code = (tmp & SELECT_LSBits) | ((tmp2 * SHL_12_BITS) & SELECT_MSBbits); // put together the real part and the imaginary part
|
||||
local_code = (tmp & SELECT_LSBits) | ((tmp2 * SHL_16_BITS) & SELECT_MSBbits); // put together the real part and the imaginary part
|
||||
//fft_data = MEM_LOCAL_CODE_WR_ENABLE | (local_code & SELECT_24_BITS);
|
||||
fft_data = local_code & SELECT_32_BITS;
|
||||
d_map_base[6] = fft_data;
|
||||
|
||||
|
||||
//printf("debug local code %d real = %d imag = %d local_code = %d fft_data = %d\n", k, tmp, tmp2, local_code, fft_data);
|
||||
//printf("debug local code %d real = 0x%08X imag = 0x%08X local_code = 0x%08X fft_data = 0x%08X\n", k, tmp, tmp2, local_code, fft_data);
|
||||
}
|
||||
//printf("d_vector_length = %d\n", d_vector_length);
|
||||
//while(1);
|
||||
}
|
||||
|
||||
|
||||
void fpga_acquisition::run_acquisition(void)
|
||||
{
|
||||
|
||||
// enable interrupts
|
||||
int reenable = 1;
|
||||
write(d_fd, reinterpret_cast<void *>(&reenable), sizeof(int));
|
||||
// launch the acquisition process
|
||||
d_map_base[6] = LAUNCH_ACQUISITION; // writing anything to reg 6 launches the acquisition process
|
||||
//printf("launchin acquisition ...\n");
|
||||
d_map_base[8] = LAUNCH_ACQUISITION; // writing a 1 to reg 8 launches the acquisition process
|
||||
|
||||
int irq_count;
|
||||
ssize_t nb;
|
||||
// wait for interrupt
|
||||
nb = read(d_fd, &irq_count, sizeof(irq_count));
|
||||
//printf("interrupt received\n");
|
||||
if (nb != sizeof(irq_count))
|
||||
{
|
||||
printf("acquisition module Read failed to retrieve 4 bytes!\n");
|
||||
@ -188,12 +229,111 @@ void fpga_acquisition::run_acquisition(void)
|
||||
}
|
||||
|
||||
|
||||
|
||||
void fpga_acquisition::set_doppler_sweep(unsigned int num_sweeps)
|
||||
{
|
||||
float phase_step_rad_real;
|
||||
float phase_step_rad_int_temp;
|
||||
int32_t phase_step_rad_int;
|
||||
//int doppler = static_cast<int>(-d_doppler_max) + d_doppler_step * doppler_index;
|
||||
int doppler = static_cast<int>(-d_doppler_max);
|
||||
float phase_step_rad = GPS_TWO_PI * (d_freq + 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 = (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<int>(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 = (int32_t)(phase_step_rad_int_temp * (POW_2_29)); // * 2^29 (in total it makes x2^31 in two steps to avoid the warnings
|
||||
//printf("AAA writing phase_step_rad_int for doppler step = %d to d map base 4\n", phase_step_rad_int);
|
||||
d_map_base[4] = phase_step_rad_int;
|
||||
//printf("AAA writing num sweeps to d map base 5 = %d\n", num_sweeps);
|
||||
d_map_base[5] = num_sweeps;
|
||||
}
|
||||
|
||||
void fpga_acquisition::set_doppler_sweep_debug(unsigned int num_sweeps, unsigned int doppler_index)
|
||||
{
|
||||
float phase_step_rad_real;
|
||||
float phase_step_rad_int_temp;
|
||||
int32_t phase_step_rad_int;
|
||||
int doppler = static_cast<int>(-d_doppler_max) + d_doppler_step * doppler_index;
|
||||
//int doppler = static_cast<int>(-d_doppler_max);
|
||||
float phase_step_rad = GPS_TWO_PI * (d_freq + 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 = (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<int>(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 = (int32_t)(phase_step_rad_int_temp * (POW_2_29)); // * 2^29 (in total it makes x2^31 in two steps to avoid the warnings
|
||||
//printf("AAAh writing phase_step_rad_int for doppler step = %d to d map base 4\n", phase_step_rad_int);
|
||||
d_map_base[4] = phase_step_rad_int;
|
||||
//printf("AAAh writing num sweeps to d map base 5 = %d\n", num_sweeps);
|
||||
d_map_base[5] = num_sweeps;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void fpga_acquisition::configure_acquisition()
|
||||
{
|
||||
d_map_base[0] = d_select_queue;
|
||||
//printf("AAA writing d_vector_length = %d to d map base 1\n ", d_vector_length);
|
||||
d_map_base[1] = d_vector_length;
|
||||
//printf("AAA writing d_nsamples = %d to d map base 2\n ", d_nsamples);
|
||||
d_map_base[2] = d_nsamples;
|
||||
d_map_base[5] = (int)log2((float)d_vector_length); // log2 FFTlength
|
||||
//printf("AAA writing LOG2 d_vector_length = %d to d map base 7\n ", (int)log2((float)d_vector_length));
|
||||
d_map_base[7] = (int)log2((float)d_vector_length); // log2 FFTlength
|
||||
//printf("acquisition debug vector length = %d\n", d_vector_length);
|
||||
//printf("acquisition debug vector length = %d\n", (int)log2((float)d_vector_length));
|
||||
}
|
||||
|
||||
|
||||
@ -211,28 +351,38 @@ void fpga_acquisition::set_phase_step(unsigned int doppler_index)
|
||||
phase_step_rad_real = phase_step_rad / (GPS_TWO_PI / 2);
|
||||
// avoid saturation of the fixed point representation in the fpga
|
||||
// (only the positive value can saturate due to the 2's complement representation)
|
||||
//printf("AAA+ phase_step_rad_real = %f\n", phase_step_rad_real);
|
||||
if (phase_step_rad_real >= 1.0)
|
||||
{
|
||||
phase_step_rad_real = MAX_PHASE_STEP_RAD;
|
||||
}
|
||||
//printf("AAA+ phase_step_rad_real after checking = %f\n", phase_step_rad_real);
|
||||
phase_step_rad_int_temp = phase_step_rad_real * POW_2_2; // * 2^2
|
||||
phase_step_rad_int = (int32_t)(phase_step_rad_int_temp * (POW_2_29)); // * 2^29 (in total it makes x2^31 in two steps to avoid the warnings
|
||||
//printf("writing phase_step_rad_int = %d to d_map_base 3\n", phase_step_rad_int);
|
||||
d_map_base[3] = phase_step_rad_int;
|
||||
}
|
||||
|
||||
|
||||
void fpga_acquisition::read_acquisition_results(uint32_t *max_index,
|
||||
float *max_magnitude, unsigned *initial_sample, float *power_sum)
|
||||
float *max_magnitude, unsigned *initial_sample, float *power_sum, unsigned *doppler_index)
|
||||
{
|
||||
unsigned readval = 0;
|
||||
readval = d_map_base[1];
|
||||
*initial_sample = readval;
|
||||
//printf("read initial sample dmap 1 = %d\n", readval);
|
||||
readval = d_map_base[2];
|
||||
*max_magnitude = static_cast<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);
|
||||
}
|
||||
|
||||
|
||||
@ -261,5 +411,5 @@ void fpga_acquisition::close_device()
|
||||
|
||||
void fpga_acquisition::reset_acquisition(void)
|
||||
{
|
||||
d_map_base[6] = RESET_ACQUISITION; // writing a 2 to d_map_base[6] resets the multicorrelator
|
||||
d_map_base[8] = RESET_ACQUISITION; // writing a 2 to d_map_base[8] resets the multicorrelator
|
||||
}
|
||||
|
@ -56,10 +56,12 @@ public:
|
||||
bool set_local_code(
|
||||
unsigned int PRN);
|
||||
bool free();
|
||||
void set_doppler_sweep(unsigned int num_sweeps);
|
||||
void set_doppler_sweep_debug(unsigned int num_sweeps, unsigned int doppler_index);
|
||||
void run_acquisition(void);
|
||||
void set_phase_step(unsigned int doppler_index);
|
||||
void read_acquisition_results(uint32_t *max_index, float *max_magnitude,
|
||||
unsigned *initial_sample, float *power_sum);
|
||||
unsigned *initial_sample, float *power_sum, unsigned *doppler_index);
|
||||
void block_samples();
|
||||
void unblock_samples();
|
||||
|
||||
@ -102,6 +104,7 @@ private:
|
||||
void configure_acquisition();
|
||||
void reset_acquisition(void);
|
||||
void close_device();
|
||||
|
||||
};
|
||||
|
||||
#endif /* GNSS_SDR_FPGA_ACQUISITION_H_ */
|
||||
|
@ -22,7 +22,7 @@ if(ENABLE_CUDA)
|
||||
endif(ENABLE_CUDA)
|
||||
|
||||
if(ENABLE_FPGA)
|
||||
SET(OPT_TRACKING_ADAPTERS ${OPT_TRACKING_ADAPTERS} gps_l1_ca_dll_pll_tracking_fpga.cc galileo_e1_dll_pll_veml_tracking_fpga.cc)
|
||||
SET(OPT_TRACKING_ADAPTERS ${OPT_TRACKING_ADAPTERS} gps_l1_ca_dll_pll_tracking_fpga.cc gps_l2_m_dll_pll_tracking_fpga.cc galileo_e1_dll_pll_veml_tracking_fpga.cc galileo_e5a_dll_pll_tracking_fpga.cc gps_l5_dll_pll_tracking_fpga.cc)
|
||||
endif(ENABLE_FPGA)
|
||||
|
||||
set(TRACKING_ADAPTER_SOURCES
|
||||
|
@ -42,7 +42,7 @@
|
||||
#include "display.h"
|
||||
#include <glog/logging.h>
|
||||
|
||||
#define NUM_PRNs_GALILEO_E1 50
|
||||
//#define NUM_PRNs_GALILEO_E1 50
|
||||
|
||||
using google::LogMessage;
|
||||
|
||||
@ -50,7 +50,6 @@ GalileoE1DllPllVemlTrackingFpga::GalileoE1DllPllVemlTrackingFpga(
|
||||
ConfigurationInterface* configuration, std::string role,
|
||||
unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams)
|
||||
{
|
||||
printf("galileo e1 fpga constructor called\n");
|
||||
//dllpllconf_t trk_param;
|
||||
dllpllconf_fpga_t trk_param_fpga;
|
||||
DLOG(INFO) << "role " << role;
|
||||
@ -97,6 +96,7 @@ GalileoE1DllPllVemlTrackingFpga::GalileoE1DllPllVemlTrackingFpga(
|
||||
std::cout << TEXT_RED << "WARNING: Galileo E1. PLL or DLL narrow tracking bandwidth is higher than wide tracking one" << TEXT_RESET << std::endl;
|
||||
}
|
||||
trk_param_fpga.track_pilot = track_pilot;
|
||||
d_track_pilot = track_pilot;
|
||||
trk_param_fpga.extend_correlation_symbols = extend_correlation_symbols;
|
||||
std::string default_dump_filename = "./track_ch";
|
||||
std::string dump_filename = configuration->property(role + ".dump_filename", default_dump_filename);
|
||||
@ -125,49 +125,75 @@ GalileoE1DllPllVemlTrackingFpga::GalileoE1DllPllVemlTrackingFpga(
|
||||
trk_param_fpga.device_name = device_name;
|
||||
unsigned int device_base = configuration->property(role + ".device_base", 1);
|
||||
trk_param_fpga.device_base = device_base;
|
||||
//unsigned int multicorr_type = configuration->property(role + ".multicorr_type", 1);
|
||||
trk_param_fpga.multicorr_type = 1; // 0 -> 3 correlators, 1 -> 5 correlators
|
||||
|
||||
//################# PRE-COMPUTE ALL THE CODES #################
|
||||
unsigned int code_samples_per_chip = 2;
|
||||
d_ca_codes = static_cast<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;
|
||||
|
||||
d_ca_codes = static_cast<int*>(volk_gnsssdr_malloc(static_cast<int>(Galileo_E1_B_CODE_LENGTH_CHIPS)* 2 * NUM_PRNs_GALILEO_E1 * sizeof(int), volk_gnsssdr_get_alignment()));
|
||||
d_data_codes = static_cast<int *>(volk_gnsssdr_malloc((static_cast<unsigned int>(Galileo_E1_B_CODE_LENGTH_CHIPS)) * 2 * NUM_PRNs_GALILEO_E1 * sizeof(int), volk_gnsssdr_get_alignment()));
|
||||
if (trk_param_fpga.track_pilot)
|
||||
{
|
||||
d_data_codes = static_cast<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()));
|
||||
|
||||
float* ca_codes_f = static_cast<float*>(volk_gnsssdr_malloc(static_cast<int>(Galileo_E1_B_CODE_LENGTH_CHIPS)* 2 * sizeof(float), volk_gnsssdr_get_alignment()));
|
||||
float* data_codes_f = static_cast<float *>(volk_gnsssdr_malloc((static_cast<unsigned int>(Galileo_E1_B_CODE_LENGTH_CHIPS)) * 2 * 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()));
|
||||
}
|
||||
|
||||
for (unsigned int PRN = 1; PRN <= NUM_PRNs_GALILEO_E1; PRN++)
|
||||
//printf("pppppppp trk_param_fpga.track_pilot = %d\n", trk_param_fpga.track_pilot);
|
||||
|
||||
//int kk;
|
||||
|
||||
for (unsigned int PRN = 1; PRN <= Galileo_E1_NUMBER_OF_CODES; PRN++)
|
||||
{
|
||||
char data_signal[3] = "1B";
|
||||
if (trk_param_fpga.track_pilot)
|
||||
{
|
||||
//printf("yes tracking pilot !!!!!!!!!!!!!!!\n");
|
||||
char pilot_signal[3] = "1C";
|
||||
galileo_e1_code_gen_sinboc11_float(ca_codes_f, pilot_signal, PRN);
|
||||
galileo_e1_code_gen_sinboc11_float(data_codes_f, data_signal, PRN);
|
||||
|
||||
for (unsigned int s = 0; s < Galileo_E1_B_CODE_LENGTH_CHIPS; s++)
|
||||
for (unsigned int s = 0; s < 2*Galileo_E1_B_CODE_LENGTH_CHIPS; s++)
|
||||
{
|
||||
d_ca_codes[static_cast<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>(d_data_codes[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 < Galileo_E1_B_CODE_LENGTH_CHIPS; s++)
|
||||
for (unsigned int s = 0; s < 2*Galileo_E1_B_CODE_LENGTH_CHIPS; s++)
|
||||
{
|
||||
d_ca_codes[static_cast<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;
|
||||
delete[] data_codes_f;
|
||||
|
||||
if (trk_param_fpga.track_pilot)
|
||||
{
|
||||
delete[] data_codes_f;
|
||||
}
|
||||
trk_param_fpga.ca_codes = d_ca_codes;
|
||||
trk_param_fpga.data_codes = d_data_codes;
|
||||
trk_param_fpga.code_length = Galileo_E1_B_CODE_LENGTH_CHIPS;
|
||||
|
||||
trk_param_fpga.code_length_chips = Galileo_E1_B_CODE_LENGTH_CHIPS;
|
||||
trk_param_fpga.code_samples_per_chip = code_samples_per_chip; // 2 sample per chip
|
||||
//################# MAKE TRACKING GNURadio object ###################
|
||||
tracking_fpga_sc = dll_pll_veml_make_tracking_fpga(trk_param_fpga);
|
||||
channel_ = 0;
|
||||
@ -178,9 +204,12 @@ GalileoE1DllPllVemlTrackingFpga::GalileoE1DllPllVemlTrackingFpga(
|
||||
GalileoE1DllPllVemlTrackingFpga::~GalileoE1DllPllVemlTrackingFpga()
|
||||
{
|
||||
delete[] d_ca_codes;
|
||||
delete[] d_data_codes;
|
||||
}
|
||||
if (d_track_pilot)
|
||||
{
|
||||
delete[] d_data_codes;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void GalileoE1DllPllVemlTrackingFpga::start_tracking()
|
||||
{
|
||||
|
@ -66,7 +66,7 @@ public:
|
||||
//! Returns "Galileo_E1_DLL_PLL_VEML_Tracking"
|
||||
inline std::string implementation() override
|
||||
{
|
||||
return "Galileo_E1_DLL_PLL_VEML_Tracking";
|
||||
return "Galileo_E1_DLL_PLL_VEML_Tracking_Fpga";
|
||||
}
|
||||
|
||||
inline size_t item_size() override
|
||||
@ -103,6 +103,8 @@ private:
|
||||
unsigned int out_streams_;
|
||||
int* d_ca_codes;
|
||||
int* d_data_codes;
|
||||
bool d_track_pilot;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
@ -0,0 +1,285 @@
|
||||
/*!
|
||||
* \file galileo_e5a_dll_pll_tracking.cc
|
||||
* \brief Adapts a code DLL + carrier PLL
|
||||
* tracking block to a TrackingInterface for Galileo E5a signals
|
||||
* \brief Adapts a PCPS acquisition block to an AcquisitionInterface for
|
||||
* Galileo E5a data and pilot Signals
|
||||
* \author Marc Sales, 2014. marcsales92(at)gmail.com
|
||||
* \based on work from:
|
||||
* <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)
|
||||
{
|
||||
dllpllconf_fpga_t trk_param_fpga;
|
||||
DLOG(INFO) << "role " << role;
|
||||
//################# CONFIGURATION PARAMETERS ########################
|
||||
std::string default_item_type = "gr_complex";
|
||||
std::string item_type = configuration->property(role + ".item_type", default_item_type);
|
||||
int fs_in_deprecated = configuration->property("GNSS-SDR.internal_fs_hz", 12000000);
|
||||
int fs_in = configuration->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated);
|
||||
trk_param_fpga.fs_in = fs_in;
|
||||
bool dump = configuration->property(role + ".dump", false);
|
||||
trk_param_fpga.dump = dump;
|
||||
float pll_bw_hz = configuration->property(role + ".pll_bw_hz", 20.0);
|
||||
if (FLAGS_pll_bw_hz != 0.0) pll_bw_hz = static_cast<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 -> 5 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 ###################
|
||||
// if (item_type.compare("gr_complex") == 0)
|
||||
// {
|
||||
// item_size_ = sizeof(gr_complex);
|
||||
// tracking_ = dll_pll_veml_make_tracking(trk_param_fpga);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// item_size_ = sizeof(gr_complex);
|
||||
// LOG(WARNING) << item_type << " unknown tracking item type.";
|
||||
// }
|
||||
channel_ = 0;
|
||||
//DLOG(INFO) << "tracking(" << tracking_->unique_id() << ")";
|
||||
DLOG(INFO) << "tracking(" << tracking_fpga_sc->unique_id() << ")";
|
||||
}
|
||||
|
||||
|
||||
GalileoE5aDllPllTrackingFpga::~GalileoE5aDllPllTrackingFpga()
|
||||
{
|
||||
delete[] d_ca_codes;
|
||||
if (d_track_pilot)
|
||||
{
|
||||
delete[] d_data_codes;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GalileoE5aDllPllTrackingFpga::start_tracking()
|
||||
{
|
||||
//tracking_->start_tracking();
|
||||
tracking_fpga_sc->start_tracking();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set tracking channel unique ID
|
||||
*/
|
||||
void GalileoE5aDllPllTrackingFpga::set_channel(unsigned int channel)
|
||||
{
|
||||
channel_ = channel;
|
||||
//tracking_->set_channel(channel);
|
||||
tracking_fpga_sc->set_channel(channel);
|
||||
}
|
||||
|
||||
|
||||
void GalileoE5aDllPllTrackingFpga::set_gnss_synchro(Gnss_Synchro* p_gnss_synchro)
|
||||
{
|
||||
//tracking_->set_gnss_synchro(p_gnss_synchro);
|
||||
tracking_fpga_sc->set_gnss_synchro(p_gnss_synchro);
|
||||
}
|
||||
|
||||
|
||||
void GalileoE5aDllPllTrackingFpga::connect(gr::top_block_sptr top_block)
|
||||
{
|
||||
if (top_block)
|
||||
{ /* top_block is not null */
|
||||
};
|
||||
//nothing to connect, now the tracking uses gr_sync_decimator
|
||||
}
|
||||
|
||||
|
||||
void GalileoE5aDllPllTrackingFpga::disconnect(gr::top_block_sptr top_block)
|
||||
{
|
||||
if (top_block)
|
||||
{ /* top_block is not null */
|
||||
};
|
||||
//nothing to disconnect, now the tracking uses gr_sync_decimator
|
||||
}
|
||||
|
||||
|
||||
gr::basic_block_sptr GalileoE5aDllPllTrackingFpga::get_left_block()
|
||||
{
|
||||
//return tracking_;
|
||||
return tracking_fpga_sc;
|
||||
}
|
||||
|
||||
|
||||
gr::basic_block_sptr GalileoE5aDllPllTrackingFpga::get_right_block()
|
||||
{
|
||||
//return tracking_;
|
||||
return tracking_fpga_sc;
|
||||
}
|
@ -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_ */
|
@ -129,6 +129,8 @@ GpsL1CaDllPllTrackingFpga::GpsL1CaDllPllTrackingFpga(
|
||||
trk_param_fpga.device_name = device_name;
|
||||
unsigned int device_base = configuration->property(role + ".device_base", 1);
|
||||
trk_param_fpga.device_base = device_base;
|
||||
//unsigned int multicorr_type = configuration->property(role + ".multicorr_type", 0);
|
||||
trk_param_fpga.multicorr_type = 0; //multicorr_type : 0 -> 3 correlators, 1 -> 5 correlators
|
||||
|
||||
//################# PRE-COMPUTE ALL THE CODES #################
|
||||
d_ca_codes = static_cast<int*>(volk_gnsssdr_malloc(static_cast<int>(GPS_L1_CA_CODE_LENGTH_CHIPS*NUM_PRNs) * sizeof(int), volk_gnsssdr_get_alignment()));
|
||||
@ -137,7 +139,8 @@ GpsL1CaDllPllTrackingFpga::GpsL1CaDllPllTrackingFpga(
|
||||
gps_l1_ca_code_gen_int(&d_ca_codes[(int(GPS_L1_CA_CODE_LENGTH_CHIPS)) * (PRN - 1)], PRN, 0);
|
||||
}
|
||||
trk_param_fpga.ca_codes = d_ca_codes;
|
||||
trk_param_fpga.code_length = GPS_L1_CA_CODE_LENGTH_CHIPS;
|
||||
trk_param_fpga.code_length_chips = GPS_L1_CA_CODE_LENGTH_CHIPS;
|
||||
trk_param_fpga.code_samples_per_chip = 1; // 1 sample per chip
|
||||
|
||||
//################# MAKE TRACKING GNURadio object ###################
|
||||
tracking_fpga_sc = dll_pll_veml_make_tracking_fpga(trk_param_fpga);
|
||||
|
@ -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;
|
||||
dllpllconf_fpga_t trk_param_fpga;
|
||||
DLOG(INFO) << "role " << role;
|
||||
//################# CONFIGURATION PARAMETERS ########################
|
||||
//std::string default_item_type = "gr_complex";
|
||||
//std::string item_type = configuration->property(role + ".item_type", default_item_type);
|
||||
int fs_in_deprecated = configuration->property("GNSS-SDR.internal_fs_hz", 2048000);
|
||||
int fs_in = configuration->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated);
|
||||
trk_param_fpga.fs_in = fs_in;
|
||||
bool dump = configuration->property(role + ".dump", false);
|
||||
trk_param_fpga.dump = dump;
|
||||
float pll_bw_hz = configuration->property(role + ".pll_bw_hz", 2.0);
|
||||
if (FLAGS_pll_bw_hz != 0.0) pll_bw_hz = static_cast<float>(FLAGS_pll_bw_hz);
|
||||
trk_param_fpga.pll_bw_hz = pll_bw_hz;
|
||||
float dll_bw_hz = configuration->property(role + ".dll_bw_hz", 0.75);
|
||||
if (FLAGS_dll_bw_hz != 0.0) dll_bw_hz = static_cast<float>(FLAGS_dll_bw_hz);
|
||||
trk_param_fpga.dll_bw_hz = dll_bw_hz;
|
||||
float early_late_space_chips = configuration->property(role + ".early_late_space_chips", 0.5);
|
||||
trk_param_fpga.early_late_space_chips = early_late_space_chips;
|
||||
trk_param_fpga.early_late_space_narrow_chips = 0.0;
|
||||
std::string default_dump_filename = "./track_ch";
|
||||
std::string dump_filename = configuration->property(role + ".dump_filename", default_dump_filename);
|
||||
trk_param_fpga.dump_filename = dump_filename;
|
||||
int vector_length = std::round(static_cast<double>(fs_in) / (static_cast<double>(GPS_L2_M_CODE_RATE_HZ) / static_cast<double>(GPS_L2_M_CODE_LENGTH_CHIPS)));
|
||||
trk_param_fpga.vector_length = vector_length;
|
||||
int symbols_extended_correlator = configuration->property(role + ".extend_correlation_symbols", 1);
|
||||
if (symbols_extended_correlator != 1)
|
||||
{
|
||||
std::cout << TEXT_RED << "WARNING: Extended coherent integration is not allowed in GPS L2. Coherent integration has been set to 20 ms (1 symbol)" << TEXT_RESET << std::endl;
|
||||
}
|
||||
trk_param_fpga.extend_correlation_symbols = 1;
|
||||
bool track_pilot = configuration->property(role + ".track_pilot", false);
|
||||
if (track_pilot)
|
||||
{
|
||||
std::cout << TEXT_RED << "WARNING: GPS L2 does not have pilot signal. Data tracking has been enabled" << TEXT_RESET << std::endl;
|
||||
}
|
||||
trk_param_fpga.track_pilot = false;
|
||||
trk_param_fpga.very_early_late_space_chips = 0.0;
|
||||
trk_param_fpga.very_early_late_space_narrow_chips = 0.0;
|
||||
trk_param_fpga.pll_bw_narrow_hz = 0.0;
|
||||
trk_param_fpga.dll_bw_narrow_hz = 0.0;
|
||||
trk_param_fpga.system = 'G';
|
||||
char sig_[3] = "2S";
|
||||
std::memcpy(trk_param_fpga.signal, sig_, 3);
|
||||
int cn0_samples = configuration->property(role + ".cn0_samples", 20);
|
||||
if (FLAGS_cn0_samples != 20) cn0_samples = FLAGS_cn0_samples;
|
||||
trk_param_fpga.cn0_samples = cn0_samples;
|
||||
int cn0_min = configuration->property(role + ".cn0_min", 25);
|
||||
if (FLAGS_cn0_min != 25) cn0_min = FLAGS_cn0_min;
|
||||
trk_param_fpga.cn0_min = cn0_min;
|
||||
int max_lock_fail = configuration->property(role + ".max_lock_fail", 50);
|
||||
if (FLAGS_max_lock_fail != 50) max_lock_fail = FLAGS_max_lock_fail;
|
||||
trk_param_fpga.max_lock_fail = max_lock_fail;
|
||||
double carrier_lock_th = configuration->property(role + ".carrier_lock_th", 0.85);
|
||||
if (FLAGS_carrier_lock_th != 0.85) carrier_lock_th = FLAGS_carrier_lock_th;
|
||||
trk_param_fpga.carrier_lock_th = carrier_lock_th;
|
||||
|
||||
// FPGA configuration parameters
|
||||
std::string default_device_name = "/dev/uio";
|
||||
std::string device_name = configuration->property(role + ".devicename", default_device_name);
|
||||
trk_param_fpga.device_name = device_name;
|
||||
unsigned int device_base = configuration->property(role + ".device_base", 1);
|
||||
trk_param_fpga.device_base = device_base;
|
||||
//unsigned int multicorr_type = configuration->property(role + ".multicorr_type", 0);
|
||||
trk_param_fpga.multicorr_type = 0; //multicorr_type : 0 -> 3 correlators, 1 -> 5 correlators
|
||||
|
||||
//d_tracking_code = static_cast<float *>(volk_gnsssdr_malloc(2 * static_cast<unsigned int>(GPS_L2_M_CODE_LENGTH_CHIPS) * sizeof(float), volk_gnsssdr_get_alignment()));
|
||||
d_ca_codes = static_cast<int*>(volk_gnsssdr_malloc(static_cast<unsigned int>(GPS_L2_M_CODE_LENGTH_CHIPS)* NUM_PRNs * sizeof(int), volk_gnsssdr_get_alignment()));
|
||||
float* ca_codes_f = static_cast<float*>(volk_gnsssdr_malloc(static_cast<unsigned int>(GPS_L2_M_CODE_LENGTH_CHIPS)* sizeof(float), volk_gnsssdr_get_alignment()));
|
||||
|
||||
//################# PRE-COMPUTE ALL THE CODES #################
|
||||
d_ca_codes = static_cast<int*>(volk_gnsssdr_malloc(static_cast<int>(GPS_L2_M_CODE_LENGTH_CHIPS*NUM_PRNs) * sizeof(int), volk_gnsssdr_get_alignment()));
|
||||
for (unsigned int PRN = 1; PRN <= NUM_PRNs; PRN++)
|
||||
{
|
||||
//gps_l1_ca_code_gen_int(&d_ca_codes[(int(GPS_L1_CA_CODE_LENGTH_CHIPS)) * (PRN - 1)], PRN, 0);
|
||||
gps_l2c_m_code_gen_float(ca_codes_f, PRN);
|
||||
for (unsigned int s = 0; s < 2*static_cast<unsigned int>(GPS_L2_M_CODE_LENGTH_CHIPS); s++)
|
||||
{
|
||||
d_ca_codes[static_cast<int>(GPS_L2_M_CODE_LENGTH_CHIPS)* (PRN - 1) + s] = static_cast<int>(ca_codes_f[s]);
|
||||
}
|
||||
}
|
||||
|
||||
delete[] ca_codes_f;
|
||||
|
||||
trk_param_fpga.ca_codes = d_ca_codes;
|
||||
trk_param_fpga.code_length_chips = GPS_L2_M_CODE_LENGTH_CHIPS;
|
||||
trk_param_fpga.code_samples_per_chip = 1; // 1 sample per chip
|
||||
|
||||
//################# MAKE TRACKING GNURadio object ###################
|
||||
|
||||
// //################# MAKE TRACKING GNURadio object ###################
|
||||
// if (item_type.compare("gr_complex") == 0)
|
||||
// {
|
||||
// item_size_ = sizeof(gr_complex);
|
||||
// tracking_ = dll_pll_veml_make_tracking(trk_param);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// item_size_ = sizeof(gr_complex);
|
||||
// LOG(WARNING) << item_type << " unknown tracking item type.";
|
||||
// }
|
||||
|
||||
//################# MAKE TRACKING GNURadio object ###################
|
||||
tracking_fpga_sc = dll_pll_veml_make_tracking_fpga(trk_param_fpga);
|
||||
|
||||
channel_ = 0;
|
||||
DLOG(INFO) << "tracking(" << tracking_fpga_sc->unique_id() << ")";
|
||||
}
|
||||
|
||||
|
||||
GpsL2MDllPllTrackingFpga::~GpsL2MDllPllTrackingFpga()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void GpsL2MDllPllTrackingFpga::start_tracking()
|
||||
{
|
||||
//tracking_->start_tracking();
|
||||
tracking_fpga_sc->start_tracking();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set tracking channel unique ID
|
||||
*/
|
||||
void GpsL2MDllPllTrackingFpga::set_channel(unsigned int channel)
|
||||
{
|
||||
channel_ = channel;
|
||||
//tracking_->set_channel(channel);
|
||||
tracking_fpga_sc->set_channel(channel);
|
||||
}
|
||||
|
||||
|
||||
void GpsL2MDllPllTrackingFpga::set_gnss_synchro(Gnss_Synchro* p_gnss_synchro)
|
||||
{
|
||||
//tracking_->set_gnss_synchro(p_gnss_synchro);
|
||||
tracking_fpga_sc->set_gnss_synchro(p_gnss_synchro);
|
||||
}
|
||||
|
||||
|
||||
void GpsL2MDllPllTrackingFpga::connect(gr::top_block_sptr top_block)
|
||||
{
|
||||
if (top_block)
|
||||
{ /* top_block is not null */
|
||||
};
|
||||
//nothing to connect, now the tracking uses gr_sync_decimator
|
||||
}
|
||||
|
||||
|
||||
void GpsL2MDllPllTrackingFpga::disconnect(gr::top_block_sptr top_block)
|
||||
{
|
||||
if (top_block)
|
||||
{ /* top_block is not null */
|
||||
};
|
||||
//nothing to disconnect, now the tracking uses gr_sync_decimator
|
||||
}
|
||||
|
||||
|
||||
gr::basic_block_sptr GpsL2MDllPllTrackingFpga::get_left_block()
|
||||
{
|
||||
//return tracking_;
|
||||
return tracking_fpga_sc;
|
||||
}
|
||||
|
||||
|
||||
gr::basic_block_sptr GpsL2MDllPllTrackingFpga::get_right_block()
|
||||
{
|
||||
//return tracking_;
|
||||
return tracking_fpga_sc;
|
||||
}
|
@ -0,0 +1,106 @@
|
||||
/*!
|
||||
* \file gps_l2_m_dll_pll_tracking.h
|
||||
* \brief Interface of an adapter of a DLL+PLL tracking loop block
|
||||
* for GPS L1 C/A to a TrackingInterface
|
||||
* \author Carlos Aviles, 2010. carlos.avilesr(at)googlemail.com
|
||||
* Javier Arribas, 2011. jarribas(at)cttc.es
|
||||
*
|
||||
* Code DLL + carrier PLL according to the algorithms described in:
|
||||
* K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen,
|
||||
* A Software-Defined GPS and Galileo Receiver. A Single-Frequency
|
||||
* Approach, Birkhauser, 2007
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
|
||||
*
|
||||
* GNSS-SDR is a software defined Global Navigation
|
||||
* Satellite Systems receiver
|
||||
*
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* GNSS-SDR is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GNSS-SDR is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef GNSS_SDR_gps_l2_m_dll_pll_tracking_FPGA_H_
|
||||
#define GNSS_SDR_gps_l2_m_dll_pll_tracking_FPGA_H_
|
||||
|
||||
#include "tracking_interface.h"
|
||||
//#include "dll_pll_veml_tracking.h"
|
||||
#include "dll_pll_veml_tracking_fpga.h"
|
||||
#include <string>
|
||||
|
||||
class ConfigurationInterface;
|
||||
|
||||
/*!
|
||||
* \brief This class implements a code DLL + carrier PLL tracking loop
|
||||
*/
|
||||
class GpsL2MDllPllTrackingFpga : public TrackingInterface
|
||||
{
|
||||
public:
|
||||
GpsL2MDllPllTrackingFpga(ConfigurationInterface* configuration,
|
||||
std::string role,
|
||||
unsigned int in_streams,
|
||||
unsigned int out_streams);
|
||||
|
||||
virtual ~GpsL2MDllPllTrackingFpga();
|
||||
|
||||
inline std::string role() override
|
||||
{
|
||||
return role_;
|
||||
}
|
||||
|
||||
//! Returns "GPS_L2_M_DLL_PLL_Tracking"
|
||||
inline std::string implementation() override
|
||||
{
|
||||
return "GPS_L2_M_DLL_PLL_Tracking_Fpga";
|
||||
}
|
||||
|
||||
inline size_t item_size() override
|
||||
{
|
||||
return item_size_;
|
||||
}
|
||||
|
||||
void connect(gr::top_block_sptr top_block) override;
|
||||
void disconnect(gr::top_block_sptr top_block) override;
|
||||
gr::basic_block_sptr get_left_block() override;
|
||||
gr::basic_block_sptr get_right_block() override;
|
||||
|
||||
/*!
|
||||
* \brief Set tracking channel unique ID
|
||||
*/
|
||||
void set_channel(unsigned int channel) override;
|
||||
|
||||
/*!
|
||||
* \brief Set acquisition/tracking common Gnss_Synchro object pointer
|
||||
* to efficiently exchange synchronization data between acquisition and tracking blocks
|
||||
*/
|
||||
void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) override;
|
||||
|
||||
void start_tracking() override;
|
||||
|
||||
private:
|
||||
//dll_pll_veml_tracking_sptr tracking_;
|
||||
dll_pll_veml_tracking_fpga_sptr tracking_fpga_sc;
|
||||
size_t item_size_;
|
||||
unsigned int channel_;
|
||||
std::string role_;
|
||||
unsigned int in_streams_;
|
||||
unsigned int out_streams_;
|
||||
int* d_ca_codes;
|
||||
};
|
||||
|
||||
#endif // GNSS_SDR_gps_l2_m_dll_pll_tracking_FPGA_H_
|
268
src/algorithms/tracking/adapters/gps_l5_dll_pll_tracking_fpga.cc
Normal file
268
src/algorithms/tracking/adapters/gps_l5_dll_pll_tracking_fpga.cc
Normal file
@ -0,0 +1,268 @@
|
||||
/*!
|
||||
* \file gps_l5_dll_pll_tracking.cc
|
||||
* \brief Interface of an adapter of a DLL+PLL tracking loop block
|
||||
* for GPS L5 to a TrackingInterface
|
||||
* \author Javier Arribas, 2017. jarribas(at)cttc.es
|
||||
*
|
||||
* Code DLL + carrier PLL according to the algorithms described in:
|
||||
* K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen,
|
||||
* A Software-Defined GPS and Galileo Receiver. A Single-Frequency
|
||||
* Approach, Birkhauser, 2007
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
|
||||
*
|
||||
* GNSS-SDR is a software defined Global Navigation
|
||||
* Satellite Systems receiver
|
||||
*
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* GNSS-SDR is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GNSS-SDR is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNSS-SDR. If not, see <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)
|
||||
{
|
||||
//dllpllconf_t trk_param;
|
||||
dllpllconf_fpga_t trk_param_fpga;
|
||||
DLOG(INFO) << "role " << role;
|
||||
//################# CONFIGURATION PARAMETERS ########################
|
||||
//std::string default_item_type = "gr_complex";
|
||||
//std::string item_type = configuration->property(role + ".item_type", default_item_type);
|
||||
int fs_in_deprecated = configuration->property("GNSS-SDR.internal_fs_hz", 2048000);
|
||||
int fs_in = configuration->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated);
|
||||
trk_param_fpga.fs_in = fs_in;
|
||||
bool dump = configuration->property(role + ".dump", false);
|
||||
trk_param_fpga.dump = dump;
|
||||
float pll_bw_hz = configuration->property(role + ".pll_bw_hz", 50.0);
|
||||
if (FLAGS_pll_bw_hz != 0.0) pll_bw_hz = static_cast<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);
|
||||
|
||||
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()));
|
||||
}
|
||||
|
||||
for (unsigned int PRN = 1; PRN <= NUM_PRNs; PRN++)
|
||||
{
|
||||
if (track_pilot)
|
||||
{
|
||||
gps_l5q_code_gen_float(tracking_code, PRN);
|
||||
gps_l5i_code_gen_float(data_code, PRN);
|
||||
|
||||
|
||||
for (unsigned int s = 0; s < 2*code_length_chips; s++)
|
||||
{
|
||||
d_ca_codes[static_cast<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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
delete[] tracking_code;
|
||||
if (trk_param_fpga.track_pilot)
|
||||
{
|
||||
delete[] data_code;
|
||||
}
|
||||
trk_param_fpga.ca_codes = d_ca_codes;
|
||||
trk_param_fpga.data_codes = d_data_codes;
|
||||
trk_param_fpga.code_length_chips = code_length_chips;
|
||||
trk_param_fpga.code_samples_per_chip = code_samples_per_chip; // 2 sample per chip
|
||||
//################# MAKE TRACKING GNURadio object ###################
|
||||
// if (item_type.compare("gr_complex") == 0)
|
||||
// {
|
||||
// item_size_ = sizeof(gr_complex);
|
||||
// tracking_ = dll_pll_veml_make_tracking(trk_param_fpga);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// item_size_ = sizeof(gr_complex);
|
||||
// LOG(WARNING) << item_type << " unknown tracking item type.";
|
||||
// }
|
||||
tracking_fpga_sc = dll_pll_veml_make_tracking_fpga(trk_param_fpga);
|
||||
channel_ = 0;
|
||||
DLOG(INFO) << "tracking(" << tracking_fpga_sc->unique_id() << ")";
|
||||
}
|
||||
|
||||
|
||||
GpsL5DllPllTrackingFpga::~GpsL5DllPllTrackingFpga()
|
||||
{
|
||||
|
||||
delete[] d_ca_codes;
|
||||
if (d_track_pilot)
|
||||
{
|
||||
delete[] d_data_codes;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GpsL5DllPllTrackingFpga::start_tracking()
|
||||
{
|
||||
tracking_fpga_sc->start_tracking();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set tracking channel unique ID
|
||||
*/
|
||||
void GpsL5DllPllTrackingFpga::set_channel(unsigned int channel)
|
||||
{
|
||||
channel_ = channel;
|
||||
tracking_fpga_sc->set_channel(channel);
|
||||
}
|
||||
|
||||
|
||||
void GpsL5DllPllTrackingFpga::set_gnss_synchro(Gnss_Synchro* p_gnss_synchro)
|
||||
{
|
||||
tracking_fpga_sc->set_gnss_synchro(p_gnss_synchro);
|
||||
}
|
||||
|
||||
|
||||
void GpsL5DllPllTrackingFpga::connect(gr::top_block_sptr top_block)
|
||||
{
|
||||
if (top_block)
|
||||
{ /* top_block is not null */
|
||||
};
|
||||
//nothing to connect, now the tracking uses gr_sync_decimator
|
||||
}
|
||||
|
||||
|
||||
void GpsL5DllPllTrackingFpga::disconnect(gr::top_block_sptr top_block)
|
||||
{
|
||||
if (top_block)
|
||||
{ /* top_block is not null */
|
||||
};
|
||||
//nothing to disconnect, now the tracking uses gr_sync_decimator
|
||||
}
|
||||
|
||||
|
||||
gr::basic_block_sptr GpsL5DllPllTrackingFpga::get_left_block()
|
||||
{
|
||||
return tracking_fpga_sc;
|
||||
}
|
||||
|
||||
|
||||
gr::basic_block_sptr GpsL5DllPllTrackingFpga::get_right_block()
|
||||
{
|
||||
return tracking_fpga_sc;
|
||||
}
|
106
src/algorithms/tracking/adapters/gps_l5_dll_pll_tracking_fpga.h
Normal file
106
src/algorithms/tracking/adapters/gps_l5_dll_pll_tracking_fpga.h
Normal file
@ -0,0 +1,106 @@
|
||||
/*!
|
||||
* \file gps_l5_dll_pll_tracking.h
|
||||
* \brief Interface of an adapter of a DLL+PLL tracking loop block
|
||||
* for GPS L5 to a TrackingInterface
|
||||
* \author Javier Arribas, 2017. jarribas(at)cttc.es
|
||||
*
|
||||
* Code DLL + carrier PLL according to the algorithms described in:
|
||||
* K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen,
|
||||
* A Software-Defined GPS and Galileo Receiver. A Single-Frequency
|
||||
* Approach, Birkhauser, 2007
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*
|
||||
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
|
||||
*
|
||||
* GNSS-SDR is a software defined Global Navigation
|
||||
* Satellite Systems receiver
|
||||
*
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* GNSS-SDR is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* GNSS-SDR is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef GNSS_SDR_GPS_L5_DLL_PLL_TRACKING_FPGA_H_
|
||||
#define GNSS_SDR_GPS_L5_DLL_PLL_TRACKING_FPGA_H_
|
||||
|
||||
#include "tracking_interface.h"
|
||||
#include "dll_pll_veml_tracking_fpga.h"
|
||||
#include <string>
|
||||
|
||||
class ConfigurationInterface;
|
||||
|
||||
/*!
|
||||
* \brief This class implements a code DLL + carrier PLL tracking loop
|
||||
*/
|
||||
class GpsL5DllPllTrackingFpga : public TrackingInterface
|
||||
{
|
||||
public:
|
||||
GpsL5DllPllTrackingFpga(ConfigurationInterface* configuration,
|
||||
std::string role,
|
||||
unsigned int in_streams,
|
||||
unsigned int out_streams);
|
||||
|
||||
virtual ~GpsL5DllPllTrackingFpga();
|
||||
|
||||
inline std::string role() override
|
||||
{
|
||||
return role_;
|
||||
}
|
||||
|
||||
//! Returns "GPS_L5_DLL_PLL_Tracking"
|
||||
inline std::string implementation() override
|
||||
{
|
||||
return "GPS_L5_DLL_PLL_Tracking";
|
||||
}
|
||||
|
||||
inline size_t item_size() override
|
||||
{
|
||||
return item_size_;
|
||||
}
|
||||
|
||||
void connect(gr::top_block_sptr top_block) override;
|
||||
void disconnect(gr::top_block_sptr top_block) override;
|
||||
gr::basic_block_sptr get_left_block() override;
|
||||
gr::basic_block_sptr get_right_block() override;
|
||||
|
||||
/*!
|
||||
* \brief Set tracking channel unique ID
|
||||
*/
|
||||
void set_channel(unsigned int channel) override;
|
||||
|
||||
/*!
|
||||
* \brief Set acquisition/tracking common Gnss_Synchro object pointer
|
||||
* to efficiently exchange synchronization data between acquisition and tracking blocks
|
||||
*/
|
||||
void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) override;
|
||||
|
||||
void start_tracking() override;
|
||||
|
||||
private:
|
||||
//dll_pll_veml_tracking_sptr tracking_;
|
||||
dll_pll_veml_tracking_fpga_sptr tracking_fpga_sc;
|
||||
size_t item_size_;
|
||||
unsigned int channel_;
|
||||
std::string role_;
|
||||
unsigned int in_streams_;
|
||||
unsigned int out_streams_;
|
||||
bool d_track_pilot;
|
||||
int* d_ca_codes;
|
||||
int* d_data_codes;
|
||||
};
|
||||
|
||||
#endif // GNSS_SDR_GPS_L5_DLL_PLL_TRACKING_FPGA_H_
|
@ -56,6 +56,8 @@
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
|
||||
|
||||
using google::LogMessage;
|
||||
|
||||
dll_pll_veml_tracking_fpga_sptr dll_pll_veml_make_tracking_fpga(dllpllconf_fpga_t conf_)
|
||||
@ -93,6 +95,9 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_)
|
||||
|
||||
signal_pretty_name = map_signal_pretty_name[signal_type];
|
||||
|
||||
|
||||
d_prompt_data_shift = nullptr;
|
||||
|
||||
if (trk_parameters.system == 'G')
|
||||
{
|
||||
systemName = "GPS";
|
||||
@ -103,8 +108,8 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_)
|
||||
d_code_chip_rate = GPS_L1_CA_CODE_RATE_HZ;
|
||||
d_symbols_per_bit = GPS_CA_TELEMETRY_SYMBOLS_PER_BIT;
|
||||
d_correlation_length_ms = 1;
|
||||
d_code_samples_per_chip = 1;
|
||||
d_code_length_chips = static_cast<unsigned int>(GPS_L1_CA_CODE_LENGTH_CHIPS);
|
||||
//d_code_samples_per_chip = 1;
|
||||
//d_code_length_chips = static_cast<unsigned int>(GPS_L1_CA_CODE_LENGTH_CHIPS);
|
||||
// GPS L1 C/A does not have pilot component nor secondary code
|
||||
d_secondary = false;
|
||||
trk_parameters.track_pilot = false;
|
||||
@ -115,10 +120,10 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_)
|
||||
d_signal_carrier_freq = GPS_L2_FREQ_HZ;
|
||||
d_code_period = GPS_L2_M_PERIOD;
|
||||
d_code_chip_rate = GPS_L2_M_CODE_RATE_HZ;
|
||||
d_code_length_chips = static_cast<unsigned int>(GPS_L2_M_CODE_LENGTH_CHIPS);
|
||||
//d_code_length_chips = static_cast<unsigned int>(GPS_L2_M_CODE_LENGTH_CHIPS);
|
||||
d_symbols_per_bit = GPS_L2_SAMPLES_PER_SYMBOL;
|
||||
d_correlation_length_ms = 20;
|
||||
d_code_samples_per_chip = 1;
|
||||
//d_code_samples_per_chip = 1;
|
||||
// GPS L2 does not have pilot component nor secondary code
|
||||
d_secondary = false;
|
||||
trk_parameters.track_pilot = false;
|
||||
@ -131,8 +136,8 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_)
|
||||
d_code_chip_rate = GPS_L5i_CODE_RATE_HZ;
|
||||
d_symbols_per_bit = GPS_L5_SAMPLES_PER_SYMBOL;
|
||||
d_correlation_length_ms = 1;
|
||||
d_code_samples_per_chip = 1;
|
||||
d_code_length_chips = static_cast<unsigned int>(GPS_L5i_CODE_LENGTH_CHIPS);
|
||||
//d_code_samples_per_chip = 1;
|
||||
//d_code_length_chips = static_cast<unsigned int>(GPS_L5i_CODE_LENGTH_CHIPS);
|
||||
// GPS L5 does not have pilot secondary code
|
||||
d_secondary = true;
|
||||
interchange_iq = false;
|
||||
@ -159,8 +164,8 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_)
|
||||
interchange_iq = false;
|
||||
d_signal_carrier_freq = 0.0;
|
||||
d_code_period = 0.0;
|
||||
d_code_length_chips = 0;
|
||||
d_code_samples_per_chip = 0;
|
||||
//d_code_length_chips = 0;
|
||||
//d_code_samples_per_chip = 0;
|
||||
d_symbols_per_bit = 0;
|
||||
}
|
||||
}
|
||||
@ -172,10 +177,10 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_)
|
||||
d_signal_carrier_freq = Galileo_E1_FREQ_HZ;
|
||||
d_code_period = Galileo_E1_CODE_PERIOD;
|
||||
d_code_chip_rate = Galileo_E1_CODE_CHIP_RATE_HZ;
|
||||
d_code_length_chips = static_cast<unsigned int>(Galileo_E1_B_CODE_LENGTH_CHIPS);
|
||||
//d_code_length_chips = static_cast<unsigned int>(Galileo_E1_B_CODE_LENGTH_CHIPS);
|
||||
d_symbols_per_bit = 1;
|
||||
d_correlation_length_ms = 4;
|
||||
d_code_samples_per_chip = 2; // CBOC disabled: 2 samples per chip. CBOC enabled: 12 samples per chip
|
||||
//d_code_samples_per_chip = 2; // CBOC disabled: 2 samples per chip. CBOC enabled: 12 samples per chip
|
||||
d_veml = true;
|
||||
if (trk_parameters.track_pilot)
|
||||
{
|
||||
@ -198,8 +203,8 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_)
|
||||
d_code_chip_rate = Galileo_E5a_CODE_CHIP_RATE_HZ;
|
||||
d_symbols_per_bit = 20;
|
||||
d_correlation_length_ms = 1;
|
||||
d_code_samples_per_chip = 1;
|
||||
d_code_length_chips = static_cast<unsigned int>(Galileo_E5a_CODE_LENGTH_CHIPS);
|
||||
//d_code_samples_per_chip = 1;
|
||||
//d_code_length_chips = static_cast<unsigned int>(Galileo_E5a_CODE_LENGTH_CHIPS);
|
||||
d_secondary = true;
|
||||
interchange_iq = false;
|
||||
if (trk_parameters.track_pilot)
|
||||
@ -224,8 +229,8 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_)
|
||||
interchange_iq = false;
|
||||
d_signal_carrier_freq = 0.0;
|
||||
d_code_period = 0.0;
|
||||
d_code_length_chips = 0;
|
||||
d_code_samples_per_chip = 0;
|
||||
//d_code_length_chips = 0;
|
||||
//d_code_samples_per_chip = 0;
|
||||
d_symbols_per_bit = 0;
|
||||
}
|
||||
}
|
||||
@ -238,8 +243,8 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_)
|
||||
interchange_iq = false;
|
||||
d_signal_carrier_freq = 0.0;
|
||||
d_code_period = 0.0;
|
||||
d_code_length_chips = 0;
|
||||
d_code_samples_per_chip = 0;
|
||||
//d_code_length_chips = 0;
|
||||
//d_code_samples_per_chip = 0;
|
||||
d_symbols_per_bit = 0;
|
||||
}
|
||||
T_chip_seconds = 0.0;
|
||||
@ -269,6 +274,8 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_)
|
||||
d_local_code_shift_chips = static_cast<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));
|
||||
|
||||
d_code_samples_per_chip = trk_parameters.code_samples_per_chip; // number of samples per chip
|
||||
|
||||
// map memory pointers of correlator outputs
|
||||
if (d_veml)
|
||||
{
|
||||
@ -277,6 +284,11 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_)
|
||||
d_Prompt = &d_correlator_outs[2];
|
||||
d_Late = &d_correlator_outs[3];
|
||||
d_Very_Late = &d_correlator_outs[4];
|
||||
// printf("aaaa very early %f\n",-trk_parameters.very_early_late_space_chips);
|
||||
// printf("aaaa early %f\n",-trk_parameters.early_late_space_chips);
|
||||
// printf("aaaa normal %f\n",0);
|
||||
// printf("aaaa late %f\n",trk_parameters.early_late_space_chips);
|
||||
// printf("aaaa very late %f\n",trk_parameters.very_early_late_space_chips);
|
||||
d_local_code_shift_chips[0] = -trk_parameters.very_early_late_space_chips * static_cast<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;
|
||||
@ -291,6 +303,10 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_)
|
||||
d_Prompt = &d_correlator_outs[1];
|
||||
d_Late = &d_correlator_outs[2];
|
||||
d_Very_Late = nullptr;
|
||||
// printf("aaaa early %f\n",-trk_parameters.early_late_space_chips);
|
||||
// printf("aaaa normal %f\n",0);
|
||||
// printf("aaaa late %f\n",trk_parameters.early_late_space_chips);
|
||||
|
||||
d_local_code_shift_chips[0] = -trk_parameters.early_late_space_chips * static_cast<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);
|
||||
@ -361,13 +377,17 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_)
|
||||
d_last_prompt = gr_complex(0.0, 0.0);
|
||||
d_state = 0; // initial state: standby
|
||||
|
||||
//printf("hhhhhhhhhhh d_n_correlator_taps = %d\n", d_n_correlator_taps);
|
||||
|
||||
// create multicorrelator class
|
||||
std::string device_name = trk_parameters.device_name;
|
||||
unsigned int device_base = trk_parameters.device_base;
|
||||
int* ca_codes = trk_parameters.ca_codes;
|
||||
int* data_codes = trk_parameters.data_codes;
|
||||
unsigned int code_length = trk_parameters.code_length;
|
||||
multicorrelator_fpga = std::make_shared <fpga_multicorrelator_8sc>(d_n_correlator_taps, device_name, device_base, ca_codes, data_codes, code_length, trk_parameters.track_pilot);
|
||||
//unsigned int code_length = trk_parameters.code_length_chips;
|
||||
d_code_length_chips = trk_parameters.code_length_chips;
|
||||
unsigned int multicorr_type = trk_parameters.multicorr_type;
|
||||
multicorrelator_fpga = std::make_shared <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;
|
||||
@ -388,6 +408,7 @@ void dll_pll_veml_tracking_fpga::start_tracking()
|
||||
// new chip and prn sequence periods based on acq Doppler
|
||||
d_code_freq_chips = radial_velocity * d_code_chip_rate;
|
||||
d_code_phase_step_chips = d_code_freq_chips / trk_parameters.fs_in;
|
||||
|
||||
double T_chip_mod_seconds = 1.0 / d_code_freq_chips;
|
||||
double T_prn_mod_seconds = T_chip_mod_seconds * static_cast<double>(d_code_length_chips);
|
||||
double T_prn_mod_samples = T_prn_mod_seconds * trk_parameters.fs_in;
|
||||
@ -437,7 +458,7 @@ void dll_pll_veml_tracking_fpga::start_tracking()
|
||||
{
|
||||
if (trk_parameters.track_pilot)
|
||||
{
|
||||
char pilot_signal[3] = "1C";
|
||||
//char pilot_signal[3] = "1C";
|
||||
d_Prompt_Data[0] = gr_complex(0.0, 0.0);
|
||||
// MISSING _: set_local_code_and_taps for the data correlator
|
||||
}
|
||||
@ -507,7 +528,8 @@ void dll_pll_veml_tracking_fpga::start_tracking()
|
||||
LOG(INFO) << "PULL-IN Doppler [Hz] = " << d_carrier_doppler_hz
|
||||
<< ". Code Phase correction [samples] = " << delay_correction_samples
|
||||
<< ". PULL-IN Code Phase [samples] = " << d_acq_code_phase_samples;
|
||||
multicorrelator_fpga->set_local_code_and_taps(d_code_length_chips, d_local_code_shift_chips, d_acquisition_gnss_synchro->PRN);
|
||||
//multicorrelator_fpga->set_local_code_and_taps(d_code_length_chips, d_local_code_shift_chips, d_acquisition_gnss_synchro->PRN);
|
||||
multicorrelator_fpga->set_local_code_and_taps(d_local_code_shift_chips, d_prompt_data_shift, d_acquisition_gnss_synchro->PRN);
|
||||
d_pull_in = 1;
|
||||
// enable tracking pull-in and d_state at the end to avoid general work from starting pull-in before the start tracking function is finished
|
||||
d_state = 1;
|
||||
@ -600,6 +622,7 @@ bool dll_pll_veml_tracking_fpga::acquire_secondary()
|
||||
|
||||
bool dll_pll_veml_tracking_fpga::cn0_and_tracking_lock_status(double coh_integration_time_s)
|
||||
{
|
||||
//printf("kkkkkkkkkkkkk d_cn0_estimation_counter = %d\n", d_cn0_estimation_counter);
|
||||
// ####### CN0 ESTIMATION AND LOCK DETECTORS ######
|
||||
if (d_cn0_estimation_counter < trk_parameters.cn0_samples)
|
||||
{
|
||||
@ -610,6 +633,7 @@ bool dll_pll_veml_tracking_fpga::cn0_and_tracking_lock_status(double coh_integra
|
||||
}
|
||||
else
|
||||
{
|
||||
//printf("KKKKKKKKKKK checking count fail ...\n");
|
||||
d_cn0_estimation_counter = 0;
|
||||
// Code lock indicator
|
||||
d_CN0_SNV_dB_Hz = cn0_svn_estimator(d_Prompt_buffer, trk_parameters.cn0_samples, coh_integration_time_s);
|
||||
@ -719,6 +743,11 @@ void dll_pll_veml_tracking_fpga::update_tracking_vars()
|
||||
// remnant code phase [chips]
|
||||
d_rem_code_phase_samples = K_blk_samples - static_cast<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);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -1176,8 +1205,14 @@ int dll_pll_veml_tracking_fpga::general_work (int noutput_items __attribute__((u
|
||||
d_pull_in = 0;
|
||||
multicorrelator_fpga->lock_channel();
|
||||
unsigned counter_value = multicorrelator_fpga->read_sample_counter();
|
||||
//printf("333333 counter_value = %d\n", counter_value);
|
||||
//printf("333333 current_synchro_data.Acq_samplestamp_samples = %d\n", current_synchro_data.Acq_samplestamp_samples);
|
||||
//printf("333333 current_synchro_data.Acq_delay_samples = %f\n", current_synchro_data.Acq_delay_samples);
|
||||
//printf("333333 d_correlation_length_samples = %d\n", d_correlation_length_samples);
|
||||
unsigned num_frames = ceil((counter_value - current_synchro_data.Acq_samplestamp_samples - current_synchro_data.Acq_delay_samples)/d_correlation_length_samples);
|
||||
//printf("333333 num_frames = %d\n", num_frames);
|
||||
unsigned absolute_samples_offset = current_synchro_data.Acq_delay_samples + current_synchro_data.Acq_samplestamp_samples + num_frames*d_correlation_length_samples;
|
||||
//printf("333333 absolute_samples_offset = %d\n", absolute_samples_offset);
|
||||
multicorrelator_fpga->set_initial_sample(absolute_samples_offset);
|
||||
d_sample_counter = absolute_samples_offset;
|
||||
current_synchro_data.Tracking_sample_counter = absolute_samples_offset;
|
||||
@ -1196,7 +1231,7 @@ int dll_pll_veml_tracking_fpga::general_work (int noutput_items __attribute__((u
|
||||
// perform carrier wipe-off and compute Early, Prompt and Late correlation
|
||||
multicorrelator_fpga->Carrier_wipeoff_multicorrelator_resampler(
|
||||
d_rem_carr_phase_rad, d_carrier_phase_step_rad,
|
||||
d_rem_code_phase_chips, d_code_phase_step_chips,
|
||||
d_rem_code_phase_chips * static_cast<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
|
||||
@ -1339,7 +1374,7 @@ int dll_pll_veml_tracking_fpga::general_work (int noutput_items __attribute__((u
|
||||
// perform a correlation step
|
||||
multicorrelator_fpga->Carrier_wipeoff_multicorrelator_resampler(
|
||||
d_rem_carr_phase_rad, d_carrier_phase_step_rad,
|
||||
d_rem_code_phase_chips, d_code_phase_step_chips,
|
||||
d_rem_code_phase_chips * static_cast<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();
|
||||
@ -1398,7 +1433,7 @@ int dll_pll_veml_tracking_fpga::general_work (int noutput_items __attribute__((u
|
||||
//do_correlation_step(in);
|
||||
multicorrelator_fpga->Carrier_wipeoff_multicorrelator_resampler(
|
||||
d_rem_carr_phase_rad, d_carrier_phase_step_rad,
|
||||
d_rem_code_phase_chips, d_code_phase_step_chips,
|
||||
d_rem_code_phase_chips * static_cast<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();
|
||||
|
@ -74,7 +74,9 @@ typedef struct
|
||||
char signal[3];
|
||||
std::string device_name;
|
||||
unsigned int device_base;
|
||||
unsigned int code_length;
|
||||
unsigned int multicorr_type;
|
||||
unsigned int code_length_chips;
|
||||
unsigned int code_samples_per_chip;
|
||||
int* ca_codes;
|
||||
int* data_codes;
|
||||
} dllpllconf_fpga_t;
|
||||
@ -223,6 +225,7 @@ private:
|
||||
unsigned long int d_sample_counter_next;
|
||||
unsigned int d_pull_in = 0;
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif //GNSS_SDR_DLL_PLL_VEML_TRACKING_FPGA_H
|
||||
|
@ -86,21 +86,25 @@
|
||||
|
||||
int fpga_multicorrelator_8sc::read_sample_counter()
|
||||
{
|
||||
return d_map_base[7];
|
||||
return d_map_base[d_SAMPLE_COUNTER_REG_ADDR];
|
||||
}
|
||||
|
||||
void fpga_multicorrelator_8sc::set_initial_sample(int samples_offset)
|
||||
{
|
||||
d_initial_sample_counter = samples_offset;
|
||||
d_map_base[13] = d_initial_sample_counter;
|
||||
//printf("www writing d map base %d = d_initial_sample_counter = %d\n", d_INITIAL_COUNTER_VALUE_REG_ADDR, d_initial_sample_counter);
|
||||
d_map_base[d_INITIAL_COUNTER_VALUE_REG_ADDR] = d_initial_sample_counter;
|
||||
}
|
||||
|
||||
void fpga_multicorrelator_8sc::set_local_code_and_taps(int code_length_chips,
|
||||
float *shifts_chips, int PRN)
|
||||
//void fpga_multicorrelator_8sc::set_local_code_and_taps(int code_length_chips,
|
||||
// float *shifts_chips, int PRN)
|
||||
|
||||
void fpga_multicorrelator_8sc::set_local_code_and_taps(float *shifts_chips, float *prompt_data_shift, int PRN)
|
||||
{
|
||||
|
||||
d_shifts_chips = shifts_chips;
|
||||
d_code_length_chips = code_length_chips;
|
||||
d_prompt_data_shift = prompt_data_shift;
|
||||
//d_code_length_chips = code_length_chips;
|
||||
fpga_multicorrelator_8sc::fpga_configure_tracking_gps_local_code(PRN);
|
||||
}
|
||||
|
||||
@ -113,6 +117,7 @@ void fpga_multicorrelator_8sc::set_output_vectors(gr_complex* corr_out, gr_compl
|
||||
void fpga_multicorrelator_8sc::update_local_code(float rem_code_phase_chips)
|
||||
{
|
||||
d_rem_code_phase_chips = rem_code_phase_chips;
|
||||
//printf("uuuuu d_rem_code_phase_chips = %f\n", d_rem_code_phase_chips);
|
||||
fpga_multicorrelator_8sc::fpga_compute_code_shift_parameters();
|
||||
fpga_multicorrelator_8sc::fpga_configure_code_parameters_in_fpga();
|
||||
}
|
||||
@ -135,7 +140,9 @@ void fpga_multicorrelator_8sc::Carrier_wipeoff_multicorrelator_resampler(
|
||||
fpga_multicorrelator_8sc::fpga_launch_multicorrelator_fpga();
|
||||
int irq_count;
|
||||
ssize_t nb;
|
||||
//printf("$$$$$ waiting for interrupt ... \n");
|
||||
nb = read(d_device_descriptor, &irq_count, sizeof(irq_count));
|
||||
//printf("$$$$$ interrupt received ... \n");
|
||||
if (nb != sizeof(irq_count))
|
||||
{
|
||||
printf("Tracking_module Read failed to retrieve 4 bytes!\n");
|
||||
@ -145,7 +152,8 @@ void fpga_multicorrelator_8sc::Carrier_wipeoff_multicorrelator_resampler(
|
||||
}
|
||||
|
||||
fpga_multicorrelator_8sc::fpga_multicorrelator_8sc(int n_correlators,
|
||||
std::string device_name, unsigned int device_base, int *ca_codes, int *data_codes, unsigned int code_length, bool track_pilot)
|
||||
std::string device_name, unsigned int device_base, int *ca_codes, int *data_codes, unsigned int code_length_chips, bool track_pilot,
|
||||
unsigned int multicorr_type, unsigned int code_samples_per_chip)
|
||||
{
|
||||
d_n_correlators = n_correlators;
|
||||
d_device_name = device_name;
|
||||
@ -155,12 +163,23 @@ fpga_multicorrelator_8sc::fpga_multicorrelator_8sc(int n_correlators,
|
||||
d_map_base = nullptr;
|
||||
|
||||
// instantiate variable length vectors
|
||||
d_initial_index = static_cast<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()));
|
||||
if (d_track_pilot)
|
||||
{
|
||||
d_initial_index = static_cast<unsigned*>(volk_gnsssdr_malloc(
|
||||
(n_correlators + 1) * sizeof(unsigned), volk_gnsssdr_get_alignment()));
|
||||
d_initial_interp_counter = static_cast<unsigned*>(volk_gnsssdr_malloc(
|
||||
(n_correlators + 1)* sizeof(unsigned), volk_gnsssdr_get_alignment()));
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
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_shifts_chips = nullptr;
|
||||
d_prompt_data_shift = nullptr;
|
||||
d_corr_out = nullptr;
|
||||
d_code_length_chips = 0;
|
||||
d_rem_code_phase_chips = 0;
|
||||
@ -172,8 +191,92 @@ fpga_multicorrelator_8sc::fpga_multicorrelator_8sc(int n_correlators,
|
||||
d_initial_sample_counter = 0;
|
||||
d_channel = 0;
|
||||
d_correlator_length_samples = 0,
|
||||
d_code_length = code_length;
|
||||
//d_code_length = code_length;
|
||||
d_code_length_chips = code_length_chips;
|
||||
d_ca_codes = ca_codes;
|
||||
d_data_codes = data_codes;
|
||||
d_multicorr_type = multicorr_type;
|
||||
|
||||
d_code_samples_per_chip = code_samples_per_chip;
|
||||
// set up register mapping
|
||||
|
||||
// write-only registers
|
||||
d_CODE_PHASE_STEP_CHIPS_NUM_REG_ADDR = 0;
|
||||
d_INITIAL_INDEX_REG_BASE_ADDR = 1;
|
||||
if (d_multicorr_type == 0)
|
||||
{
|
||||
// multicorrelator with 3 correlators (16 registers only)
|
||||
d_INITIAL_INTERP_COUNTER_REG_BASE_ADDR = 4;
|
||||
d_NSAMPLES_MINUS_1_REG_ADDR = 7;
|
||||
d_CODE_LENGTH_MINUS_1_REG_ADDR = 8;
|
||||
d_REM_CARR_PHASE_RAD_REG_ADDR = 9;
|
||||
d_PHASE_STEP_RAD_REG_ADDR = 10;
|
||||
d_PROG_MEMS_ADDR = 11;
|
||||
d_DROP_SAMPLES_REG_ADDR = 12;
|
||||
d_INITIAL_COUNTER_VALUE_REG_ADDR = 13;
|
||||
d_START_FLAG_ADDR = 14;
|
||||
}
|
||||
else
|
||||
{
|
||||
// other types of multicorrelators (32 registers)
|
||||
d_INITIAL_INTERP_COUNTER_REG_BASE_ADDR = 7;
|
||||
d_NSAMPLES_MINUS_1_REG_ADDR = 13;
|
||||
d_CODE_LENGTH_MINUS_1_REG_ADDR = 14;
|
||||
d_REM_CARR_PHASE_RAD_REG_ADDR = 15;
|
||||
d_PHASE_STEP_RAD_REG_ADDR = 16;
|
||||
d_PROG_MEMS_ADDR = 17;
|
||||
d_DROP_SAMPLES_REG_ADDR = 18;
|
||||
d_INITIAL_COUNTER_VALUE_REG_ADDR = 19;
|
||||
d_START_FLAG_ADDR = 30;
|
||||
}
|
||||
|
||||
// read-write registers
|
||||
if (d_multicorr_type == 0)
|
||||
{
|
||||
// multicorrelator with 3 correlators (16 registers only)
|
||||
d_TEST_REG_ADDR = 15;
|
||||
}
|
||||
else
|
||||
{
|
||||
// other types of multicorrelators (32 registers)
|
||||
d_TEST_REG_ADDR = 31;
|
||||
}
|
||||
|
||||
// result 2's complement saturation value
|
||||
if (d_multicorr_type == 0)
|
||||
{
|
||||
// multicorrelator with 3 correlators (16 registers only)
|
||||
d_result_SAT_value = 1048576; // 21 bits 2's complement -> 2^20
|
||||
}
|
||||
else
|
||||
{
|
||||
// other types of multicorrelators (32 registers)
|
||||
d_result_SAT_value = 4194304; // 23 bits 2's complement -> 2^22
|
||||
}
|
||||
|
||||
// read only registers
|
||||
d_RESULT_REG_REAL_BASE_ADDR = 1;
|
||||
if (d_multicorr_type == 0)
|
||||
{
|
||||
// multicorrelator with 3 correlators (16 registers only)
|
||||
d_RESULT_REG_IMAG_BASE_ADDR = 4;
|
||||
d_RESULT_REG_DATA_REAL_BASE_ADDR = 0; // no pilot tracking
|
||||
d_RESULT_REG_DATA_IMAG_BASE_ADDR = 0;
|
||||
d_SAMPLE_COUNTER_REG_ADDR = 7;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
// other types of multicorrelators (32 registers)
|
||||
d_RESULT_REG_IMAG_BASE_ADDR = 7;
|
||||
d_RESULT_REG_DATA_REAL_BASE_ADDR = 6; // no pilot tracking
|
||||
d_RESULT_REG_DATA_IMAG_BASE_ADDR = 12;
|
||||
d_SAMPLE_COUNTER_REG_ADDR = 13;
|
||||
|
||||
}
|
||||
|
||||
//printf("d_SAMPLE_COUNTER_REG_ADDR = %d\n", d_SAMPLE_COUNTER_REG_ADDR);
|
||||
//printf("mmmmmmmmmmmmm d_n_correlators = %d\n", d_n_correlators);
|
||||
DLOG(INFO) << "TRACKING FPGA CLASS CREATED";
|
||||
|
||||
}
|
||||
@ -181,7 +284,7 @@ fpga_multicorrelator_8sc::fpga_multicorrelator_8sc(int n_correlators,
|
||||
|
||||
fpga_multicorrelator_8sc::~fpga_multicorrelator_8sc()
|
||||
{
|
||||
delete[] d_ca_codes;
|
||||
//delete[] d_ca_codes;
|
||||
close_device();
|
||||
}
|
||||
|
||||
@ -220,10 +323,21 @@ void fpga_multicorrelator_8sc::set_channel(unsigned int channel)
|
||||
devicebasetemp << numdevice;
|
||||
mergedname = d_device_name + devicebasetemp.str();
|
||||
strcpy(device_io_name, mergedname.c_str());
|
||||
|
||||
//printf("ppps opening device %s\n", device_io_name);
|
||||
|
||||
if ((d_device_descriptor = open(device_io_name, O_RDWR | O_SYNC)) == -1)
|
||||
{
|
||||
LOG(WARNING) << "Cannot open deviceio" << device_io_name;
|
||||
std::cout << "Cannot open deviceio" << device_io_name << std::endl;
|
||||
|
||||
//printf("error opening device\n");
|
||||
}
|
||||
// else
|
||||
// {
|
||||
// std::cout << "deviceio" << device_io_name << " opened successfully" << std::endl;
|
||||
//
|
||||
// }
|
||||
d_map_base = reinterpret_cast<volatile unsigned *>(mmap(NULL, PAGE_SIZE,
|
||||
PROT_READ | PROT_WRITE, MAP_SHARED, d_device_descriptor, 0));
|
||||
|
||||
@ -231,7 +345,17 @@ void fpga_multicorrelator_8sc::set_channel(unsigned int channel)
|
||||
{
|
||||
LOG(WARNING) << "Cannot map the FPGA tracking module "
|
||||
<< d_channel << "into user memory";
|
||||
std::cout << "Cannot map deviceio" << device_io_name << std::endl;
|
||||
//printf("error mapping registers\n");
|
||||
}
|
||||
// else
|
||||
// {
|
||||
// std::cout << "deviceio" << device_io_name << "mapped successfully" << std::endl;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// printf("mapping registers succes\n"); // this is for debug -- remove !
|
||||
// }
|
||||
|
||||
// sanity check : check test register
|
||||
unsigned writeval = TEST_REGISTER_TRACK_WRITEVAL;
|
||||
@ -240,10 +364,15 @@ void fpga_multicorrelator_8sc::set_channel(unsigned int channel)
|
||||
if (writeval != readval)
|
||||
{
|
||||
LOG(WARNING) << "Test register sanity check failed";
|
||||
// printf("tracking test register sanity check failed\n");
|
||||
|
||||
//printf("lslslls test sanity check reg failure\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(INFO) << "Test register sanity check success !";
|
||||
//printf("tracking test register sanity check success\n");
|
||||
//printf("lslslls test sanity check reg success\n");
|
||||
}
|
||||
}
|
||||
|
||||
@ -251,11 +380,13 @@ void fpga_multicorrelator_8sc::set_channel(unsigned int channel)
|
||||
unsigned fpga_multicorrelator_8sc::fpga_acquisition_test_register(
|
||||
unsigned writeval)
|
||||
{
|
||||
unsigned readval;
|
||||
//printf("d_TEST_REG_ADDR = %d\n", d_TEST_REG_ADDR);
|
||||
|
||||
unsigned readval = 0;
|
||||
// write value to test register
|
||||
d_map_base[15] = writeval;
|
||||
d_map_base[d_TEST_REG_ADDR] = writeval;
|
||||
// read value from test register
|
||||
readval = d_map_base[15];
|
||||
readval = d_map_base[d_TEST_REG_ADDR];
|
||||
// return read value
|
||||
return readval;
|
||||
}
|
||||
@ -265,16 +396,29 @@ void fpga_multicorrelator_8sc::fpga_configure_tracking_gps_local_code(int PRN)
|
||||
{
|
||||
int k, s;
|
||||
unsigned code_chip;
|
||||
unsigned select_fpga_correlator;
|
||||
select_fpga_correlator = 0;
|
||||
unsigned select_pilot_corelator = LOCAL_CODE_FPGA_CORRELATOR_SELECT_COUNT;
|
||||
// select_fpga_correlator = 0;
|
||||
|
||||
for (s = 0; s < d_n_correlators; s++)
|
||||
{
|
||||
d_map_base[11] = LOCAL_CODE_FPGA_CLEAR_ADDRESS_COUNTER;
|
||||
for (k = 0; k < d_code_length_chips; k++)
|
||||
//printf("kkk d_n_correlators = %x\n", d_n_correlators);
|
||||
//printf("kkk d_code_length_chips = %d\n", d_code_length_chips);
|
||||
//printf("programming mems d map base %d\n", d_PROG_MEMS_ADDR);
|
||||
|
||||
//FILE *fp;
|
||||
//char str[80];
|
||||
//sprintf(str, "generated_code_PRN%d", PRN);
|
||||
//fp = fopen(str,"w");
|
||||
// for (s = 0; s < d_n_correlators; s++)
|
||||
// {
|
||||
|
||||
//printf("kkk select_fpga_correlator = %x\n", select_fpga_correlator);
|
||||
|
||||
d_map_base[d_PROG_MEMS_ADDR] = LOCAL_CODE_FPGA_CLEAR_ADDRESS_COUNTER;
|
||||
for (k = 0; k < d_code_length_chips * d_code_samples_per_chip; k++)
|
||||
{
|
||||
//if (d_local_code_in[k] == 1)
|
||||
if (d_ca_codes[((int(d_code_length)) * (PRN - 1)) + k] == 1)
|
||||
//printf("kkk d_ca_codes %d = %d\n", k, d_ca_codes[((int(d_code_length)) * (PRN - 1)) + k]);
|
||||
//fprintf(fp, "%d\n", d_ca_codes[((int(d_code_length_chips)) * d_code_samples_per_chip * (PRN - 1)) + k]);
|
||||
if (d_ca_codes[((int(d_code_length_chips)) * d_code_samples_per_chip * (PRN - 1)) + k] == 1)
|
||||
{
|
||||
code_chip = 1;
|
||||
}
|
||||
@ -282,13 +426,39 @@ void fpga_multicorrelator_8sc::fpga_configure_tracking_gps_local_code(int PRN)
|
||||
{
|
||||
code_chip = 0;
|
||||
}
|
||||
|
||||
// copy the local code to the FPGA memory one by one
|
||||
d_map_base[11] = LOCAL_CODE_FPGA_ENABLE_WRITE_MEMORY
|
||||
| code_chip | select_fpga_correlator;
|
||||
d_map_base[d_PROG_MEMS_ADDR] = LOCAL_CODE_FPGA_ENABLE_WRITE_MEMORY
|
||||
| code_chip; // | select_fpga_correlator;
|
||||
}
|
||||
// select_fpga_correlator = select_fpga_correlator
|
||||
// + LOCAL_CODE_FPGA_CORRELATOR_SELECT_COUNT;
|
||||
// }
|
||||
//fclose(fp);
|
||||
//printf("kkk d_track_pilot = %d\n", d_track_pilot);
|
||||
if (d_track_pilot)
|
||||
{
|
||||
//printf("kkk select_fpga_correlator = %x\n", select_fpga_correlator);
|
||||
|
||||
d_map_base[d_PROG_MEMS_ADDR] = LOCAL_CODE_FPGA_CLEAR_ADDRESS_COUNTER;
|
||||
for (k = 0; k < d_code_length_chips * d_code_samples_per_chip; k++)
|
||||
{
|
||||
//if (d_local_code_in[k] == 1)
|
||||
if (d_data_codes[((int(d_code_length_chips)) * d_code_samples_per_chip * (PRN - 1)) + k] == 1)
|
||||
{
|
||||
code_chip = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
code_chip = 0;
|
||||
}
|
||||
//printf("%d %d | ", d_data_codes, code_chip);
|
||||
// copy the local code to the FPGA memory one by one
|
||||
d_map_base[d_PROG_MEMS_ADDR] = LOCAL_CODE_FPGA_ENABLE_WRITE_MEMORY
|
||||
| code_chip | select_pilot_corelator;
|
||||
}
|
||||
select_fpga_correlator = select_fpga_correlator
|
||||
+ LOCAL_CODE_FPGA_CORRELATOR_SELECT_COUNT;
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
@ -297,24 +467,56 @@ void fpga_multicorrelator_8sc::fpga_compute_code_shift_parameters(void)
|
||||
float temp_calculation;
|
||||
int i;
|
||||
|
||||
//printf("ppp d_rem_code_phase_chips = %f\n", d_rem_code_phase_chips);
|
||||
for (i = 0; i < d_n_correlators; i++)
|
||||
{
|
||||
//printf("ppp d_shifts_chips %d = %f\n", i, d_shifts_chips[i]);
|
||||
//printf("ppp d_code_samples_per_chip = %d\n", d_code_samples_per_chip);
|
||||
temp_calculation = floor(
|
||||
d_shifts_chips[i] - d_rem_code_phase_chips);
|
||||
|
||||
|
||||
//printf("ppp d_rem_code_phase_chips = %f\n", d_rem_code_phase_chips);
|
||||
//printf("ppp temp calculation %d = %f ================================ \n", i, temp_calculation);
|
||||
if (temp_calculation < 0)
|
||||
{
|
||||
temp_calculation = temp_calculation + d_code_length_chips; // % operator does not work as in Matlab with negative numbers
|
||||
temp_calculation = temp_calculation + (d_code_length_chips * d_code_samples_per_chip); // % operator does not work as in Matlab with negative numbers
|
||||
}
|
||||
d_initial_index[i] = static_cast<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<unsigned>( (static_cast<int>(temp_calculation)) % (d_code_length_chips * d_code_samples_per_chip));
|
||||
//printf("ppp d_initial_index %d = %d\n", i, d_initial_index[i]);
|
||||
temp_calculation = fmod(d_shifts_chips[i] - d_rem_code_phase_chips,
|
||||
1.0);
|
||||
//printf("ppp fmod %d = fmod(%f, 1) = %f\n", i, d_shifts_chips[i] - d_rem_code_phase_chips, temp_calculation);
|
||||
if (temp_calculation < 0)
|
||||
{
|
||||
temp_calculation = temp_calculation + 1.0; // fmod operator does not work as in Matlab with negative numbers
|
||||
}
|
||||
|
||||
d_initial_interp_counter[i] = static_cast<unsigned>( 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<unsigned>( (static_cast<int>(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<unsigned>( floor( MAX_CODE_RESAMPLER_COUNTER * temp_calculation));
|
||||
}
|
||||
//while(1);
|
||||
}
|
||||
|
||||
|
||||
@ -323,10 +525,23 @@ void fpga_multicorrelator_8sc::fpga_configure_code_parameters_in_fpga(void)
|
||||
int i;
|
||||
for (i = 0; i < d_n_correlators; i++)
|
||||
{
|
||||
d_map_base[1 + i] = d_initial_index[i];
|
||||
d_map_base[1 + d_n_correlators + i] = d_initial_interp_counter[i];
|
||||
//printf("www writing d map base %d = d_initial_index %d = %d\n", d_INITIAL_INDEX_REG_BASE_ADDR + i, i, d_initial_index[i]);
|
||||
d_map_base[d_INITIAL_INDEX_REG_BASE_ADDR + i] = d_initial_index[i];
|
||||
//d_map_base[1 + d_n_correlators + i] = d_initial_interp_counter[i];
|
||||
//printf("www writing d map base %d = d_initial_interp_counter %d = %d\n", d_INITIAL_INTERP_COUNTER_REG_BASE_ADDR + i, i, d_initial_interp_counter[i]);
|
||||
d_map_base[d_INITIAL_INTERP_COUNTER_REG_BASE_ADDR + i] = d_initial_interp_counter[i];
|
||||
}
|
||||
d_map_base[8] = d_code_length_chips - 1; // number of samples - 1
|
||||
if (d_track_pilot)
|
||||
{
|
||||
//printf("www writing d map base %d = d_initial_index %d = %d\n", d_INITIAL_INDEX_REG_BASE_ADDR + d_n_correlators, d_n_correlators, d_initial_index[d_n_correlators]);
|
||||
d_map_base[d_INITIAL_INDEX_REG_BASE_ADDR + d_n_correlators] = d_initial_index[d_n_correlators];
|
||||
//d_map_base[1 + d_n_correlators + i] = d_initial_interp_counter[i];
|
||||
//printf("www writing d map base %d = d_initial_interp_counter %d = %d\n", d_INITIAL_INTERP_COUNTER_REG_BASE_ADDR + d_n_correlators, d_n_correlators, d_initial_interp_counter[d_n_correlators]);
|
||||
d_map_base[d_INITIAL_INTERP_COUNTER_REG_BASE_ADDR + d_n_correlators] = d_initial_interp_counter[d_n_correlators];
|
||||
}
|
||||
|
||||
//printf("www writing d map base %d = d_code_length_chips*d_code_samples_per_chip - 1 = %d\n", d_CODE_LENGTH_MINUS_1_REG_ADDR, (d_code_length_chips*d_code_samples_per_chip) - 1);
|
||||
d_map_base[d_CODE_LENGTH_MINUS_1_REG_ADDR] = (d_code_length_chips*d_code_samples_per_chip) - 1; // number of samples - 1
|
||||
}
|
||||
|
||||
|
||||
@ -335,6 +550,13 @@ void fpga_multicorrelator_8sc::fpga_compute_signal_parameters_in_fpga(void)
|
||||
float d_rem_carrier_phase_in_rad_temp;
|
||||
|
||||
d_code_phase_step_chips_num = static_cast<unsigned>( roundf(MAX_CODE_RESAMPLER_COUNTER * d_code_phase_step_chips));
|
||||
if (d_code_phase_step_chips > 1.0)
|
||||
{
|
||||
printf("Warning : d_code_phase_step_chips = %d cannot be bigger than one\n", d_code_phase_step_chips);
|
||||
}
|
||||
|
||||
//printf("d_rem_carrier_phase_in_rad = %f\n", d_rem_carrier_phase_in_rad);
|
||||
|
||||
if (d_rem_carrier_phase_in_rad > M_PI)
|
||||
{
|
||||
d_rem_carrier_phase_in_rad_temp = -2 * M_PI
|
||||
@ -359,19 +581,30 @@ void fpga_multicorrelator_8sc::fpga_compute_signal_parameters_in_fpga(void)
|
||||
d_phase_step_rad_int = static_cast<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
|
||||
|
||||
//printf("d_phase_step_rad_int = %d\n", d_phase_step_rad_int);
|
||||
if (d_phase_step_rad < 0)
|
||||
{
|
||||
d_phase_step_rad_int = -d_phase_step_rad_int;
|
||||
}
|
||||
|
||||
//printf("d_phase_step_rad_int = %d\n", d_phase_step_rad_int);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void fpga_multicorrelator_8sc::fpga_configure_signal_parameters_in_fpga(void)
|
||||
{
|
||||
d_map_base[0] = d_code_phase_step_chips_num;
|
||||
d_map_base[7] = d_correlator_length_samples - 1;
|
||||
d_map_base[9] = d_rem_carr_phase_rad_int;
|
||||
d_map_base[10] = d_phase_step_rad_int;
|
||||
//printf("www d map base %d = d_code_phase_step_chips_num = %d\n", d_CODE_PHASE_STEP_CHIPS_NUM_REG_ADDR, d_code_phase_step_chips_num);
|
||||
d_map_base[d_CODE_PHASE_STEP_CHIPS_NUM_REG_ADDR] = d_code_phase_step_chips_num;
|
||||
|
||||
//printf("www d map base %d = d_correlator_length_samples - 1 = %d\n", d_NSAMPLES_MINUS_1_REG_ADDR, d_correlator_length_samples - 1);
|
||||
d_map_base[d_NSAMPLES_MINUS_1_REG_ADDR] = d_correlator_length_samples - 1;
|
||||
|
||||
//printf("www d map base %d = d_rem_carr_phase_rad_int = %d\n", d_REM_CARR_PHASE_RAD_REG_ADDR, d_rem_carr_phase_rad_int);
|
||||
d_map_base[d_REM_CARR_PHASE_RAD_REG_ADDR] = d_rem_carr_phase_rad_int;
|
||||
|
||||
//printf("www d map base %d = d_phase_step_rad_int = %d\n", d_PHASE_STEP_RAD_REG_ADDR, d_phase_step_rad_int);
|
||||
d_map_base[d_PHASE_STEP_RAD_REG_ADDR] = d_phase_step_rad_int;
|
||||
}
|
||||
|
||||
|
||||
@ -382,7 +615,10 @@ void fpga_multicorrelator_8sc::fpga_launch_multicorrelator_fpga(void)
|
||||
write(d_device_descriptor, reinterpret_cast<void*>(&reenable), sizeof(int));
|
||||
|
||||
// writing 1 to reg 14 launches the tracking
|
||||
d_map_base[14] = 1;
|
||||
//printf("www writing 1 to d map base %d = start flag\n", d_START_FLAG_ADDR);
|
||||
d_map_base[d_START_FLAG_ADDR] = 1;
|
||||
//while(1);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -392,28 +628,86 @@ void fpga_multicorrelator_8sc::read_tracking_gps_results(void)
|
||||
int readval_imag;
|
||||
int k;
|
||||
|
||||
|
||||
for (k = 0; k < d_n_correlators; k++)
|
||||
{
|
||||
readval_real = d_map_base[1 + k];
|
||||
if (readval_real >= 1048576) // 0x100000 (21 bits two's complement)
|
||||
readval_real = d_map_base[d_RESULT_REG_REAL_BASE_ADDR + k];
|
||||
//printf("read real before checking d map base %d = %d\n", d_RESULT_REG_BASE_ADDR + k, readval_real);
|
||||
// if (readval_real > debug_max_readval_real[k])
|
||||
// {
|
||||
// debug_max_readval_real[k] = readval_real;
|
||||
// }
|
||||
if (readval_real >= d_result_SAT_value) // 0x100000 (21 bits two's complement)
|
||||
{
|
||||
readval_real = -2097152 + readval_real;
|
||||
readval_real = -2*d_result_SAT_value + readval_real;
|
||||
}
|
||||
// if (readval_real > debug_max_readval_real_after_check[k])
|
||||
// {
|
||||
// debug_max_readval_real_after_check[k] = readval_real;
|
||||
// }
|
||||
//printf("read real d map base %d = %d\n", d_RESULT_REG_BASE_ADDR + k, readval_real);
|
||||
readval_imag = d_map_base[d_RESULT_REG_IMAG_BASE_ADDR + k];
|
||||
//printf("read imag before checking d map base %d = %d\n", d_RESULT_REG_BASE_ADDR + k, readval_imag);
|
||||
// if (readval_imag > debug_max_readval_imag[k])
|
||||
// {
|
||||
// debug_max_readval_imag[k] = readval_imag;
|
||||
// }
|
||||
|
||||
if (readval_imag >= d_result_SAT_value) // 0x100000 (21 bits two's complement)
|
||||
{
|
||||
readval_imag = -2*d_result_SAT_value + readval_imag;
|
||||
}
|
||||
// if (readval_imag > debug_max_readval_imag_after_check[k])
|
||||
// {
|
||||
// debug_max_readval_imag_after_check[k] = readval_real;
|
||||
// }
|
||||
//printf("read imag d map base %d = %d\n", d_RESULT_REG_BASE_ADDR + k, readval_imag);
|
||||
d_corr_out[k] = gr_complex(readval_real,readval_imag);
|
||||
|
||||
// if (printcounter > 100)
|
||||
// {
|
||||
// printcounter = 0;
|
||||
// for (int ll=0;ll<d_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[1 + d_n_correlators + k];
|
||||
if (readval_imag >= 1048576) // 0x100000 (21 bits two's complement)
|
||||
readval_imag = d_map_base[d_RESULT_REG_DATA_IMAG_BASE_ADDR];
|
||||
if (readval_imag >= d_result_SAT_value) // 0x100000 (21 bits two's complement)
|
||||
{
|
||||
readval_imag = -2097152 + readval_imag;
|
||||
readval_imag = -2*d_result_SAT_value + readval_imag;
|
||||
}
|
||||
d_corr_out[k] = gr_complex(readval_real,readval_imag);
|
||||
d_Prompt_Data[0] = gr_complex(readval_real,readval_imag);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void fpga_multicorrelator_8sc::unlock_channel(void)
|
||||
{
|
||||
// unlock the channel to let the next samples go through
|
||||
d_map_base[12] = 1; // unlock the channel
|
||||
//printf("www writing 1 to d map base %d = drop samples\n", d_DROP_SAMPLES_REG_ADDR);
|
||||
d_map_base[d_DROP_SAMPLES_REG_ADDR] = 1; // unlock the channel
|
||||
}
|
||||
|
||||
void fpga_multicorrelator_8sc::close_device()
|
||||
@ -430,19 +724,20 @@ void fpga_multicorrelator_8sc::close_device()
|
||||
void fpga_multicorrelator_8sc::lock_channel(void)
|
||||
{
|
||||
// lock the channel for processing
|
||||
d_map_base[12] = 0; // lock the channel
|
||||
//printf("www writing 0 to d map base %d = drop samples\n", d_DROP_SAMPLES_REG_ADDR);
|
||||
d_map_base[d_DROP_SAMPLES_REG_ADDR] = 0; // lock the channel
|
||||
}
|
||||
|
||||
void fpga_multicorrelator_8sc::read_sample_counters(int *sample_counter, int *secondary_sample_counter, int *counter_corr_0_in, int *counter_corr_0_out)
|
||||
{
|
||||
*sample_counter = d_map_base[11];
|
||||
*secondary_sample_counter = d_map_base[8];
|
||||
*counter_corr_0_in = d_map_base[10];
|
||||
*counter_corr_0_out = d_map_base[9];
|
||||
|
||||
}
|
||||
//void fpga_multicorrelator_8sc::read_sample_counters(int *sample_counter, int *secondary_sample_counter, int *counter_corr_0_in, int *counter_corr_0_out)
|
||||
//{
|
||||
// *sample_counter = d_map_base[11];
|
||||
// *secondary_sample_counter = d_map_base[8];
|
||||
// *counter_corr_0_in = d_map_base[10];
|
||||
// *counter_corr_0_out = d_map_base[9];
|
||||
//
|
||||
//}
|
||||
|
||||
void fpga_multicorrelator_8sc::reset_multicorrelator(void)
|
||||
{
|
||||
d_map_base[14] = 2; // writing a 2 to d_map_base[14] resets the multicorrelator
|
||||
}
|
||||
//void fpga_multicorrelator_8sc::reset_multicorrelator(void)
|
||||
//{
|
||||
// d_map_base[14] = 2; // writing a 2 to d_map_base[14] resets the multicorrelator
|
||||
//}
|
||||
|
@ -49,7 +49,7 @@ class fpga_multicorrelator_8sc
|
||||
{
|
||||
public:
|
||||
fpga_multicorrelator_8sc(int n_correlators, std::string device_name,
|
||||
unsigned int device_base, int *ca_codes, int *data_codes, unsigned int code_length, bool track_pilot);
|
||||
unsigned int device_base, int *ca_codes, int *data_codes, unsigned int code_length_chips, bool track_pilot, unsigned int multicorr_type, unsigned int code_samples_per_chip);
|
||||
~fpga_multicorrelator_8sc();
|
||||
//bool set_output_vectors(gr_complex* corr_out);
|
||||
void set_output_vectors(gr_complex* corr_out, gr_complex* Prompt_Data);
|
||||
@ -58,8 +58,8 @@ public:
|
||||
// float *shifts_chips, int PRN);
|
||||
//bool set_local_code_and_taps(
|
||||
void set_local_code_and_taps(
|
||||
int code_length_chips,
|
||||
float *shifts_chips, int PRN);
|
||||
// int code_length_chips,
|
||||
float *shifts_chips, float *prompt_data_shift, int PRN);
|
||||
//bool set_output_vectors(lv_16sc_t* corr_out);
|
||||
void update_local_code(float rem_code_phase_chips);
|
||||
//bool Carrier_wipeoff_multicorrelator_resampler(
|
||||
@ -72,7 +72,7 @@ public:
|
||||
int read_sample_counter();
|
||||
void lock_channel(void);
|
||||
void unlock_channel(void);
|
||||
void read_sample_counters(int *sample_counter, int *secondary_sample_counter, int *counter_corr_0_in, int *counter_corr_0_out); // debug
|
||||
//void read_sample_counters(int *sample_counter, int *secondary_sample_counter, int *counter_corr_0_in, int *counter_corr_0_out); // debug
|
||||
|
||||
|
||||
private:
|
||||
@ -80,6 +80,7 @@ private:
|
||||
gr_complex * d_corr_out;
|
||||
gr_complex * d_Prompt_Data;
|
||||
float *d_shifts_chips;
|
||||
float *d_prompt_data_shift;
|
||||
int d_code_length_chips;
|
||||
int d_n_correlators;
|
||||
|
||||
@ -110,11 +111,37 @@ private:
|
||||
|
||||
|
||||
int* d_ca_codes;
|
||||
int* d_data_codes;
|
||||
|
||||
unsigned int d_code_length; // nominal number of chips
|
||||
//unsigned int d_code_length; // nominal number of chips
|
||||
|
||||
unsigned int d_code_samples_per_chip;
|
||||
bool d_track_pilot;
|
||||
|
||||
unsigned int d_multicorr_type;
|
||||
|
||||
// register addresses
|
||||
// write-only regs
|
||||
unsigned int d_CODE_PHASE_STEP_CHIPS_NUM_REG_ADDR;
|
||||
unsigned int d_INITIAL_INDEX_REG_BASE_ADDR;
|
||||
unsigned int d_INITIAL_INTERP_COUNTER_REG_BASE_ADDR;
|
||||
unsigned int d_NSAMPLES_MINUS_1_REG_ADDR;
|
||||
unsigned int d_CODE_LENGTH_MINUS_1_REG_ADDR;
|
||||
unsigned int d_REM_CARR_PHASE_RAD_REG_ADDR;
|
||||
unsigned int d_PHASE_STEP_RAD_REG_ADDR;
|
||||
unsigned int d_PROG_MEMS_ADDR;
|
||||
unsigned int d_DROP_SAMPLES_REG_ADDR;
|
||||
unsigned int d_INITIAL_COUNTER_VALUE_REG_ADDR;
|
||||
unsigned int d_START_FLAG_ADDR;
|
||||
// read-write regs
|
||||
unsigned int d_TEST_REG_ADDR;
|
||||
// read-only regs
|
||||
unsigned int d_RESULT_REG_REAL_BASE_ADDR;
|
||||
unsigned int d_RESULT_REG_IMAG_BASE_ADDR;
|
||||
unsigned int d_RESULT_REG_DATA_REAL_BASE_ADDR;
|
||||
unsigned int d_RESULT_REG_DATA_IMAG_BASE_ADDR;
|
||||
unsigned int d_SAMPLE_COUNTER_REG_ADDR;
|
||||
|
||||
// private functions
|
||||
unsigned fpga_acquisition_test_register(unsigned writeval);
|
||||
void fpga_configure_tracking_gps_local_code(int PRN);
|
||||
@ -124,9 +151,17 @@ private:
|
||||
void fpga_configure_signal_parameters_in_fpga(void);
|
||||
void fpga_launch_multicorrelator_fpga(void);
|
||||
void read_tracking_gps_results(void);
|
||||
void reset_multicorrelator(void);
|
||||
//void reset_multicorrelator(void);
|
||||
void close_device(void);
|
||||
|
||||
unsigned int d_result_SAT_value;
|
||||
|
||||
int debug_max_readval_real[5] = {0, 0, 0, 0, 0};
|
||||
int debug_max_readval_imag[5] = {0, 0, 0, 0, 0};;
|
||||
int debug_max_readval_real_after_check[5] = {0, 0, 0, 0, 0};
|
||||
int debug_max_readval_imag_after_check[5] = {0, 0, 0, 0, 0};
|
||||
int printcounter = 0;
|
||||
|
||||
};
|
||||
|
||||
#endif /* GNSS_SDR_FPGA_MULTICORRELATOR_H_ */
|
||||
|
@ -106,9 +106,15 @@
|
||||
|
||||
#if ENABLE_FPGA
|
||||
#include "gps_l1_ca_pcps_acquisition_fpga.h"
|
||||
#include "gps_l2_m_pcps_acquisition_fpga.h"
|
||||
#include "galileo_e1_pcps_ambiguous_acquisition_fpga.h"
|
||||
#include "galileo_e5a_pcps_acquisition_fpga.h"
|
||||
#include "gps_l5i_pcps_acquisition_fpga.h"
|
||||
#include "gps_l1_ca_dll_pll_tracking_fpga.h"
|
||||
#include "gps_l2_m_dll_pll_tracking_fpga.h"
|
||||
#include "galileo_e1_dll_pll_veml_tracking_fpga.h"
|
||||
#include "galileo_e5a_dll_pll_tracking_fpga.h"
|
||||
#include "gps_l5_dll_pll_tracking_fpga.h"
|
||||
#endif
|
||||
|
||||
#if OPENCL_BLOCKS
|
||||
@ -1374,12 +1380,28 @@ std::unique_ptr<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,
|
||||
@ -1424,6 +1446,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,
|
||||
@ -1475,12 +1505,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)
|
||||
{
|
||||
@ -1515,6 +1561,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,
|
||||
@ -1683,12 +1737,28 @@ 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,
|
||||
@ -1740,6 +1810,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,
|
||||
@ -1822,18 +1900,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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user