1
0
mirror of https://github.com/gnss-sdr/gnss-sdr synced 2024-12-15 12:40:35 +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:
Marc Majoral 2018-08-01 15:55:40 +02:00
parent 75cbc3fcdd
commit bb33faea21
29 changed files with 3894 additions and 145 deletions

View File

@ -37,7 +37,7 @@ set(ACQ_ADAPTER_SOURCES
) )
if(ENABLE_FPGA) 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) endif(ENABLE_FPGA)
if(OPENCL_FOUND) if(OPENCL_FOUND)

View File

@ -38,7 +38,7 @@
#include <boost/math/distributions/exponential.hpp> #include <boost/math/distributions/exponential.hpp>
#include <glog/logging.h> #include <glog/logging.h>
#define NUM_PRNs_GALILEO_E1 50
using google::LogMessage; using google::LogMessage;
@ -46,7 +46,7 @@ GalileoE1PcpsAmbiguousAcquisitionFpga::GalileoE1PcpsAmbiguousAcquisitionFpga(
ConfigurationInterface* configuration, std::string role, ConfigurationInterface* configuration, std::string role,
unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams) 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; pcpsconf_fpga_t acq_parameters;
configuration_ = configuration; configuration_ = configuration;
std::string default_item_type = "gr_complex"; std::string default_item_type = "gr_complex";
@ -61,16 +61,17 @@ GalileoE1PcpsAmbiguousAcquisitionFpga::GalileoE1PcpsAmbiguousAcquisitionFpga(
acq_parameters.fs_in = fs_in; acq_parameters.fs_in = fs_in;
if_ = configuration_->property(role + ".if", 0); if_ = configuration_->property(role + ".if", 0);
acq_parameters.freq = if_; acq_parameters.freq = if_;
dump_ = configuration_->property(role + ".dump", false);
// dump_ = configuration_->property(role + ".dump", false);
// acq_parameters.dump = dump_; // acq_parameters.dump = dump_;
blocking_ = configuration_->property(role + ".blocking", true); // blocking_ = configuration_->property(role + ".blocking", true);
// acq_parameters.blocking = blocking_; // acq_parameters.blocking = blocking_;
doppler_max_ = configuration_->property(role + ".doppler_max", 5000); doppler_max_ = configuration_->property(role + ".doppler_max", 5000);
if (FLAGS_doppler_max != 0) doppler_max_ = FLAGS_doppler_max; if (FLAGS_doppler_max != 0) doppler_max_ = FLAGS_doppler_max;
acq_parameters.doppler_max = doppler_max_; acq_parameters.doppler_max = doppler_max_;
unsigned int sampled_ms = 4; unsigned int sampled_ms = 4;
acq_parameters.sampled_ms = sampled_ms; 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_; // 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 // 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_; // acq_parameters.use_CFAR_algorithm_flag = use_CFAR_algorithm_flag_;
@ -78,7 +79,7 @@ GalileoE1PcpsAmbiguousAcquisitionFpga::GalileoE1PcpsAmbiguousAcquisitionFpga(
// max_dwells_ = configuration_->property(role + ".max_dwells", 1); // max_dwells_ = configuration_->property(role + ".max_dwells", 1);
// acq_parameters.max_dwells = max_dwells_; // 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_; // acq_parameters.dump_filename = dump_filename_;
//--- Find number of samples per spreading code (4 ms) ----------------- //--- 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))); 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; // 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. // The FPGA can only use FFT lengths that are a power of two.
float nbits = ceilf(log2f((float)code_length)); float nbits = ceilf(log2f((float)code_length));
unsigned int nsamples_total = pow(2, nbits); unsigned int nsamples_total = pow(2, nbits);
unsigned int vector_length = nsamples_total; 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); unsigned int select_queue_Fpga = configuration_->property(role + ".select_queue_Fpga", 0);
acq_parameters.select_queue_Fpga = select_queue_Fpga; acq_parameters.select_queue_Fpga = select_queue_Fpga;
std::string default_device_name = "/dev/uio0"; 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_ms = nsamples_total/sampled_ms;
acq_parameters.samples_per_code = nsamples_total; 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 // 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) // a channel is assigned)
gr::fft::fft_complex* fft_if = new gr::fft::fft_complex(nsamples_total, true); // Direct FFT 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 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())); 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 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_]; //code_ = new gr_complex[vector_length_];
@ -128,15 +132,17 @@ GalileoE1PcpsAmbiguousAcquisitionFpga::GalileoE1PcpsAmbiguousAcquisitionFpga(
if (acquire_pilot_ == true) if (acquire_pilot_ == true)
{ {
//printf("yes acquiring pilot!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1\n");
//set local signal generator to Galileo E1 pilot component (1C) //set local signal generator to Galileo E1 pilot component (1C)
char pilot_signal[3] = "1C"; char pilot_signal[3] = "1C";
galileo_e1_code_gen_complex_sampled(code, pilot_signal, galileo_e1_code_gen_complex_sampled(code, pilot_signal,
cboc, gnss_synchro_->PRN, fs_in, 0, false); cboc, PRN, fs_in, 0, false);
} }
else else
{ {
galileo_e1_code_gen_complex_sampled(code, gnss_synchro_->Signal, char data_signal[3] = "1B";
cboc, gnss_synchro_->PRN, fs_in, 0, false); 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++) // 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_); // 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 // // fill in zero padding
for (int s = code_length; s < nsamples_total; s++) for (int s = code_length; s < nsamples_total; s++)
{ {
code[s] = 0; code[s] = std::complex<float>(static_cast<float>(0,0));
//code[s] = 0;
} }
memcpy(fft_if->get_inbuf(), code, sizeof(gr_complex) * nsamples_total); // copy to FFT buffer memcpy(fft_if->get_inbuf(), code, sizeof(gr_complex) * nsamples_total); // copy to FFT buffer
fft_if->execute(); // Run the FFT of local code fft_if->execute(); // Run the FFT of local code
volk_32fc_conjugate_32fc(fft_codes_padded, fft_if->get_outbuf(), nsamples_total); // conjugate values 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 // normalize the code
max = 0; // initialize maximum value 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 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)), //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(fft_codes_padded[i].imag() * (pow(2, 7) - 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
acq_parameters.all_fft_codes = d_all_fft_codes_; acq_parameters.all_fft_codes = d_all_fft_codes_;
@ -203,25 +294,31 @@ GalileoE1PcpsAmbiguousAcquisitionFpga::GalileoE1PcpsAmbiguousAcquisitionFpga(
//threshold_ = 0.0; //threshold_ = 0.0;
doppler_step_ = 0; doppler_step_ = 0;
gnss_synchro_ = 0; gnss_synchro_ = 0;
//printf("top acq constructor end\n");
} }
GalileoE1PcpsAmbiguousAcquisitionFpga::~GalileoE1PcpsAmbiguousAcquisitionFpga() GalileoE1PcpsAmbiguousAcquisitionFpga::~GalileoE1PcpsAmbiguousAcquisitionFpga()
{ {
//printf("top acq destructor start\n");
//delete[] code_; //delete[] code_;
delete[] d_all_fft_codes_; delete[] d_all_fft_codes_;
//printf("top acq destructor end\n");
} }
void GalileoE1PcpsAmbiguousAcquisitionFpga::set_channel(unsigned int channel) void GalileoE1PcpsAmbiguousAcquisitionFpga::set_channel(unsigned int channel)
{ {
//printf("top acq set channel start\n");
channel_ = channel; channel_ = channel;
acquisition_fpga_->set_channel(channel_); acquisition_fpga_->set_channel(channel_);
//printf("top acq set channel end\n");
} }
void GalileoE1PcpsAmbiguousAcquisitionFpga::set_threshold(float threshold) 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. // 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. // 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; DLOG(INFO) << "Channel " << channel_ << " Threshold = " << threshold;
acquisition_fpga_->set_threshold(threshold); acquisition_fpga_->set_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) void GalileoE1PcpsAmbiguousAcquisitionFpga::set_doppler_max(unsigned int doppler_max)
{ {
//printf("top acq set doppler max start\n");
doppler_max_ = doppler_max; doppler_max_ = doppler_max;
acquisition_fpga_->set_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) void GalileoE1PcpsAmbiguousAcquisitionFpga::set_doppler_step(unsigned int doppler_step)
{ {
//printf("top acq set doppler step start\n");
doppler_step_ = doppler_step; doppler_step_ = doppler_step;
acquisition_fpga_->set_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) void GalileoE1PcpsAmbiguousAcquisitionFpga::set_gnss_synchro(Gnss_Synchro* gnss_synchro)
{ {
//printf("top acq set gnss synchro start\n");
gnss_synchro_ = gnss_synchro; gnss_synchro_ = gnss_synchro;
acquisition_fpga_->set_gnss_synchro(gnss_synchro_); acquisition_fpga_->set_gnss_synchro(gnss_synchro_);
//printf("top acq set gnss synchro end\n");
} }
signed int GalileoE1PcpsAmbiguousAcquisitionFpga::mag() signed int GalileoE1PcpsAmbiguousAcquisitionFpga::mag()
{ {
// printf("top acq mag start\n");
return acquisition_fpga_->mag(); return acquisition_fpga_->mag();
//printf("top acq mag end\n");
} }
void GalileoE1PcpsAmbiguousAcquisitionFpga::init() void GalileoE1PcpsAmbiguousAcquisitionFpga::init()
{ {
// printf("top acq init start\n");
acquisition_fpga_->init(); acquisition_fpga_->init();
// printf("top acq init end\n");
//set_local_code(); //set_local_code();
} }
void GalileoE1PcpsAmbiguousAcquisitionFpga::set_local_code() void GalileoE1PcpsAmbiguousAcquisitionFpga::set_local_code()
{ {
// printf("top acq set local code start\n");
// bool cboc = configuration_->property( // bool cboc = configuration_->property(
// "Acquisition" + boost::lexical_cast<std::string>(channel_) + ".cboc", false); // "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(code_);
acquisition_fpga_->set_local_code(); acquisition_fpga_->set_local_code();
// delete[] code; // delete[] code;
// printf("top acq set local code end\n");
} }
void GalileoE1PcpsAmbiguousAcquisitionFpga::reset() void GalileoE1PcpsAmbiguousAcquisitionFpga::reset()
{ {
// printf("top acq reset start\n");
acquisition_fpga_->set_active(true); acquisition_fpga_->set_active(true);
// printf("top acq reset end\n");
} }
void GalileoE1PcpsAmbiguousAcquisitionFpga::set_state(int state) void GalileoE1PcpsAmbiguousAcquisitionFpga::set_state(int state)
{ {
// printf("top acq set state start\n");
acquisition_fpga_->set_state(state); 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) void GalileoE1PcpsAmbiguousAcquisitionFpga::connect(gr::top_block_sptr top_block)
{ {
// printf("top acq connect\n");
// if (item_type_.compare("gr_complex") == 0) // if (item_type_.compare("gr_complex") == 0)
// { // {
// top_block->connect(stream_to_vector_, 0, acquisition_fpga_, 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 // nothing to disconnect
// printf("top acq disconnect\n");
} }
gr::basic_block_sptr GalileoE1PcpsAmbiguousAcquisitionFpga::get_left_block() gr::basic_block_sptr GalileoE1PcpsAmbiguousAcquisitionFpga::get_left_block()
{ {
// printf("top acq get left block start\n");
// if (item_type_.compare("gr_complex") == 0) // if (item_type_.compare("gr_complex") == 0)
// { // {
// return stream_to_vector_; // return stream_to_vector_;
@ -419,10 +536,14 @@ gr::basic_block_sptr GalileoE1PcpsAmbiguousAcquisitionFpga::get_left_block()
// LOG(WARNING) << item_type_ << " unknown acquisition item type"; // LOG(WARNING) << item_type_ << " unknown acquisition item type";
return nullptr; return nullptr;
// } // }
// printf("top acq get left block end\n");
} }
gr::basic_block_sptr GalileoE1PcpsAmbiguousAcquisitionFpga::get_right_block() gr::basic_block_sptr GalileoE1PcpsAmbiguousAcquisitionFpga::get_right_block()
{ {
// printf("top acq get right block start\n");
return acquisition_fpga_; return acquisition_fpga_;
// printf("top acq get right block end\n");
} }

View File

@ -59,6 +59,7 @@ public:
inline std::string role() override inline std::string role() override
{ {
// printf("top acq role\n");
return role_; return role_;
} }
@ -67,11 +68,13 @@ public:
*/ */
inline std::string implementation() override inline std::string implementation() override
{ {
// printf("top acq implementation\n");
return "Galileo_E1_PCPS_Ambiguous_Acquisition_Fpga"; return "Galileo_E1_PCPS_Ambiguous_Acquisition_Fpga";
} }
size_t item_size() override size_t item_size() override
{ {
// printf("top acq item size\n");
size_t item_size = sizeof(lv_16sc_t); size_t item_size = sizeof(lv_16sc_t);
return item_size; return item_size;
} }

View File

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

View File

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

View File

@ -60,6 +60,8 @@ GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga(
long fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 2048000); 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); long fs_in = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated);
//fs_in = fs_in/2.0; // downampling filter
//printf("####### DEBUG Acq: fs_in = %d\n", fs_in);
acq_parameters.fs_in = fs_in; acq_parameters.fs_in = fs_in;
long ifreq = configuration_->property(role + ".if", 0); long ifreq = configuration_->property(role + ".if", 0);
acq_parameters.freq = ifreq; acq_parameters.freq = ifreq;
@ -69,7 +71,7 @@ GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga(
unsigned int sampled_ms = configuration_->property(role + ".coherent_integration_time_ms", 1); unsigned int sampled_ms = configuration_->property(role + ".coherent_integration_time_ms", 1);
acq_parameters.sampled_ms = sampled_ms; 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))); 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. // The FPGA can only use FFT lengths that are a power of two.
float nbits = ceilf(log2f((float)code_length)); float nbits = ceilf(log2f((float)code_length));
unsigned int nsamples_total = pow(2, nbits); unsigned int nsamples_total = pow(2, nbits);
@ -96,12 +98,29 @@ GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga(
// fill in zero padding // fill in zero padding
for (int s = code_length; s < nsamples_total; s++) for (int s = code_length; s < nsamples_total; s++)
{ {
code[s] = 0; code[s] = std::complex<float>(static_cast<float>(0,0));
//code[s] = 0;
} }
int offset = 0; int offset = 0;
memcpy(fft_if->get_inbuf() + offset, code, sizeof(gr_complex) * nsamples_total); // copy to FFT buffer 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 fft_if->execute(); // Run the FFT of local code
volk_32fc_conjugate_32fc(fft_codes_padded, fft_if->get_outbuf(), nsamples_total); // conjugate values 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 max = 0; // initialize maximum value
for (unsigned int i = 0; i < nsamples_total; i++) // search for maxima 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 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)), //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(fft_codes_padded[i].imag() * (pow(2, 7) - 1) / max))); // static_cast<int>(floor(256*fft_codes_padded[i].imag() * (pow(2, 7) - 1) / max)));
//d_all_fft_codes_[i + nsamples_total * (PRN - 1)] = lv_16sc_t(static_cast<int>(16*floor(fft_codes_padded[i].real() * (pow(2, 11) - 1) / max)),
// static_cast<int>(16*floor(fft_codes_padded[i].imag() * (pow(2, 11) - 1) / max)));
//d_all_fft_codes_[i + nsamples_total * (PRN - 1)] = lv_16sc_t(static_cast<int>(floor(fft_codes_padded[i].real() * (pow(2, 15) - 1) / max)),
// static_cast<int>(floor(fft_codes_padded[i].imag() * (pow(2, 15) - 1) / max)));
d_all_fft_codes_[i + nsamples_total * (PRN - 1)] = lv_16sc_t(static_cast<int>(floor(fft_codes_padded[i].real() * (pow(2, 15) - 1) / max)),
static_cast<int>(floor(fft_codes_padded[i].imag() * (pow(2, 15) - 1) / max)));
} }
//// // debug
// char filename2[25];
// FILE *fid2;
// sprintf(filename2,"fft_gps_prn%d_norm_new.txt", PRN);
// fid2 = fopen(filename2, "w");
// for (unsigned int kk=0;kk< nsamples_total; kk++)
// {
// fprintf(fid2, "%d\n", d_all_fft_codes_[kk + nsamples_total * (PRN - 1)].real());
// fprintf(fid2, "%d\n", d_all_fft_codes_[kk + nsamples_total * (PRN - 1)].imag());
// }
// fclose(fid2);
} }
//acq_parameters //acq_parameters

View File

@ -0,0 +1,398 @@
/*!
* \file gps_l2_m_pcps_acquisition.cc
* \brief Adapts a PCPS acquisition block to an AcquisitionInterface for
* GPS L2 M signals
* \authors <ul>
* <li> Javier Arribas, 2015. jarribas(at)cttc.es
* </ul>
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#include "gps_l2_m_pcps_acquisition_fpga.h"
#include "configuration_interface.h"
#include "gps_l2c_signal.h"
#include "GPS_L2C.h"
#include "gnss_sdr_flags.h"
#include <boost/math/distributions/exponential.hpp>
#include <glog/logging.h>
#define NUM_PRNs 32
using google::LogMessage;
GpsL2MPcpsAcquisitionFpga::GpsL2MPcpsAcquisitionFpga(
ConfigurationInterface* configuration, std::string role,
unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams)
{
//pcpsconf_t acq_parameters;
pcpsconf_fpga_t acq_parameters;
configuration_ = configuration;
std::string default_item_type = "gr_complex";
std::string default_dump_filename = "./data/acquisition.dat";
LOG(INFO) << "role " << role;
item_type_ = configuration_->property(role + ".item_type", default_item_type);
//float pfa = configuration_->property(role + ".pfa", 0.0);
long fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 2048000);
fs_in_ = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated);
acq_parameters.fs_in = fs_in_;
if_ = configuration_->property(role + ".if", 0);
acq_parameters.freq = if_;
//dump_ = configuration_->property(role + ".dump", false);
//acq_parameters.dump = dump_;
//blocking_ = configuration_->property(role + ".blocking", true);
//acq_parameters.blocking = blocking_;
doppler_max_ = configuration->property(role + ".doppler_max", 5000);
if (FLAGS_doppler_max != 0) doppler_max_ = FLAGS_doppler_max;
acq_parameters.doppler_max = doppler_max_;
//bit_transition_flag_ = configuration_->property(role + ".bit_transition_flag", false);
//acq_parameters.bit_transition_flag = bit_transition_flag_;
//use_CFAR_algorithm_flag_ = configuration_->property(role + ".use_CFAR_algorithm", true); //will be false in future versions
//acq_parameters.use_CFAR_algorithm_flag = use_CFAR_algorithm_flag_;
//max_dwells_ = configuration_->property(role + ".max_dwells", 1);
//acq_parameters.max_dwells = max_dwells_;
//dump_filename_ = configuration_->property(role + ".dump_filename", default_dump_filename);
//acq_parameters.dump_filename = dump_filename_;
//--- Find number of samples per spreading code -------------------------
//code_length_ = std::round(static_cast<double>(fs_in_) / (GPS_L2_M_CODE_RATE_HZ / static_cast<double>(GPS_L2_M_CODE_LENGTH_CHIPS)));
acq_parameters.sampled_ms = 20;
unsigned code_length = std::round(static_cast<double>(fs_in_) / (GPS_L2_M_CODE_RATE_HZ / static_cast<double>(GPS_L2_M_CODE_LENGTH_CHIPS)));
acq_parameters.code_length = code_length;
// The FPGA can only use FFT lengths that are a power of two.
float nbits = ceilf(log2f((float)code_length));
unsigned int nsamples_total = pow(2, nbits);
unsigned int vector_length = nsamples_total;
unsigned int select_queue_Fpga = configuration_->property(role + ".select_queue_Fpga", 0);
acq_parameters.select_queue_Fpga = select_queue_Fpga;
std::string default_device_name = "/dev/uio0";
std::string device_name = configuration_->property(role + ".devicename", default_device_name);
acq_parameters.device_name = device_name;
acq_parameters.samples_per_ms = nsamples_total/acq_parameters.sampled_ms;
//acq_parameters.samples_per_ms = static_cast<int>(std::round(static_cast<double>(fs_in_) * 0.001));
acq_parameters.samples_per_code = nsamples_total;
// compute all the GPS L1 PRN Codes (this is done only once upon the class constructor in order to avoid re-computing the PRN codes every time
// a channel is assigned)
gr::fft::fft_complex* fft_if = new gr::fft::fft_complex(vector_length, true); // Direct FFT
// allocate memory to compute all the PRNs and compute all the possible codes
std::complex<float>* code = new std::complex<float>[nsamples_total]; // buffer for the local code
gr_complex* fft_codes_padded = static_cast<gr_complex*>(volk_gnsssdr_malloc(nsamples_total * sizeof(gr_complex), volk_gnsssdr_get_alignment()));
d_all_fft_codes_ = new lv_16sc_t[nsamples_total * NUM_PRNs]; // memory containing all the possible fft codes for PRN 0 to 32
float max; // temporary maxima search
for (unsigned int PRN = 1; PRN <= NUM_PRNs; PRN++)
{
gps_l2c_m_code_gen_complex_sampled(code, PRN, fs_in_);
// fill in zero padding
for (int s = code_length; s < nsamples_total; s++)
{
code[s] = std::complex<float>(static_cast<float>(0,0));
//code[s] = 0;
}
memcpy(fft_if->get_inbuf(), code, sizeof(gr_complex) * nsamples_total); // copy to FFT buffer
fft_if->execute(); // Run the FFT of local code
volk_32fc_conjugate_32fc(fft_codes_padded, fft_if->get_outbuf(), nsamples_total); // conjugate values
max = 0; // initialize maximum value
for (unsigned int i = 0; i < nsamples_total; i++) // search for maxima
{
if (std::abs(fft_codes_padded[i].real()) > max)
{
max = std::abs(fft_codes_padded[i].real());
}
if (std::abs(fft_codes_padded[i].imag()) > max)
{
max = std::abs(fft_codes_padded[i].imag());
}
}
for (unsigned int i = 0; i < nsamples_total; i++) // map the FFT to the dynamic range of the fixed point values an copy to buffer containing all FFTs
{
d_all_fft_codes_[i + nsamples_total * (PRN - 1)] = lv_16sc_t(static_cast<int>(floor(fft_codes_padded[i].real() * (pow(2, 7) - 1) / max)),
static_cast<int>(floor(fft_codes_padded[i].imag() * (pow(2, 7) - 1) / max)));
}
}
//acq_parameters
acq_parameters.all_fft_codes = d_all_fft_codes_;
// temporary buffers that we can delete
delete[] code;
delete fft_if;
delete[] fft_codes_padded;
acquisition_fpga_ = pcps_make_acquisition_fpga(acq_parameters);
DLOG(INFO) << "acquisition(" << acquisition_fpga_->unique_id() << ")";
channel_ = 0;
doppler_step_ = 0;
gnss_synchro_ = 0;
// vector_length_ = code_length_;
//
// if (bit_transition_flag_)
// {
// vector_length_ *= 2;
// }
// code_ = new gr_complex[vector_length_];
//
// if (item_type_.compare("cshort") == 0)
// {
// item_size_ = sizeof(lv_16sc_t);
// }
// else
// {
// item_size_ = sizeof(gr_complex);
// }
//acq_parameters.samples_per_ms = static_cast<int>(std::round(static_cast<double>(fs_in_) * 0.001));
//acq_parameters.samples_per_code = code_length_;
//acq_parameters.it_size = item_size_;
//acq_parameters.sampled_ms = 20;
//acq_parameters.num_doppler_bins_step2 = configuration_->property(role + ".second_nbins", 4);
//acq_parameters.doppler_step2 = configuration_->property(role + ".second_doppler_step", 125.0);
//acq_parameters.make_2_steps = configuration_->property(role + ".make_two_steps", true);
//acquisition_ = pcps_make_acquisition(acq_parameters);
DLOG(INFO) << "acquisition(" << acquisition_fpga_->unique_id() << ")";
// stream_to_vector_ = gr::blocks::stream_to_vector::make(item_size_, vector_length_);
// DLOG(INFO) << "stream_to_vector(" << stream_to_vector_->unique_id() << ")";
//
// if (item_type_.compare("cbyte") == 0)
// {
// cbyte_to_float_x2_ = make_complex_byte_to_float_x2();
// float_to_complex_ = gr::blocks::float_to_complex::make();
// }
// channel_ = 0;
threshold_ = 0.0;
// doppler_step_ = 0;
// gnss_synchro_ = 0;
}
GpsL2MPcpsAcquisitionFpga::~GpsL2MPcpsAcquisitionFpga()
{
//delete[] code_;
delete[] d_all_fft_codes_;
}
void GpsL2MPcpsAcquisitionFpga::set_channel(unsigned int channel)
{
channel_ = channel;
acquisition_fpga_->set_channel(channel_);
}
void GpsL2MPcpsAcquisitionFpga::set_threshold(float threshold)
{
// float pfa = configuration_->property(role_ + boost::lexical_cast<std::string>(channel_) + ".pfa", 0.0);
//
// if (pfa == 0.0)
// {
// pfa = configuration_->property(role_ + ".pfa", 0.0);
// }
// if (pfa == 0.0)
// {
// threshold_ = threshold;
// }
// else
// {
// threshold_ = calculate_threshold(pfa);
// }
DLOG(INFO) << "Channel " << channel_ << " Threshold = " << threshold_;
acquisition_fpga_->set_threshold(threshold_);
}
void GpsL2MPcpsAcquisitionFpga::set_doppler_max(unsigned int doppler_max)
{
doppler_max_ = doppler_max;
acquisition_fpga_->set_doppler_max(doppler_max_);
}
// Be aware that Doppler step should be set to 2/(3T) Hz, where T is the coherent integration time (GPS L2 period is 0.02s)
// Doppler bin minimum size= 33 Hz
void GpsL2MPcpsAcquisitionFpga::set_doppler_step(unsigned int doppler_step)
{
doppler_step_ = doppler_step;
acquisition_fpga_->set_doppler_step(doppler_step_);
}
void GpsL2MPcpsAcquisitionFpga::set_gnss_synchro(Gnss_Synchro* gnss_synchro)
{
gnss_synchro_ = gnss_synchro;
acquisition_fpga_->set_gnss_synchro(gnss_synchro_);
}
signed int GpsL2MPcpsAcquisitionFpga::mag()
{
return acquisition_fpga_->mag();
}
void GpsL2MPcpsAcquisitionFpga::init()
{
acquisition_fpga_->init();
//set_local_code();
}
void GpsL2MPcpsAcquisitionFpga::set_local_code()
{
//gps_l2c_m_code_gen_complex_sampled(code_, gnss_synchro_->PRN, fs_in_);
//acquisition_fpga_->set_local_code(code_);
acquisition_fpga_->set_local_code();
}
void GpsL2MPcpsAcquisitionFpga::reset()
{
acquisition_fpga_->set_active(true);
}
void GpsL2MPcpsAcquisitionFpga::set_state(int state)
{
acquisition_fpga_->set_state(state);
}
//float GpsL2MPcpsAcquisitionFpga::calculate_threshold(float pfa)
//{
// //Calculate the threshold
// unsigned int frequency_bins = 0;
// for (int doppler = static_cast<int>(-doppler_max_); doppler <= static_cast<int>(doppler_max_); doppler += doppler_step_)
// {
// frequency_bins++;
// }
// DLOG(INFO) << "Channel " << channel_ << " Pfa = " << pfa;
// unsigned int ncells = vector_length_ * frequency_bins;
// double exponent = 1.0 / static_cast<double>(ncells);
// double val = pow(1.0 - pfa, exponent);
// double lambda = double(vector_length_);
// boost::math::exponential_distribution<double> mydist(lambda);
// float threshold = static_cast<float>(quantile(mydist, val));
//
// return threshold;
//}
void GpsL2MPcpsAcquisitionFpga::connect(gr::top_block_sptr top_block)
{
// if (item_type_.compare("gr_complex") == 0)
// {
// top_block->connect(stream_to_vector_, 0, acquisition_, 0);
// }
// else if (item_type_.compare("cshort") == 0)
// {
// top_block->connect(stream_to_vector_, 0, acquisition_, 0);
// }
// else if (item_type_.compare("cbyte") == 0)
// {
// top_block->connect(cbyte_to_float_x2_, 0, float_to_complex_, 0);
// top_block->connect(cbyte_to_float_x2_, 1, float_to_complex_, 1);
// top_block->connect(float_to_complex_, 0, stream_to_vector_, 0);
// top_block->connect(stream_to_vector_, 0, acquisition_, 0);
// }
// else
// {
// LOG(WARNING) << item_type_ << " unknown acquisition item type";
// }
// nothing to connect
}
void GpsL2MPcpsAcquisitionFpga::disconnect(gr::top_block_sptr top_block)
{
// if (item_type_.compare("gr_complex") == 0)
// {
// top_block->disconnect(stream_to_vector_, 0, acquisition_, 0);
// }
// else if (item_type_.compare("cshort") == 0)
// {
// top_block->disconnect(stream_to_vector_, 0, acquisition_, 0);
// }
// else if (item_type_.compare("cbyte") == 0)
// {
// // Since a byte-based acq implementation is not available,
// // we just convert cshorts to gr_complex
// top_block->disconnect(cbyte_to_float_x2_, 0, float_to_complex_, 0);
// top_block->disconnect(cbyte_to_float_x2_, 1, float_to_complex_, 1);
// top_block->disconnect(float_to_complex_, 0, stream_to_vector_, 0);
// top_block->disconnect(stream_to_vector_, 0, acquisition_, 0);
// }
// else
// {
// LOG(WARNING) << item_type_ << " unknown acquisition item type";
// }
// nothing to disconnect
}
gr::basic_block_sptr GpsL2MPcpsAcquisitionFpga::get_left_block()
{
// if (item_type_.compare("gr_complex") == 0)
// {
// return stream_to_vector_;
// }
// else if (item_type_.compare("cshort") == 0)
// {
// return stream_to_vector_;
// }
// else if (item_type_.compare("cbyte") == 0)
// {
// return cbyte_to_float_x2_;
// }
// else
// {
// LOG(WARNING) << item_type_ << " unknown acquisition item type";
// return nullptr;
// }
return nullptr;
}
gr::basic_block_sptr GpsL2MPcpsAcquisitionFpga::get_right_block()
{
return acquisition_fpga_;
}

View File

@ -0,0 +1,171 @@
/*!
* \file gps_l2_m_pcps_acquisition.h
* \brief Adapts a PCPS acquisition block to an AcquisitionInterface for
* GPS L2 M signals
* \authors <ul>
* <li> Javier Arribas, 2015. jarribas(at)cttc.es
* </ul>
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_GPS_L2_M_PCPS_ACQUISITION_FPGA_H_
#define GNSS_SDR_GPS_L2_M_PCPS_ACQUISITION_FPGA_H_
#include "acquisition_interface.h"
#include "gnss_synchro.h"
#include "pcps_acquisition_fpga.h"
#include "complex_byte_to_float_x2.h"
#include <gnuradio/blocks/stream_to_vector.h>
#include <gnuradio/blocks/float_to_complex.h>
#include <volk_gnsssdr/volk_gnsssdr.h>
#include <string>
class ConfigurationInterface;
/*!
* \brief This class adapts a PCPS acquisition block to an AcquisitionInterface
* for GPS L2 M signals
*/
class GpsL2MPcpsAcquisitionFpga : public AcquisitionInterface
{
public:
GpsL2MPcpsAcquisitionFpga(ConfigurationInterface* configuration,
std::string role, unsigned int in_streams,
unsigned int out_streams);
virtual ~GpsL2MPcpsAcquisitionFpga();
inline std::string role() override
{
return role_;
}
/*!
* \brief Returns "GPS_L2_M_PCPS_Acquisition"
*/
inline std::string implementation() override
{
return "GPS_L2_M_PCPS_Acquisition";
}
inline size_t item_size() override
{
return item_size_;
}
void connect(gr::top_block_sptr top_block) override;
void disconnect(gr::top_block_sptr top_block) override;
gr::basic_block_sptr get_left_block() override;
gr::basic_block_sptr get_right_block() override;
/*!
* \brief Set acquisition/tracking common Gnss_Synchro object pointer
* to efficiently exchange synchronization data between acquisition and
* tracking blocks
*/
void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) override;
/*!
* \brief Set acquisition channel unique ID
*/
void set_channel(unsigned int channel) override;
/*!
* \brief Set statistics threshold of PCPS algorithm
*/
void set_threshold(float threshold) override;
/*!
* \brief Set maximum Doppler off grid search
*/
void set_doppler_max(unsigned int doppler_max) override;
/*!
* \brief Set Doppler steps for the grid search
*/
void set_doppler_step(unsigned int doppler_step) override;
/*!
* \brief Initializes acquisition algorithm.
*/
void init() override;
/*!
* \brief Sets local code for GPS L2/M PCPS acquisition algorithm.
*/
void set_local_code() override;
/*!
* \brief Returns the maximum peak of grid search
*/
signed int mag() override;
/*!
* \brief Restart acquisition algorithm
*/
void reset() override;
/*!
* \brief If state = 1, it forces the block to start acquiring from the first sample
*/
void set_state(int state);
private:
ConfigurationInterface* configuration_;
//pcps_acquisition_sptr acquisition_;
pcps_acquisition_fpga_sptr acquisition_fpga_;
gr::blocks::stream_to_vector::sptr stream_to_vector_;
gr::blocks::float_to_complex::sptr float_to_complex_;
complex_byte_to_float_x2_sptr cbyte_to_float_x2_;
size_t item_size_;
std::string item_type_;
unsigned int vector_length_;
unsigned int code_length_;
bool bit_transition_flag_;
bool use_CFAR_algorithm_flag_;
unsigned int channel_;
float threshold_;
unsigned int doppler_max_;
unsigned int doppler_step_;
unsigned int max_dwells_;
long fs_in_;
long if_;
bool dump_;
bool blocking_;
std::string dump_filename_;
std::complex<float>* code_;
Gnss_Synchro* gnss_synchro_;
std::string role_;
unsigned int in_streams_;
unsigned int out_streams_;
lv_16sc_t* d_all_fft_codes_; // memory that contains all the code ffts
//float calculate_threshold(float pfa);
};
#endif /* GNSS_SDR_GPS_L2_M_PCPS_ACQUISITION_FPGA_H_ */

View File

@ -0,0 +1,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_;
}

View File

@ -0,0 +1,171 @@
/*!
* \file GPS_L5i_PCPS_Acquisition.h
* \brief Adapts a PCPS acquisition block to an AcquisitionInterface for
* GPS L5i signals
* \authors <ul>
* <li> Javier Arribas, 2017. jarribas(at)cttc.es
* </ul>
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2017 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_GPS_L5i_PCPS_ACQUISITION_FPGA_H_
#define GNSS_SDR_GPS_L5i_PCPS_ACQUISITION_FPGA_H_
#include "acquisition_interface.h"
#include "gnss_synchro.h"
#include "pcps_acquisition_fpga.h"
#include "complex_byte_to_float_x2.h"
#include <gnuradio/blocks/stream_to_vector.h>
#include <gnuradio/blocks/float_to_complex.h>
#include <volk_gnsssdr/volk_gnsssdr.h>
#include <string>
class ConfigurationInterface;
/*!
* \brief This class adapts a PCPS acquisition block to an AcquisitionInterface
* for GPS L5i signals
*/
class GpsL5iPcpsAcquisitionFpga : public AcquisitionInterface
{
public:
GpsL5iPcpsAcquisitionFpga(ConfigurationInterface* configuration,
std::string role, unsigned int in_streams,
unsigned int out_streams);
virtual ~GpsL5iPcpsAcquisitionFpga();
inline std::string role() override
{
return role_;
}
/*!
* \brief Returns "GPS_L5i_PCPS_Acquisition"
*/
inline std::string implementation() override
{
return "GPS_L5i_PCPS_Acquisition";
}
inline size_t item_size() override
{
return item_size_;
}
void connect(gr::top_block_sptr top_block) override;
void disconnect(gr::top_block_sptr top_block) override;
gr::basic_block_sptr get_left_block() override;
gr::basic_block_sptr get_right_block() override;
/*!
* \brief Set acquisition/tracking common Gnss_Synchro object pointer
* to efficiently exchange synchronization data between acquisition and
* tracking blocks
*/
void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) override;
/*!
* \brief Set acquisition channel unique ID
*/
void set_channel(unsigned int channel) override;
/*!
* \brief Set statistics threshold of PCPS algorithm
*/
void set_threshold(float threshold) override;
/*!
* \brief Set maximum Doppler off grid search
*/
void set_doppler_max(unsigned int doppler_max) override;
/*!
* \brief Set Doppler steps for the grid search
*/
void set_doppler_step(unsigned int doppler_step) override;
/*!
* \brief Initializes acquisition algorithm.
*/
void init() override;
/*!
* \brief Sets local code for GPS L2/M PCPS acquisition algorithm.
*/
void set_local_code() override;
/*!
* \brief Returns the maximum peak of grid search
*/
signed int mag() override;
/*!
* \brief Restart acquisition algorithm
*/
void reset() override;
/*!
* \brief If state = 1, it forces the block to start acquiring from the first sample
*/
void set_state(int state);
private:
ConfigurationInterface* configuration_;
//pcps_acquisition_sptr acquisition_;
pcps_acquisition_fpga_sptr acquisition_fpga_;
gr::blocks::stream_to_vector::sptr stream_to_vector_;
gr::blocks::float_to_complex::sptr float_to_complex_;
complex_byte_to_float_x2_sptr cbyte_to_float_x2_;
size_t item_size_;
std::string item_type_;
unsigned int vector_length_;
unsigned int code_length_;
bool bit_transition_flag_;
bool use_CFAR_algorithm_flag_;
unsigned int channel_;
float threshold_;
unsigned int doppler_max_;
unsigned int doppler_step_;
unsigned int max_dwells_;
long fs_in_;
long if_;
bool dump_;
bool blocking_;
std::string dump_filename_;
std::complex<float>* code_;
Gnss_Synchro* gnss_synchro_;
std::string role_;
unsigned int in_streams_;
unsigned int out_streams_;
lv_16sc_t* d_all_fft_codes_; // memory that contains all the code ffts
float calculate_threshold(float pfa);
};
#endif /* GNSS_SDR_GPS_L5i_PCPS_ACQUISITION_FPGA_H_ */

View File

@ -43,6 +43,9 @@
#include <gnuradio/io_signature.h> #include <gnuradio/io_signature.h>
#include "pcps_acquisition_fpga.h" #include "pcps_acquisition_fpga.h"
#define AQ_DOWNSAMPLING_DELAY 40 // delay due to the downsampling filter in the acquisition
using google::LogMessage; using google::LogMessage;
pcps_acquisition_fpga_sptr pcps_make_acquisition_fpga(pcpsconf_fpga_t conf_) 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),
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")); this->message_port_register_out(pmt::mp("events"));
acq_parameters = conf_; acq_parameters = conf_;
d_sample_counter = 0; // SAMPLE COUNTER d_sample_counter = 0; // SAMPLE COUNTER
d_active = false; d_active = false;
d_state = 0; 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_mag = 0;
d_input_power = 0.0; d_input_power = 0.0;
d_num_doppler_bins = 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_channel = 0;
d_gnss_synchro = 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> 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); 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() pcps_acquisition_fpga::~pcps_acquisition_fpga()
{ {
// printf("acq destructor start\n");
acquisition_fpga->free(); acquisition_fpga->free();
// printf("acq destructor end\n");
} }
void pcps_acquisition_fpga::set_local_code() void pcps_acquisition_fpga::set_local_code()
{ {
// printf("acq set local code start\n");
acquisition_fpga->set_local_code(d_gnss_synchro->PRN); acquisition_fpga->set_local_code(d_gnss_synchro->PRN);
// printf("acq set local code end\n");
} }
void pcps_acquisition_fpga::init() void pcps_acquisition_fpga::init()
{ {
// printf("acq init start\n");
d_gnss_synchro->Flag_valid_acquisition = false; d_gnss_synchro->Flag_valid_acquisition = false;
d_gnss_synchro->Flag_valid_symbol_output = false; d_gnss_synchro->Flag_valid_symbol_output = false;
d_gnss_synchro->Flag_valid_pseudorange = 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))); 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(); acquisition_fpga->init();
// printf("acq init end\n");
} }
void pcps_acquisition_fpga::set_state(int state) void pcps_acquisition_fpga::set_state(int state)
{ {
// printf("acq set state start\n");
d_state = state; d_state = state;
if (d_state == 1) 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"; LOG(ERROR) << "State can only be set to 0 or 1";
} }
// printf("acq set state end\n");
} }
void pcps_acquisition_fpga::send_positive_acquisition() void pcps_acquisition_fpga::send_positive_acquisition()
{ {
// printf("acq send positive acquisition start\n");
// 6.1- Declare positive acquisition using a message port // 6.1- Declare positive acquisition using a message port
//0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL //0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL
DLOG(INFO) << "positive acquisition" DLOG(INFO) << "positive acquisition"
@ -146,11 +178,13 @@ void pcps_acquisition_fpga::send_positive_acquisition()
<< ", input signal power " << d_input_power; << ", input signal power " << d_input_power;
this->message_port_pub(pmt::mp("events"), pmt::from_long(1)); 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() void pcps_acquisition_fpga::send_negative_acquisition()
{ {
// printf("acq send negative acquisition start\n");
// 6.2- Declare negative acquisition using a message port // 6.2- Declare negative acquisition using a message port
//0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL //0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL
DLOG(INFO) << "negative acquisition" DLOG(INFO) << "negative acquisition"
@ -164,11 +198,13 @@ void pcps_acquisition_fpga::send_negative_acquisition()
<< ", input signal power " << d_input_power; << ", input signal power " << d_input_power;
this->message_port_pub(pmt::mp("events"), pmt::from_long(2)); 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) void pcps_acquisition_fpga::set_active(bool active)
{ {
// printf("acq set active start\n");
d_active = active; d_active = active;
// initialize acquisition algorithm // initialize acquisition algorithm
@ -190,21 +226,29 @@ void pcps_acquisition_fpga::set_active(bool active)
unsigned int initial_sample; unsigned int initial_sample;
float input_power_all = 0.0; float input_power_all = 0.0;
float input_power_computed = 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++) for (unsigned int doppler_index = 0; doppler_index < d_num_doppler_bins; doppler_index++)
{ {
// doppler search steps // doppler search steps
int doppler = -static_cast<int>(acq_parameters.doppler_max) + d_doppler_step * doppler_index; 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->run_acquisition(); // runs acquisition and waits until it is finished
acquisition_fpga->read_acquisition_results(&indext, &magt, 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; d_sample_counter = initial_sample;
if (d_mag < magt) if (d_mag < magt)
{ {
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_all = d_input_power / (d_fft_size - 1);
input_power_computed = (d_input_power - d_mag) / (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); 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 // 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 // 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) if (d_test_statistics > d_threshold)
{ {
d_active = false; 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(); send_positive_acquisition();
d_state = 0; // Positive acquisition d_state = 0; // Positive acquisition
} }
@ -232,6 +338,9 @@ void pcps_acquisition_fpga::set_active(bool active)
d_active = false; d_active = false;
send_negative_acquisition(); send_negative_acquisition();
} }
// printf("acq set active end\n");
} }

View File

@ -70,6 +70,7 @@ typedef struct
long fs_in; long fs_in;
int samples_per_ms; int samples_per_ms;
int samples_per_code; int samples_per_code;
int code_length;
unsigned int select_queue_Fpga; unsigned int select_queue_Fpga;
std::string device_name; std::string device_name;
lv_16sc_t* all_fft_codes; // memory that contains all the code ffts lv_16sc_t* all_fft_codes; // memory that contains all the code ffts
@ -107,6 +108,7 @@ private:
float d_threshold; float d_threshold;
float d_mag; float d_mag;
float d_input_power; float d_input_power;
unsigned d_doppler_index;
float d_test_statistics; float d_test_statistics;
int d_state; int d_state;
unsigned int d_channel; unsigned int d_channel;
@ -117,6 +119,12 @@ private:
Gnss_Synchro* d_gnss_synchro; Gnss_Synchro* d_gnss_synchro;
std::shared_ptr<fpga_acquisition> acquisition_fpga; 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: public:
~pcps_acquisition_fpga(); ~pcps_acquisition_fpga();
@ -127,7 +135,9 @@ public:
*/ */
inline void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) inline void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro)
{ {
// printf("acq set gnss synchro start\n");
d_gnss_synchro = p_gnss_synchro; d_gnss_synchro = p_gnss_synchro;
// printf("acq set gnss synchro end\n");
} }
/*! /*!
@ -135,7 +145,9 @@ public:
*/ */
inline unsigned int mag() const inline unsigned int mag() const
{ {
// printf("acq dmag start\n");
return d_mag; return d_mag;
// printf("acq dmag end\n");
} }
/*! /*!
@ -179,7 +191,9 @@ public:
*/ */
inline void set_threshold(float threshold) inline void set_threshold(float threshold)
{ {
// printf("acq set threshold start\n");
d_threshold = threshold; d_threshold = threshold;
// printf("acq set threshold end\n");
} }
/*! /*!
@ -188,8 +202,10 @@ public:
*/ */
inline void set_doppler_max(unsigned int doppler_max) inline void set_doppler_max(unsigned int doppler_max)
{ {
// printf("acq set doppler max start\n");
acq_parameters.doppler_max = doppler_max; acq_parameters.doppler_max = doppler_max;
acquisition_fpga->set_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) inline void set_doppler_step(unsigned int doppler_step)
{ {
// printf("acq set doppler step start\n");
d_doppler_step = doppler_step; d_doppler_step = doppler_step;
acquisition_fpga->set_doppler_step(doppler_step); acquisition_fpga->set_doppler_step(doppler_step);
// printf("acq set doppler step end\n");
} }
/*! /*!

View File

@ -55,6 +55,18 @@
#define SELECT_16_BITS 0xFFFF // value to select 16 bits #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 #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() bool fpga_acquisition::init()
{ {
@ -69,6 +81,10 @@ bool fpga_acquisition::set_local_code(unsigned int PRN)
// select the code with the chosen PRN // select the code with the chosen PRN
fpga_acquisition::fpga_configure_acquisition_local_code( fpga_acquisition::fpga_configure_acquisition_local_code(
&d_all_fft_codes[d_nsamples_total * (PRN - 1)]); &d_all_fft_codes[d_nsamples_total * (PRN - 1)]);
//fpga_acquisition::fpga_configure_acquisition_local_code(
// &d_all_fft_codes[0]);
return true; return true;
} }
@ -80,7 +96,11 @@ fpga_acquisition::fpga_acquisition(std::string device_name,
unsigned int sampled_ms, unsigned select_queue, unsigned int sampled_ms, unsigned select_queue,
lv_16sc_t *all_fft_codes) 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 // initial values
d_device_name = device_name; d_device_name = device_name;
d_freq = freq; 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) if ((d_fd = open(d_device_name.c_str(), O_RDWR | O_SYNC)) == -1)
{ {
LOG(WARNING) << "Cannot open deviceio" << d_device_name; 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, d_map_base = reinterpret_cast<volatile unsigned *>(mmap(NULL, PAGE_SIZE,
PROT_READ | PROT_WRITE, MAP_SHARED, d_fd, 0)); 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)) if (d_map_base == reinterpret_cast<void *>(-1))
{ {
LOG(WARNING) << "Cannot map the FPGA acquisition module into user memory"; 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 // sanity check : check test register
@ -119,6 +141,7 @@ fpga_acquisition::fpga_acquisition(std::string device_name,
else else
{ {
LOG(INFO) << "Acquisition test register sanity check success!"; LOG(INFO) << "Acquisition test register sanity check success!";
//std::cout << "Acquisition test register sanity check success!" << std::endl;
} }
fpga_acquisition::reset_acquisition(); fpga_acquisition::reset_acquisition();
DLOG(INFO) << "Acquisition FPGA class created"; 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[]) 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 k, tmp, tmp2;
unsigned int fft_data; unsigned int fft_data;
// clear memory address counter // 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 // write local code
for (k = 0; k < d_vector_length; k++) for (k = 0; k < d_vector_length; k++)
{ {
tmp = fft_local_code[k].real(); tmp = fft_local_code[k].real();
tmp2 = fft_local_code[k].imag(); 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 //tmp = k;
fft_data = MEM_LOCAL_CODE_WR_ENABLE | (local_code & SELECT_16_BITS); //tmp2 = k;
d_map_base[4] = fft_data;
//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) void fpga_acquisition::run_acquisition(void)
{ {
// enable interrupts // enable interrupts
int reenable = 1; int reenable = 1;
write(d_fd, reinterpret_cast<void *>(&reenable), sizeof(int)); write(d_fd, reinterpret_cast<void *>(&reenable), sizeof(int));
// launch the acquisition process // 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; int irq_count;
ssize_t nb; ssize_t nb;
// wait for interrupt // wait for interrupt
nb = read(d_fd, &irq_count, sizeof(irq_count)); nb = read(d_fd, &irq_count, sizeof(irq_count));
//printf("interrupt received\n");
if (nb != sizeof(irq_count)) if (nb != sizeof(irq_count))
{ {
printf("acquisition module Read failed to retrieve 4 bytes!\n"); 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() void fpga_acquisition::configure_acquisition()
{ {
d_map_base[0] = d_select_queue; d_map_base[0] = d_select_queue;
//printf("AAA writing d_vector_length = %d to d map base 1\n ", d_vector_length);
d_map_base[1] = d_vector_length; 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[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); phase_step_rad_real = phase_step_rad / (GPS_TWO_PI / 2);
// avoid saturation of the fixed point representation in the fpga // avoid saturation of the fixed point representation in the fpga
// (only the positive value can saturate due to the 2's complement representation) // (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) if (phase_step_rad_real >= 1.0)
{ {
phase_step_rad_real = MAX_PHASE_STEP_RAD; 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_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 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; d_map_base[3] = phase_step_rad_int;
} }
void fpga_acquisition::read_acquisition_results(uint32_t *max_index, 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; unsigned readval = 0;
readval = d_map_base[1]; readval = d_map_base[1];
*initial_sample = readval; *initial_sample = readval;
//printf("read initial sample dmap 1 = %d\n", readval);
readval = d_map_base[2]; readval = d_map_base[2];
*max_magnitude = static_cast<float>(readval); *max_magnitude = static_cast<float>(readval);
//printf("read max_magnitude dmap 2 = %d\n", readval);
readval = d_map_base[4]; readval = d_map_base[4];
*power_sum = static_cast<float>(readval); *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]; readval = d_map_base[3];
*max_index = readval; *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) void fpga_acquisition::reset_acquisition(void)
{ {
d_map_base[6] = RESET_ACQUISITION; // writing a 2 to d_map_base[6] resets the multicorrelator d_map_base[8] = RESET_ACQUISITION; // writing a 2 to d_map_base[8] resets the multicorrelator
} }

View File

@ -56,10 +56,12 @@ public:
bool set_local_code( bool set_local_code(
unsigned int PRN); unsigned int PRN);
bool free(); 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 run_acquisition(void);
void set_phase_step(unsigned int doppler_index); void set_phase_step(unsigned int doppler_index);
void read_acquisition_results(uint32_t *max_index, float *max_magnitude, 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 block_samples();
void unblock_samples(); void unblock_samples();
@ -102,6 +104,7 @@ private:
void configure_acquisition(); void configure_acquisition();
void reset_acquisition(void); void reset_acquisition(void);
void close_device(); void close_device();
}; };
#endif /* GNSS_SDR_FPGA_ACQUISITION_H_ */ #endif /* GNSS_SDR_FPGA_ACQUISITION_H_ */

View File

@ -22,7 +22,7 @@ if(ENABLE_CUDA)
endif(ENABLE_CUDA) endif(ENABLE_CUDA)
if(ENABLE_FPGA) 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) endif(ENABLE_FPGA)
set(TRACKING_ADAPTER_SOURCES set(TRACKING_ADAPTER_SOURCES

View File

@ -42,7 +42,7 @@
#include "display.h" #include "display.h"
#include <glog/logging.h> #include <glog/logging.h>
#define NUM_PRNs_GALILEO_E1 50 //#define NUM_PRNs_GALILEO_E1 50
using google::LogMessage; using google::LogMessage;
@ -50,7 +50,6 @@ GalileoE1DllPllVemlTrackingFpga::GalileoE1DllPllVemlTrackingFpga(
ConfigurationInterface* configuration, std::string role, ConfigurationInterface* configuration, std::string role,
unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams) 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_t trk_param;
dllpllconf_fpga_t trk_param_fpga; dllpllconf_fpga_t trk_param_fpga;
DLOG(INFO) << "role " << role; 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; std::cout << TEXT_RED << "WARNING: Galileo E1. PLL or DLL narrow tracking bandwidth is higher than wide tracking one" << TEXT_RESET << std::endl;
} }
trk_param_fpga.track_pilot = track_pilot; trk_param_fpga.track_pilot = track_pilot;
d_track_pilot = track_pilot;
trk_param_fpga.extend_correlation_symbols = extend_correlation_symbols; trk_param_fpga.extend_correlation_symbols = extend_correlation_symbols;
std::string default_dump_filename = "./track_ch"; std::string default_dump_filename = "./track_ch";
std::string dump_filename = configuration->property(role + ".dump_filename", default_dump_filename); 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; trk_param_fpga.device_name = device_name;
unsigned int device_base = configuration->property(role + ".device_base", 1); unsigned int device_base = configuration->property(role + ".device_base", 1);
trk_param_fpga.device_base = device_base; 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 ################# //################# 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())); 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)) * 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)) * 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())); if (trk_param_fpga.track_pilot)
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())); {
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"; char data_signal[3] = "1B";
if (trk_param_fpga.track_pilot) if (trk_param_fpga.track_pilot)
{ {
//printf("yes tracking pilot !!!!!!!!!!!!!!!\n");
char pilot_signal[3] = "1C"; char pilot_signal[3] = "1C";
galileo_e1_code_gen_sinboc11_float(ca_codes_f, pilot_signal, PRN); galileo_e1_code_gen_sinboc11_float(ca_codes_f, pilot_signal, PRN);
galileo_e1_code_gen_sinboc11_float(data_codes_f, data_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_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 else
{ {
//printf("no tracking pilot\n");
galileo_e1_code_gen_sinboc11_float(ca_codes_f, data_signal, PRN); 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]); 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[] ca_codes_f;
if (trk_param_fpga.track_pilot)
{
delete[] data_codes_f; delete[] data_codes_f;
}
trk_param_fpga.ca_codes = d_ca_codes; trk_param_fpga.ca_codes = d_ca_codes;
trk_param_fpga.data_codes = d_data_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 ################### //################# MAKE TRACKING GNURadio object ###################
tracking_fpga_sc = dll_pll_veml_make_tracking_fpga(trk_param_fpga); tracking_fpga_sc = dll_pll_veml_make_tracking_fpga(trk_param_fpga);
channel_ = 0; channel_ = 0;
@ -178,9 +204,12 @@ GalileoE1DllPllVemlTrackingFpga::GalileoE1DllPllVemlTrackingFpga(
GalileoE1DllPllVemlTrackingFpga::~GalileoE1DllPllVemlTrackingFpga() GalileoE1DllPllVemlTrackingFpga::~GalileoE1DllPllVemlTrackingFpga()
{ {
delete[] d_ca_codes; delete[] d_ca_codes;
if (d_track_pilot)
{
delete[] d_data_codes; delete[] d_data_codes;
}
}
}
void GalileoE1DllPllVemlTrackingFpga::start_tracking() void GalileoE1DllPllVemlTrackingFpga::start_tracking()
{ {

View File

@ -66,7 +66,7 @@ public:
//! Returns "Galileo_E1_DLL_PLL_VEML_Tracking" //! Returns "Galileo_E1_DLL_PLL_VEML_Tracking"
inline std::string implementation() override 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 inline size_t item_size() override
@ -103,6 +103,8 @@ private:
unsigned int out_streams_; unsigned int out_streams_;
int* d_ca_codes; int* d_ca_codes;
int* d_data_codes; int* d_data_codes;
bool d_track_pilot;
}; };

View File

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

View File

@ -0,0 +1,110 @@
/*!
* \file galileo_e5a_dll_pll_tracking.h
* \brief Adapts a code DLL + carrier PLL
* tracking block to a TrackingInterface for Galileo E5a signals
* \brief Adapts a PCPS acquisition block to an AcquisitionInterface for
* Galileo E5a data and pilot Signals
* \author Marc Sales, 2014. marcsales92(at)gmail.com
* \based on work from:
* <ul>
* <li> Javier Arribas, 2011. jarribas(at)cttc.es
* <li> Luis Esteve, 2012. luis(at)epsilon-formacion.com
* </ul>
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_GALILEO_E5A_DLL_PLL_TRACKING_FPGA_H_
#define GNSS_SDR_GALILEO_E5A_DLL_PLL_TRACKING_FPGA_H_
#include "tracking_interface.h"
#include "dll_pll_veml_tracking_fpga.h"
#include <string>
class ConfigurationInterface;
/*!
* \brief This class implements a code DLL + carrier PLL tracking loop
*/
class GalileoE5aDllPllTrackingFpga : public TrackingInterface
{
public:
GalileoE5aDllPllTrackingFpga(ConfigurationInterface* configuration,
std::string role,
unsigned int in_streams,
unsigned int out_streams);
virtual ~GalileoE5aDllPllTrackingFpga();
inline std::string role() override
{
return role_;
}
//! Returns "Galileo_E5a_DLL_PLL_Tracking"
inline std::string implementation() override
{
return "Galileo_E5a_DLL_PLL_Tracking";
}
inline size_t item_size() override
{
return item_size_;
}
void connect(gr::top_block_sptr top_block) override;
void disconnect(gr::top_block_sptr top_block) override;
gr::basic_block_sptr get_left_block() override;
gr::basic_block_sptr get_right_block() override;
/*!
* \brief Set tracking channel unique ID
*/
void set_channel(unsigned int channel) override;
/*!
* \brief Set acquisition/tracking common Gnss_Synchro object pointer
* to efficiently exchange synchronization data between acquisition and tracking blocks
*/
void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) override;
void start_tracking() override;
private:
dll_pll_veml_tracking_fpga_sptr tracking_fpga_sc;
size_t item_size_;
unsigned int channel_;
std::string role_;
unsigned int in_streams_;
unsigned int out_streams_;
int* d_ca_codes;
int* d_data_codes;
bool d_track_pilot;
};
#endif /* GNSS_SDR_GALILEO_E5A_DLL_PLL_TRACKING_FPGA_H_ */

View File

@ -129,6 +129,8 @@ GpsL1CaDllPllTrackingFpga::GpsL1CaDllPllTrackingFpga(
trk_param_fpga.device_name = device_name; trk_param_fpga.device_name = device_name;
unsigned int device_base = configuration->property(role + ".device_base", 1); unsigned int device_base = configuration->property(role + ".device_base", 1);
trk_param_fpga.device_base = device_base; 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 ################# //################# PRE-COMPUTE ALL THE CODES #################
d_ca_codes = static_cast<int*>(volk_gnsssdr_malloc(static_cast<int>(GPS_L1_CA_CODE_LENGTH_CHIPS*NUM_PRNs) * sizeof(int), volk_gnsssdr_get_alignment())); d_ca_codes = static_cast<int*>(volk_gnsssdr_malloc(static_cast<int>(GPS_L1_CA_CODE_LENGTH_CHIPS*NUM_PRNs) * sizeof(int), volk_gnsssdr_get_alignment()));
@ -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); 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.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 ################### //################# MAKE TRACKING GNURadio object ###################
tracking_fpga_sc = dll_pll_veml_make_tracking_fpga(trk_param_fpga); tracking_fpga_sc = dll_pll_veml_make_tracking_fpga(trk_param_fpga);

View File

@ -0,0 +1,223 @@
/*!
* \file gps_l2_m_dll_pll_tracking.cc
* \brief Implementation of an adapter of a DLL+PLL tracking loop block
* for GPS L1 C/A to a TrackingInterface
* \author Javier Arribas, 2015. jarribas(at)cttc.es
*
* Code DLL + carrier PLL according to the algorithms described in:
* K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen,
* A Software-Defined GPS and Galileo Receiver. A Single-Frequency
* Approach, Birkhauser, 2007
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#include "gps_l2_m_dll_pll_tracking_fpga.h"
#include "configuration_interface.h"
#include "GPS_L2C.h"
#include "gps_l2c_signal.h"
#include "gnss_sdr_flags.h"
#include "display.h"
#include <glog/logging.h>
#define NUM_PRNs 32
using google::LogMessage;
GpsL2MDllPllTrackingFpga::GpsL2MDllPllTrackingFpga(
ConfigurationInterface* configuration, std::string role,
unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams)
{
//dllpllconf_t trk_param;
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;
}

View File

@ -0,0 +1,106 @@
/*!
* \file gps_l2_m_dll_pll_tracking.h
* \brief Interface of an adapter of a DLL+PLL tracking loop block
* for GPS L1 C/A to a TrackingInterface
* \author Carlos Aviles, 2010. carlos.avilesr(at)googlemail.com
* Javier Arribas, 2011. jarribas(at)cttc.es
*
* Code DLL + carrier PLL according to the algorithms described in:
* K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen,
* A Software-Defined GPS and Galileo Receiver. A Single-Frequency
* Approach, Birkhauser, 2007
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_gps_l2_m_dll_pll_tracking_FPGA_H_
#define GNSS_SDR_gps_l2_m_dll_pll_tracking_FPGA_H_
#include "tracking_interface.h"
//#include "dll_pll_veml_tracking.h"
#include "dll_pll_veml_tracking_fpga.h"
#include <string>
class ConfigurationInterface;
/*!
* \brief This class implements a code DLL + carrier PLL tracking loop
*/
class GpsL2MDllPllTrackingFpga : public TrackingInterface
{
public:
GpsL2MDllPllTrackingFpga(ConfigurationInterface* configuration,
std::string role,
unsigned int in_streams,
unsigned int out_streams);
virtual ~GpsL2MDllPllTrackingFpga();
inline std::string role() override
{
return role_;
}
//! Returns "GPS_L2_M_DLL_PLL_Tracking"
inline std::string implementation() override
{
return "GPS_L2_M_DLL_PLL_Tracking_Fpga";
}
inline size_t item_size() override
{
return item_size_;
}
void connect(gr::top_block_sptr top_block) override;
void disconnect(gr::top_block_sptr top_block) override;
gr::basic_block_sptr get_left_block() override;
gr::basic_block_sptr get_right_block() override;
/*!
* \brief Set tracking channel unique ID
*/
void set_channel(unsigned int channel) override;
/*!
* \brief Set acquisition/tracking common Gnss_Synchro object pointer
* to efficiently exchange synchronization data between acquisition and tracking blocks
*/
void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) override;
void start_tracking() override;
private:
//dll_pll_veml_tracking_sptr tracking_;
dll_pll_veml_tracking_fpga_sptr tracking_fpga_sc;
size_t item_size_;
unsigned int channel_;
std::string role_;
unsigned int in_streams_;
unsigned int out_streams_;
int* d_ca_codes;
};
#endif // GNSS_SDR_gps_l2_m_dll_pll_tracking_FPGA_H_

View File

@ -0,0 +1,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;
}

View File

@ -0,0 +1,106 @@
/*!
* \file gps_l5_dll_pll_tracking.h
* \brief Interface of an adapter of a DLL+PLL tracking loop block
* for GPS L5 to a TrackingInterface
* \author Javier Arribas, 2017. jarribas(at)cttc.es
*
* Code DLL + carrier PLL according to the algorithms described in:
* K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen,
* A Software-Defined GPS and Galileo Receiver. A Single-Frequency
* Approach, Birkhauser, 2007
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
*
* This file is part of GNSS-SDR.
*
* GNSS-SDR is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GNSS-SDR is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_GPS_L5_DLL_PLL_TRACKING_FPGA_H_
#define GNSS_SDR_GPS_L5_DLL_PLL_TRACKING_FPGA_H_
#include "tracking_interface.h"
#include "dll_pll_veml_tracking_fpga.h"
#include <string>
class ConfigurationInterface;
/*!
* \brief This class implements a code DLL + carrier PLL tracking loop
*/
class GpsL5DllPllTrackingFpga : public TrackingInterface
{
public:
GpsL5DllPllTrackingFpga(ConfigurationInterface* configuration,
std::string role,
unsigned int in_streams,
unsigned int out_streams);
virtual ~GpsL5DllPllTrackingFpga();
inline std::string role() override
{
return role_;
}
//! Returns "GPS_L5_DLL_PLL_Tracking"
inline std::string implementation() override
{
return "GPS_L5_DLL_PLL_Tracking";
}
inline size_t item_size() override
{
return item_size_;
}
void connect(gr::top_block_sptr top_block) override;
void disconnect(gr::top_block_sptr top_block) override;
gr::basic_block_sptr get_left_block() override;
gr::basic_block_sptr get_right_block() override;
/*!
* \brief Set tracking channel unique ID
*/
void set_channel(unsigned int channel) override;
/*!
* \brief Set acquisition/tracking common Gnss_Synchro object pointer
* to efficiently exchange synchronization data between acquisition and tracking blocks
*/
void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) override;
void start_tracking() override;
private:
//dll_pll_veml_tracking_sptr tracking_;
dll_pll_veml_tracking_fpga_sptr tracking_fpga_sc;
size_t item_size_;
unsigned int channel_;
std::string role_;
unsigned int in_streams_;
unsigned int out_streams_;
bool d_track_pilot;
int* d_ca_codes;
int* d_data_codes;
};
#endif // GNSS_SDR_GPS_L5_DLL_PLL_TRACKING_FPGA_H_

View File

@ -56,6 +56,8 @@
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
using google::LogMessage; using google::LogMessage;
dll_pll_veml_tracking_fpga_sptr dll_pll_veml_make_tracking_fpga(dllpllconf_fpga_t conf_) dll_pll_veml_tracking_fpga_sptr dll_pll_veml_make_tracking_fpga(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]; signal_pretty_name = map_signal_pretty_name[signal_type];
d_prompt_data_shift = nullptr;
if (trk_parameters.system == 'G') if (trk_parameters.system == 'G')
{ {
systemName = "GPS"; 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_code_chip_rate = GPS_L1_CA_CODE_RATE_HZ;
d_symbols_per_bit = GPS_CA_TELEMETRY_SYMBOLS_PER_BIT; d_symbols_per_bit = GPS_CA_TELEMETRY_SYMBOLS_PER_BIT;
d_correlation_length_ms = 1; d_correlation_length_ms = 1;
d_code_samples_per_chip = 1; //d_code_samples_per_chip = 1;
d_code_length_chips = static_cast<unsigned int>(GPS_L1_CA_CODE_LENGTH_CHIPS); //d_code_length_chips = static_cast<unsigned int>(GPS_L1_CA_CODE_LENGTH_CHIPS);
// GPS L1 C/A does not have pilot component nor secondary code // GPS L1 C/A does not have pilot component nor secondary code
d_secondary = false; d_secondary = false;
trk_parameters.track_pilot = 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_signal_carrier_freq = GPS_L2_FREQ_HZ;
d_code_period = GPS_L2_M_PERIOD; d_code_period = GPS_L2_M_PERIOD;
d_code_chip_rate = GPS_L2_M_CODE_RATE_HZ; 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_symbols_per_bit = GPS_L2_SAMPLES_PER_SYMBOL;
d_correlation_length_ms = 20; 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 // GPS L2 does not have pilot component nor secondary code
d_secondary = false; d_secondary = false;
trk_parameters.track_pilot = 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_code_chip_rate = GPS_L5i_CODE_RATE_HZ;
d_symbols_per_bit = GPS_L5_SAMPLES_PER_SYMBOL; d_symbols_per_bit = GPS_L5_SAMPLES_PER_SYMBOL;
d_correlation_length_ms = 1; d_correlation_length_ms = 1;
d_code_samples_per_chip = 1; //d_code_samples_per_chip = 1;
d_code_length_chips = static_cast<unsigned int>(GPS_L5i_CODE_LENGTH_CHIPS); //d_code_length_chips = static_cast<unsigned int>(GPS_L5i_CODE_LENGTH_CHIPS);
// GPS L5 does not have pilot secondary code // GPS L5 does not have pilot secondary code
d_secondary = true; d_secondary = true;
interchange_iq = false; interchange_iq = false;
@ -159,8 +164,8 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(dllpllconf_fpga_t conf_)
interchange_iq = false; interchange_iq = false;
d_signal_carrier_freq = 0.0; d_signal_carrier_freq = 0.0;
d_code_period = 0.0; d_code_period = 0.0;
d_code_length_chips = 0; //d_code_length_chips = 0;
d_code_samples_per_chip = 0; //d_code_samples_per_chip = 0;
d_symbols_per_bit = 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_signal_carrier_freq = Galileo_E1_FREQ_HZ;
d_code_period = Galileo_E1_CODE_PERIOD; d_code_period = Galileo_E1_CODE_PERIOD;
d_code_chip_rate = Galileo_E1_CODE_CHIP_RATE_HZ; 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_symbols_per_bit = 1;
d_correlation_length_ms = 4; 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; d_veml = true;
if (trk_parameters.track_pilot) 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_code_chip_rate = Galileo_E5a_CODE_CHIP_RATE_HZ;
d_symbols_per_bit = 20; d_symbols_per_bit = 20;
d_correlation_length_ms = 1; d_correlation_length_ms = 1;
d_code_samples_per_chip = 1; //d_code_samples_per_chip = 1;
d_code_length_chips = static_cast<unsigned int>(Galileo_E5a_CODE_LENGTH_CHIPS); //d_code_length_chips = static_cast<unsigned int>(Galileo_E5a_CODE_LENGTH_CHIPS);
d_secondary = true; d_secondary = true;
interchange_iq = false; interchange_iq = false;
if (trk_parameters.track_pilot) 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; interchange_iq = false;
d_signal_carrier_freq = 0.0; d_signal_carrier_freq = 0.0;
d_code_period = 0.0; d_code_period = 0.0;
d_code_length_chips = 0; //d_code_length_chips = 0;
d_code_samples_per_chip = 0; //d_code_samples_per_chip = 0;
d_symbols_per_bit = 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; interchange_iq = false;
d_signal_carrier_freq = 0.0; d_signal_carrier_freq = 0.0;
d_code_period = 0.0; d_code_period = 0.0;
d_code_length_chips = 0; //d_code_length_chips = 0;
d_code_samples_per_chip = 0; //d_code_samples_per_chip = 0;
d_symbols_per_bit = 0; d_symbols_per_bit = 0;
} }
T_chip_seconds = 0.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())); d_local_code_shift_chips = static_cast<float *>(volk_gnsssdr_malloc(d_n_correlator_taps * sizeof(float), volk_gnsssdr_get_alignment()));
std::fill_n(d_correlator_outs, d_n_correlator_taps, gr_complex(0.0, 0.0)); std::fill_n(d_correlator_outs, d_n_correlator_taps, gr_complex(0.0, 0.0));
d_code_samples_per_chip = trk_parameters.code_samples_per_chip; // number of samples per chip
// map memory pointers of correlator outputs // map memory pointers of correlator outputs
if (d_veml) 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_Prompt = &d_correlator_outs[2];
d_Late = &d_correlator_outs[3]; d_Late = &d_correlator_outs[3];
d_Very_Late = &d_correlator_outs[4]; 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[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[1] = -trk_parameters.early_late_space_chips * static_cast<float>(d_code_samples_per_chip);
d_local_code_shift_chips[2] = 0.0; 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_Prompt = &d_correlator_outs[1];
d_Late = &d_correlator_outs[2]; d_Late = &d_correlator_outs[2];
d_Very_Late = nullptr; 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[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[1] = 0.0;
d_local_code_shift_chips[2] = trk_parameters.early_late_space_chips * static_cast<float>(d_code_samples_per_chip); 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_last_prompt = gr_complex(0.0, 0.0);
d_state = 0; // initial state: standby d_state = 0; // initial state: standby
//printf("hhhhhhhhhhh d_n_correlator_taps = %d\n", d_n_correlator_taps);
// create multicorrelator class // create multicorrelator class
std::string device_name = trk_parameters.device_name; std::string device_name = trk_parameters.device_name;
unsigned int device_base = trk_parameters.device_base; unsigned int device_base = trk_parameters.device_base;
int* ca_codes = trk_parameters.ca_codes; int* ca_codes = trk_parameters.ca_codes;
int* data_codes = trk_parameters.data_codes; int* data_codes = trk_parameters.data_codes;
unsigned int code_length = trk_parameters.code_length; //unsigned int code_length = trk_parameters.code_length_chips;
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); 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); multicorrelator_fpga->set_output_vectors(d_correlator_outs, d_Prompt_Data);
d_pull_in = 0; 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 // new chip and prn sequence periods based on acq Doppler
d_code_freq_chips = radial_velocity * d_code_chip_rate; d_code_freq_chips = radial_velocity * d_code_chip_rate;
d_code_phase_step_chips = d_code_freq_chips / trk_parameters.fs_in; 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_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_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; 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) 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); d_Prompt_Data[0] = gr_complex(0.0, 0.0);
// MISSING _: set_local_code_and_taps for the data correlator // 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 LOG(INFO) << "PULL-IN Doppler [Hz] = " << d_carrier_doppler_hz
<< ". Code Phase correction [samples] = " << delay_correction_samples << ". Code Phase correction [samples] = " << delay_correction_samples
<< ". PULL-IN Code Phase [samples] = " << d_acq_code_phase_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; 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 // 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; 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) 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 ###### // ####### CN0 ESTIMATION AND LOCK DETECTORS ######
if (d_cn0_estimation_counter < trk_parameters.cn0_samples) 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 else
{ {
//printf("KKKKKKKKKKK checking count fail ...\n");
d_cn0_estimation_counter = 0; d_cn0_estimation_counter = 0;
// Code lock indicator // Code lock indicator
d_CN0_SNV_dB_Hz = cn0_svn_estimator(d_Prompt_buffer, trk_parameters.cn0_samples, coh_integration_time_s); 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] // 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_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; 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; d_pull_in = 0;
multicorrelator_fpga->lock_channel(); multicorrelator_fpga->lock_channel();
unsigned counter_value = multicorrelator_fpga->read_sample_counter(); 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); unsigned num_frames = ceil((counter_value - current_synchro_data.Acq_samplestamp_samples - current_synchro_data.Acq_delay_samples)/d_correlation_length_samples);
//printf("333333 num_frames = %d\n", num_frames);
unsigned absolute_samples_offset = current_synchro_data.Acq_delay_samples + current_synchro_data.Acq_samplestamp_samples + num_frames*d_correlation_length_samples; unsigned 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); multicorrelator_fpga->set_initial_sample(absolute_samples_offset);
d_sample_counter = absolute_samples_offset; d_sample_counter = absolute_samples_offset;
current_synchro_data.Tracking_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 // perform carrier wipe-off and compute Early, Prompt and Late correlation
multicorrelator_fpga->Carrier_wipeoff_multicorrelator_resampler( multicorrelator_fpga->Carrier_wipeoff_multicorrelator_resampler(
d_rem_carr_phase_rad, d_carrier_phase_step_rad, 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); d_current_prn_length_samples);
// Save single correlation step variables // 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 // perform a correlation step
multicorrelator_fpga->Carrier_wipeoff_multicorrelator_resampler( multicorrelator_fpga->Carrier_wipeoff_multicorrelator_resampler(
d_rem_carr_phase_rad, d_carrier_phase_step_rad, 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); d_current_prn_length_samples);
update_tracking_vars(); update_tracking_vars();
save_correlation_results(); save_correlation_results();
@ -1398,7 +1433,7 @@ int dll_pll_veml_tracking_fpga::general_work (int noutput_items __attribute__((u
//do_correlation_step(in); //do_correlation_step(in);
multicorrelator_fpga->Carrier_wipeoff_multicorrelator_resampler( multicorrelator_fpga->Carrier_wipeoff_multicorrelator_resampler(
d_rem_carr_phase_rad, d_carrier_phase_step_rad, 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); d_current_prn_length_samples);
save_correlation_results(); save_correlation_results();

View File

@ -74,7 +74,9 @@ typedef struct
char signal[3]; char signal[3];
std::string device_name; std::string device_name;
unsigned int device_base; 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* ca_codes;
int* data_codes; int* data_codes;
} dllpllconf_fpga_t; } dllpllconf_fpga_t;
@ -223,6 +225,7 @@ private:
unsigned long int d_sample_counter_next; unsigned long int d_sample_counter_next;
unsigned int d_pull_in = 0; unsigned int d_pull_in = 0;
}; };
#endif //GNSS_SDR_DLL_PLL_VEML_TRACKING_FPGA_H #endif //GNSS_SDR_DLL_PLL_VEML_TRACKING_FPGA_H

View File

@ -86,21 +86,25 @@
int fpga_multicorrelator_8sc::read_sample_counter() 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) void fpga_multicorrelator_8sc::set_initial_sample(int samples_offset)
{ {
d_initial_sample_counter = 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, //void fpga_multicorrelator_8sc::set_local_code_and_taps(int code_length_chips,
float *shifts_chips, int PRN) // 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_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); 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) void fpga_multicorrelator_8sc::update_local_code(float rem_code_phase_chips)
{ {
d_rem_code_phase_chips = 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_compute_code_shift_parameters();
fpga_multicorrelator_8sc::fpga_configure_code_parameters_in_fpga(); 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(); fpga_multicorrelator_8sc::fpga_launch_multicorrelator_fpga();
int irq_count; int irq_count;
ssize_t nb; ssize_t nb;
//printf("$$$$$ waiting for interrupt ... \n");
nb = read(d_device_descriptor, &irq_count, sizeof(irq_count)); nb = read(d_device_descriptor, &irq_count, sizeof(irq_count));
//printf("$$$$$ interrupt received ... \n");
if (nb != sizeof(irq_count)) if (nb != sizeof(irq_count))
{ {
printf("Tracking_module Read failed to retrieve 4 bytes!\n"); 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, 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_n_correlators = n_correlators;
d_device_name = device_name; d_device_name = device_name;
@ -155,12 +163,23 @@ fpga_multicorrelator_8sc::fpga_multicorrelator_8sc(int n_correlators,
d_map_base = nullptr; d_map_base = nullptr;
// instantiate variable length vectors // instantiate variable length vectors
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( d_initial_index = static_cast<unsigned*>(volk_gnsssdr_malloc(
n_correlators * sizeof(unsigned), volk_gnsssdr_get_alignment())); n_correlators * sizeof(unsigned), volk_gnsssdr_get_alignment()));
d_initial_interp_counter = static_cast<unsigned*>(volk_gnsssdr_malloc( d_initial_interp_counter = static_cast<unsigned*>(volk_gnsssdr_malloc(
n_correlators * sizeof(unsigned), volk_gnsssdr_get_alignment())); n_correlators * sizeof(unsigned), volk_gnsssdr_get_alignment()));
}
d_shifts_chips = nullptr; d_shifts_chips = nullptr;
d_prompt_data_shift = nullptr;
d_corr_out = nullptr; d_corr_out = nullptr;
d_code_length_chips = 0; d_code_length_chips = 0;
d_rem_code_phase_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_initial_sample_counter = 0;
d_channel = 0; d_channel = 0;
d_correlator_length_samples = 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_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"; 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() fpga_multicorrelator_8sc::~fpga_multicorrelator_8sc()
{ {
delete[] d_ca_codes; //delete[] d_ca_codes;
close_device(); close_device();
} }
@ -220,10 +323,21 @@ void fpga_multicorrelator_8sc::set_channel(unsigned int channel)
devicebasetemp << numdevice; devicebasetemp << numdevice;
mergedname = d_device_name + devicebasetemp.str(); mergedname = d_device_name + devicebasetemp.str();
strcpy(device_io_name, mergedname.c_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) if ((d_device_descriptor = open(device_io_name, O_RDWR | O_SYNC)) == -1)
{ {
LOG(WARNING) << "Cannot open deviceio" << device_io_name; 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, d_map_base = reinterpret_cast<volatile unsigned *>(mmap(NULL, PAGE_SIZE,
PROT_READ | PROT_WRITE, MAP_SHARED, d_device_descriptor, 0)); 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 " LOG(WARNING) << "Cannot map the FPGA tracking module "
<< d_channel << "into user memory"; << d_channel << "into user memory";
std::cout << "Cannot map deviceio" << device_io_name << std::endl;
//printf("error mapping registers\n");
} }
// else
// {
// std::cout << "deviceio" << device_io_name << "mapped successfully" << std::endl;
// }
// else
// {
// printf("mapping registers succes\n"); // this is for debug -- remove !
// }
// sanity check : check test register // sanity check : check test register
unsigned writeval = TEST_REGISTER_TRACK_WRITEVAL; unsigned writeval = TEST_REGISTER_TRACK_WRITEVAL;
@ -240,10 +364,15 @@ void fpga_multicorrelator_8sc::set_channel(unsigned int channel)
if (writeval != readval) if (writeval != readval)
{ {
LOG(WARNING) << "Test register sanity check failed"; LOG(WARNING) << "Test register sanity check failed";
// printf("tracking test register sanity check failed\n");
//printf("lslslls test sanity check reg failure\n");
} }
else else
{ {
LOG(INFO) << "Test register sanity check success !"; 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 fpga_multicorrelator_8sc::fpga_acquisition_test_register(
unsigned writeval) unsigned writeval)
{ {
unsigned readval; //printf("d_TEST_REG_ADDR = %d\n", d_TEST_REG_ADDR);
unsigned readval = 0;
// write value to test register // write value to test register
d_map_base[15] = writeval; d_map_base[d_TEST_REG_ADDR] = writeval;
// read value from test register // read value from test register
readval = d_map_base[15]; readval = d_map_base[d_TEST_REG_ADDR];
// return read value // return read value
return readval; return readval;
} }
@ -265,16 +396,29 @@ void fpga_multicorrelator_8sc::fpga_configure_tracking_gps_local_code(int PRN)
{ {
int k, s; int k, s;
unsigned code_chip; unsigned code_chip;
unsigned select_fpga_correlator; unsigned select_pilot_corelator = LOCAL_CODE_FPGA_CORRELATOR_SELECT_COUNT;
select_fpga_correlator = 0; // select_fpga_correlator = 0;
for (s = 0; s < d_n_correlators; s++) //printf("kkk d_n_correlators = %x\n", d_n_correlators);
{ //printf("kkk d_code_length_chips = %d\n", d_code_length_chips);
d_map_base[11] = LOCAL_CODE_FPGA_CLEAR_ADDRESS_COUNTER; //printf("programming mems d map base %d\n", d_PROG_MEMS_ADDR);
for (k = 0; k < d_code_length_chips; k++)
//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_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; code_chip = 1;
} }
@ -282,13 +426,39 @@ void fpga_multicorrelator_8sc::fpga_configure_tracking_gps_local_code(int PRN)
{ {
code_chip = 0; code_chip = 0;
} }
// copy the local code to the FPGA memory one by one // copy the local code to the FPGA memory one by one
d_map_base[11] = LOCAL_CODE_FPGA_ENABLE_WRITE_MEMORY d_map_base[d_PROG_MEMS_ADDR] = LOCAL_CODE_FPGA_ENABLE_WRITE_MEMORY
| code_chip | select_fpga_correlator; | code_chip; // | select_fpga_correlator;
} }
select_fpga_correlator = select_fpga_correlator // select_fpga_correlator = select_fpga_correlator
+ LOCAL_CODE_FPGA_CORRELATOR_SELECT_COUNT; // + 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;
}
}
printf("\n");
} }
@ -297,24 +467,56 @@ void fpga_multicorrelator_8sc::fpga_compute_code_shift_parameters(void)
float temp_calculation; float temp_calculation;
int i; int i;
//printf("ppp d_rem_code_phase_chips = %f\n", d_rem_code_phase_chips);
for (i = 0; i < d_n_correlators; i++) 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( temp_calculation = floor(
d_shifts_chips[i] - d_rem_code_phase_chips); d_shifts_chips[i] - d_rem_code_phase_chips);
//printf("ppp d_rem_code_phase_chips = %f\n", d_rem_code_phase_chips);
//printf("ppp temp calculation %d = %f ================================ \n", i, temp_calculation);
if (temp_calculation < 0) 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, temp_calculation = fmod(d_shifts_chips[i] - d_rem_code_phase_chips,
1.0); 1.0);
//printf("ppp fmod %d = fmod(%f, 1) = %f\n", i, d_shifts_chips[i] - d_rem_code_phase_chips, temp_calculation);
if (temp_calculation < 0)
{
temp_calculation = temp_calculation + 1.0; // fmod operator does not work as in Matlab with negative numbers
}
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) if (temp_calculation < 0)
{ {
temp_calculation = temp_calculation + 1.0; // fmod operator does not work as in Matlab with negative numbers temp_calculation = temp_calculation + 1.0; // fmod operator does not work as in Matlab with negative numbers
} }
d_initial_interp_counter[i] = static_cast<unsigned>( floor( MAX_CODE_RESAMPLER_COUNTER * temp_calculation)); d_initial_interp_counter[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; int i;
for (i = 0; i < d_n_correlators; i++) for (i = 0; i < d_n_correlators; i++)
{ {
d_map_base[1 + i] = d_initial_index[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[1 + d_n_correlators + i] = d_initial_interp_counter[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; float d_rem_carrier_phase_in_rad_temp;
d_code_phase_step_chips_num = static_cast<unsigned>( roundf(MAX_CODE_RESAMPLER_COUNTER * d_code_phase_step_chips)); d_code_phase_step_chips_num = static_cast<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) if (d_rem_carrier_phase_in_rad > M_PI)
{ {
d_rem_carrier_phase_in_rad_temp = -2 * M_PI d_rem_carrier_phase_in_rad_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( 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 (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) if (d_phase_step_rad < 0)
{ {
d_phase_step_rad_int = -d_phase_step_rad_int; 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) void fpga_multicorrelator_8sc::fpga_configure_signal_parameters_in_fpga(void)
{ {
d_map_base[0] = d_code_phase_step_chips_num; //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[7] = d_correlator_length_samples - 1; d_map_base[d_CODE_PHASE_STEP_CHIPS_NUM_REG_ADDR] = d_code_phase_step_chips_num;
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_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)); write(d_device_descriptor, reinterpret_cast<void*>(&reenable), sizeof(int));
// writing 1 to reg 14 launches the tracking // 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 readval_imag;
int k; int k;
for (k = 0; k < d_n_correlators; k++) for (k = 0; k < d_n_correlators; k++)
{ {
readval_real = d_map_base[1 + k]; readval_real = d_map_base[d_RESULT_REG_REAL_BASE_ADDR + k];
if (readval_real >= 1048576) // 0x100000 (21 bits two's complement) //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]; readval_imag = d_map_base[d_RESULT_REG_DATA_IMAG_BASE_ADDR];
if (readval_imag >= 1048576) // 0x100000 (21 bits two's complement) 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) void fpga_multicorrelator_8sc::unlock_channel(void)
{ {
// unlock the channel to let the next samples go through // 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() void fpga_multicorrelator_8sc::close_device()
@ -430,19 +724,20 @@ void fpga_multicorrelator_8sc::close_device()
void fpga_multicorrelator_8sc::lock_channel(void) void fpga_multicorrelator_8sc::lock_channel(void)
{ {
// lock the channel for processing // 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) //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]; // *sample_counter = d_map_base[11];
*secondary_sample_counter = d_map_base[8]; // *secondary_sample_counter = d_map_base[8];
*counter_corr_0_in = d_map_base[10]; // *counter_corr_0_in = d_map_base[10];
*counter_corr_0_out = d_map_base[9]; // *counter_corr_0_out = d_map_base[9];
//
//}
} //void fpga_multicorrelator_8sc::reset_multicorrelator(void)
//{
void fpga_multicorrelator_8sc::reset_multicorrelator(void) // d_map_base[14] = 2; // writing a 2 to d_map_base[14] resets the multicorrelator
{ //}
d_map_base[14] = 2; // writing a 2 to d_map_base[14] resets the multicorrelator
}

View File

@ -49,7 +49,7 @@ class fpga_multicorrelator_8sc
{ {
public: public:
fpga_multicorrelator_8sc(int n_correlators, std::string device_name, 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(); ~fpga_multicorrelator_8sc();
//bool set_output_vectors(gr_complex* corr_out); //bool set_output_vectors(gr_complex* corr_out);
void set_output_vectors(gr_complex* corr_out, gr_complex* Prompt_Data); void set_output_vectors(gr_complex* corr_out, gr_complex* Prompt_Data);
@ -58,8 +58,8 @@ public:
// float *shifts_chips, int PRN); // float *shifts_chips, int PRN);
//bool set_local_code_and_taps( //bool set_local_code_and_taps(
void set_local_code_and_taps( void set_local_code_and_taps(
int code_length_chips, // int code_length_chips,
float *shifts_chips, int PRN); float *shifts_chips, float *prompt_data_shift, int PRN);
//bool set_output_vectors(lv_16sc_t* corr_out); //bool set_output_vectors(lv_16sc_t* corr_out);
void update_local_code(float rem_code_phase_chips); void update_local_code(float rem_code_phase_chips);
//bool Carrier_wipeoff_multicorrelator_resampler( //bool Carrier_wipeoff_multicorrelator_resampler(
@ -72,7 +72,7 @@ public:
int read_sample_counter(); int read_sample_counter();
void lock_channel(void); void lock_channel(void);
void unlock_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: private:
@ -80,6 +80,7 @@ private:
gr_complex * d_corr_out; gr_complex * d_corr_out;
gr_complex * d_Prompt_Data; gr_complex * d_Prompt_Data;
float *d_shifts_chips; float *d_shifts_chips;
float *d_prompt_data_shift;
int d_code_length_chips; int d_code_length_chips;
int d_n_correlators; int d_n_correlators;
@ -110,11 +111,37 @@ private:
int* d_ca_codes; 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; 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 // private functions
unsigned fpga_acquisition_test_register(unsigned writeval); unsigned fpga_acquisition_test_register(unsigned writeval);
void fpga_configure_tracking_gps_local_code(int PRN); void fpga_configure_tracking_gps_local_code(int PRN);
@ -124,9 +151,17 @@ private:
void fpga_configure_signal_parameters_in_fpga(void); void fpga_configure_signal_parameters_in_fpga(void);
void fpga_launch_multicorrelator_fpga(void); void fpga_launch_multicorrelator_fpga(void);
void read_tracking_gps_results(void); void read_tracking_gps_results(void);
void reset_multicorrelator(void); //void reset_multicorrelator(void);
void close_device(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_ */ #endif /* GNSS_SDR_FPGA_MULTICORRELATOR_H_ */

View File

@ -106,9 +106,15 @@
#if ENABLE_FPGA #if ENABLE_FPGA
#include "gps_l1_ca_pcps_acquisition_fpga.h" #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_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_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_e1_dll_pll_veml_tracking_fpga.h"
#include "galileo_e5a_dll_pll_tracking_fpga.h"
#include "gps_l5_dll_pll_tracking_fpga.h"
#endif #endif
#if OPENCL_BLOCKS #if OPENCL_BLOCKS
@ -1374,12 +1380,28 @@ std::unique_ptr<GNSSBlockInterface> GNSSBlockFactory::GetBlock(
out_streams)); out_streams));
block = std::move(block_); 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) else if (implementation.compare("GPS_L5i_PCPS_Acquisition") == 0)
{ {
std::unique_ptr<AcquisitionInterface> block_(new GpsL5iPcpsAcquisition(configuration.get(), role, in_streams, std::unique_ptr<AcquisitionInterface> block_(new GpsL5iPcpsAcquisition(configuration.get(), role, in_streams,
out_streams)); out_streams));
block = std::move(block_); 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) else if (implementation.compare("Galileo_E1_PCPS_Ambiguous_Acquisition") == 0)
{ {
std::unique_ptr<GNSSBlockInterface> block_(new GalileoE1PcpsAmbiguousAcquisition(configuration.get(), role, in_streams, std::unique_ptr<GNSSBlockInterface> block_(new GalileoE1PcpsAmbiguousAcquisition(configuration.get(), role, in_streams,
@ -1424,6 +1446,14 @@ std::unique_ptr<GNSSBlockInterface> GNSSBlockFactory::GetBlock(
out_streams)); out_streams));
block = std::move(block_); 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) else if (implementation.compare("Galileo_E1_PCPS_QuickSync_Ambiguous_Acquisition") == 0)
{ {
std::unique_ptr<GNSSBlockInterface> block_(new GalileoE1PcpsQuickSyncAmbiguousAcquisition(configuration.get(), role, in_streams, std::unique_ptr<GNSSBlockInterface> block_(new GalileoE1PcpsQuickSyncAmbiguousAcquisition(configuration.get(), role, in_streams,
@ -1475,12 +1505,28 @@ std::unique_ptr<GNSSBlockInterface> GNSSBlockFactory::GetBlock(
out_streams)); out_streams));
block = std::move(block_); 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)) 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, std::unique_ptr<GNSSBlockInterface> block_(new GpsL5DllPllTracking(configuration.get(), role, in_streams,
out_streams)); out_streams));
block = std::move(block_); 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 #if CUDA_GPU_ACCEL
else if (implementation.compare("GPS_L1_CA_DLL_PLL_Tracking_GPU") == 0) else if (implementation.compare("GPS_L1_CA_DLL_PLL_Tracking_GPU") == 0)
{ {
@ -1515,6 +1561,14 @@ std::unique_ptr<GNSSBlockInterface> GNSSBlockFactory::GetBlock(
out_streams)); out_streams));
block = std::move(block_); 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) else if (implementation.compare("GLONASS_L1_CA_DLL_PLL_Tracking") == 0)
{ {
std::unique_ptr<GNSSBlockInterface> block_(new GlonassL1CaDllPllTracking(configuration.get(), role, in_streams, std::unique_ptr<GNSSBlockInterface> block_(new GlonassL1CaDllPllTracking(configuration.get(), role, in_streams,
@ -1683,12 +1737,28 @@ std::unique_ptr<AcquisitionInterface> GNSSBlockFactory::GetAcqBlock(
out_streams)); out_streams));
block = std::move(block_); 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) else if (implementation.compare("GPS_L5i_PCPS_Acquisition") == 0)
{ {
std::unique_ptr<AcquisitionInterface> block_(new GpsL5iPcpsAcquisition(configuration.get(), role, in_streams, std::unique_ptr<AcquisitionInterface> block_(new GpsL5iPcpsAcquisition(configuration.get(), role, in_streams,
out_streams)); out_streams));
block = std::move(block_); 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) else if (implementation.compare("Galileo_E1_PCPS_Ambiguous_Acquisition") == 0)
{ {
std::unique_ptr<AcquisitionInterface> block_(new GalileoE1PcpsAmbiguousAcquisition(configuration.get(), role, in_streams, std::unique_ptr<AcquisitionInterface> block_(new GalileoE1PcpsAmbiguousAcquisition(configuration.get(), role, in_streams,
@ -1740,6 +1810,14 @@ std::unique_ptr<AcquisitionInterface> GNSSBlockFactory::GetAcqBlock(
out_streams)); out_streams));
block = std::move(block_); 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) else if (implementation.compare("GLONASS_L1_CA_PCPS_Acquisition") == 0)
{ {
std::unique_ptr<AcquisitionInterface> block_(new GlonassL1CaPcpsAcquisition(configuration.get(), role, in_streams, std::unique_ptr<AcquisitionInterface> block_(new GlonassL1CaPcpsAcquisition(configuration.get(), role, in_streams,
@ -1822,18 +1900,42 @@ std::unique_ptr<TrackingInterface> GNSSBlockFactory::GetTrkBlock(
out_streams)); out_streams));
block = std::move(block_); 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) else if (implementation.compare("GPS_L2_M_DLL_PLL_Tracking") == 0)
{ {
std::unique_ptr<TrackingInterface> block_(new GpsL2MDllPllTracking(configuration.get(), role, in_streams, std::unique_ptr<TrackingInterface> block_(new GpsL2MDllPllTracking(configuration.get(), role, in_streams,
out_streams)); out_streams));
block = std::move(block_); 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)) 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, std::unique_ptr<TrackingInterface> block_(new GpsL5DllPllTracking(configuration.get(), role, in_streams,
out_streams)); out_streams));
block = std::move(block_); 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 #if CUDA_GPU_ACCEL
else if (implementation.compare("GPS_L1_CA_DLL_PLL_Tracking_GPU") == 0) else if (implementation.compare("GPS_L1_CA_DLL_PLL_Tracking_GPU") == 0)
{ {