Merge branch 'next' into bds_b3i

This commit is contained in:
Damian Miralles 2019-03-01 13:29:10 -06:00
commit 9ccb86dac6
76 changed files with 4455 additions and 3193 deletions

View File

@ -1,29 +1,52 @@
## [Unreleased](https://github.com/gnss-sdr/gnss-sdr/tree/next)
### Improvements in Availability
- Fixed bug that caused a random deadlock in the Observables block, preventing the computation of PVT fixes.
### Improvements in Efficiency
- Improved preamble detection implementation in the decoding of navigation messages (acceleration by x1.6 on average).
- Applied clang-tidy checks and fixes related to performance.
### Improvements in Interoperability:
- Added the BeiDou B1I receiver chain.
- Fix bug in GLONASS dual frequency receiver.
### Improvements in Maintainability:
- Usage of clang-tidy integrated into CMake scripts. New option -DENABLE_CLANG_TIDY=ON executes clang-tidy along with compilation. Requires clang compiler.
- Applied clang-tidy checks and fixes related to readability.
### Improvements in Portability:
- Added interfaces for FPGA off-loading.
- CMake scripts now follow a modern approach (targets and properties) but still work in 2.8.12
## Improvements in Reliability
### Improvements in Reliability
- Applied clang-tidy checks and fixes related to High Integrity C++.
### Improvements in Usability
- The receiver now admits FPGA off-loading, allowing for real time operation at high sampling rates and higher number of signals and channels.
- Fixed program termination (avoiding hangs and segfaults in some platforms/configurations).
- Improved information provided to the user in case of failure.
See the definitions of concepts and metrics at https://gnss-sdr.org/design-forces/
## [0.0.10](https://github.com/gnss-sdr/gnss-sdr/releases/tag/v0.0.10)
This release has several improvements in different dimensions, addition of new features and bug fixes:

View File

@ -1,12 +1,12 @@
/*!
* \file galileo_e1_pcps_ambiguous_acquisition.cc
* \file galileo_e1_pcps_ambiguous_acquisition_fpga.cc
* \brief Adapts a PCPS acquisition block to an AcquisitionInterface for
* Galileo E1 Signals
* \author Luis Esteve, 2012. luis(at)epsilon-formacion.com
* Galileo E1 Signals for the FPGA
* \author Marc Majoral, 2019. mmajoral(at)cttc.es
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
* Copyright (C) 2010-2019 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
@ -34,8 +34,6 @@
#include "configuration_interface.h"
#include "galileo_e1_signal_processing.h"
#include "gnss_sdr_flags.h"
#include <boost/lexical_cast.hpp>
#include <boost/math/distributions/exponential.hpp>
#include <glog/logging.h>
@ -50,75 +48,50 @@ GalileoE1PcpsAmbiguousAcquisitionFpga::GalileoE1PcpsAmbiguousAcquisitionFpga(
in_streams_(in_streams),
out_streams_(out_streams)
{
//printf("top acq constructor start\n");
pcpsconf_fpga_t acq_parameters;
configuration_ = configuration;
std::string default_item_type = "gr_complex";
std::string default_dump_filename = "./acquisition.mat";
std::string default_item_type = "cshort";
std::string default_dump_filename = "./data/acquisition.dat";
DLOG(INFO) << "role " << role;
// item_type_ = configuration_->property(role + ".item_type", default_item_type);
int64_t fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 4000000);
int64_t 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_;
float downsampling_factor = configuration_->property(role + ".downsampling_factor", 4.0);
acq_parameters.downsampling_factor = downsampling_factor;
fs_in = fs_in / downsampling_factor;
acq_parameters.fs_in = fs_in;
doppler_max_ = configuration_->property(role + ".doppler_max", 5000);
if (FLAGS_doppler_max != 0) doppler_max_ = FLAGS_doppler_max;
acq_parameters.doppler_max = doppler_max_;
//unsigned int sampled_ms = 4;
//acq_parameters.sampled_ms = sampled_ms;
unsigned int sampled_ms = configuration_->property(role + ".coherent_integration_time_ms", 4);
uint32_t sampled_ms = configuration_->property(role + ".coherent_integration_time_ms", 4);
acq_parameters.sampled_ms = sampled_ms;
// bit_transition_flag_ = configuration_->property(role + ".bit_transition_flag", false);
// acq_parameters.bit_transition_flag = bit_transition_flag_;
// use_CFAR_algorithm_flag_ = configuration_->property(role + ".use_CFAR_algorithm", true); //will be false in future versions
// acq_parameters.use_CFAR_algorithm_flag = use_CFAR_algorithm_flag_;
acquire_pilot_ = configuration_->property(role + ".acquire_pilot", false); //will be true in future versions
// max_dwells_ = configuration_->property(role + ".max_dwells", 1);
// acq_parameters.max_dwells = max_dwells_;
// dump_filename_ = configuration_->property(role + ".dump_filename", default_dump_filename);
// acq_parameters.dump_filename = dump_filename_;
//--- Find number of samples per spreading code (4 ms) -----------------
auto code_length = static_cast<unsigned int>(std::round(static_cast<double>(fs_in) / (GALILEO_E1_CODE_CHIP_RATE_HZ / GALILEO_E1_B_CODE_LENGTH_CHIPS)));
//acq_parameters.samples_per_code = code_length_;
//int samples_per_ms = static_cast<int>(std::round(static_cast<double>(fs_in_) * 0.001));
//acq_parameters.samples_per_ms = samples_per_ms;
//unsigned int vector_length = sampled_ms * samples_per_ms;
auto code_length = static_cast<uint32_t>(std::round(static_cast<double>(fs_in) / (GALILEO_E1_CODE_CHIP_RATE_HZ / GALILEO_E1_B_CODE_LENGTH_CHIPS)));
// if (bit_transition_flag_)
// {
// vector_length_ *= 2;
// }
//printf("fs_in = %d\n", fs_in);
//printf("GALILEO_E1_B_CODE_LENGTH_CHIPS = %f\n", GALILEO_E1_B_CODE_LENGTH_CHIPS);
//printf("GALILEO_E1_CODE_CHIP_RATE_HZ = %f\n", GALILEO_E1_CODE_CHIP_RATE_HZ);
//printf("acq adapter code_length = %d\n", code_length);
acq_parameters.code_length = code_length;
// The FPGA can only use FFT lengths that are a power of two.
float nbits = ceilf(log2f((float)code_length));
unsigned int nsamples_total = pow(2, nbits);
unsigned int vector_length = nsamples_total;
//printf("acq adapter nsamples_total (= vector_length) = %d\n", vector_length);
unsigned int select_queue_Fpga = configuration_->property(role + ".select_queue_Fpga", 0);
float nbits = ceilf(log2f((float)code_length * 2));
uint32_t nsamples_total = pow(2, nbits);
uint32_t select_queue_Fpga = configuration_->property(role + ".select_queue_Fpga", 0);
acq_parameters.select_queue_Fpga = select_queue_Fpga;
std::string default_device_name = "/dev/uio0";
std::string device_name = configuration_->property(role + ".devicename", default_device_name);
acq_parameters.device_name = device_name;
acq_parameters.samples_per_ms = nsamples_total / sampled_ms;
acq_parameters.samples_per_code = nsamples_total;
acq_parameters.excludelimit = static_cast<uint32_t>(std::round(static_cast<double>(fs_in) / GALILEO_E1_CODE_CHIP_RATE_HZ));
// 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 in the class constructor in order to avoid re-computing the PRN codes every time
// a channel is assigned)
auto* fft_if = new gr::fft::fft_complex(nsamples_total, true); // Direct FFT
auto* code = new std::complex<float>[nsamples_total]; // buffer for the local code
@ -126,19 +99,12 @@ GalileoE1PcpsAmbiguousAcquisitionFpga::GalileoE1PcpsAmbiguousAcquisitionFpga(
d_all_fft_codes_ = new lv_16sc_t[nsamples_total * GALILEO_E1_NUMBER_OF_CODES]; // memory containing all the possible fft codes for PRN 0 to 32
float max; // temporary maxima search
//int tmp_re, tmp_im;
for (unsigned int PRN = 1; PRN <= GALILEO_E1_NUMBER_OF_CODES; PRN++)
for (uint32_t PRN = 1; PRN <= GALILEO_E1_NUMBER_OF_CODES; PRN++)
{
//code_ = new gr_complex[vector_length_];
bool cboc = false; // cboc is set to 0 when using the FPGA
//std::complex<float>* code = new std::complex<float>[code_length_];
if (acquire_pilot_ == true)
{
//printf("yes acquiring pilot!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!1\n");
//set local signal generator to Galileo E1 pilot component (1C)
char pilot_signal[3] = "1C";
galileo_e1_code_gen_complex_sampled(code, pilot_signal,
@ -151,53 +117,24 @@ GalileoE1PcpsAmbiguousAcquisitionFpga::GalileoE1PcpsAmbiguousAcquisitionFpga(
cboc, PRN, fs_in, 0, false);
}
// for (unsigned int i = 0; i < sampled_ms / 4; i++)
// {
// //memcpy(&(code_[i * code_length_]), code, sizeof(gr_complex) * code_length_);
// memcpy(&(d_all_fft_codes_[i * code_length_]), code, sizeof(gr_complex) * code_length_);
// }
for (uint32_t s = code_length; s < 2 * code_length; s++)
{
code[s] = code[s - code_length];
}
// // debug
// char filename[25];
// FILE *fid;
// sprintf(filename,"gal_prn%d.txt", PRN);
// fid = fopen(filename, "w");
// for (unsigned int kk=0;kk< nsamples_total; kk++)
// {
// fprintf(fid, "%f\n", code[kk].real());
// fprintf(fid, "%f\n", code[kk].imag());
// }
// fclose(fid);
// // fill in zero padding
for (int s = code_length; s < nsamples_total; s++)
// fill in zero padding
for (uint32_t s = 2 * code_length; s < nsamples_total; s++)
{
code[s] = std::complex<float>(0.0, 0.0);
//code[s] = 0;
}
memcpy(fft_if->get_inbuf(), code, sizeof(gr_complex) * nsamples_total); // copy to FFT buffer
fft_if->execute(); // Run the FFT of local code
volk_32fc_conjugate_32fc(fft_codes_padded, fft_if->get_outbuf(), nsamples_total); // conjugate values
// // debug
// char filename[25];
// FILE *fid;
// sprintf(filename,"fft_gal_prn%d.txt", PRN);
// fid = fopen(filename, "w");
// for (unsigned int kk=0;kk< nsamples_total; kk++)
// {
// fprintf(fid, "%f\n", fft_codes_padded[kk].real());
// fprintf(fid, "%f\n", fft_codes_padded[kk].imag());
// }
// fclose(fid);
// normalize the code
max = 0; // initialize maximum value
for (unsigned int i = 0; i < nsamples_total; i++) // search for maxima
max = 0; // initialize maximum value
for (uint32_t i = 0; i < nsamples_total; i++) // search for maxima
{
if (std::abs(fft_codes_padded[i].real()) > max)
{
@ -208,350 +145,135 @@ GalileoE1PcpsAmbiguousAcquisitionFpga::GalileoE1PcpsAmbiguousAcquisitionFpga(
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
for (uint32_t i = 0; i < nsamples_total; i++) // map the FFT to the dynamic range of the fixed point values an copy to buffer containing all FFTs
{
//d_all_fft_codes_[i + nsamples_total * (PRN - 1)] = lv_16sc_t(static_cast<int>(floor(4096*fft_codes_padded[i].real() * (pow(2, 3) - 1) / max)),
// static_cast<int>(floor(4096*fft_codes_padded[i].imag() * (pow(2, 3) - 1) / max)));
// d_all_fft_codes_[i + nsamples_total * (PRN - 1)] = lv_16sc_t(static_cast<int>(floor(1024*fft_codes_padded[i].real() * (pow(2, 5) - 1) / max)),
// static_cast<int>(floor(1024*fft_codes_padded[i].imag() * (pow(2, 5) - 1) / max)));
// d_all_fft_codes_[i + nsamples_total * (PRN - 1)] = lv_16sc_t(static_cast<int>(floor(256*fft_codes_padded[i].real() * (pow(2, 7) - 1) / max)),
// static_cast<int>(floor(256*fft_codes_padded[i].imag() * (pow(2, 7) - 1) / max)));
// d_all_fft_codes_[i + nsamples_total * (PRN - 1)] = lv_16sc_t(static_cast<int>(floor(16*fft_codes_padded[i].real() * (pow(2, 11) - 1) / max)),
// static_cast<int>(floor(16*fft_codes_padded[i].imag() * (pow(2, 11) - 1) / max)));
d_all_fft_codes_[i + nsamples_total * (PRN - 1)] = lv_16sc_t(static_cast<int>(floor(fft_codes_padded[i].real() * (pow(2, 15) - 1) / max)),
static_cast<int>(floor(fft_codes_padded[i].imag() * (pow(2, 15) - 1) / max)));
// tmp_re = static_cast<int>(floor(fft_codes_padded[i].real() * (pow(2, 7) - 1) / max));
// tmp_im = static_cast<int>(floor(fft_codes_padded[i].imag() * (pow(2, 7) - 1) / max));
// if (tmp_re > 127)
// {
// tmp_re = 127;
// }
// if (tmp_re < -128)
// {
// tmp_re = -128;
// }
// if (tmp_im > 127)
// {
// tmp_im = 127;
// }
// if (tmp_im < -128)
// {
// tmp_im = -128;
// }
// d_all_fft_codes_[i + nsamples_total * (PRN - 1)] = lv_16sc_t(static_cast<int>(tmp_re), static_cast<int>(tmp_im));
//
d_all_fft_codes_[i + nsamples_total * (PRN - 1)] = lv_16sc_t(static_cast<int32_t>(floor(fft_codes_padded[i].real() * (pow(2, 9) - 1) / max)),
static_cast<int32_t>(floor(fft_codes_padded[i].imag() * (pow(2, 9) - 1) / max)));
}
// // debug
// char filename2[25];
// FILE *fid2;
// sprintf(filename2,"fft_gal_prn%d_norm.txt", PRN);
// fid2 = fopen(filename2, "w");
// for (unsigned int kk=0;kk< nsamples_total; kk++)
// {
// fprintf(fid2, "%d\n", d_all_fft_codes_[kk + nsamples_total * (PRN - 1)].real());
// fprintf(fid2, "%d\n", d_all_fft_codes_[kk + nsamples_total * (PRN - 1)].imag());
// }
// fclose(fid2);
}
// for (unsigned int PRN = 1; PRN <= GALILEO_E1_NUMBER_OF_CODES; PRN++)
// {
// // debug
// char filename2[25];
// FILE *fid2;
// sprintf(filename2,"fft_gal_prn%d_norm_last.txt", PRN);
// fid2 = fopen(filename2, "w");
// for (unsigned int kk=0;kk< nsamples_total; kk++)
// {
// fprintf(fid2, "%d\n", d_all_fft_codes_[kk + nsamples_total * (PRN - 1)].real());
// fprintf(fid2, "%d\n", d_all_fft_codes_[kk + nsamples_total * (PRN - 1)].imag());
// }
// fclose(fid2);
// }
//acq_parameters
acq_parameters.all_fft_codes = d_all_fft_codes_;
// reference for the FPGA FFT-IFFT attenuation factor
acq_parameters.total_block_exp = configuration_->property(role + ".total_block_exp", 14);
acquisition_fpga_ = pcps_make_acquisition_fpga(acq_parameters);
DLOG(INFO) << "acquisition(" << acquisition_fpga_->unique_id() << ")";
channel_ = 0;
doppler_step_ = 0;
gnss_synchro_ = nullptr;
// temporary buffers that we can delete
delete[] code;
delete fft_if;
delete[] fft_codes_padded;
acquisition_fpga_ = pcps_make_acquisition_fpga(acq_parameters);
DLOG(INFO) << "acquisition(" << acquisition_fpga_->unique_id() << ")";
// stream_to_vector_ = gr::blocks::stream_to_vector::make(item_size_, vector_length_);
// DLOG(INFO) << "stream_to_vector(" << stream_to_vector_->unique_id() << ")";
// if (item_type_.compare("cbyte") == 0)
// {
// cbyte_to_float_x2_ = make_complex_byte_to_float_x2();
// float_to_complex_ = gr::blocks::float_to_complex::make();
// }
channel_ = 0;
//threshold_ = 0.0;
doppler_step_ = 0;
gnss_synchro_ = nullptr;
//printf("top acq constructor end\n");
}
GalileoE1PcpsAmbiguousAcquisitionFpga::~GalileoE1PcpsAmbiguousAcquisitionFpga()
{
//printf("top acq destructor start\n");
//delete[] code_;
delete[] d_all_fft_codes_;
//printf("top acq destructor end\n");
}
void GalileoE1PcpsAmbiguousAcquisitionFpga::stop_acquisition()
{
// this command causes the SW to reset the HW.
acquisition_fpga_->reset_acquisition();
}
void GalileoE1PcpsAmbiguousAcquisitionFpga::set_channel(unsigned int channel)
{
//printf("top acq set channel start\n");
channel_ = channel;
acquisition_fpga_->set_channel(channel_);
//printf("top acq set channel end\n");
}
void GalileoE1PcpsAmbiguousAcquisitionFpga::set_threshold(float threshold)
{
//printf("top acq set threshold start\n");
// the .pfa parameter and the threshold calculation is only used for the CFAR algorithm.
// We don't use the CFAR algorithm in the FPGA. Therefore the threshold is set as such.
// float pfa = configuration_->property(role_ + boost::lexical_cast<std::string>(channel_) + ".pfa", 0.0);
//
// if (pfa == 0.0) pfa = configuration_->property(role_ + ".pfa", 0.0);
//
// if (pfa == 0.0)
// {
// threshold_ = threshold;
// }
// else
// {
// threshold_ = calculate_threshold(pfa);
// }
DLOG(INFO) << "Channel " << channel_ << " Threshold = " << threshold;
acquisition_fpga_->set_threshold(threshold);
// acquisition_fpga_->set_threshold(threshold_);
//printf("top acq set threshold end\n");
}
void GalileoE1PcpsAmbiguousAcquisitionFpga::set_doppler_max(unsigned int doppler_max)
{
//printf("top acq set doppler max start\n");
doppler_max_ = doppler_max;
acquisition_fpga_->set_doppler_max(doppler_max_);
//printf("top acq set doppler max end\n");
}
void GalileoE1PcpsAmbiguousAcquisitionFpga::set_doppler_step(unsigned int doppler_step)
{
//printf("top acq set doppler step start\n");
doppler_step_ = doppler_step;
acquisition_fpga_->set_doppler_step(doppler_step_);
//printf("top acq set doppler step end\n");
}
void GalileoE1PcpsAmbiguousAcquisitionFpga::set_gnss_synchro(Gnss_Synchro* gnss_synchro)
{
//printf("top acq set gnss synchro start\n");
gnss_synchro_ = gnss_synchro;
acquisition_fpga_->set_gnss_synchro(gnss_synchro_);
//printf("top acq set gnss synchro end\n");
}
signed int GalileoE1PcpsAmbiguousAcquisitionFpga::mag()
{
// printf("top acq mag start\n");
return acquisition_fpga_->mag();
//printf("top acq mag end\n");
}
void GalileoE1PcpsAmbiguousAcquisitionFpga::init()
{
// printf("top acq init start\n");
acquisition_fpga_->init();
// printf("top acq init end\n");
//set_local_code();
}
void GalileoE1PcpsAmbiguousAcquisitionFpga::set_local_code()
{
// printf("top acq set local code start\n");
// bool cboc = configuration_->property(
// "Acquisition" + boost::lexical_cast<std::string>(channel_) + ".cboc", false);
//
// std::complex<float>* code = new std::complex<float>[code_length_];
//
// if (acquire_pilot_ == true)
// {
// //set local signal generator to Galileo E1 pilot component (1C)
// char pilot_signal[3] = "1C";
// galileo_e1_code_gen_complex_sampled(code, pilot_signal,
// cboc, gnss_synchro_->PRN, fs_in_, 0, false);
// }
// else
// {
// galileo_e1_code_gen_complex_sampled(code, gnss_synchro_->Signal,
// cboc, gnss_synchro_->PRN, fs_in_, 0, false);
// }
//
//
// for (unsigned int i = 0; i < sampled_ms_ / 4; i++)
// {
// memcpy(&(code_[i * code_length_]), code, sizeof(gr_complex) * code_length_);
// }
//acquisition_fpga_->set_local_code(code_);
acquisition_fpga_->set_local_code();
// delete[] code;
// printf("top acq set local code end\n");
}
void GalileoE1PcpsAmbiguousAcquisitionFpga::reset()
{
// printf("top acq reset start\n");
// This command starts the acquisition process
acquisition_fpga_->set_active(true);
// printf("top acq reset end\n");
}
void GalileoE1PcpsAmbiguousAcquisitionFpga::set_state(int state)
{
// printf("top acq set state start\n");
acquisition_fpga_->set_state(state);
// printf("top acq set state end\n");
}
//float GalileoE1PcpsAmbiguousAcquisitionFpga::calculate_threshold(float pfa)
//{
// unsigned int frequency_bins = 0;
// for (int doppler = static_cast<int>(-doppler_max_); doppler <= static_cast<int>(doppler_max_); doppler += doppler_step_)
// {
// frequency_bins++;
// }
//
// DLOG(INFO) << "Channel " << channel_ << " Pfa = " << pfa;
//
// unsigned int ncells = vector_length_ * frequency_bins;
// double exponent = 1 / static_cast<double>(ncells);
// double val = pow(1.0 - pfa, exponent);
// double lambda = double(vector_length_);
// boost::math::exponential_distribution<double> mydist(lambda);
// float threshold = static_cast<float>(quantile(mydist, val));
//
// return threshold;
//}
void GalileoE1PcpsAmbiguousAcquisitionFpga::connect(gr::top_block_sptr top_block)
{
// printf("top acq connect\n");
// if (item_type_.compare("gr_complex") == 0)
// {
// top_block->connect(stream_to_vector_, 0, acquisition_fpga_, 0);
// }
// else if (item_type_.compare("cshort") == 0)
// {
// top_block->connect(stream_to_vector_, 0, acquisition_fpga_, 0);
// }
// else if (item_type_.compare("cbyte") == 0)
// {
// top_block->connect(cbyte_to_float_x2_, 0, float_to_complex_, 0);
// top_block->connect(cbyte_to_float_x2_, 1, float_to_complex_, 1);
// top_block->connect(float_to_complex_, 0, stream_to_vector_, 0);
// top_block->connect(stream_to_vector_, 0, acquisition_fpga_, 0);
// }
// else
// {
// LOG(WARNING) << item_type_ << " unknown acquisition item type";
// }
// nothing to connect
if (top_block)
{ /* top_block is not null */
};
// Nothing to connect
}
void GalileoE1PcpsAmbiguousAcquisitionFpga::disconnect(gr::top_block_sptr top_block)
{
// if (item_type_.compare("gr_complex") == 0)
// {
// top_block->disconnect(stream_to_vector_, 0, acquisition_fpga_, 0);
// }
// else if (item_type_.compare("cshort") == 0)
// {
// top_block->disconnect(stream_to_vector_, 0, acquisition_fpga_, 0);
// }
// else if (item_type_.compare("cbyte") == 0)
// {
// // Since a byte-based acq implementation is not available,
// // we just convert cshorts to gr_complex
// top_block->disconnect(cbyte_to_float_x2_, 0, float_to_complex_, 0);
// top_block->disconnect(cbyte_to_float_x2_, 1, float_to_complex_, 1);
// top_block->disconnect(float_to_complex_, 0, stream_to_vector_, 0);
// top_block->disconnect(stream_to_vector_, 0, acquisition_fpga_, 0);
// }
// else
// {
// LOG(WARNING) << item_type_ << " unknown acquisition item type";
// }
// nothing to disconnect
// printf("top acq disconnect\n");
if (top_block)
{ /* top_block is not null */
};
// Nothing to disconnect
}
gr::basic_block_sptr GalileoE1PcpsAmbiguousAcquisitionFpga::get_left_block()
{
// printf("top acq get left block start\n");
// if (item_type_.compare("gr_complex") == 0)
// {
// return stream_to_vector_;
// }
// else if (item_type_.compare("cshort") == 0)
// {
// return stream_to_vector_;
// }
// else if (item_type_.compare("cbyte") == 0)
// {
// return cbyte_to_float_x2_;
// }
// else
// {
// LOG(WARNING) << item_type_ << " unknown acquisition item type";
return nullptr;
// }
// printf("top acq get left block end\n");
}
gr::basic_block_sptr GalileoE1PcpsAmbiguousAcquisitionFpga::get_right_block()
{
// printf("top acq get right block start\n");
return acquisition_fpga_;
// printf("top acq get right block end\n");
}

View File

@ -1,12 +1,12 @@
/*!
* \file galileo_e1_pcps_ambiguous_acquisition.h
* \file galileo_e1_pcps_ambiguous_acquisition_fpga.h
* \brief Adapts a PCPS acquisition block to an AcquisitionInterface for
* Galileo E1 Signals
* \author Luis Esteve, 2012. luis(at)epsilon-formacion.com
* \author Marc Majoral, 2019. mmajoral(at)cttc.es
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
* Copyright (C) 2010-2019 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
@ -60,22 +60,19 @@ public:
inline std::string role() override
{
// printf("top acq role\n");
return role_;
}
/*!
* \brief Returns "Galileo_E1_PCPS_Ambiguous_Acquisition"
* \brief Returns "Galileo_E1_PCPS_Ambiguous_Acquisition_Fpga"
*/
inline std::string implementation() override
{
// printf("top acq implementation\n");
return "Galileo_E1_PCPS_Ambiguous_Acquisition_Fpga";
}
size_t item_size() override
{
// printf("top acq item size\n");
size_t item_size = sizeof(lv_16sc_t);
return item_size;
}
@ -138,45 +135,28 @@ public:
void set_state(int state) override;
/*!
* \brief Stop running acquisition
*/
* \brief Stop running acquisition
*/
void stop_acquisition() override;
void set_resampler_latency(uint32_t latency_samples __attribute__((unused))) override{};
private:
ConfigurationInterface* configuration_;
//pcps_acquisition_sptr acquisition_;
pcps_acquisition_fpga_sptr acquisition_fpga_;
gr::blocks::stream_to_vector::sptr stream_to_vector_;
gr::blocks::float_to_complex::sptr float_to_complex_;
complex_byte_to_float_x2_sptr cbyte_to_float_x2_;
// size_t item_size_;
// std::string item_type_;
//unsigned int vector_length_;
//unsigned int code_length_;
bool bit_transition_flag_;
bool use_CFAR_algorithm_flag_;
bool acquire_pilot_;
unsigned int channel_;
//float threshold_;
unsigned int doppler_max_;
unsigned int doppler_step_;
//unsigned int sampled_ms_;
unsigned int max_dwells_;
//long fs_in_;
//long if_;
bool dump_;
bool blocking_;
uint32_t channel_;
uint32_t doppler_max_;
uint32_t doppler_step_;
std::string dump_filename_;
//std::complex<float>* code_;
Gnss_Synchro* gnss_synchro_;
std::string role_;
unsigned int in_streams_;
unsigned int out_streams_;
//float calculate_threshold(float pfa);
// extra for the FPGA
lv_16sc_t* d_all_fft_codes_; // memory that contains all the code ffts
};

View File

@ -1,11 +1,12 @@
/*!
* \file galileo_e5a_pcps_acquisition.cc
* \file galileo_e5a_pcps_acquisition_fpga.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
* Galileo E5a data and pilot Signals for the FPGA
* \author Marc Majoral, 2019. mmajoral(at)cttc.es
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2018 (see AUTHORS file for a list of contributors)
* Copyright (C) 2010-2019 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
@ -48,39 +49,27 @@ GalileoE5aPcpsAcquisitionFpga::GalileoE5aPcpsAcquisitionFpga(ConfigurationInterf
in_streams_(in_streams),
out_streams_(out_streams)
{
//printf("creating the E5A acquisition");
pcpsconf_fpga_t acq_parameters;
configuration_ = configuration;
std::string default_item_type = "gr_complex";
std::string default_dump_filename = "./acquisition.mat";
std::string default_dump_filename = "../data/acquisition.dat";
DLOG(INFO) << "Role " << role;
//item_type_ = configuration_->property(role + ".item_type", default_item_type);
int64_t fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 32000000);
int64_t fs_in = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated);
float downsampling_factor = configuration_->property(role + ".downsampling_factor", 1.0);
acq_parameters.downsampling_factor = downsampling_factor;
fs_in = fs_in / downsampling_factor;
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)-------------------------
uint32_t sampled_ms = configuration_->property(role + ".coherent_integration_time_ms", 1);
acq_parameters.sampled_ms = sampled_ms;
acq_pilot_ = configuration_->property(role + ".acquire_pilot", false);
acq_iq_ = configuration_->property(role + ".acquire_iq", false);
@ -89,14 +78,13 @@ GalileoE5aPcpsAcquisitionFpga::GalileoE5aPcpsAcquisitionFpga(ConfigurationInterf
acq_pilot_ = false;
}
auto 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)));
auto code_length = static_cast<uint32_t>(std::round(static_cast<double>(fs_in) / GALILEO_E5A_CODE_CHIP_RATE_HZ * static_cast<double>(GALILEO_E5A_CODE_LENGTH_CHIPS)));
acq_parameters.code_length = code_length;
// The FPGA can only use FFT lengths that are a power of two.
float nbits = ceilf(log2f((float)code_length));
unsigned int nsamples_total = pow(2, nbits);
unsigned int vector_length = nsamples_total;
unsigned int select_queue_Fpga = configuration_->property(role + ".select_queue_Fpga", 1);
//printf("select_queue_Fpga = %d\n", select_queue_Fpga);
float nbits = ceilf(log2f((float)code_length * 2));
uint32_t nsamples_total = pow(2, nbits);
uint32_t 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);
@ -104,9 +92,9 @@ GalileoE5aPcpsAcquisitionFpga::GalileoE5aPcpsAcquisitionFpga(ConfigurationInterf
acq_parameters.samples_per_ms = nsamples_total / sampled_ms;
acq_parameters.samples_per_code = nsamples_total;
//vector_length_ = code_length_ * sampled_ms_;
acq_parameters.excludelimit = static_cast<uint32_t>(ceil((1.0 / GALILEO_E5A_CODE_CHIP_RATE_HZ) * static_cast<float>(acq_parameters.fs_in)));
// 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
// compute all the GALILEO E5 PRN Codes (this is done only once in the class constructor in order to avoid re-computing the PRN codes every time
// a channel is assigned)
auto* fft_if = new gr::fft::fft_complex(nsamples_total, true); // Direct FFT
auto* code = new std::complex<float>[nsamples_total]; // buffer for the local code
@ -114,12 +102,8 @@ GalileoE5aPcpsAcquisitionFpga::GalileoE5aPcpsAcquisitionFpga(ConfigurationInterf
d_all_fft_codes_ = new lv_16sc_t[nsamples_total * GALILEO_E5A_NUMBER_OF_CODES]; // memory containing all the possible fft codes for PRN 0 to 32
float max; // temporary maxima search
//printf("creating the E5A acquisition CONT");
//printf("nsamples_total = %d\n", nsamples_total);
for (unsigned int PRN = 1; PRN <= GALILEO_E5A_NUMBER_OF_CODES; PRN++)
for (uint32_t PRN = 1; PRN <= GALILEO_E5A_NUMBER_OF_CODES; PRN++)
{
// gr_complex* code = new gr_complex[code_length_];
char signal_[3];
if (acq_iq_)
@ -135,22 +119,25 @@ GalileoE5aPcpsAcquisitionFpga::GalileoE5aPcpsAcquisitionFpga(ConfigurationInterf
strcpy(signal_, "5I");
}
galileo_e5_a_code_gen_complex_sampled(code, signal_, PRN, fs_in, 0);
for (uint32_t s = code_length; s < 2 * code_length; s++)
{
code[s] = code[s - code_length];
}
// fill in zero padding
for (int s = code_length; s < nsamples_total; s++)
for (uint32_t s = 2 * code_length; s < nsamples_total; s++)
{
code[s] = std::complex<float>(0.0, 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
max = 0; // initialize maximum value
for (uint32_t i = 0; i < nsamples_total; i++) // search for maxima
{
if (std::abs(fft_codes_padded[i].real()) > max)
{
@ -161,101 +148,55 @@ GalileoE5aPcpsAcquisitionFpga::GalileoE5aPcpsAcquisitionFpga(ConfigurationInterf
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
for (uint32_t 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)));
d_all_fft_codes_[i + nsamples_total * (PRN - 1)] = lv_16sc_t(static_cast<int32_t>(floor(fft_codes_padded[i].real() * (pow(2, 9) - 1) / max)),
static_cast<int32_t>(floor(fft_codes_padded[i].imag() * (pow(2, 9) - 1) / max)));
}
}
acq_parameters.all_fft_codes = d_all_fft_codes_;
// reference for the FPGA FFT-IFFT attenuation factor
acq_parameters.total_block_exp = configuration_->property(role + ".total_block_exp", 14);
acquisition_fpga_ = pcps_make_acquisition_fpga(acq_parameters);
DLOG(INFO) << "acquisition(" << acquisition_fpga_->unique_id() << ")";
channel_ = 0;
doppler_step_ = 0;
gnss_synchro_ = nullptr;
// 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_ = nullptr;
//printf("creating the E5A acquisition end");
}
GalileoE5aPcpsAcquisitionFpga::~GalileoE5aPcpsAcquisitionFpga()
{
//delete[] code_;
delete[] d_all_fft_codes_;
}
void GalileoE5aPcpsAcquisitionFpga::stop_acquisition()
{
// this command causes the SW to reset the HW.
acquisition_fpga_->reset_acquisition();
}
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_ + std::to_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);
}
@ -263,7 +204,6 @@ void GalileoE5aPcpsAcquisitionFpga::set_threshold(float 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_);
}
@ -271,7 +211,6 @@ void GalileoE5aPcpsAcquisitionFpga::set_doppler_max(unsigned int 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_);
}
@ -279,132 +218,65 @@ void GalileoE5aPcpsAcquisitionFpga::set_doppler_step(unsigned int 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";
// }
if (top_block)
{ /* top_block is not null */
};
// Nothing to connect
}
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";
// }
if (top_block)
{ /* top_block is not null */
};
// Nothing to disconnect
}
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

@ -1,11 +1,12 @@
/*!
* \file galileo_e5a_pcps_acquisition.h
* \file galileo_e5a_pcps_acquisition_fpga.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
* Galileo E5a data and pilot Signals for the FPGA
* \author Marc Majoral, 2019. mmajoral(at)cttc.es
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2018 (see AUTHORS file for a list of contributors)
* Copyright (C) 2010-2019 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
@ -28,8 +29,8 @@
* -------------------------------------------------------------------------
*/
#ifndef GALILEO_E5A_PCPS_ACQUISITION_FPGA_H_
#define GALILEO_E5A_PCPS_ACQUISITION_FPGA_H_
#ifndef GNSS_SDR_GALILEO_E5A_PCPS_ACQUISITION_FPGA_H_
#define GNSS_SDR_GALILEO_E5A_PCPS_ACQUISITION_FPGA_H_
#include "acquisition_interface.h"
@ -56,6 +57,9 @@ public:
return role_;
}
/*!
* \brief Returns "Galileo_E5a_Pcps_Acquisition_Fpga"
*/
inline std::string implementation() override
{
return "Galileo_E5a_Pcps_Acquisition_Fpga";
@ -63,7 +67,7 @@ public:
inline size_t item_size() override
{
return item_size_;
return sizeof(int);
}
void connect(gr::top_block_sptr top_block) override;
@ -125,59 +129,43 @@ public:
*/
void set_state(int state) override;
/*!
* \brief This function is only used in the unit tests
*/
void set_single_doppler_flag(unsigned int single_doppler_flag);
/*!
* \brief Stop running acquisition
*/
void stop_acquisition() override;
/*!
* \brief Sets the resampler latency to account it in the acquisition code delay estimation
*/
void set_resampler_latency(uint32_t latency_samples __attribute__((unused))) override{};
private:
//float calculate_threshold(float pfa);
ConfigurationInterface* configuration_;
pcps_acquisition_fpga_sptr acquisition_fpga_;
gr::blocks::stream_to_vector::sptr stream_to_vector_;
size_t item_size_;
std::string item_type_;
std::string dump_filename_;
std::string role_;
bool bit_transition_flag_;
bool dump_;
bool acq_pilot_;
bool use_CFAR_;
bool blocking_;
bool acq_iq_;
unsigned int vector_length_;
unsigned int code_length_;
unsigned int channel_;
unsigned int doppler_max_;
unsigned int doppler_step_;
unsigned int sampled_ms_;
unsigned int max_dwells_;
uint32_t channel_;
uint32_t doppler_max_;
uint32_t doppler_step_;
unsigned int in_streams_;
unsigned int out_streams_;
int64_t 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_ */
#endif /* GNSS_SDR_GALILEO_E5A_PCPS_ACQUISITION_FPGA_H_ */

View File

@ -1,17 +1,15 @@
/*!
* \file gps_l1_ca_pcps_acquisition_fpga.cc
* \brief Adapts a PCPS acquisition block to an FPGA AcquisitionInterface
* for GPS L1 C/A signals
* \brief Adapts a PCPS acquisition block to an AcquisitionInterface
* for GPS L1 C/A signals for the FPGA
* \authors <ul>
* <li> Marc Majoral, 2018. mmajoral(at)cttc.es
* <li> Javier Arribas, 2011. jarribas(at)cttc.es
* <li> Luis Esteve, 2012. luis(at)epsilon-formacion.com
* <li> Marc Molina, 2013. marc.molina.pena(at)gmail.com
* <li> Marc Majoral, 2019. mmajoral(at)cttc.es
* <li> Javier Arribas, 2019. jarribas(at)cttc.es
* </ul>
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
* Copyright (C) 2010-2019 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
@ -59,72 +57,67 @@ GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga(
{
pcpsconf_fpga_t acq_parameters;
configuration_ = configuration;
std::string default_item_type = "gr_complex";
std::string default_item_type = "cshort";
DLOG(INFO) << "role " << role;
int64_t fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 2048000);
int64_t 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);
float downsampling_factor = configuration_->property(role + ".downsampling_factor", 4.0);
acq_parameters.downsampling_factor = downsampling_factor;
fs_in = fs_in / downsampling_factor;
acq_parameters.fs_in = fs_in;
acq_parameters.samples_per_code = static_cast<unsigned int>(ceil(GPS_L1_CA_CHIP_PERIOD * static_cast<float>(acq_parameters.fs_in)));
doppler_max_ = configuration_->property(role + ".doppler_max", 5000);
if (FLAGS_doppler_max != 0) doppler_max_ = FLAGS_doppler_max;
acq_parameters.doppler_max = doppler_max_;
unsigned int sampled_ms = configuration_->property(role + ".coherent_integration_time_ms", 1);
uint32_t sampled_ms = configuration_->property(role + ".coherent_integration_time_ms", 1);
acq_parameters.sampled_ms = sampled_ms;
auto 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)));
auto code_length = static_cast<uint32_t>(std::round(static_cast<double>(fs_in) / (GPS_L1_CA_CODE_RATE_HZ / GPS_L1_CA_CODE_LENGTH_CHIPS)));
acq_parameters.code_length = code_length;
// The FPGA can only use FFT lengths that are a power of two.
float nbits = ceilf(log2f((float)code_length));
unsigned int nsamples_total = pow(2, nbits);
unsigned int vector_length = nsamples_total;
unsigned int select_queue_Fpga = configuration_->property(role + ".select_queue_Fpga", 0);
float nbits = ceilf(log2f((float)code_length * 2));
uint32_t nsamples_total = pow(2, nbits);
uint32_t select_queue_Fpga = configuration_->property(role + ".select_queue_Fpga", 0);
acq_parameters.select_queue_Fpga = select_queue_Fpga;
std::string default_device_name = "/dev/uio0";
std::string device_name = configuration_->property(role + ".devicename", default_device_name);
acq_parameters.device_name = device_name;
acq_parameters.samples_per_ms = nsamples_total / sampled_ms;
acq_parameters.samples_per_code = nsamples_total;
acq_parameters.excludelimit = static_cast<uint32_t>(std::round(static_cast<double>(fs_in) / GPS_L1_CA_CODE_RATE_HZ));
// 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)
auto* fft_if = new gr::fft::fft_complex(vector_length, true); // Direct FFT
auto* fft_if = new gr::fft::fft_complex(nsamples_total, true); // Direct FFT
// allocate memory to compute all the PRNs and compute all the possible codes
auto* code = new std::complex<float>[nsamples_total]; // buffer for the local code
auto* 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++)
for (uint32_t PRN = 1; PRN <= NUM_PRNs; PRN++)
{
gps_l1_ca_code_gen_complex_sampled(code, PRN, fs_in, 0); // generate PRN code
for (uint32_t s = code_length; s < 2 * code_length; s++)
{
code[s] = code[s - code_length];
}
// fill in zero padding
for (int s = code_length; s < nsamples_total; s++)
for (uint32_t s = 2 * code_length; s < nsamples_total; s++)
{
code[s] = std::complex<float>(0.0, 0.0);
//code[s] = 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(), code, sizeof(gr_complex) * nsamples_total); // copy to FFT buffer
fft_if->execute(); // Run the FFT of local code
volk_32fc_conjugate_32fc(fft_codes_padded, fft_if->get_outbuf(), nsamples_total); // conjugate values
// // debug
// char filename[25];
// FILE *fid;
// sprintf(filename,"fft_gps_prn%d.txt", PRN);
// fid = fopen(filename, "w");
// for (unsigned int kk=0;kk< nsamples_total; kk++)
// {
// fprintf(fid, "%f\n", fft_codes_padded[kk].real());
// fprintf(fid, "%f\n", fft_codes_padded[kk].imag());
// }
// fclose(fid);
max = 0; // initialize maximum value
for (unsigned int i = 0; i < nsamples_total; i++) // search for maxima
max = 0; // initialize maximum value
for (uint32_t i = 0; i < nsamples_total; i++) // search for maxima
{
if (std::abs(fft_codes_padded[i].real()) > max)
{
@ -135,39 +128,18 @@ GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga(
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
for (uint32_t 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)));
d_all_fft_codes_[i + nsamples_total * (PRN - 1)] = lv_16sc_t(static_cast<int32_t>(floor(fft_codes_padded[i].real() * (pow(2, 9) - 1) / max)),
static_cast<int32_t>(floor(fft_codes_padded[i].imag() * (pow(2, 9) - 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.all_fft_codes = d_all_fft_codes_;
// temporary buffers that we can delete
delete[] code;
delete fft_if;
delete[] fft_codes_padded;
// reference for the FPGA FFT-IFFT attenuation factor
acq_parameters.total_block_exp = configuration_->property(role + ".total_block_exp", 14);
acquisition_fpga_ = pcps_make_acquisition_fpga(acq_parameters);
DLOG(INFO) << "acquisition(" << acquisition_fpga_->unique_id() << ")";
@ -175,6 +147,11 @@ GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga(
channel_ = 0;
doppler_step_ = 0;
gnss_synchro_ = nullptr;
// temporary buffers that we can delete
delete[] code;
delete fft_if;
delete[] fft_codes_padded;
}
@ -186,6 +163,8 @@ GpsL1CaPcpsAcquisitionFpga::~GpsL1CaPcpsAcquisitionFpga()
void GpsL1CaPcpsAcquisitionFpga::stop_acquisition()
{
// this command causes the SW to reset the HW.
acquisition_fpga_->reset_acquisition();
}
@ -198,8 +177,6 @@ void GpsL1CaPcpsAcquisitionFpga::set_channel(unsigned int channel)
void GpsL1CaPcpsAcquisitionFpga::set_threshold(float threshold)
{
// the .pfa parameter and the threshold calculation is only used for the CFAR algorithm.
// We don't use the CFAR algorithm in the FPGA. Therefore the threshold is set as such.
DLOG(INFO) << "Channel " << channel_ << " Threshold = " << threshold;
acquisition_fpga_->set_threshold(threshold);
}
@ -246,6 +223,7 @@ void GpsL1CaPcpsAcquisitionFpga::set_local_code()
void GpsL1CaPcpsAcquisitionFpga::reset()
{
// this function starts the acquisition process
acquisition_fpga_->set_active(true);
}
@ -255,15 +233,22 @@ void GpsL1CaPcpsAcquisitionFpga::set_state(int state)
acquisition_fpga_->set_state(state);
}
void GpsL1CaPcpsAcquisitionFpga::connect(gr::top_block_sptr top_block)
{
// nothing to connect
if (top_block)
{ /* top_block is not null */
};
// Nothing to connect
}
void GpsL1CaPcpsAcquisitionFpga::disconnect(gr::top_block_sptr top_block)
{
// nothing to disconnect
if (top_block)
{ /* top_block is not null */
};
// Nothing to disconnect
}

View File

@ -1,17 +1,15 @@
/*!
* \file gps_l1_ca_pcps_acquisition_fpga.h
* \brief Adapts a PCPS acquisition block that uses the FPGA to
* an AcquisitionInterface for GPS L1 C/A signals
* \brief Adapts a PCPS acquisition block to an AcquisitionInterface
* for GPS L1 C/A signals for the FPGA
* \authors <ul>
* <li> Marc Majoral, 2018. mmajoral(at)cttc.es
* <li> Javier Arribas, 2011. jarribas(at)cttc.es
* <li> Luis Esteve, 2012. luis(at)epsilon-formacion.com
* <li> Marc Molina, 2013. marc.molina.pena(at)gmail.com
* <li> Marc Majoral, 2019. mmajoral(at)cttc.es
* <li> Javier Arribas, 2019. jarribas(at)cttc.es
* </ul>
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2018 (see AUTHORS file for a list of contributors)
* Copyright (C) 2010-2019 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
@ -65,7 +63,7 @@ public:
}
/*!
* \brief Returns "GPS_L1_CA_PCPS_Acquisition"
* \brief Returns "GPS_L1_CA_PCPS_Acquisition_Fpga"
*/
inline std::string implementation() override
{
@ -145,9 +143,9 @@ public:
private:
ConfigurationInterface* configuration_;
pcps_acquisition_fpga_sptr acquisition_fpga_;
unsigned int channel_;
unsigned int doppler_max_;
unsigned int doppler_step_;
uint32_t channel_;
uint32_t doppler_max_;
uint32_t doppler_step_;
Gnss_Synchro* gnss_synchro_;
std::string role_;
unsigned int in_streams_;

View File

@ -375,6 +375,8 @@ gr::basic_block_sptr GpsL2MPcpsAcquisition::get_right_block()
{
return acquisition_;
}
void GpsL2MPcpsAcquisition::set_resampler_latency(uint32_t latency_samples)
{
acquisition_->set_resampler_latency(latency_samples);

View File

@ -52,7 +52,6 @@ GpsL2MPcpsAcquisitionFpga::GpsL2MPcpsAcquisitionFpga(
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";
@ -61,33 +60,17 @@ GpsL2MPcpsAcquisitionFpga::GpsL2MPcpsAcquisitionFpga(
LOG(INFO) << "role " << role;
item_type_ = configuration_->property(role + ".item_type", default_item_type);
//float pfa = configuration_->property(role + ".pfa", 0.0);
int64_t 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)));
unsigned int 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));
@ -114,10 +97,9 @@ GpsL2MPcpsAcquisitionFpga::GpsL2MPcpsAcquisitionFpga(
{
gps_l2c_m_code_gen_complex_sampled(code, PRN, fs_in_);
// fill in zero padding
for (int s = code_length; s < nsamples_total; s++)
for (unsigned int s = code_length; s < nsamples_total; s++)
{
code[s] = std::complex<float>(0.0, 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
@ -156,53 +138,14 @@ GpsL2MPcpsAcquisitionFpga::GpsL2MPcpsAcquisitionFpga(
doppler_step_ = 0;
gnss_synchro_ = nullptr;
// 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_;
}
@ -221,23 +164,8 @@ void GpsL2MPcpsAcquisitionFpga::set_channel(unsigned int channel)
void GpsL2MPcpsAcquisitionFpga::set_threshold(float threshold)
{
// float pfa = configuration_->property(role_ + std::to_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);
// }
threshold_ = threshold;
DLOG(INFO) << "Channel " << channel_ << " Threshold = " << threshold_;
acquisition_fpga_->set_threshold(threshold_);
}
@ -283,9 +211,6 @@ void GpsL2MPcpsAcquisitionFpga::init()
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();
}
@ -301,99 +226,26 @@ void GpsL2MPcpsAcquisitionFpga::set_state(int 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
if (top_block)
{ /* top_block is not null */
};
// 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
if (top_block)
{ /* top_block is not null */
};
// Nothing to diconnect
}
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;
}

View File

@ -75,7 +75,7 @@ public:
inline size_t item_size() override
{
return item_size_;
return sizeof(int);
}
void connect(gr::top_block_sptr top_block) override;
@ -149,23 +149,13 @@ private:
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_;
int64_t 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_;

View File

@ -1,14 +1,15 @@
/*!
* \file gps_l5i pcps_acquisition.cc
* \file gps_l5i pcps_acquisition_fpga.cc
* \brief Adapts a PCPS acquisition block to an Acquisition Interface for
* GPS L5i signals
* GPS L5i signals for the FPGA
* \authors <ul>
* <li> Javier Arribas, 2017. jarribas(at)cttc.es
* <li> Marc Majoral, 2019. mmajoral(at)cttc.es
* <li> Javier Arribas, 2019. jarribas(at)cttc.es
* </ul>
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2017 (see AUTHORS file for a list of contributors)
* Copyright (C) 2010-2019 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
@ -52,87 +53,71 @@ GpsL5iPcpsAcquisitionFpga::GpsL5iPcpsAcquisitionFpga(
in_streams_(in_streams),
out_streams_(out_streams)
{
//printf("L5 ACQ CLASS CREATED\n");
pcpsconf_fpga_t acq_parameters;
configuration_ = configuration;
std::string default_item_type = "gr_complex";
std::string default_dump_filename = "./acquisition.mat";
std::string default_dump_filename = "./data/acquisition.dat";
LOG(INFO) << "role " << role;
//item_type_ = configuration_->property(role + ".item_type", default_item_type);
int64_t fs_in_deprecated = configuration_->property("GNSS-SDR.internal_fs_hz", 2048000);
int64_t fs_in = configuration_->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated);
float downsampling_factor = configuration_->property(role + ".downsampling_factor", 1.0);
acq_parameters.downsampling_factor = downsampling_factor;
fs_in = fs_in / downsampling_factor;
acq_parameters.fs_in = fs_in;
//if_ = configuration_->property(role + ".if", 0);
//acq_parameters.freq = if_;
//dump_ = configuration_->property(role + ".dump", false);
//acq_parameters.dump = dump_;
//blocking_ = configuration_->property(role + ".blocking", true);
//acq_parameters.blocking = blocking_;
doppler_max_ = configuration->property(role + ".doppler_max", 5000);
if (FLAGS_doppler_max != 0) doppler_max_ = FLAGS_doppler_max;
acq_parameters.doppler_max = doppler_max_;
//acq_parameters.sampled_ms = 1;
unsigned int sampled_ms = configuration_->property(role + ".coherent_integration_time_ms", 1);
uint32_t sampled_ms = configuration_->property(role + ".coherent_integration_time_ms", 1);
acq_parameters.sampled_ms = sampled_ms;
//printf("L5 ACQ CLASS MID 0\n");
//bit_transition_flag_ = configuration_->property(role + ".bit_transition_flag", false);
//acq_parameters.bit_transition_flag = bit_transition_flag_;
//use_CFAR_algorithm_flag_ = configuration_->property(role + ".use_CFAR_algorithm", true); //will be false in future versions
//acq_parameters.use_CFAR_algorithm_flag = use_CFAR_algorithm_flag_;
//max_dwells_ = configuration_->property(role + ".max_dwells", 1);
//acq_parameters.max_dwells = max_dwells_;
//dump_filename_ = configuration_->property(role + ".dump_filename", default_dump_filename);
//acq_parameters.dump_filename = dump_filename_;
//--- Find number of samples per spreading code -------------------------
auto 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))));
auto code_length = static_cast<uint32_t>(std::round(static_cast<double>(fs_in) / (GPS_L5I_CODE_RATE_HZ / static_cast<double>(GPS_L5I_CODE_LENGTH_CHIPS))));
acq_parameters.code_length = code_length;
// The FPGA can only use FFT lengths that are a power of two.
float nbits = ceilf(log2f((float)code_length));
unsigned int nsamples_total = pow(2, nbits);
unsigned int vector_length = nsamples_total;
unsigned int select_queue_Fpga = configuration_->property(role + ".select_queue_Fpga", 1);
float nbits = ceilf(log2f((float)code_length * 2));
uint32_t nsamples_total = pow(2, nbits);
uint32_t select_queue_Fpga = configuration_->property(role + ".select_queue_Fpga", 1);
acq_parameters.select_queue_Fpga = select_queue_Fpga;
std::string default_device_name = "/dev/uio0";
std::string device_name = configuration_->property(role + ".devicename", default_device_name);
acq_parameters.device_name = device_name;
acq_parameters.samples_per_ms = nsamples_total;
acq_parameters.samples_per_ms = nsamples_total / sampled_ms;
acq_parameters.samples_per_code = nsamples_total;
//printf("L5 ACQ CLASS MID 01\n");
acq_parameters.excludelimit = static_cast<uint32_t>(ceil((1.0 / GPS_L5I_CODE_RATE_HZ) * static_cast<float>(acq_parameters.fs_in)));
// 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)
auto* fft_if = new gr::fft::fft_complex(vector_length, true); // Direct FFT
//printf("L5 ACQ CLASS MID 02\n");
auto* code = new gr_complex[vector_length];
//printf("L5 ACQ CLASS MID 03\n");
auto* fft_if = new gr::fft::fft_complex(nsamples_total, true); // Direct FFT
auto* code = new gr_complex[nsamples_total];
auto* fft_codes_padded = static_cast<gr_complex*>(volk_gnsssdr_malloc(nsamples_total * sizeof(gr_complex), volk_gnsssdr_get_alignment()));
//printf("L5 ACQ CLASS MID 04\n");
d_all_fft_codes_ = new lv_16sc_t[nsamples_total * NUM_PRNs]; // memory containing all the possible fft codes for PRN 0 to 32
//printf("L5 ACQ CLASS MID 1 vector_length = %d\n", vector_length);
float max; // temporary maxima search
for (unsigned int PRN = 1; PRN <= NUM_PRNs; PRN++)
for (uint32_t PRN = 1; PRN <= NUM_PRNs; PRN++)
{
//printf("L5 ACQ CLASS processing PRN = %d\n", PRN);
gps_l5i_code_gen_complex_sampled(code, PRN, fs_in);
//printf("L5 ACQ CLASS processing PRN = %d (cont) \n", PRN);
// fill in zero padding
for (int s = code_length; s < nsamples_total; s++)
for (uint32_t s = code_length; s < 2 * code_length; s++)
{
code[s] = code[s - code_length];
}
for (uint32_t s = 2 * code_length; s < nsamples_total; s++)
{
// fill in zero padding
code[s] = std::complex<float>(0.0, 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
max = 0; // initialize maximum value
for (uint32_t i = 0; i < nsamples_total; i++) // search for maxima
{
if (std::abs(fft_codes_padded[i].real()) > max)
{
@ -143,73 +128,30 @@ GpsL5iPcpsAcquisitionFpga::GpsL5iPcpsAcquisitionFpga(
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
for (uint32_t 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)));
d_all_fft_codes_[i + nsamples_total * (PRN - 1)] = lv_16sc_t(static_cast<int32_t>(floor(fft_codes_padded[i].real() * (pow(2, 9) - 1) / max)),
static_cast<int32_t>(floor(fft_codes_padded[i].imag() * (pow(2, 9) - 1) / max)));
}
}
//printf("L5 ACQ CLASS MID 2\n");
//acq_parameters
acq_parameters.all_fft_codes = d_all_fft_codes_;
// reference for the FPGA FFT-IFFT attenuation factor
acq_parameters.total_block_exp = configuration_->property(role + ".total_block_exp", 14);
acquisition_fpga_ = pcps_make_acquisition_fpga(acq_parameters);
DLOG(INFO) << "acquisition(" << acquisition_fpga_->unique_id() << ")";
channel_ = 0;
doppler_step_ = 0;
gnss_synchro_ = nullptr;
// 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_ = nullptr;
//printf("L5 ACQ CLASS FINISHED\n");
}
@ -222,6 +164,8 @@ GpsL5iPcpsAcquisitionFpga::~GpsL5iPcpsAcquisitionFpga()
void GpsL5iPcpsAcquisitionFpga::stop_acquisition()
{
// this command causes the SW to reset the HW.
acquisition_fpga_->reset_acquisition();
}
@ -234,25 +178,6 @@ void GpsL5iPcpsAcquisitionFpga::set_channel(unsigned int channel)
void GpsL5iPcpsAcquisitionFpga::set_threshold(float threshold)
{
// float pfa = configuration_->property(role_ + std::to_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);
}
@ -303,103 +228,33 @@ 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
if (top_block)
{ /* top_block is not null */
};
// 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
if (top_block)
{ /* top_block is not null */
};
// 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;
}

View File

@ -1,14 +1,15 @@
/*!
* \file GPS_L5i_PCPS_Acquisition.h
* \file GPS_L5i_PCPS_Acquisition_fpga.h
* \brief Adapts a PCPS acquisition block to an AcquisitionInterface for
* GPS L5i signals
* GPS L5i signals for the FPGA
* \authors <ul>
* <li> Javier Arribas, 2017. jarribas(at)cttc.es
* <li> Marc Majoral, 2019. mmajoral(at)cttc.es
* <li> Javier Arribas, 2019. jarribas(at)cttc.es
* </ul>
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2017 (see AUTHORS file for a list of contributors)
* Copyright (C) 2010-2019 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
@ -66,16 +67,16 @@ public:
}
/*!
* \brief Returns "GPS_L5i_PCPS_Acquisition"
* \brief Returns "GPS_L5i_PCPS_Acquisition_Fpga"
*/
inline std::string implementation() override
{
return "GPS_L5i_PCPS_Acquisition";
return "GPS_L5i_PCPS_Acquisition_Fpga";
}
inline size_t item_size() override
{
return item_size_;
return sizeof(int);
}
void connect(gr::top_block_sptr top_block) override;
@ -144,28 +145,15 @@ public:
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_;
int64_t fs_in_;
//long if_;
bool dump_;
bool blocking_;
uint32_t channel_;
uint32_t doppler_max_;
uint32_t doppler_step_;
std::string dump_filename_;
std::complex<float>* code_;
Gnss_Synchro* gnss_synchro_;
std::string role_;
unsigned int in_streams_;

View File

@ -187,6 +187,7 @@ pcps_acquisition::pcps_acquisition(const Acq_Conf& conf_) : gr::block("pcps_acqu
}
}
pcps_acquisition::~pcps_acquisition()
{
if (d_num_doppler_bins > 0)
@ -227,6 +228,7 @@ void pcps_acquisition::set_resampler_latency(uint32_t latency_samples)
acq_parameters.resampler_latency_samples = latency_samples;
}
void pcps_acquisition::set_local_code(std::complex<float>* code)
{
// reset the intermediate frequency
@ -912,6 +914,7 @@ void pcps_acquisition::acquisition_core(uint64_t samp_count)
}
}
// Called by gnuradio to enable drivers, etc for i/o devices.
bool pcps_acquisition::start()
{
@ -919,8 +922,10 @@ bool pcps_acquisition::start()
return true;
}
int pcps_acquisition::general_work(int noutput_items __attribute__((unused)),
gr_vector_int& ninput_items, gr_vector_const_void_star& input_items,
gr_vector_int& ninput_items,
gr_vector_const_void_star& input_items,
gr_vector_void_star& output_items __attribute__((unused)))
{
/*

View File

@ -1,21 +1,14 @@
/*!
* \file pcps_acquisition_fpga.cc
* \brief This class implements a Parallel Code Phase Search Acquisition in the FPGA
*
* Note: The CFAR algorithm is not implemented in the FPGA.
* Note 2: The bit transition flag is not implemented in the FPGA
*
* \brief This class implements a Parallel Code Phase Search Acquisition for the FPGA
* \authors <ul>
* <li> Marc Majoral, 2017. mmajoral(at)cttc.cat
* <li> Javier Arribas, 2011. jarribas(at)cttc.es
* <li> Luis Esteve, 2012. luis(at)epsilon-formacion.com
* <li> Marc Molina, 2013. marc.molina.pena@gmail.com
* <li> Cillian O'Driscoll, 2017. cillian(at)ieee.org
* <li> Marc Majoral, 2019. mmajoral(at)cttc.es
* <li> Javier Arribas, 2019. jarribas(at)cttc.es
* </ul>
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2017 (see AUTHORS file for a list of contributors)
* Copyright (C) 2010-2019 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
@ -33,7 +26,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
* along with GNSS-SDR. If not, see <https://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
@ -44,7 +37,6 @@
#include <gnuradio/io_signature.h>
#include <utility>
#define AQ_DOWNSAMPLING_DELAY 40 // delay due to the downsampling filter in the acquisition
using google::LogMessage;
@ -59,14 +51,12 @@ pcps_acquisition_fpga::pcps_acquisition_fpga(pcpsconf_fpga_t conf_) : gr::block(
gr::io_signature::make(0, 0, 0),
gr::io_signature::make(0, 0, 0))
{
// printf("acq constructor start\n");
this->message_port_register_out(pmt::mp("events"));
acq_parameters = std::move(conf_);
d_sample_counter = 0ULL; // SAMPLE COUNTER
d_active = false;
d_state = 0;
//d_fft_size = acq_parameters.sampled_ms * acq_parameters.samples_per_ms;
d_fft_size = acq_parameters.samples_per_code;
d_mag = 0;
d_input_power = 0.0;
@ -77,49 +67,30 @@ pcps_acquisition_fpga::pcps_acquisition_fpga(pcpsconf_fpga_t conf_) : gr::block(
d_channel = 0U;
d_gnss_synchro = nullptr;
//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);
d_downsampling_factor = acq_parameters.downsampling_factor;
d_select_queue_Fpga = acq_parameters.select_queue_Fpga;
// 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);
d_total_block_exp = acq_parameters.total_block_exp;
// this one is the one it should be but it doesn't work
acquisition_fpga = std::make_shared<fpga_acquisition>(acq_parameters.device_name, acq_parameters.code_length, acq_parameters.doppler_max, d_fft_size,
acq_parameters.fs_in, acq_parameters.sampled_ms, acq_parameters.select_queue_Fpga, acq_parameters.all_fft_codes);
// acquisition_fpga = std::make_shared <fpga_acquisition>
// (acq_parameters.device_name, acq_parameters.samples_per_code, acq_parameters.doppler_max, acq_parameters.samples_per_code,
// acq_parameters.fs_in, acq_parameters.freq, acq_parameters.sampled_ms, acq_parameters.select_queue_Fpga, acq_parameters.all_fft_codes);
// debug
//debug_d_max_absolute = 0.0;
//debug_d_input_power_absolute = 0.0;
// printf("acq constructor end\n");
acquisition_fpga = std::make_shared<Fpga_Acquisition>(acq_parameters.device_name, acq_parameters.code_length, acq_parameters.doppler_max, d_fft_size,
acq_parameters.fs_in, acq_parameters.sampled_ms, acq_parameters.select_queue_Fpga, acq_parameters.all_fft_codes, acq_parameters.excludelimit);
}
pcps_acquisition_fpga::~pcps_acquisition_fpga()
{
// printf("acq destructor start\n");
acquisition_fpga->free();
// printf("acq destructor end\n");
}
void pcps_acquisition_fpga::set_local_code()
{
// printf("acq set local code start\n");
acquisition_fpga->set_local_code(d_gnss_synchro->PRN);
// printf("acq set local code end\n");
}
void pcps_acquisition_fpga::init()
{
// printf("acq init start\n");
d_gnss_synchro->Flag_valid_acquisition = false;
d_gnss_synchro->Flag_valid_symbol_output = false;
d_gnss_synchro->Flag_valid_pseudorange = false;
@ -129,23 +100,21 @@ void pcps_acquisition_fpga::init()
d_gnss_synchro->Acq_samplestamp_samples = 0;
d_mag = 0.0;
d_input_power = 0.0;
d_num_doppler_bins = static_cast<uint32_t>(std::ceil(static_cast<double>(static_cast<int32_t>(acq_parameters.doppler_max) - static_cast<int32_t>(-acq_parameters.doppler_max)) / static_cast<double>(d_doppler_step)));
d_num_doppler_bins = static_cast<uint32_t>(std::ceil(static_cast<double>(static_cast<int32_t>(acq_parameters.doppler_max) - static_cast<int32_t>(-acq_parameters.doppler_max)) / static_cast<double>(d_doppler_step))) + 1;
acquisition_fpga->init();
// printf("acq init end\n");
}
void pcps_acquisition_fpga::set_state(int32_t state)
{
// printf("acq set state start\n");
d_state = state;
if (d_state == 1)
{
d_gnss_synchro->Acq_delay_samples = 0.0;
d_gnss_synchro->Acq_doppler_hz = 0.0;
d_gnss_synchro->Acq_samplestamp_samples = 0;
//d_well_count = 0;
d_mag = 0.0;
d_input_power = 0.0;
d_test_statistics = 0.0;
@ -158,14 +127,12 @@ void pcps_acquisition_fpga::set_state(int32_t state)
{
LOG(ERROR) << "State can only be set to 0 or 1";
}
// printf("acq set state end\n");
}
void pcps_acquisition_fpga::send_positive_acquisition()
{
// printf("acq send positive acquisition start\n");
// 6.1- Declare positive acquisition using a message port
// Declare positive acquisition using a message port
//0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL
DLOG(INFO) << "positive acquisition"
<< ", satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN
@ -178,15 +145,12 @@ void pcps_acquisition_fpga::send_positive_acquisition()
<< ", input signal power " << d_input_power;
this->message_port_pub(pmt::mp("events"), pmt::from_long(1));
// printf("acq send positive acquisition end\n");
}
void pcps_acquisition_fpga::send_negative_acquisition()
{
// printf("acq send negative acquisition start\n");
// 6.2- Declare negative acquisition using a message port
//0=STOP_CHANNEL 1=ACQ_SUCCEES 2=ACQ_FAIL
// Declare negative acquisition using a message port
DLOG(INFO) << "negative acquisition"
<< ", satellite " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN
<< ", sample_stamp " << d_sample_counter
@ -198,23 +162,24 @@ void pcps_acquisition_fpga::send_negative_acquisition()
<< ", input signal power " << d_input_power;
this->message_port_pub(pmt::mp("events"), pmt::from_long(2));
// printf("acq send negative acquisition end\n");
}
void pcps_acquisition_fpga::set_active(bool active)
{
// printf("acq set active start\n");
d_active = active;
// initialize acquisition algorithm
uint32_t indext = 0U;
float magt = 0.0;
float fft_normalization_factor = static_cast<float>(d_fft_size) * static_cast<float>(d_fft_size);
float firstpeak = 0.0;
float secondpeak = 0.0;
uint32_t total_block_exp;
d_input_power = 0.0;
d_mag = 0.0;
int32_t doppler;
DLOG(INFO) << "Channel: " << d_channel
<< " , doing acquisition of satellite: " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN
<< " ,sample stamp: " << d_sample_counter << ", threshold: "
@ -224,112 +189,57 @@ void pcps_acquisition_fpga::set_active(bool active)
<< ", use_CFAR_algorithm_flag: false";
uint64_t initial_sample;
float input_power_all = 0.0;
float input_power_computed = 0.0;
float temp_d_input_power;
// loop through acquisition
/*
for (unsigned int doppler_index = 0; doppler_index < d_num_doppler_bins; doppler_index++)
{
// doppler search steps
int32_t doppler = -static_cast<int32_t>(acq_parameters.doppler_max) + d_doppler_step * doppler_index;
//acquisition_fpga->set_phase_step(doppler_index);
acquisition_fpga->set_doppler_sweep_debug(1, doppler_index);
acquisition_fpga->run_acquisition(); // runs acquisition and waits until it is finished
acquisition_fpga->read_acquisition_results(&indext, &magt,
&initial_sample, &d_input_power, &d_doppler_index);
d_sample_counter = initial_sample;
if (d_mag < magt)
{
d_mag = magt;
temp_d_input_power = d_input_power;
input_power_all = d_input_power / (d_fft_size - 1);
input_power_computed = (d_input_power - d_mag) / (d_fft_size - 1);
d_input_power = (d_input_power - d_mag) / (d_fft_size - 1);
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_gnss_synchro->Acq_samplestamp_samples = d_sample_counter;
d_test_statistics = (d_mag / d_input_power); // correction_factor;
}
// In the case of the FPGA the option of dumping the results of the acquisition to a file is not available
// because the IFFT vector is not available
}
*/
// debug
//acquisition_fpga->block_samples();
// run loop in hw
//printf("LAUNCH ACQ\n");
acquisition_fpga->configure_acquisition();
acquisition_fpga->set_doppler_sweep(d_num_doppler_bins);
acquisition_fpga->write_local_code();
acquisition_fpga->set_block_exp(d_total_block_exp);
acquisition_fpga->run_acquisition();
acquisition_fpga->read_acquisition_results(&indext, &magt,
&initial_sample, &d_input_power, &d_doppler_index);
//printf("READ ACQ RESULTS\n");
acquisition_fpga->read_acquisition_results(&indext, &firstpeak, &secondpeak, &initial_sample, &d_input_power, &d_doppler_index, &total_block_exp);
// debug
//acquisition_fpga->unblock_samples();
if (total_block_exp > d_total_block_exp)
{
// if the attenuation factor of the FPGA FFT-IFFT is smaller than the reference attenuation factor then we need to update the reference attenuation factor
std::cout << "changing blk exp..... d_total_block_exp = " << d_total_block_exp << " total_block_exp = " << total_block_exp << " chan = " << d_channel << std::endl;
d_total_block_exp = total_block_exp;
}
d_mag = magt;
doppler = -static_cast<int32_t>(acq_parameters.doppler_max) + d_doppler_step * (d_doppler_index - 1);
if (secondpeak > 0)
{
d_test_statistics = firstpeak / secondpeak;
}
else
{
d_test_statistics = 0.0;
}
// debug
debug_d_max_absolute = magt;
debug_d_input_power_absolute = d_input_power;
debug_indext = indext;
debug_doppler_index = d_doppler_index;
// temp_d_input_power = d_input_power;
d_input_power = (d_input_power - d_mag) / (d_fft_size - 1);
int32_t doppler = -static_cast<int32_t>(acq_parameters.doppler_max) + d_doppler_step * d_doppler_index;
//d_gnss_synchro->Acq_delay_samples = static_cast<double>(2*(indext % (2*acq_parameters.samples_per_code)));
d_gnss_synchro->Acq_delay_samples = static_cast<double>(indext % acq_parameters.samples_per_code);
d_gnss_synchro->Acq_doppler_hz = static_cast<double>(doppler);
d_sample_counter = initial_sample;
//d_gnss_synchro->Acq_samplestamp_samples = 2*d_sample_counter - 81; // delay due to the downsampling filter in the acquisition
//d_gnss_synchro->Acq_samplestamp_samples = d_sample_counter - 40; // delay due to the downsampling filter in the acquisition
d_gnss_synchro->Acq_samplestamp_samples = d_sample_counter; // delay due to the downsampling filter in the acquisition
d_test_statistics = (d_mag / d_input_power); //* correction_factor;
// debug
// if (d_gnss_synchro->Acq_delay_samples > acq_parameters.code_length)
// {
// printf("d_gnss_synchro->Acq_samplestamp_samples = %d\n", d_gnss_synchro->Acq_samplestamp_samples);
// printf("d_gnss_synchro->Acq_delay_samples = %f\n", d_gnss_synchro->Acq_delay_samples);
// }
// if (temp_d_input_power > debug_d_input_power_absolute)
// {
// debug_d_max_absolute = d_mag;
// debug_d_input_power_absolute = temp_d_input_power;
// }
// printf ("max debug_d_max_absolute = %f\n", debug_d_max_absolute);
// printf ("debug_d_input_power_absolute = %f\n", debug_d_input_power_absolute);
// printf("&&&&& d_test_statistics = %f\n", d_test_statistics);
// printf("&&&&& debug_d_max_absolute =%f\n",debug_d_max_absolute);
// printf("&&&&& debug_d_input_power_absolute =%f\n",debug_d_input_power_absolute);
// printf("&&&&& debug_indext = %d\n",debug_indext);
// printf("&&&&& debug_doppler_index = %d\n",debug_doppler_index);
if (d_select_queue_Fpga == 0)
{
if (d_downsampling_factor > 1)
{
d_gnss_synchro->Acq_delay_samples = static_cast<double>(d_downsampling_factor * (indext));
d_gnss_synchro->Acq_samplestamp_samples = d_downsampling_factor * d_sample_counter - 44; //33; //41; //+ 81*0.5; // delay due to the downsampling filter in the acquisition
}
else
{
d_gnss_synchro->Acq_delay_samples = static_cast<double>(indext);
d_gnss_synchro->Acq_samplestamp_samples = d_sample_counter; // delay due to the downsampling filter in the acquisition
}
}
else
{
d_gnss_synchro->Acq_delay_samples = static_cast<double>(indext);
d_gnss_synchro->Acq_samplestamp_samples = d_sample_counter; // delay due to the downsampling filter in the acquisition
}
if (d_test_statistics > d_threshold)
{
d_active = false;
// printf("##### d_test_statistics = %f\n", d_test_statistics);
// printf("##### debug_d_max_absolute =%f\n",debug_d_max_absolute);
// printf("##### debug_d_input_power_absolute =%f\n",debug_d_input_power_absolute);
// printf("##### initial_sample = %llu\n",initial_sample);
// printf("##### debug_doppler_index = %d\n",debug_doppler_index);
send_positive_acquisition();
d_state = 0; // Positive acquisition
}
@ -339,15 +249,27 @@ void pcps_acquisition_fpga::set_active(bool active)
d_active = false;
send_negative_acquisition();
}
// printf("acq set active end\n");
}
int pcps_acquisition_fpga::general_work(int noutput_items __attribute__((unused)),
gr_vector_int& ninput_items, gr_vector_const_void_star& input_items,
gr_vector_int& ninput_items __attribute__((unused)),
gr_vector_const_void_star& input_items __attribute__((unused)),
gr_vector_void_star& output_items __attribute__((unused)))
{
// the general work is not used with the acquisition that uses the FPGA
return noutput_items;
}
void pcps_acquisition_fpga::reset_acquisition(void)
{
// this function triggers a HW reset of the FPGA PL.
acquisition_fpga->reset_acquisition();
}
void pcps_acquisition_fpga::read_fpga_total_scale_factor(uint32_t* total_scale_factor, uint32_t* fw_scale_factor)
{
acquisition_fpga->read_fpga_total_scale_factor(total_scale_factor, fw_scale_factor);
}

View File

@ -1,36 +1,20 @@
/*!
* \file pcps_acquisition_fpga.h
* \brief This class implements a Parallel Code Phase Search Acquisition in the FPGA.
* \brief This class implements a Parallel Code Phase Search Acquisition for the FPGA
*
* Note: The CFAR algorithm is not implemented in the FPGA.
* Note 2: The bit transition flag is not implemented in the FPGA
*
* Acquisition strategy (Kay Borre book + CFAR threshold).
* <ol>
* <li> Compute the input signal power estimation
* <li> Doppler serial search loop
* <li> Perform the FFT-based circular convolution (parallel time search)
* <li> Record the maximum peak and the associated synchronization parameters
* <li> Compute the test statistics and compare to the threshold
* <li> Declare positive or negative acquisition using a message queue
* </ol>
*
* Kay Borre book: 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. pp 81-84
*
* \authors <ul>
* <li> Marc Majoral, 2017. mmajoral(at)cttc.cat
* <li> Javier Arribas, 2011. jarribas(at)cttc.es
* <li> Luis Esteve, 2012. luis(at)epsilon-formacion.com
* <li> Marc Molina, 2013. marc.molina.pena@gmail.com
* <li> Cillian O'Driscoll, 2017. cillian(at)ieee.org
* <li> Antonio Ramos, 2017. antonio.ramos@cttc.es
* <li> Marc Majoral, 2019. mmajoral(at)cttc.es
* <li> Javier Arribas, 2019. jarribas(at)cttc.es
* </ul>
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2018 (see AUTHORS file for a list of contributors)
* Copyright (C) 2010-2019 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
@ -73,12 +57,14 @@ typedef struct
uint32_t select_queue_Fpga;
std::string device_name;
lv_16sc_t* all_fft_codes; // memory that contains all the code ffts
float downsampling_factor;
uint32_t total_block_exp;
uint32_t excludelimit;
} pcpsconf_fpga_t;
class pcps_acquisition_fpga;
typedef boost::shared_ptr<pcps_acquisition_fpga> pcps_acquisition_fpga_sptr;
using pcps_acquisition_fpga_sptr = boost::shared_ptr<pcps_acquisition_fpga>;
pcps_acquisition_fpga_sptr
pcps_make_acquisition_fpga(pcpsconf_fpga_t conf_);
@ -102,6 +88,8 @@ private:
void send_positive_acquisition();
float first_vs_second_peak_statistic(uint32_t& indext, int32_t& doppler, uint32_t num_doppler_bins, int32_t doppler_max, int32_t doppler_step);
pcpsconf_fpga_t acq_parameters;
bool d_active;
float d_threshold;
@ -116,13 +104,12 @@ private:
uint32_t d_num_doppler_bins;
uint64_t d_sample_counter;
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;
int32_t debug_indext;
int32_t debug_doppler_index;
float d_downsampling_factor;
uint32_t d_select_queue_Fpga;
uint32_t d_total_block_exp;
public:
~pcps_acquisition_fpga();
@ -134,9 +121,7 @@ public:
*/
inline void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro)
{
// printf("acq set gnss synchro start\n");
d_gnss_synchro = p_gnss_synchro;
// printf("acq set gnss synchro end\n");
}
/*!
@ -144,9 +129,7 @@ public:
*/
inline uint32_t mag() const
{
// printf("acq dmag start\n");
return d_mag;
// printf("acq dmag end\n");
}
/*!
@ -190,9 +173,7 @@ public:
*/
inline void set_threshold(float threshold)
{
// printf("acq set threshold start\n");
d_threshold = threshold;
// printf("acq set threshold end\n");
}
/*!
@ -201,10 +182,8 @@ public:
*/
inline void set_doppler_max(uint32_t doppler_max)
{
// printf("acq set doppler max start\n");
acq_parameters.doppler_max = doppler_max;
acquisition_fpga->set_doppler_max(doppler_max);
// printf("acq set doppler max end\n");
}
/*!
@ -213,10 +192,8 @@ public:
*/
inline void set_doppler_step(uint32_t doppler_step)
{
// printf("acq set doppler step start\n");
d_doppler_step = doppler_step;
acquisition_fpga->set_doppler_step(doppler_step);
// printf("acq set doppler step end\n");
}
/*!
@ -225,6 +202,16 @@ public:
int general_work(int noutput_items, gr_vector_int& ninput_items,
gr_vector_const_void_star& input_items,
gr_vector_void_star& output_items);
/*!
* \brief This funciton triggers a HW reset of the FPGA PL.
*/
void reset_acquisition(void);
/*!
* \brief This funciton is only used for the unit tests
*/
void read_fpga_total_scale_factor(uint32_t* total_scale_factor, uint32_t* fw_scale_factor);
};
#endif /* GNSS_SDR_PCPS_ACQUISITION_FPGA_H_*/

View File

@ -2,7 +2,7 @@
* \file fpga_acquisition.cc
* \brief High optimized FPGA vector correlator class
* \authors <ul>
* <li> Marc Majoral, 2018. mmajoral(at)cttc.cat
* <li> Marc Majoral, 2019. mmajoral(at)cttc.cat
* </ul>
*
* Class that controls and executes a high optimized acquisition HW
@ -43,6 +43,7 @@
#include <utility>
// FPGA register parameters
#define PAGE_SIZE 0x10000 // default page size for the multicorrelator memory map
#define MAX_PHASE_STEP_RAD 0.999999999534339 // 1 - pow(2,-31);
#define RESET_ACQUISITION 2 // command to reset the multicorrelator
@ -56,57 +57,62 @@
#define SELECT_MSB 0XFF00 // value to select the most significant byte
#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 SELECT_LSBits 0x000003FF // Select the 10 LSbits out of a 20-bit word
#define SELECT_MSBbits 0x000FFC00 // Select the 10 MSbits out of a 20-bit word
#define SELECT_ALL_CODE_BITS 0x000FFFFF // Select a 20 bit word
#define SHL_CODE_BITS 1024 // shift left by 10 bits
// 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
#ifndef TEMP_FAILURE_RETRY
#define TEMP_FAILURE_RETRY(exp) \
({ \
decltype(exp) _rc; \
do \
{ \
_rc = (exp); \
} \
while (_rc == -1 && errno == EINTR); \
_rc; \
})
#endif
bool fpga_acquisition::init()
bool Fpga_Acquisition::init()
{
// configure the acquisition with the main initialization values
fpga_acquisition::configure_acquisition();
return true;
}
bool fpga_acquisition::set_local_code(uint32_t PRN)
bool Fpga_Acquisition::set_local_code(uint32_t PRN)
{
// select the code with the chosen PRN
fpga_acquisition::fpga_configure_acquisition_local_code(
&d_all_fft_codes[d_nsamples_total * (PRN - 1)]);
//fpga_acquisition::fpga_configure_acquisition_local_code(
// &d_all_fft_codes[0]);
d_PRN = PRN;
return true;
}
fpga_acquisition::fpga_acquisition(std::string device_name,
void Fpga_Acquisition::write_local_code()
{
Fpga_Acquisition::fpga_configure_acquisition_local_code(
&d_all_fft_codes[d_nsamples_total * (d_PRN - 1)]);
}
Fpga_Acquisition::Fpga_Acquisition(std::string device_name,
uint32_t nsamples,
uint32_t doppler_max,
uint32_t nsamples_total, int64_t fs_in,
uint32_t sampled_ms, uint32_t select_queue,
lv_16sc_t *all_fft_codes)
uint32_t nsamples_total,
int64_t fs_in,
uint32_t sampled_ms __attribute__((unused)),
uint32_t select_queue,
lv_16sc_t *all_fft_codes,
uint32_t excludelimit)
{
//printf("AAA- sampled_ms = %d\n ", sampled_ms);
uint32_t vector_length = nsamples_total;
uint32_t vector_length = nsamples_total; // * sampled_ms;
//printf("AAA- vector_length = %d\n ", vector_length);
// initial values
d_device_name = std::move(device_name);
//d_freq = freq;
d_fs_in = fs_in;
d_vector_length = vector_length;
d_excludelimit = excludelimit;
d_nsamples = nsamples; // number of samples not including padding
d_select_queue = select_queue;
d_nsamples_total = nsamples_total;
@ -116,6 +122,18 @@ fpga_acquisition::fpga_acquisition(std::string device_name,
d_map_base = nullptr; // driver memory map
d_all_fft_codes = all_fft_codes;
Fpga_Acquisition::reset_acquisition();
Fpga_Acquisition::open_device();
Fpga_Acquisition::fpga_acquisition_test_register();
Fpga_Acquisition::close_device();
d_PRN = 0;
DLOG(INFO) << "Acquisition FPGA class created";
}
void Fpga_Acquisition::open_device()
{
// open communication with HW accelerator
if ((d_fd = open(d_device_name.c_str(), O_RDWR | O_SYNC)) == -1)
{
@ -130,11 +148,29 @@ fpga_acquisition::fpga_acquisition(std::string device_name,
LOG(WARNING) << "Cannot map the FPGA acquisition module into user memory";
std::cout << "Acq: cannot map deviceio" << d_device_name << std::endl;
}
}
Fpga_Acquisition::~Fpga_Acquisition() = default;
bool Fpga_Acquisition::free()
{
return true;
}
void Fpga_Acquisition::fpga_acquisition_test_register()
{
// sanity check : check test register
uint32_t writeval = TEST_REG_SANITY_CHECK;
uint32_t readval;
readval = fpga_acquisition::fpga_acquisition_test_register(writeval);
// write value to test register
d_map_base[15] = writeval;
// read value from test register
readval = d_map_base[15];
if (writeval != readval)
{
LOG(WARNING) << "Acquisition test register sanity check failed";
@ -142,208 +178,123 @@ fpga_acquisition::fpga_acquisition(std::string device_name,
else
{
LOG(INFO) << "Acquisition test register sanity check success!";
//std::cout << "Acquisition test register sanity check success!" << std::endl;
}
fpga_acquisition::reset_acquisition();
DLOG(INFO) << "Acquisition FPGA class created";
}
fpga_acquisition::~fpga_acquisition()
{
close_device();
}
bool fpga_acquisition::free()
{
return true;
}
uint32_t fpga_acquisition::fpga_acquisition_test_register(uint32_t writeval)
{
uint32_t readval;
// write value to test register
d_map_base[15] = writeval;
// read value from test register
readval = d_map_base[15];
// return read value
return readval;
}
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[])
{
uint32_t local_code;
uint32_t k, tmp, tmp2;
uint32_t fft_data;
// clear memory address counter
//d_map_base[6] = LOCAL_CODE_CLEAR_MEM;
d_map_base[9] = LOCAL_CODE_CLEAR_MEM;
// write local code
for (k = 0; k < d_vector_length; k++)
{
tmp = fft_local_code[k].real();
tmp2 = fft_local_code[k].imag();
//tmp = k;
//tmp2 = k;
//local_code = (tmp & SELECT_LSB) | ((tmp2 * SHL_8_BITS) & SELECT_MSB); // put together the real part and the imaginary part
//fft_data = MEM_LOCAL_CODE_WR_ENABLE | (local_code & SELECT_16_BITS);
//local_code = (tmp & SELECT_LSBits) | ((tmp2 * SHL_12_BITS) & SELECT_MSBbits); // put together the real part and the imaginary part
local_code = (tmp & SELECT_LSBits) | ((tmp2 * SHL_16_BITS) & SELECT_MSBbits); // put together the real part and the imaginary part
//fft_data = MEM_LOCAL_CODE_WR_ENABLE | (local_code & SELECT_24_BITS);
fft_data = local_code & SELECT_32_BITS;
local_code = (tmp & SELECT_LSBits) | ((tmp2 * SHL_CODE_BITS) & SELECT_MSBbits); // put together the real part and the imaginary part
fft_data = local_code & SELECT_ALL_CODE_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
int32_t reenable = 1;
write(d_fd, reinterpret_cast<void *>(&reenable), sizeof(int32_t));
// launch the acquisition process
//printf("launchin acquisition ...\n");
d_map_base[8] = LAUNCH_ACQUISITION; // writing a 1 to reg 8 launches the acquisition process
int32_t disable_int = 0;
ssize_t nbytes = TEMP_FAILURE_RETRY(write(d_fd, reinterpret_cast<void *>(&reenable), sizeof(int32_t)));
if (nbytes != sizeof(int32_t))
{
std::cerr << "Error enabling run in the FPGA." << std::endl;
}
// launch the acquisition process
d_map_base[8] = LAUNCH_ACQUISITION; // writing a 1 to reg 8 launches the acquisition process
int32_t irq_count;
ssize_t nb;
// wait for interrupt
nb = read(d_fd, &irq_count, sizeof(irq_count));
//printf("interrupt received\n");
if (nb != sizeof(irq_count))
{
printf("acquisition module Read failed to retrieve 4 bytes!\n");
printf("acquisition module Interrupt number %d\n", irq_count);
std::cout << "acquisition module Read failed to retrieve 4 bytes!" << std::endl;
std::cout << "acquisition module Interrupt number " << irq_count << std::endl;
}
nbytes = TEMP_FAILURE_RETRY(write(d_fd, reinterpret_cast<void *>(&disable_int), sizeof(int32_t)));
if (nbytes != sizeof(int32_t))
{
std::cerr << "Error disabling interruptions in the FPGA." << std::endl;
}
}
void fpga_acquisition::set_doppler_sweep(uint32_t num_sweeps)
void Fpga_Acquisition::set_block_exp(uint32_t total_block_exp)
{
d_map_base[11] = total_block_exp;
}
void Fpga_Acquisition::set_doppler_sweep(uint32_t num_sweeps)
{
float phase_step_rad_real;
float phase_step_rad_int_temp;
int32_t phase_step_rad_int;
//int32_t doppler = static_cast<int32_t>(-d_doppler_max) + d_doppler_step * doppler_index;
auto doppler = static_cast<int32_t>(-d_doppler_max);
//float phase_step_rad = GPS_TWO_PI * (d_freq + doppler) / static_cast<float>(d_fs_in);
float phase_step_rad = GPS_TWO_PI * (doppler) / static_cast<float>(d_fs_in);
// The doppler step can never be outside the range -pi to +pi, otherwise there would be aliasing
// The FPGA expects phase_step_rad between -1 (-pi) to +1 (+pi)
// The FPGA also expects the phase to be negative since it produces cos(x) -j*sin(x)
// while the gnss-sdr software (volk_gnsssdr_s32f_sincos_32fc) generates cos(x) + j*sin(x)
phase_step_rad_real = phase_step_rad / (GPS_TWO_PI / 2);
// avoid saturation of the fixed point representation in the fpga
// (only the positive value can saturate due to the 2's complement representation)
//printf("AAA phase_step_rad_real for initial doppler = %f\n", phase_step_rad_real);
if (phase_step_rad_real >= 1.0)
{
phase_step_rad_real = MAX_PHASE_STEP_RAD;
}
//printf("AAA phase_step_rad_real for initial doppler after checking = %f\n", phase_step_rad_real);
phase_step_rad_int_temp = phase_step_rad_real * POW_2_2; // * 2^2
phase_step_rad_int = static_cast<int32_t>(phase_step_rad_int_temp * (POW_2_29)); // * 2^29 (in total it makes x2^31 in two steps to avoid the warnings
//printf("AAA writing phase_step_rad_int for initial doppler = %d to d map base 3\n", phase_step_rad_int);
d_map_base[3] = phase_step_rad_int;
// repeat the calculation with the doppler step
doppler = static_cast<int32_t>(d_doppler_step);
phase_step_rad = GPS_TWO_PI * (doppler) / static_cast<float>(d_fs_in);
phase_step_rad_real = phase_step_rad / (GPS_TWO_PI / 2);
//printf("AAA phase_step_rad_real for doppler step = %f\n", phase_step_rad_real);
if (phase_step_rad_real >= 1.0)
{
phase_step_rad_real = MAX_PHASE_STEP_RAD;
}
//printf("AAA phase_step_rad_real for doppler step after checking = %f\n", phase_step_rad_real);
phase_step_rad_int_temp = phase_step_rad_real * POW_2_2; // * 2^2
phase_step_rad_int = static_cast<int32_t>(phase_step_rad_int_temp * (POW_2_29)); // * 2^29 (in total it makes x2^31 in two steps to avoid the warnings
//printf("AAA writing phase_step_rad_int for doppler step = %d to d map base 4\n", phase_step_rad_int);
d_map_base[4] = phase_step_rad_int;
//printf("AAA writing num sweeps to d map base 5 = %d\n", num_sweeps);
d_map_base[5] = num_sweeps;
}
void fpga_acquisition::set_doppler_sweep_debug(uint32_t num_sweeps, uint32_t doppler_index)
{
float phase_step_rad_real;
float phase_step_rad_int_temp;
int32_t phase_step_rad_int;
int32_t doppler = -static_cast<int32_t>(d_doppler_max) + d_doppler_step * doppler_index;
//int32_t doppler = static_cast<int32_t>(-d_doppler_max);
//float phase_step_rad = GPS_TWO_PI * (d_freq + doppler) / static_cast<float>(d_fs_in);
float phase_step_rad = GPS_TWO_PI * (doppler) / static_cast<float>(d_fs_in);
// The doppler step can never be outside the range -pi to +pi, otherwise there would be aliasing
// The FPGA expects phase_step_rad between -1 (-pi) to +1 (+pi)
// The FPGA also expects the phase to be negative since it produces cos(x) -j*sin(x)
// while the gnss-sdr software (volk_gnsssdr_s32f_sincos_32fc) generates cos(x) + j*sin(x)
phase_step_rad_real = phase_step_rad / (GPS_TWO_PI / 2);
// avoid saturation of the fixed point representation in the fpga
// (only the positive value can saturate due to the 2's complement representation)
//printf("AAAh phase_step_rad_real for initial doppler = %f\n", phase_step_rad_real);
if (phase_step_rad_real >= 1.0)
{
phase_step_rad_real = MAX_PHASE_STEP_RAD;
}
//printf("AAAh phase_step_rad_real for initial doppler after checking = %f\n", phase_step_rad_real);
phase_step_rad_int_temp = phase_step_rad_real * POW_2_2; // * 2^2
phase_step_rad_int = static_cast<int32_t>(phase_step_rad_int_temp * (POW_2_29)); // * 2^29 (in total it makes x2^31 in two steps to avoid the warnings
//printf("AAAh writing phase_step_rad_int for initial doppler = %d to d map base 3\n", phase_step_rad_int);
d_map_base[3] = phase_step_rad_int;
// repeat the calculation with the doppler step
doppler = static_cast<int32_t>(d_doppler_step);
phase_step_rad = GPS_TWO_PI * (doppler) / static_cast<float>(d_fs_in);
phase_step_rad_real = phase_step_rad / (GPS_TWO_PI / 2);
//printf("AAAh phase_step_rad_real for doppler step = %f\n", phase_step_rad_real);
if (phase_step_rad_real >= 1.0)
{
phase_step_rad_real = MAX_PHASE_STEP_RAD;
}
//printf("AAAh phase_step_rad_real for doppler step after checking = %f\n", phase_step_rad_real);
phase_step_rad_int_temp = phase_step_rad_real * POW_2_2; // * 2^2
phase_step_rad_int = static_cast<int32_t>(phase_step_rad_int_temp * (POW_2_29)); // * 2^29 (in total it makes x2^31 in two steps to avoid the warnings
//printf("AAAh writing phase_step_rad_int for doppler step = %d to d map base 4\n", phase_step_rad_int);
d_map_base[4] = phase_step_rad_int;
//printf("AAAh writing num sweeps to d map base 5 = %d\n", num_sweeps);
d_map_base[5] = num_sweeps;
}
void fpga_acquisition::configure_acquisition()
void Fpga_Acquisition::configure_acquisition()
{
//printf("AAA d_select_queue = %d\n", d_select_queue);
Fpga_Acquisition::open_device();
d_map_base[0] = d_select_queue;
//printf("AAA writing d_vector_length = %d to d map base 1\n ", d_vector_length);
d_map_base[1] = d_vector_length;
//printf("AAA writing d_nsamples = %d to d map base 2\n ", d_nsamples);
d_map_base[2] = d_nsamples;
//printf("AAA writing LOG2 d_vector_length = %d to d map base 7\n ", (int)log2((float)d_vector_length));
d_map_base[7] = static_cast<int32_t>(log2(static_cast<float>(d_vector_length))); // log2 FFTlength
//printf("acquisition debug vector length = %d\n", d_vector_length);
//printf("acquisition debug vector length = %d\n", (int)log2((float)d_vector_length));
d_map_base[12] = d_excludelimit;
}
void fpga_acquisition::set_phase_step(uint32_t doppler_index)
void Fpga_Acquisition::set_phase_step(uint32_t doppler_index)
{
float phase_step_rad_real;
float phase_step_rad_int_temp;
int32_t phase_step_rad_int;
int32_t doppler = -static_cast<int32_t>(d_doppler_max) + d_doppler_step * doppler_index;
//float phase_step_rad = GPS_TWO_PI * (d_freq + doppler) / static_cast<float>(d_fs_in);
float phase_step_rad = GPS_TWO_PI * (doppler) / static_cast<float>(d_fs_in);
// The doppler step can never be outside the range -pi to +pi, otherwise there would be aliasing
// The FPGA expects phase_step_rad between -1 (-pi) to +1 (+pi)
@ -352,73 +303,101 @@ void fpga_acquisition::set_phase_step(uint32_t doppler_index)
phase_step_rad_real = phase_step_rad / (GPS_TWO_PI / 2);
// avoid saturation of the fixed point representation in the fpga
// (only the positive value can saturate due to the 2's complement representation)
//printf("AAA+ phase_step_rad_real = %f\n", phase_step_rad_real);
if (phase_step_rad_real >= 1.0)
{
phase_step_rad_real = MAX_PHASE_STEP_RAD;
}
//printf("AAA+ phase_step_rad_real after checking = %f\n", phase_step_rad_real);
phase_step_rad_int_temp = phase_step_rad_real * POW_2_2; // * 2^2
phase_step_rad_int = static_cast<int32_t>(phase_step_rad_int_temp * (POW_2_29)); // * 2^29 (in total it makes x2^31 in two steps to avoid the warnings
//printf("writing phase_step_rad_int = %d to d_map_base 3\n", phase_step_rad_int);
d_map_base[3] = phase_step_rad_int;
}
void fpga_acquisition::read_acquisition_results(uint32_t *max_index,
float *max_magnitude, uint64_t *initial_sample, float *power_sum, uint32_t *doppler_index)
void Fpga_Acquisition::read_acquisition_results(uint32_t *max_index,
float *firstpeak, float *secondpeak, uint64_t *initial_sample, float *power_sum, uint32_t *doppler_index, uint32_t *total_blk_exp)
{
uint64_t initial_sample_tmp = 0;
uint32_t readval = 0;
uint64_t readval_long = 0;
uint64_t readval_long_shifted = 0;
readval = d_map_base[1];
initial_sample_tmp = readval;
readval_long = d_map_base[2];
readval_long_shifted = readval_long << 32; // 2^32
readval_long_shifted = readval_long << 32; // 2^32
initial_sample_tmp = initial_sample_tmp + readval_long_shifted; // 2^32
//printf("----------------------------------------------------------------> acq initial sample TOTAL = %llu\n", initial_sample_tmp);
*initial_sample = initial_sample_tmp;
readval = d_map_base[6];
*max_magnitude = static_cast<float>(readval);
//printf("read max_magnitude dmap 2 = %d\n", readval);
readval = d_map_base[4];
*power_sum = static_cast<float>(readval);
//printf("read power sum dmap 4 = %d\n", readval);
readval = d_map_base[5]; // read doppler index
*doppler_index = readval;
//printf("read doppler_index dmap 5 = %d\n", readval);
readval = d_map_base[3];
*firstpeak = static_cast<float>(readval);
readval = d_map_base[4];
*secondpeak = static_cast<float>(readval);
readval = d_map_base[5];
*max_index = readval;
//printf("read max index dmap 3 = %d\n", readval);
*power_sum = 0;
readval = d_map_base[8];
*total_blk_exp = readval;
readval = d_map_base[7]; // read doppler index -- this read releases the interrupt line
*doppler_index = readval;
readval = d_map_base[15]; // read dummy
Fpga_Acquisition::close_device();
}
void fpga_acquisition::block_samples()
void Fpga_Acquisition::block_samples()
{
d_map_base[14] = 1; // block the samples
}
void fpga_acquisition::unblock_samples()
void Fpga_Acquisition::unblock_samples()
{
d_map_base[14] = 0; // unblock the samples
}
void fpga_acquisition::close_device()
void Fpga_Acquisition::close_device()
{
auto *aux = const_cast<uint32_t *>(d_map_base);
if (munmap(static_cast<void *>(aux), PAGE_SIZE) == -1)
{
printf("Failed to unmap memory uio\n");
std::cout << "Failed to unmap memory uio" << std::endl;
}
close(d_fd);
}
void fpga_acquisition::reset_acquisition(void)
void Fpga_Acquisition::reset_acquisition(void)
{
Fpga_Acquisition::open_device();
d_map_base[8] = RESET_ACQUISITION; // writing a 2 to d_map_base[8] resets the multicorrelator
Fpga_Acquisition::close_device();
}
// this function is only used for the unit tests
void Fpga_Acquisition::read_fpga_total_scale_factor(uint32_t *total_scale_factor, uint32_t *fw_scale_factor)
{
uint32_t readval = 0;
readval = d_map_base[8];
*total_scale_factor = readval;
//readval = d_map_base[8];
*fw_scale_factor = 0;
}
void Fpga_Acquisition::read_result_valid(uint32_t *result_valid)
{
uint32_t readval = 0;
readval = d_map_base[0];
*result_valid = readval;
}

View File

@ -2,7 +2,7 @@
* \file fpga_acquisition.h
* \brief High optimized FPGA vector correlator class
* \authors <ul>
* <li> Marc Majoral, 2018. mmajoral(at)cttc.cat
* <li> Marc Majoral, 2019. mmajoral(at)cttc.cat
* </ul>
*
* Class that controls and executes a high optimized acquisition HW
@ -10,7 +10,7 @@
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2018 (see AUTHORS file for a list of contributors)
* Copyright (C) 2010-2019 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
@ -43,28 +43,28 @@
/*!
* \brief Class that implements carrier wipe-off and correlators.
*/
class fpga_acquisition
class Fpga_Acquisition
{
public:
fpga_acquisition(std::string device_name,
Fpga_Acquisition(std::string device_name,
uint32_t nsamples,
uint32_t doppler_max,
uint32_t nsamples_total,
int64_t fs_in,
uint32_t sampled_ms,
uint32_t select_queue,
lv_16sc_t *all_fft_codes);
lv_16sc_t *all_fft_codes,
uint32_t excludelimit);
~fpga_acquisition();
~Fpga_Acquisition();
bool init();
bool set_local_code(uint32_t PRN);
bool free();
void set_doppler_sweep(uint32_t num_sweeps);
void set_doppler_sweep_debug(uint32_t num_sweeps, uint32_t doppler_index);
void run_acquisition(void);
void set_phase_step(uint32_t doppler_index);
void read_acquisition_results(uint32_t *max_index, float *max_magnitude,
uint64_t *initial_sample, float *power_sum, uint32_t *doppler_index);
void read_acquisition_results(uint32_t *max_index, float *firstpeak, float *secondpeak, uint64_t *initial_sample, float *power_sum, uint32_t *doppler_index, uint32_t *total_blk_exp);
void block_samples();
void unblock_samples();
@ -86,6 +86,25 @@ public:
d_doppler_step = doppler_step;
}
/*!
* \brief Reset the FPGA PL.
*/
void reset_acquisition(void);
/*!
* \brief read the scaling factor that has been used by the FFT-IFFT
*/
void read_fpga_total_scale_factor(uint32_t *total_scale_factor, uint32_t *fw_scale_factor);
void set_block_exp(uint32_t total_block_exp);
void write_local_code(void);
void configure_acquisition(void);
void close_device();
void open_device();
private:
int64_t d_fs_in;
// data related to the hardware module and the driver
@ -93,18 +112,18 @@ private:
volatile uint32_t *d_map_base; // driver memory map
lv_16sc_t *d_all_fft_codes; // memory that contains all the code ffts
uint32_t d_vector_length; // number of samples incluing padding and number of ms
uint32_t d_nsamples_total; // number of samples including padding
uint32_t d_nsamples; // number of samples not including padding
uint32_t d_select_queue; // queue selection
std::string d_device_name; // HW device name
uint32_t d_doppler_max; // max doppler
uint32_t d_doppler_step; // doppler step
uint32_t d_excludelimit;
uint32_t d_nsamples_total; // number of samples including padding
uint32_t d_nsamples; // number of samples not including padding
uint32_t d_select_queue; // queue selection
std::string d_device_name; // HW device name
uint32_t d_doppler_max; // max doppler
uint32_t d_doppler_step; // doppler step
uint32_t d_PRN; // PRN
// FPGA private functions
uint32_t fpga_acquisition_test_register(uint32_t writeval);
void fpga_acquisition_test_register(void);
void fpga_configure_acquisition_local_code(lv_16sc_t fft_local_code[]);
void configure_acquisition();
void reset_acquisition(void);
void close_device();
void read_result_valid(uint32_t *result_valid);
};
#endif /* GNSS_SDR_FPGA_ACQUISITION_H_ */

View File

@ -1,9 +1,9 @@
/*!
* \file gnss_sdr_fpga_sample_counter.cc
* \brief Simple block to report the current receiver time based on the output of the tracking or telemetry blocks
* \brief Simple block to report the current receiver time based on the output
* of the tracking or telemetry blocks
* \author Javier Arribas 2018. jarribas(at)cttc.es
*
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2018 (see AUTHORS file for a list of contributors)
@ -40,8 +40,23 @@
#include <string>
#include <sys/mman.h> // libraries used by the GIPO
using google::LogMessage;
#define PAGE_SIZE 0x10000 // default page size for the multicorrelator memory map
#define TEST_REG_SANITY_CHECK 0x55AA // value to check the presence of the test register (to detect the hw)
#ifndef TEMP_FAILURE_RETRY
#define TEMP_FAILURE_RETRY(exp) \
({ \
decltype(exp) _rc; \
do \
{ \
_rc = (exp); \
} \
while (_rc == -1 && errno == EINTR); \
_rc; \
})
#endif
gnss_sdr_fpga_sample_counter::gnss_sdr_fpga_sample_counter(
double _fs,
@ -53,16 +68,13 @@ gnss_sdr_fpga_sample_counter::gnss_sdr_fpga_sample_counter(
set_max_noutput_items(1);
interval_ms = _interval_ms;
fs = _fs;
//printf("CREATOR fs = %f\n", fs);
//printf("CREATOR interval_ms = %" PRIu32 "\n", interval_ms);
samples_per_output = std::round(fs * static_cast<double>(interval_ms) / 1e3);
//printf("CREATOR samples_per_output = %" PRIu32 "\n", samples_per_output);
//todo: Load here the hardware counter register with this amount of samples. It should produce an
//interrupt every samples_per_output count.
//The hardware timer must keep always interrupting the PS. It must not wait for the interrupt to
//be served.
open_device();
is_open = true;
sample_counter = 0ULL;
current_T_rx_ms = 0;
current_s = 0;
@ -84,6 +96,15 @@ gnss_sdr_fpga_sample_counter_sptr gnss_sdr_make_fpga_sample_counter(double _fs,
}
gnss_sdr_fpga_sample_counter::~gnss_sdr_fpga_sample_counter()
{
if (is_open)
{
close_device();
}
}
// Called by gnuradio to enable drivers, etc for i/o devices.
bool gnss_sdr_fpga_sample_counter::start()
{
@ -103,11 +124,107 @@ bool gnss_sdr_fpga_sample_counter::stop()
//todo: place here the routines to stop the associated hardware (if needed).This function will be called by GNURadio at every stop of the flowgraph.
// return true if everything is ok.
close_device();
is_open = false;
return true;
}
uint32_t gnss_sdr_fpga_sample_counter::test_register(uint32_t writeval)
{
uint32_t readval;
// write value to test register
map_base[3] = writeval;
// read value from test register
readval = map_base[3];
// return read value
return readval;
}
void gnss_sdr_fpga_sample_counter::configure_samples_per_output(uint32_t interval)
{
// note : the counter is a 48-bit value in the HW.
map_base[0] = interval - 1;
}
void gnss_sdr_fpga_sample_counter::open_device()
{
// open communication with HW accelerator
if ((fd = open(device_name.c_str(), O_RDWR | O_SYNC)) == -1)
{
LOG(WARNING) << "Cannot open deviceio" << device_name;
std::cout << "Counter-Intr: cannot open deviceio" << device_name << std::endl;
}
map_base = reinterpret_cast<volatile uint32_t *>(mmap(nullptr, PAGE_SIZE,
PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
if (map_base == reinterpret_cast<void *>(-1))
{
LOG(WARNING) << "Cannot map the FPGA acquisition module into user memory";
std::cout << "Counter-Intr: cannot map deviceio" << device_name << std::endl;
}
// sanity check : check test register
uint32_t writeval = TEST_REG_SANITY_CHECK;
uint32_t readval;
readval = gnss_sdr_fpga_sample_counter::test_register(writeval);
if (writeval != readval)
{
LOG(WARNING) << "Acquisition test register sanity check failed";
}
else
{
LOG(INFO) << "Acquisition test register sanity check success!";
//std::cout << "Acquisition test register sanity check success!" << std::endl;
}
}
void gnss_sdr_fpga_sample_counter::close_device()
{
map_base[2] = 0; // disable the generation of the interrupt in the device
auto *aux = const_cast<uint32_t *>(map_base);
if (munmap(static_cast<void *>(aux), PAGE_SIZE) == -1)
{
std::cout << "Failed to unmap memory uio" << std::endl;
}
close(fd);
}
uint32_t gnss_sdr_fpga_sample_counter::wait_for_interrupt_and_read_counter()
{
int32_t irq_count;
ssize_t nb;
int32_t counter;
// enable interrupts
int32_t reenable = 1;
ssize_t nbytes = TEMP_FAILURE_RETRY(write(fd, reinterpret_cast<void *>(&reenable), sizeof(int32_t)));
if (nbytes != sizeof(int32_t))
{
std::cerr << "Error enabling interruptions in the FPGA." << std::endl;
}
// wait for interrupt
nb = read(fd, &irq_count, sizeof(irq_count));
if (nb != sizeof(irq_count))
{
std::cout << "FPGA sample counter module read failed to retrieve 4 bytes!" << std::endl;
std::cout << "FPGA sample counter module interrupt number " << irq_count << std::endl;
}
// it is a rising edge interrupt, the interrupt does not need to be acknowledged
//map_base[1] = 0; // writing anything to reg 1 acknowledges the interrupt
// add number of passed samples or read the current counter value for more accuracy
counter = samples_per_output; //map_base[0];
return counter;
}
int gnss_sdr_fpga_sample_counter::general_work(int noutput_items __attribute__((unused)),
__attribute__((unused)) gr_vector_int &ninput_items,
__attribute__((unused)) gr_vector_const_void_star &input_items,
@ -122,7 +239,6 @@ int gnss_sdr_fpga_sample_counter::general_work(int noutput_items __attribute__((
uint32_t counter = wait_for_interrupt_and_read_counter();
uint64_t samples_passed = 2 * static_cast<uint64_t>(samples_per_output) - static_cast<uint64_t>(counter); // ellapsed samples
//printf("============================================ interrupter : samples_passed = %" PRIu64 "\n", samples_passed);
// Note: at this moment the sample counter is implemented as a sample counter that decreases to zero and then it is automatically
// reloaded again and keeps counter. It is done in this way to minimize the logic in the FPGA and maximize the FPGA clock performance
// (it takes less resources and latency in the FPGA to compare a number against a fixed value like zero than to compare it to a programmable
@ -137,10 +253,6 @@ int gnss_sdr_fpga_sample_counter::general_work(int noutput_items __attribute__((
out[0].fs = fs;
if ((current_T_rx_ms % report_interval_ms) == 0)
{
//printf("time to print sample_counter = %" PRIu64 "\n", sample_counter);
//printf("time to print current Tx ms : %" PRIu64 "\n", current_T_rx_ms);
//printf("time to print report_interval_ms : %" PRIu32 "\n", report_interval_ms);
//printf("time to print %f\n", (current_T_rx_ms % report_interval_ms));
current_s++;
if ((current_s % 60) == 0)
{
@ -202,102 +314,3 @@ int gnss_sdr_fpga_sample_counter::general_work(int noutput_items __attribute__((
current_T_rx_ms = interval_ms * (sample_counter) / samples_per_output;
return 1;
}
uint32_t gnss_sdr_fpga_sample_counter::test_register(uint32_t writeval)
{
uint32_t readval;
// write value to test register
map_base[3] = writeval;
// read value from test register
readval = map_base[3];
// return read value
return readval;
}
void gnss_sdr_fpga_sample_counter::configure_samples_per_output(uint32_t interval)
{
// note : the counter is a 48-bit value in the HW.
//printf("============================================ total counter - interrupted interval : %" PRIu32 "\n", interval);
//uint64_t temp_interval;
//temp_interval = (interval & static_cast<uint32_t>(0xFFFFFFFF));
//printf("LSW counter - interrupted interval : %" PRIu32 "\n", static_cast<uint32_t>(temp_interval));
//map_base[0] = static_cast<uint32_t>(temp_interval);
map_base[0] = interval - 1;
//temp_interval = (interval >> 32) & static_cast<uint32_t>(0xFFFFFFFF);
//printf("MSbits counter - interrupted interval : %" PRIu32 "\n", static_cast<uint32_t>(temp_interval));
//map_base[1] = static_cast<uint32_t>(temp_interval); // writing the most significant bits also enables the interrupts
}
void gnss_sdr_fpga_sample_counter::open_device()
{
// open communication with HW accelerator
if ((fd = open(device_name.c_str(), O_RDWR | O_SYNC)) == -1)
{
LOG(WARNING) << "Cannot open deviceio" << device_name;
std::cout << "Counter-Intr: cannot open deviceio" << device_name << std::endl;
}
map_base = reinterpret_cast<volatile uint32_t *>(mmap(nullptr, PAGE_SIZE,
PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0));
if (map_base == reinterpret_cast<void *>(-1))
{
LOG(WARNING) << "Cannot map the FPGA acquisition module into user memory";
std::cout << "Counter-Intr: cannot map deviceio" << device_name << std::endl;
}
// sanity check : check test register
uint32_t writeval = TEST_REG_SANITY_CHECK;
uint32_t readval;
readval = gnss_sdr_fpga_sample_counter::test_register(writeval);
if (writeval != readval)
{
LOG(WARNING) << "Acquisition test register sanity check failed";
}
else
{
LOG(INFO) << "Acquisition test register sanity check success!";
//std::cout << "Acquisition test register sanity check success!" << std::endl;
}
}
void gnss_sdr_fpga_sample_counter::close_device()
{
//printf("=========================================== NOW closing device ...\n");
map_base[2] = 0; // disable the generation of the interrupt in the device
auto *aux = const_cast<uint32_t *>(map_base);
if (munmap(static_cast<void *>(aux), PAGE_SIZE) == -1)
{
printf("Failed to unmap memory uio\n");
}
close(fd);
}
uint32_t gnss_sdr_fpga_sample_counter::wait_for_interrupt_and_read_counter()
{
int32_t irq_count;
ssize_t nb;
int32_t counter;
// enable interrupts
int32_t reenable = 1;
write(fd, reinterpret_cast<void *>(&reenable), sizeof(int32_t));
// wait for interrupt
//printf("============================================ interrupter : going to wait for interupt\n");
nb = read(fd, &irq_count, sizeof(irq_count));
//printf("============================================ interrupter : interrupt received\n");
//printf("interrupt received\n");
if (nb != sizeof(irq_count))
{
printf("acquisition module Read failed to retrieve 4 bytes!\n");
printf("acquisition module Interrupt number %d\n", irq_count);
}
// acknowledge the interrupt
map_base[1] = 0; // writing anything to reg 1 acknowledges the interrupt
// add number of passed samples or read the current counter value for more accuracy
counter = samples_per_output; //map_base[0];
return counter;
}

View File

@ -1,6 +1,7 @@
/*!
* \file gnss_sdr_fpga_sample_counter.h
* \brief Simple block to report the current receiver time based on the output of the tracking or telemetry blocks
* \brief Simple block to report the current receiver time based on the output
* of the tracking or telemetry blocks
* \author Javier Arribas 2018. jarribas(at)cttc.es
*
*
@ -28,16 +29,18 @@
*
* -------------------------------------------------------------------------
*/
#ifndef GNSS_SDR_FPGA_sample_counter_H_
#define GNSS_SDR_FPGA_sample_counter_H_
#ifndef GNSS_SDR_GNSS_SDR_FPGA_SAMPLE_COUNTER_H_
#define GNSS_SDR_GNSS_SDR_FPGA_SAMPLE_COUNTER_H_
#include <boost/shared_ptr.hpp>
#include <gnuradio/block.h>
#include <cstdint>
#include <string>
class gnss_sdr_fpga_sample_counter;
typedef boost::shared_ptr<gnss_sdr_fpga_sample_counter> gnss_sdr_fpga_sample_counter_sptr;
using gnss_sdr_fpga_sample_counter_sptr = boost::shared_ptr<gnss_sdr_fpga_sample_counter>;
gnss_sdr_fpga_sample_counter_sptr gnss_sdr_make_fpga_sample_counter(double _fs, int32_t _interval_ms);
@ -66,16 +69,18 @@ private:
uint32_t current_days; // Receiver time in days since the beginning of the run
int32_t report_interval_ms;
bool flag_enable_send_msg;
int32_t fd; // driver descriptor
volatile uint32_t *map_base; // driver memory map
std::string device_name = "/dev/uio26"; // HW device name
int32_t fd; // driver descriptor
volatile uint32_t *map_base; // driver memory map
std::string device_name = "/dev/uio2"; // HW device name
bool is_open;
public:
friend gnss_sdr_fpga_sample_counter_sptr gnss_sdr_make_fpga_sample_counter(double _fs, int32_t _interval_ms);
~gnss_sdr_fpga_sample_counter();
int general_work(int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
};
#endif /*GNSS_SDR_FPGA_sample_counter_H_*/
#endif // GNSS_SDR_GNSS_SDR_FPGA_SAMPLE_COUNTER_H_

View File

@ -37,7 +37,7 @@
class gnss_sdr_time_counter;
typedef boost::shared_ptr<gnss_sdr_time_counter> gnss_sdr_time_counter_sptr;
using gnss_sdr_time_counter_sptr = boost::shared_ptr<gnss_sdr_time_counter>;
gnss_sdr_time_counter_sptr gnss_sdr_make_time_counter();

View File

@ -570,9 +570,41 @@ int hybrid_observables_cc::general_work(int noutput_items __attribute__((unused)
if (n_valid > 0)
{
update_TOW(epoch_data);
if (T_rx_TOW_ms % 20 != 0)
int tow_inc_loop_count = 0;
while (T_rx_TOW_ms % 20 != 0 and tow_inc_loop_count < 20)
{
T_rx_TOW_offset_ms = T_rx_TOW_ms % 20;
tow_inc_loop_count++;
T_rx_TOW_offset_ms++;
T_rx_TOW_offset_ms = T_rx_TOW_offset_ms % 20;
//check if effectively the receiver TOW is now multiple of 20 ms
n_valid = 0;
epoch_data.clear();
for (uint32_t n = 0; n < d_nchannels_out; n++)
{
Gnss_Synchro interpolated_gnss_synchro{};
if (!interp_trk_obs(interpolated_gnss_synchro, n, d_Rx_clock_buffer.front() + T_rx_TOW_offset_ms * T_rx_clock_step_samples))
{
// Produce an empty observation
interpolated_gnss_synchro = Gnss_Synchro();
interpolated_gnss_synchro.Flag_valid_pseudorange = false;
interpolated_gnss_synchro.Flag_valid_word = false;
interpolated_gnss_synchro.Flag_valid_acquisition = false;
interpolated_gnss_synchro.fs = 0;
interpolated_gnss_synchro.Channel_ID = n;
}
else
{
n_valid++;
}
epoch_data.push_back(interpolated_gnss_synchro);
}
update_TOW(epoch_data);
//debug code:
// if (T_rx_TOW_ms % 20 != 0)
// {
// std::cout << "Warning: RX TOW is not multiple of 20 ms\n";
// }
// std::cout << "T_rx_TOW_ms=" << T_rx_TOW_ms << " T_rx_TOW_offset_ms=" << T_rx_TOW_offset_ms << " ->" << T_rx_TOW_ms % 20 << std::endl;
}
}

View File

@ -107,9 +107,9 @@ Ad9361FpgaSignalSource::Ad9361FpgaSignalSource(ConfigurationInterface* configura
}
// turn switch to A/D position
std::string default_device_name = "/dev/uio13";
std::string default_device_name = "/dev/uio1";
std::string device_name = configuration->property(role + ".devicename", default_device_name);
int switch_position = configuration->property(role + ".switch_position", 0);
int32_t switch_position = configuration->property(role + ".switch_position", 0);
switch_fpga = std::make_shared<Fpga_Switch>(device_name);
switch_fpga->set_switch_position(switch_position);
if (in_stream_ > 0)

View File

@ -2,7 +2,7 @@
* \file fpga_switch.cc
* \brief Switch that connects the HW accelerator queues to the analog front end or the DMA.
* \authors <ul>
* <li> Marc Majoral, 2017. mmajoral(at)cttc.cat
* <li> Marc Majoral, 2019. mmajoral(at)cttc.cat
* <li> Javier Arribas, 2015. jarribas(at)cttc.es
* </ul>
*
@ -43,7 +43,7 @@
// constants
const size_t PAGE_SIZE = 0x10000;
const unsigned int TEST_REGISTER_TRACK_WRITEVAL = 0x55AA;
const uint32_t TEST_REGISTER_TRACK_WRITEVAL = 0x55AA;
Fpga_Switch::Fpga_Switch(const std::string &device_name)
{
@ -87,7 +87,7 @@ Fpga_Switch::~Fpga_Switch()
}
void Fpga_Switch::set_switch_position(int switch_position)
void Fpga_Switch::set_switch_position(int32_t switch_position)
{
d_map_base[0] = switch_position;
}

View File

@ -2,7 +2,7 @@
* \file fpga_switch.h
* \brief Switch that connects the HW accelerator queues to the analog front end or the DMA.
* \authors <ul>
* <li> Marc Majoral, 2017. mmajoral(at)cttc.cat
* <li> Marc Majoral, 2019. mmajoral(at)cttc.cat
* <li> Javier Arribas, 2016. jarribas(at)cttc.es
* </ul>
*
@ -46,7 +46,7 @@ class Fpga_Switch
public:
Fpga_Switch(const std::string& device_name);
~Fpga_Switch();
void set_switch_position(int switch_position);
void set_switch_position(int32_t switch_position);
private:
int d_device_descriptor; // driver descriptor

View File

@ -52,13 +52,13 @@ add_library(telemetry_decoder_gr_blocks
target_link_libraries(telemetry_decoder_gr_blocks
PUBLIC
Gnuradio::runtime
Volkgnsssdr::volkgnsssdr
telemetry_decoder_libswiftcnav
telemetry_decoder_libs
core_system_parameters
PRIVATE
Gnuradio::runtime
Volkgnsssdr::volkgnsssdr
Boost::boost
PRIVATE
Gflags::gflags
Glog::glog
)

View File

@ -117,6 +117,7 @@ beidou_b1i_telemetry_decoder_cc::beidou_b1i_telemetry_decoder_cc(
d_subframe_symbols = static_cast<double *>(volk_gnsssdr_malloc(BEIDOU_DNAV_PREAMBLE_PERIOD_SYMBOLS * sizeof(double), volk_gnsssdr_get_alignment()));
d_required_symbols = BEIDOU_DNAV_SUBFRAME_SYMBOLS * d_samples_per_symbol + d_samples_per_preamble;
d_symbol_history.set_capacity(d_required_symbols + 1);
// Generic settings
d_sample_counter = 0;
d_stat = 0;
@ -317,12 +318,8 @@ void beidou_b1i_telemetry_decoder_cc::set_satellite(const Gnss_Satellite &satell
volk_gnsssdr_free(d_secondary_code_symbols);
volk_gnsssdr_free(d_subframe_symbols);
d_samples_per_symbol = (BEIDOU_B1I_CODE_RATE_HZ / BEIDOU_B1I_CODE_LENGTH_CHIPS) / BEIDOU_D2NAV_SYMBOL_RATE_SPS;
d_symbols_per_preamble = BEIDOU_DNAV_PREAMBLE_LENGTH_SYMBOLS;
d_samples_per_preamble = BEIDOU_DNAV_PREAMBLE_LENGTH_SYMBOLS * d_samples_per_symbol;
d_secondary_code_symbols = nullptr;
d_preamble_samples = static_cast<int32_t *>(volk_gnsssdr_malloc(d_samples_per_preamble * sizeof(int32_t), volk_gnsssdr_get_alignment()));
d_preamble_period_samples = BEIDOU_DNAV_PREAMBLE_PERIOD_SYMBOLS * d_samples_per_symbol;
// Setting samples of preamble code
int32_t n = 0;
@ -402,7 +399,7 @@ int beidou_b1i_telemetry_decoder_cc::general_work(int noutput_items __attribute_
//******* preamble correlation ********
for (int32_t i = 0; i < d_samples_per_preamble; i++)
{
if (d_symbol_history.at(i) < 0) // symbols clipping
if (d_symbol_history[i] < 0) // symbols clipping
{
corr_value -= d_preamble_samples[i];
}
@ -580,11 +577,6 @@ int beidou_b1i_telemetry_decoder_cc::general_work(int noutput_items __attribute_
}
}
// remove used symbols from history
if (d_symbol_history.size() > d_required_symbols)
{
d_symbol_history.pop_front();
}
// 3. Make the output (copy the object contents to the GNURadio reserved memory)
*out[0] = current_symbol;

View File

@ -43,6 +43,7 @@
#include "beidou_dnav_utc_model.h"
#include "gnss_satellite.h"
#include "gnss_synchro.h"
#include <boost/circular_buffer.hpp>
#include <gnuradio/block.h>
#include <fstream>
#include <string>
@ -97,7 +98,7 @@ private:
uint32_t d_required_symbols;
// Storage for incoming data
std::deque<float> d_symbol_history;
boost::circular_buffer<float> d_symbol_history;
// Variables for internal functionality
uint64_t d_sample_counter; // Sample counter as an index (1,2,3,..etc) indicating number of samples processed

View File

@ -52,25 +52,6 @@ galileo_make_telemetry_decoder_cc(const Gnss_Satellite &satellite, int frame_typ
}
void galileo_telemetry_decoder_cc::viterbi_decoder(double *page_part_symbols, int32_t *page_part_bits)
{
Viterbi(page_part_bits, out0, state0, out1, state1,
page_part_symbols, KK, nn, DataLength);
}
void galileo_telemetry_decoder_cc::deinterleaver(int32_t rows, int32_t cols, const double *in, double *out)
{
for (int32_t r = 0; r < rows; r++)
{
for (int32_t c = 0; c < cols; c++)
{
out[c * rows + r] = in[r * cols + c];
}
}
}
galileo_telemetry_decoder_cc::galileo_telemetry_decoder_cc(
const Gnss_Satellite &satellite, int frame_type,
bool dump) : gr::block("galileo_telemetry_decoder_cc", gr::io_signature::make(1, 1, sizeof(Gnss_Synchro)),
@ -82,13 +63,13 @@ galileo_telemetry_decoder_cc::galileo_telemetry_decoder_cc(
d_dump = dump;
d_satellite = Gnss_Satellite(satellite.get_system(), satellite.get_PRN());
d_frame_type = frame_type;
LOG(INFO) << "Initializing GALILEO UNIFIED TELEMETRY DECODER";
DLOG(INFO) << "Initializing GALILEO UNIFIED TELEMETRY DECODER";
switch (d_frame_type)
{
case 1: // INAV
{
d_PRN_code_period_ms = static_cast<uint32_t>(GALILEO_E5A_CODE_PERIOD_MS);
d_PRN_code_period_ms = static_cast<uint32_t>(GALILEO_E1_CODE_PERIOD_MS);
d_samples_per_symbol = GALILEO_E1_B_SAMPLES_PER_SYMBOL;
d_bits_per_preamble = GALILEO_INAV_PREAMBLE_LENGTH_BITS;
// set the preamble
@ -216,6 +197,8 @@ galileo_telemetry_decoder_cc::galileo_telemetry_decoder_cc(
d_channel = 0;
flag_TOW_set = false;
d_symbol_history.set_capacity(d_required_symbols + 1);
// vars for Viterbi decoder
int32_t max_states = 1 << mm; // 2^mm
g_encoder[0] = 121; // Polynomial G1
@ -256,6 +239,25 @@ galileo_telemetry_decoder_cc::~galileo_telemetry_decoder_cc()
}
void galileo_telemetry_decoder_cc::viterbi_decoder(double *page_part_symbols, int32_t *page_part_bits)
{
Viterbi(page_part_bits, out0, state0, out1, state1,
page_part_symbols, KK, nn, DataLength);
}
void galileo_telemetry_decoder_cc::deinterleaver(int32_t rows, int32_t cols, const double *in, double *out)
{
for (int32_t r = 0; r < rows; r++)
{
for (int32_t c = 0; c < cols; c++)
{
out[c * rows + r] = in[r * cols + c];
}
}
}
void galileo_telemetry_decoder_cc::decode_INAV_word(double *page_part_symbols, int32_t frame_length)
{
// 1. De-interleave
@ -297,11 +299,11 @@ void galileo_telemetry_decoder_cc::decode_INAV_word(double *page_part_symbols, i
d_inav_nav.split_page(page_String, flag_even_word_arrived);
if (d_inav_nav.flag_CRC_test == true)
{
LOG(INFO) << "Galileo E1 CRC correct in channel " << d_channel << " from satellite " << d_satellite;
DLOG(INFO) << "Galileo E1 CRC correct in channel " << d_channel << " from satellite " << d_satellite;
}
else
{
LOG(INFO) << "Galileo E1 CRC error in channel " << d_channel << " from satellite " << d_satellite;
DLOG(INFO) << "Galileo E1 CRC error in channel " << d_channel << " from satellite " << d_satellite;
}
flag_even_word_arrived = 0;
}
@ -389,11 +391,11 @@ void galileo_telemetry_decoder_cc::decode_FNAV_word(double *page_symbols, int32_
d_fnav_nav.split_page(page_String);
if (d_fnav_nav.flag_CRC_test == true)
{
LOG(INFO) << "Galileo E5a CRC correct in channel " << d_channel << " from satellite " << d_satellite;
DLOG(INFO) << "Galileo E5a CRC correct in channel " << d_channel << " from satellite " << d_satellite;
}
else
{
LOG(INFO) << "Galileo E5a CRC error in channel " << d_channel << " from satellite " << d_satellite;
DLOG(INFO) << "Galileo E5a CRC error in channel " << d_channel << " from satellite " << d_satellite;
}
// 4. Push the new navigation data to the queues
@ -429,7 +431,7 @@ void galileo_telemetry_decoder_cc::set_satellite(const Gnss_Satellite &satellite
void galileo_telemetry_decoder_cc::set_channel(int32_t channel)
{
d_channel = channel;
LOG(INFO) << "Navigation channel set to " << channel;
DLOG(INFO) << "Navigation channel set to " << channel;
// ############# ENABLE DATA FILE LOG #################
if (d_dump == true)
{
@ -473,11 +475,10 @@ int galileo_telemetry_decoder_cc::general_work(int noutput_items __attribute__((
if (d_symbol_history.size() > d_required_symbols)
{
// TODO Optimize me!
// ******* preamble correlation ********
for (int32_t i = 0; i < d_samples_per_preamble; i++)
{
if (d_symbol_history.at(i) < 0.0) // symbols clipping
if (d_symbol_history[i] < 0.0) // symbols clipping
{
corr_value -= d_preamble_samples[i];
}
@ -496,7 +497,7 @@ int galileo_telemetry_decoder_cc::general_work(int noutput_items __attribute__((
if (abs(corr_value) >= d_samples_per_preamble)
{
d_preamble_index = d_sample_counter; // record the preamble sample stamp
LOG(INFO) << "Preamble detection for Galileo satellite " << this->d_satellite;
DLOG(INFO) << "Preamble detection for Galileo satellite " << this->d_satellite;
d_stat = 1; // enter into frame pre-detection status
}
break;
@ -510,7 +511,7 @@ int galileo_telemetry_decoder_cc::general_work(int noutput_items __attribute__((
if (abs(preamble_diff - d_preamble_period_symbols) == 0)
{
// try to decode frame
LOG(INFO) << "Starting page decoder for Galileo satellite " << this->d_satellite;
DLOG(INFO) << "Starting page decoder for Galileo satellite " << this->d_satellite;
d_preamble_index = d_sample_counter; // record the preamble sample stamp
d_stat = 2;
}
@ -524,7 +525,7 @@ int galileo_telemetry_decoder_cc::general_work(int noutput_items __attribute__((
}
break;
}
case 2: //preamble acquired
case 2: // preamble acquired
{
if (d_sample_counter == d_preamble_index + static_cast<uint64_t>(d_preamble_period_symbols))
{
@ -534,14 +535,14 @@ int galileo_telemetry_decoder_cc::general_work(int noutput_items __attribute__((
case 1: // INAV
// NEW Galileo page part is received
// 0. fetch the symbols into an array
if (corr_value > 0) //normal PLL lock
if (corr_value > 0) // normal PLL lock
{
for (uint32_t i = 0; i < d_frame_length_symbols; i++)
{
d_page_part_symbols[i] = d_symbol_history.at(i + d_samples_per_preamble); // because last symbol of the preamble is just received now!
}
}
else //180 deg. inverted carrier phase PLL lock
else // 180 deg. inverted carrier phase PLL lock
{
for (uint32_t i = 0; i < d_frame_length_symbols; i++)
{
@ -553,7 +554,7 @@ int galileo_telemetry_decoder_cc::general_work(int noutput_items __attribute__((
case 2: // FNAV
// NEW Galileo page part is received
// 0. fetch the symbols into an array
if (corr_value > 0) //normal PLL lock
if (corr_value > 0) // normal PLL lock
{
int k = 0;
for (uint32_t i = 0; i < d_frame_length_symbols; i++)
@ -567,13 +568,13 @@ int galileo_telemetry_decoder_cc::general_work(int noutput_items __attribute__((
}
}
}
else //180 deg. inverted carrier phase PLL lock
else // 180 deg. inverted carrier phase PLL lock
{
int k = 0;
for (uint32_t i = 0; i < d_frame_length_symbols; i++)
{
d_page_part_symbols[i] = 0;
for (uint32_t m = 0; m < d_samples_per_symbol; m++) //integrate samples into symbols
for (uint32_t m = 0; m < d_samples_per_symbol; m++) // integrate samples into symbols
{
d_page_part_symbols[i] -= static_cast<float>(d_secondary_code_samples[k]) * d_symbol_history.at(i * d_samples_per_symbol + d_samples_per_preamble + m); // because last symbol of the preamble is just received now!
k++;
@ -605,7 +606,7 @@ int galileo_telemetry_decoder_cc::general_work(int noutput_items __attribute__((
d_preamble_index = d_sample_counter; // record the preamble sample stamp
if (d_CRC_error_counter > CRC_ERROR_LIMIT)
{
LOG(INFO) << "Lost of frame sync SAT " << this->d_satellite;
DLOG(INFO) << "Lost of frame sync SAT " << this->d_satellite;
d_flag_frame_sync = false;
d_stat = 0;
d_TOW_at_current_symbol_ms = 0;
@ -634,7 +635,7 @@ int galileo_telemetry_decoder_cc::general_work(int noutput_items __attribute__((
{
// TOW_5 refers to the even preamble, but when we decode it we are in the odd part, so 1 second later plus the decoding delay
d_TOW_at_Preamble_ms = static_cast<uint32_t>(d_inav_nav.TOW_5 * 1000.0);
d_TOW_at_current_symbol_ms = d_TOW_at_Preamble_ms + static_cast<uint32_t>(GALILEO_INAV_PAGE_PART_MS + (d_required_symbols + 1) * GALILEO_E5A_CODE_PERIOD_MS);
d_TOW_at_current_symbol_ms = d_TOW_at_Preamble_ms + static_cast<uint32_t>(GALILEO_INAV_PAGE_PART_MS + (d_required_symbols + 1) * GALILEO_E1_CODE_PERIOD_MS);
d_inav_nav.flag_TOW_5 = false;
}
@ -642,13 +643,13 @@ int galileo_telemetry_decoder_cc::general_work(int noutput_items __attribute__((
{
// TOW_6 refers to the even preamble, but when we decode it we are in the odd part, so 1 second later plus the decoding delay
d_TOW_at_Preamble_ms = static_cast<uint32_t>(d_inav_nav.TOW_6 * 1000.0);
d_TOW_at_current_symbol_ms = d_TOW_at_Preamble_ms + static_cast<uint32_t>(GALILEO_INAV_PAGE_PART_MS + (d_required_symbols + 1) * GALILEO_E5A_CODE_PERIOD_MS);
d_TOW_at_current_symbol_ms = d_TOW_at_Preamble_ms + static_cast<uint32_t>(GALILEO_INAV_PAGE_PART_MS + (d_required_symbols + 1) * GALILEO_E1_CODE_PERIOD_MS);
d_inav_nav.flag_TOW_6 = false;
}
else
{
// this page has no timing information
d_TOW_at_current_symbol_ms += static_cast<uint32_t>(GALILEO_E5A_CODE_PERIOD_MS); // + GALILEO_INAV_PAGE_PART_SYMBOLS*GALILEO_E1_CODE_PERIOD;
d_TOW_at_current_symbol_ms += static_cast<uint32_t>(GALILEO_E1_CODE_PERIOD_MS); // + GALILEO_INAV_PAGE_PART_SYMBOLS*GALILEO_E1_CODE_PERIOD;
}
}
break;
@ -717,13 +718,6 @@ int galileo_telemetry_decoder_cc::general_work(int noutput_items __attribute__((
}
}
// remove used symbols from history
// todo: Use circular buffer here
if (d_symbol_history.size() > d_required_symbols)
{
d_symbol_history.pop_front();
}
switch (d_frame_type)
{
case 1: // INAV

View File

@ -43,11 +43,11 @@
#include "galileo_utc_model.h"
#include "gnss_satellite.h"
#include "gnss_synchro.h"
#include <boost/circular_buffer.hpp>
#include <gnuradio/block.h>
#include <fstream>
#include <string>
class galileo_telemetry_decoder_cc;
using galileo_telemetry_decoder_cc_sptr = boost::shared_ptr<galileo_telemetry_decoder_cc>;
@ -80,7 +80,7 @@ private:
void deinterleaver(int32_t rows, int32_t cols, const double *in, double *out);
void decode_INAV_word(double *symbols, int32_t frame_length);
void decode_INAV_word(double *page_part_symbols, int32_t frame_length);
void decode_FNAV_word(double *page_symbols, int32_t frame_length);
int d_frame_type;
@ -95,7 +95,7 @@ private:
uint32_t d_frame_length_symbols;
double *d_page_part_symbols;
std::deque<float> d_symbol_history;
boost::circular_buffer<float> d_symbol_history;
uint64_t d_sample_counter;
uint64_t d_preamble_index;

View File

@ -89,6 +89,8 @@ glonass_l1_ca_telemetry_decoder_cc::glonass_l1_ca_telemetry_decoder_cc(
n++;
}
}
d_symbol_history.set_capacity(GLONASS_GNAV_PREAMBLE_LENGTH_SYMBOLS);
d_sample_counter = 0ULL;
d_stat = 0;
d_preamble_index = 0ULL;
@ -276,14 +278,14 @@ int glonass_l1_ca_telemetry_decoder_cc::general_work(int noutput_items __attribu
consume_each(1);
d_flag_preamble = false;
uint32_t required_symbols = GLONASS_GNAV_STRING_SYMBOLS;
if (d_symbol_history.size() > required_symbols)
if (static_cast<int32_t>(d_symbol_history.size()) == d_symbols_per_preamble)
{
// ******* preamble correlation ********
for (int32_t i = 0; i < d_symbols_per_preamble; i++)
int i = 0;
for (const auto &iter : d_symbol_history)
{
if (d_symbol_history.at(i).Prompt_I < 0) // symbols clipping
if (iter.Prompt_I < 0.0) // symbols clipping
{
corr_value -= d_preambles_symbols[i];
}
@ -291,6 +293,7 @@ int glonass_l1_ca_telemetry_decoder_cc::general_work(int noutput_items __attribu
{
corr_value += d_preambles_symbols[i];
}
i++;
}
}
@ -304,7 +307,7 @@ int glonass_l1_ca_telemetry_decoder_cc::general_work(int noutput_items __attribu
LOG(INFO) << "Preamble detection for GLONASS L1 C/A SAT " << this->d_satellite;
// Enter into frame pre-detection status
d_stat = 1;
d_preamble_time_samples = d_symbol_history.at(0).Tracking_sample_counter; // record the preamble sample stamp
d_preamble_time_samples = d_symbol_history[0].Tracking_sample_counter; // record the preamble sample stamp
}
}
else if (d_stat == 1) // possible preamble lock
@ -314,7 +317,7 @@ int glonass_l1_ca_telemetry_decoder_cc::general_work(int noutput_items __attribu
// check preamble separation
preamble_diff = static_cast<int32_t>(d_sample_counter - d_preamble_index);
// Record the PRN start sample index associated to the preamble
d_preamble_time_samples = static_cast<double>(d_symbol_history.at(0).Tracking_sample_counter);
d_preamble_time_samples = static_cast<double>(d_symbol_history[0].Tracking_sample_counter);
if (abs(preamble_diff - GLONASS_GNAV_PREAMBLE_PERIOD_SYMBOLS) == 0)
{
// try to decode frame
@ -366,7 +369,7 @@ int glonass_l1_ca_telemetry_decoder_cc::general_work(int noutput_items __attribu
{
d_flag_frame_sync = true;
DLOG(INFO) << " Frame sync SAT " << this->d_satellite << " with preamble start at "
<< d_symbol_history.at(0).Tracking_sample_counter << " [samples]";
<< d_symbol_history[0].Tracking_sample_counter << " [samples]";
}
}
else
@ -437,11 +440,6 @@ int glonass_l1_ca_telemetry_decoder_cc::general_work(int noutput_items __attribu
}
}
// remove used symbols from history
if (d_symbol_history.size() > required_symbols)
{
d_symbol_history.pop_front();
}
// 3. Make the output (copy the object contents to the GNURadio reserved memory)
*out[0] = current_symbol;

View File

@ -41,6 +41,7 @@
#include "glonass_gnav_utc_model.h"
#include "gnss_satellite.h"
#include "gnss_synchro.h"
#include <boost/circular_buffer.hpp>
#include <gnuradio/block.h>
#include <fstream>
#include <string>
@ -88,7 +89,7 @@ private:
int32_t d_symbols_per_preamble;
//!< Storage for incoming data
std::deque<Gnss_Synchro> d_symbol_history;
boost::circular_buffer<Gnss_Synchro> d_symbol_history;
//!< Variables for internal functionality
uint64_t d_sample_counter; //!< Sample counter as an index (1,2,3,..etc) indicating number of samples processed

View File

@ -89,6 +89,8 @@ glonass_l2_ca_telemetry_decoder_cc::glonass_l2_ca_telemetry_decoder_cc(
n++;
}
}
d_symbol_history.set_capacity(GLONASS_GNAV_PREAMBLE_PERIOD_SYMBOLS);
d_sample_counter = 0ULL;
d_stat = 0;
d_preamble_index = 0ULL;
@ -276,14 +278,14 @@ int glonass_l2_ca_telemetry_decoder_cc::general_work(int noutput_items __attribu
consume_each(1);
d_flag_preamble = false;
uint32_t required_symbols = GLONASS_GNAV_STRING_SYMBOLS;
if (d_symbol_history.size() > required_symbols)
if (d_symbol_history.size() == GLONASS_GNAV_PREAMBLE_PERIOD_SYMBOLS)
{
// ******* preamble correlation ********
for (int32_t i = 0; i < d_symbols_per_preamble; i++)
int i = 0;
for (const auto &iter : d_symbol_history)
{
if (d_symbol_history.at(i).Prompt_I < 0) // symbols clipping
if (iter.Prompt_I < 0.0) // symbols clipping
{
corr_value -= d_preambles_symbols[i];
}
@ -291,6 +293,7 @@ int glonass_l2_ca_telemetry_decoder_cc::general_work(int noutput_items __attribu
{
corr_value += d_preambles_symbols[i];
}
i++;
}
}
@ -304,7 +307,7 @@ int glonass_l2_ca_telemetry_decoder_cc::general_work(int noutput_items __attribu
LOG(INFO) << "Preamble detection for GLONASS L2 C/A SAT " << this->d_satellite;
// Enter into frame pre-detection status
d_stat = 1;
d_preamble_time_samples = d_symbol_history.at(0).Tracking_sample_counter; // record the preamble sample stamp
d_preamble_time_samples = d_symbol_history[0].Tracking_sample_counter; // record the preamble sample stamp
}
}
else if (d_stat == 1) // possible preamble lock
@ -314,7 +317,7 @@ int glonass_l2_ca_telemetry_decoder_cc::general_work(int noutput_items __attribu
// check preamble separation
preamble_diff = static_cast<int32_t>(d_sample_counter - d_preamble_index);
// Record the PRN start sample index associated to the preamble
d_preamble_time_samples = static_cast<double>(d_symbol_history.at(0).Tracking_sample_counter);
d_preamble_time_samples = static_cast<double>(d_symbol_history[0].Tracking_sample_counter);
if (abs(preamble_diff - GLONASS_GNAV_PREAMBLE_PERIOD_SYMBOLS) == 0)
{
// try to decode frame
@ -366,7 +369,7 @@ int glonass_l2_ca_telemetry_decoder_cc::general_work(int noutput_items __attribu
{
d_flag_frame_sync = true;
DLOG(INFO) << " Frame sync SAT " << this->d_satellite << " with preamble start at "
<< d_symbol_history.at(0).Tracking_sample_counter << " [samples]";
<< d_symbol_history[0].Tracking_sample_counter << " [samples]";
}
}
else
@ -437,11 +440,6 @@ int glonass_l2_ca_telemetry_decoder_cc::general_work(int noutput_items __attribu
}
}
// remove used symbols from history
if (d_symbol_history.size() > required_symbols)
{
d_symbol_history.pop_front();
}
// 3. Make the output (copy the object contents to the GNURadio reserved memory)
*out[0] = current_symbol;

View File

@ -40,6 +40,7 @@
#include "glonass_gnav_utc_model.h"
#include "gnss_satellite.h"
#include "gnss_synchro.h"
#include <boost/circular_buffer.hpp>
#include <gnuradio/block.h>
#include <fstream>
#include <string>
@ -86,7 +87,7 @@ private:
int32_t d_symbols_per_preamble;
//!< Storage for incoming data
std::deque<Gnss_Synchro> d_symbol_history;
boost::circular_buffer<Gnss_Synchro> d_symbol_history;
//!< Variables for internal functionality
uint64_t d_sample_counter; //!< Sample counter as an index (1,2,3,..etc) indicating number of samples processed

View File

@ -343,7 +343,7 @@ int gps_l1_ca_telemetry_decoder_cc::general_work(int noutput_items __attribute__
{
if (iter.Flag_valid_symbol_output == true)
{
if (iter.Prompt_I < 0) // symbols clipping
if (iter.Prompt_I < 0.0) // symbols clipping
{
corr_value -= d_preambles_symbols[i];
}

View File

@ -32,6 +32,7 @@
#define GNSS_SDR_GPS_L2C_TELEMETRY_DECODER_CC_H
#include "GPS_L2C.h"
#include "gnss_satellite.h"
#include "gps_cnav_ephemeris.h"
#include "gps_cnav_iono.h"
@ -39,13 +40,11 @@
#include <gnuradio/block.h>
#include <algorithm> // for copy
#include <cstdint>
#include <deque>
#include <fstream>
#include <string>
#include <utility> // for pair
#include <vector>
extern "C"
{
#include "bits.h"
@ -53,7 +52,6 @@ extern "C"
#include "edc.h"
}
#include "GPS_L2C.h"
class gps_l2c_telemetry_decoder_cc;

View File

@ -66,6 +66,8 @@ gps_l5_telemetry_decoder_cc::gps_l5_telemetry_decoder_cc(
d_flag_valid_word = false;
d_TOW_at_current_symbol_ms = 0U;
d_TOW_at_Preamble_ms = 0U;
sym_hist.set_capacity(GPS_L5I_NH_CODE_LENGTH);
// initialize the CNAV frame decoder (libswiftcnav)
cnav_msg_decoder_init(&d_cnav_decoder);
for (int32_t aux = 0; aux < GPS_L5I_NH_CODE_LENGTH; aux++)
@ -103,7 +105,7 @@ gps_l5_telemetry_decoder_cc::~gps_l5_telemetry_decoder_cc()
void gps_l5_telemetry_decoder_cc::set_satellite(const Gnss_Satellite &satellite)
{
d_satellite = Gnss_Satellite(satellite.get_system(), satellite.get_PRN());
LOG(INFO) << "GPS L5 CNAV telemetry decoder in channel " << this->d_channel << " set to satellite " << d_satellite;
DLOG(INFO) << "GPS L5 CNAV telemetry decoder in channel " << this->d_channel << " set to satellite " << d_satellite;
d_CNAV_Message.reset();
}
@ -112,7 +114,7 @@ void gps_l5_telemetry_decoder_cc::set_channel(int32_t channel)
{
d_channel = channel;
d_CNAV_Message.reset();
LOG(INFO) << "GPS L5 CNAV channel set to " << channel;
DLOG(INFO) << "GPS L5 CNAV channel set to " << channel;
// ############# ENABLE DATA FILE LOG #################
if (d_dump == true)
{
@ -145,10 +147,10 @@ int gps_l5_telemetry_decoder_cc::general_work(int noutput_items __attribute__((u
const auto *in = reinterpret_cast<const Gnss_Synchro *>(input_items[0]); // Get the input buffer pointer
// UPDATE GNSS SYNCHRO DATA
Gnss_Synchro current_synchro_data{}; //structure to save the synchronization information and send the output object to the next block
Gnss_Synchro current_synchro_data{}; // structure to save the synchronization information and send the output object to the next block
// 1. Copy the current tracking output
current_synchro_data = in[0];
consume_each(1); //one by one
consume_each(1); // one by one
sym_hist.push_back(in[0].Prompt_I);
int32_t corr_NH = 0;
int32_t symbol_value = 0;
@ -158,7 +160,7 @@ int gps_l5_telemetry_decoder_cc::general_work(int noutput_items __attribute__((u
{
for (int32_t i = 0; i < GPS_L5I_NH_CODE_LENGTH; i++)
{
if ((bits_NH[i] * sym_hist.at(i)) > 0.0)
if ((bits_NH[i] * sym_hist[i]) > 0.0)
{
corr_NH += 1;
}
@ -183,7 +185,6 @@ int gps_l5_telemetry_decoder_cc::general_work(int noutput_items __attribute__((u
}
else
{
sym_hist.pop_front();
sync_NH = false;
new_sym = false;
}

View File

@ -31,12 +31,13 @@
#define GNSS_SDR_GPS_L5_TELEMETRY_DECODER_CC_H
#include "GPS_L5.h"
#include "gnss_satellite.h"
#include "gps_cnav_navigation_message.h"
#include <boost/circular_buffer.hpp>
#include <gnuradio/block.h>
#include <algorithm>
#include <cstdint>
#include <deque>
#include <fstream>
#include <string>
#include <utility>
@ -49,7 +50,6 @@ extern "C"
#include "edc.h"
}
#include "GPS_L5.h"
class gps_l5_telemetry_decoder_cc;
@ -90,8 +90,8 @@ private:
bool d_flag_valid_word;
Gps_CNAV_Navigation_Message d_CNAV_Message;
double bits_NH[GPS_L5I_NH_CODE_LENGTH]{};
std::deque<double> sym_hist;
float bits_NH[GPS_L5I_NH_CODE_LENGTH]{};
boost::circular_buffer<float> sym_hist;
bool sync_NH;
bool new_sym;
};

View File

@ -1,8 +1,8 @@
/*!
* \file galileo_e1_dll_pll_veml_tracking.cc
* \file galileo_e1_dll_pll_veml_tracking_fpga.cc
* \brief Adapts a DLL+PLL VEML (Very Early Minus Late) tracking loop block
* to a TrackingInterface for Galileo E1 signals
* \author Luis Esteve, 2012. luis(at)epsilon-formacion.com
* to a TrackingInterface for Galileo E1 signals for the FPGA
* \author Marc Majoral, 2019. mmajoral(at)cttc.cat
*
* Code DLL + carrier PLL according to the algorithms described in:
* K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen,
@ -11,7 +11,7 @@
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
* Copyright (C) 2010-2019 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
@ -42,26 +42,19 @@
#include "gnss_sdr_flags.h"
#include <glog/logging.h>
//#define NUM_PRNs_GALILEO_E1 50
using google::LogMessage;
void GalileoE1DllPllVemlTrackingFpga::stop_tracking()
{
}
GalileoE1DllPllVemlTrackingFpga::GalileoE1DllPllVemlTrackingFpga(
ConfigurationInterface* configuration, const std::string& role,
unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams)
{
//dllpllconf_t trk_param;
Dll_Pll_Conf_Fpga trk_param_fpga = Dll_Pll_Conf_Fpga();
DLOG(INFO) << "role " << role;
//################# CONFIGURATION PARAMETERS ########################
std::string default_item_type = "gr_complex";
std::string item_type = configuration->property(role + ".item_type", default_item_type);
int fs_in_deprecated = configuration->property("GNSS-SDR.internal_fs_hz", 2048000);
int fs_in = configuration->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated);
int32_t fs_in_deprecated = configuration->property("GNSS-SDR.internal_fs_hz", 2048000);
int32_t 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;
@ -80,7 +73,7 @@ GalileoE1DllPllVemlTrackingFpga::GalileoE1DllPllVemlTrackingFpga(
trk_param_fpga.pll_bw_narrow_hz = pll_bw_narrow_hz;
float dll_bw_narrow_hz = configuration->property(role + ".dll_bw_narrow_hz", 0.25);
trk_param_fpga.dll_bw_narrow_hz = dll_bw_narrow_hz;
int extend_correlation_symbols = configuration->property(role + ".extend_correlation_symbols", 1);
int32_t extend_correlation_symbols = configuration->property(role + ".extend_correlation_symbols", 1);
float early_late_space_chips = configuration->property(role + ".early_late_space_chips", 0.15);
trk_param_fpga.early_late_space_chips = early_late_space_chips;
float very_early_late_space_chips = configuration->property(role + ".very_early_late_space_chips", 0.6);
@ -107,18 +100,18 @@ GalileoE1DllPllVemlTrackingFpga::GalileoE1DllPllVemlTrackingFpga(
trk_param_fpga.track_pilot = track_pilot;
d_track_pilot = track_pilot;
trk_param_fpga.extend_correlation_symbols = extend_correlation_symbols;
int vector_length = std::round(fs_in / (GALILEO_E1_CODE_CHIP_RATE_HZ / GALILEO_E1_B_CODE_LENGTH_CHIPS));
int32_t vector_length = std::round(fs_in / (GALILEO_E1_CODE_CHIP_RATE_HZ / GALILEO_E1_B_CODE_LENGTH_CHIPS));
trk_param_fpga.vector_length = vector_length;
trk_param_fpga.system = 'E';
char sig_[3] = "1B";
std::memcpy(trk_param_fpga.signal, sig_, 3);
int cn0_samples = configuration->property(role + ".cn0_samples", 20);
int32_t 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);
int32_t 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);
int32_t 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);
@ -129,70 +122,58 @@ GalileoE1DllPllVemlTrackingFpga::GalileoE1DllPllVemlTrackingFpga(
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);
uint32_t device_base = configuration->property(role + ".device_base", 15);
trk_param_fpga.device_base = device_base;
//unsigned int multicorr_type = configuration->property(role + ".multicorr_type", 1);
trk_param_fpga.multicorr_type = 1; // 0 -> 3 correlators, 1 -> 5 correlators
//################# PRE-COMPUTE ALL THE CODES #################
unsigned int code_samples_per_chip = 2;
d_ca_codes = static_cast<int*>(volk_gnsssdr_malloc(static_cast<int>(GALILEO_E1_B_CODE_LENGTH_CHIPS) * code_samples_per_chip * GALILEO_E1_NUMBER_OF_CODES * sizeof(int), volk_gnsssdr_get_alignment()));
uint32_t code_samples_per_chip = 2;
d_ca_codes = static_cast<int32_t*>(volk_gnsssdr_malloc(static_cast<int32_t>(GALILEO_E1_B_CODE_LENGTH_CHIPS) * code_samples_per_chip * GALILEO_E1_NUMBER_OF_CODES * sizeof(int32_t), volk_gnsssdr_get_alignment()));
float* ca_codes_f;
float* data_codes_f;
float* data_codes_f = nullptr;
d_data_codes = nullptr;
if (trk_param_fpga.track_pilot)
if (d_track_pilot)
{
d_data_codes = static_cast<int*>(volk_gnsssdr_malloc((static_cast<unsigned int>(GALILEO_E1_B_CODE_LENGTH_CHIPS)) * code_samples_per_chip * GALILEO_E1_NUMBER_OF_CODES * sizeof(int), volk_gnsssdr_get_alignment()));
d_data_codes = static_cast<int32_t*>(volk_gnsssdr_malloc((static_cast<uint32_t>(GALILEO_E1_B_CODE_LENGTH_CHIPS)) * code_samples_per_chip * GALILEO_E1_NUMBER_OF_CODES * sizeof(int32_t), 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()));
ca_codes_f = static_cast<float*>(volk_gnsssdr_malloc(static_cast<int32_t>(GALILEO_E1_B_CODE_LENGTH_CHIPS) * code_samples_per_chip * sizeof(float), volk_gnsssdr_get_alignment()));
if (trk_param_fpga.track_pilot)
if (d_track_pilot)
{
data_codes_f = static_cast<float*>(volk_gnsssdr_malloc((static_cast<unsigned int>(GALILEO_E1_B_CODE_LENGTH_CHIPS)) * code_samples_per_chip * sizeof(float), volk_gnsssdr_get_alignment()));
data_codes_f = static_cast<float*>(volk_gnsssdr_malloc((static_cast<uint32_t>(GALILEO_E1_B_CODE_LENGTH_CHIPS)) * code_samples_per_chip * sizeof(float), volk_gnsssdr_get_alignment()));
}
//printf("pppppppp trk_param_fpga.track_pilot = %d\n", trk_param_fpga.track_pilot);
//int kk;
for (unsigned int PRN = 1; PRN <= GALILEO_E1_NUMBER_OF_CODES; PRN++)
for (uint32_t PRN = 1; PRN <= GALILEO_E1_NUMBER_OF_CODES; PRN++)
{
char data_signal[3] = "1B";
if (trk_param_fpga.track_pilot)
if (d_track_pilot)
{
//printf("yes tracking pilot !!!!!!!!!!!!!!!\n");
char pilot_signal[3] = "1C";
galileo_e1_code_gen_sinboc11_float(ca_codes_f, pilot_signal, PRN);
galileo_e1_code_gen_sinboc11_float(data_codes_f, data_signal, PRN);
for (unsigned int s = 0; s < 2 * GALILEO_E1_B_CODE_LENGTH_CHIPS; s++)
for (uint32_t s = 0; s < 2 * GALILEO_E1_B_CODE_LENGTH_CHIPS; s++)
{
d_ca_codes[static_cast<int>(GALILEO_E1_B_CODE_LENGTH_CHIPS) * 2 * (PRN - 1) + s] = static_cast<int>(ca_codes_f[s]);
d_data_codes[static_cast<int>(GALILEO_E1_B_CODE_LENGTH_CHIPS) * 2 * (PRN - 1) + s] = static_cast<int>(data_codes_f[s]);
//printf("%f %d | ", data_codes_f[s], d_data_codes[static_cast<int>(GALILEO_E1_B_CODE_LENGTH_CHIPS)* 2 * (PRN - 1) + s]);
d_ca_codes[static_cast<int32_t>(GALILEO_E1_B_CODE_LENGTH_CHIPS) * 2 * (PRN - 1) + s] = static_cast<int32_t>(ca_codes_f[s]);
d_data_codes[static_cast<int32_t>(GALILEO_E1_B_CODE_LENGTH_CHIPS) * 2 * (PRN - 1) + s] = static_cast<int32_t>(data_codes_f[s]);
}
//printf("\n next \n");
//scanf ("%d",&kk);
}
else
{
//printf("no tracking pilot\n");
galileo_e1_code_gen_sinboc11_float(ca_codes_f, data_signal, PRN);
for (unsigned int s = 0; s < 2 * GALILEO_E1_B_CODE_LENGTH_CHIPS; s++)
for (uint32_t s = 0; s < 2 * GALILEO_E1_B_CODE_LENGTH_CHIPS; s++)
{
d_ca_codes[static_cast<int>(GALILEO_E1_B_CODE_LENGTH_CHIPS) * 2 * (PRN - 1) + s] = static_cast<int>(ca_codes_f[s]);
//printf("%f %d | ", ca_codes_f[s], d_ca_codes[static_cast<int>(GALILEO_E1_B_CODE_LENGTH_CHIPS)* 2 * (PRN - 1) + s]);
d_ca_codes[static_cast<int32_t>(GALILEO_E1_B_CODE_LENGTH_CHIPS) * 2 * (PRN - 1) + s] = static_cast<int32_t>(ca_codes_f[s]);
}
//printf("\n next \n");
//scanf ("%d",&kk);
}
}
delete[] ca_codes_f;
if (trk_param_fpga.track_pilot)
if (d_track_pilot)
{
delete[] data_codes_f;
volk_gnsssdr_free(data_codes_f);
}
trk_param_fpga.ca_codes = d_ca_codes;
trk_param_fpga.data_codes = d_data_codes;
@ -214,9 +195,14 @@ GalileoE1DllPllVemlTrackingFpga::~GalileoE1DllPllVemlTrackingFpga()
}
}
void GalileoE1DllPllVemlTrackingFpga::stop_tracking()
{
}
void GalileoE1DllPllVemlTrackingFpga::start_tracking()
{
//tracking_->start_tracking();
tracking_fpga_sc->start_tracking();
}
@ -227,14 +213,12 @@ void GalileoE1DllPllVemlTrackingFpga::start_tracking()
void GalileoE1DllPllVemlTrackingFpga::set_channel(unsigned int channel)
{
channel_ = channel;
//tracking_->set_channel(channel);
tracking_fpga_sc->set_channel(channel);
}
void GalileoE1DllPllVemlTrackingFpga::set_gnss_synchro(Gnss_Synchro* p_gnss_synchro)
{
//tracking_->set_gnss_synchro(p_gnss_synchro);
tracking_fpga_sc->set_gnss_synchro(p_gnss_synchro);
}
@ -244,7 +228,7 @@ void GalileoE1DllPllVemlTrackingFpga::connect(gr::top_block_sptr top_block)
if (top_block)
{ /* top_block is not null */
};
//nothing to connect, now the tracking uses gr_sync_decimator
// nothing to connect, now the tracking uses gr_sync_decimator
}
@ -253,19 +237,17 @@ void GalileoE1DllPllVemlTrackingFpga::disconnect(gr::top_block_sptr top_block)
if (top_block)
{ /* top_block is not null */
};
//nothing to disconnect, now the tracking uses gr_sync_decimator
// nothing to disconnect, now the tracking uses gr_sync_decimator
}
gr::basic_block_sptr GalileoE1DllPllVemlTrackingFpga::get_left_block()
{
//return tracking_;
return tracking_fpga_sc;
}
gr::basic_block_sptr GalileoE1DllPllVemlTrackingFpga::get_right_block()
{
//return tracking_;
return tracking_fpga_sc;
}

View File

@ -1,8 +1,8 @@
/*!
* \file galileo_e1_dll_pll_veml_tracking.h
* \file galileo_e1_dll_pll_veml_tracking_fpga.h
* \brief Adapts a DLL+PLL VEML (Very Early Minus Late) tracking loop block
* to a TrackingInterface for Galileo E1 signals
* \author Luis Esteve, 2012. luis(at)epsilon-formacion.com
* to a TrackingInterface for Galileo E1 signals for the FPGA
* \author Marc Majoral, 2019. mmajoral(at)cttc.cat
*
* Code DLL + carrier PLL according to the algorithms described in:
* K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen,
@ -11,7 +11,7 @@
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
* Copyright (C) 2010-2019 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
@ -63,7 +63,7 @@ public:
return role_;
}
//! Returns "Galileo_E1_DLL_PLL_VEML_Tracking"
//! Returns "Galileo_E1_DLL_PLL_VEML_Tracking_Fpga"
inline std::string implementation() override
{
return "Galileo_E1_DLL_PLL_VEML_Tracking_Fpga";
@ -71,7 +71,7 @@ public:
inline size_t item_size() override
{
return item_size_;
return sizeof(int);
}
void connect(gr::top_block_sptr top_block) override;
@ -100,15 +100,13 @@ public:
private:
//dll_pll_veml_tracking_sptr tracking_;
dll_pll_veml_tracking_fpga_sptr tracking_fpga_sc;
size_t item_size_;
unsigned int channel_;
uint32_t channel_;
std::string role_;
unsigned int in_streams_;
unsigned int out_streams_;
int* d_ca_codes;
int* d_data_codes;
uint32_t in_streams_;
uint32_t out_streams_;
int32_t* d_ca_codes;
int32_t* d_data_codes;
bool d_track_pilot;
};

View File

@ -1,19 +1,12 @@
/*!
* \file galileo_e5a_dll_pll_tracking.cc
* \file galileo_e5a_dll_pll_tracking_fpga.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>
* tracking block to a TrackingInterface for Galileo E5a signals for the FPGA
* \author Marc Majoral, 2019. mmajoral(at)cttc.cat
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
* Copyright (C) 2010-2019 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
@ -54,16 +47,13 @@ GalileoE5aDllPllTrackingFpga::GalileoE5aDllPllTrackingFpga(
ConfigurationInterface *configuration, const std::string &role,
unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams)
{
//printf("creating the E5A tracking");
Dll_Pll_Conf_Fpga trk_param_fpga = Dll_Pll_Conf_Fpga();
DLOG(INFO) << "role " << role;
//################# CONFIGURATION PARAMETERS ########################
std::string default_item_type = "gr_complex";
std::string item_type = configuration->property(role + ".item_type", default_item_type);
int fs_in_deprecated = configuration->property("GNSS-SDR.internal_fs_hz", 12000000);
int fs_in = configuration->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated);
int32_t fs_in_deprecated = configuration->property("GNSS-SDR.internal_fs_hz", 12000000);
int32_t 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;
@ -84,9 +74,9 @@ GalileoE5aDllPllTrackingFpga::GalileoE5aDllPllTrackingFpga(
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;
int vector_length = std::round(fs_in / (GALILEO_E5A_CODE_CHIP_RATE_HZ / GALILEO_E5A_CODE_LENGTH_CHIPS));
int32_t 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);
int32_t 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);
@ -112,110 +102,70 @@ GalileoE5aDllPllTrackingFpga::GalileoE5aDllPllTrackingFpga(
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);
int32_t 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);
int32_t 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);
int32_t 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;
d_data_codes = nullptr;
// 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);
uint32_t device_base = configuration->property(role + ".device_base", 27);
trk_param_fpga.device_base = device_base;
//unsigned int multicorr_type = configuration->property(role + ".multicorr_type", 1);
trk_param_fpga.multicorr_type = 1; // 0 -> 3 correlators, 1 -> up to 5+1 correlators
//################# PRE-COMPUTE ALL THE CODES #################
unsigned int code_samples_per_chip = 1;
auto code_length_chips = static_cast<unsigned int>(GALILEO_E5A_CODE_LENGTH_CHIPS);
uint32_t code_samples_per_chip = 1;
auto code_length_chips = static_cast<uint32_t>(GALILEO_E5A_CODE_LENGTH_CHIPS);
auto *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;
d_ca_codes = static_cast<int32_t *>(volk_gnsssdr_malloc(static_cast<int32_t>(code_length_chips) * code_samples_per_chip * GALILEO_E5A_NUMBER_OF_CODES * sizeof(int32_t), volk_gnsssdr_get_alignment()));
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()));
d_data_codes = static_cast<int32_t *>(volk_gnsssdr_malloc((static_cast<uint32_t>(code_length_chips)) * code_samples_per_chip * GALILEO_E5A_NUMBER_OF_CODES * sizeof(int32_t), volk_gnsssdr_get_alignment()));
}
for (unsigned int PRN = 1; PRN <= GALILEO_E5A_NUMBER_OF_CODES; PRN++)
for (uint32_t 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++)
for (uint32_t s = 0; s < code_length_chips; s++)
{
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]);
d_ca_codes[static_cast<int32_t>(code_length_chips) * (PRN - 1) + s] = static_cast<int32_t>(aux_code[s].imag());
d_data_codes[static_cast<int32_t>(code_length_chips) * (PRN - 1) + s] = static_cast<int32_t>(aux_code[s].real());
}
}
else
{
for (unsigned int i = 0; i < code_length_chips; i++)
for (uint32_t s = 0; s < code_length_chips; s++)
{
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]);
d_ca_codes[static_cast<int32_t>(code_length_chips) * (PRN - 1) + s] = static_cast<int32_t>(aux_code[s].real());
}
}
}
volk_gnsssdr_free(aux_code);
volk_gnsssdr_free(tracking_code);
if (trk_param_fpga.track_pilot)
{
volk_gnsssdr_free(data_code);
}
trk_param_fpga.ca_codes = d_ca_codes;
trk_param_fpga.data_codes = d_data_codes;
trk_param_fpga.code_length_chips = code_length_chips;
trk_param_fpga.code_samples_per_chip = code_samples_per_chip; // 2 sample per chip
//################# MAKE TRACKING GNURadio object ###################
tracking_fpga_sc = dll_pll_veml_make_tracking_fpga(trk_param_fpga);
// if (item_type.compare("gr_complex") == 0)
// {
// item_size_ = sizeof(gr_complex);
// tracking_ = dll_pll_veml_make_tracking(trk_param_fpga);
// }
// else
// {
// item_size_ = sizeof(gr_complex);
// LOG(WARNING) << item_type << " unknown tracking item type.";
// }
channel_ = 0;
//DLOG(INFO) << "tracking(" << tracking_->unique_id() << ")";
DLOG(INFO) << "tracking(" << tracking_fpga_sc->unique_id() << ")";
}
@ -232,7 +182,6 @@ GalileoE5aDllPllTrackingFpga::~GalileoE5aDllPllTrackingFpga()
void GalileoE5aDllPllTrackingFpga::start_tracking()
{
//tracking_->start_tracking();
tracking_fpga_sc->start_tracking();
}
@ -242,16 +191,13 @@ void GalileoE5aDllPllTrackingFpga::start_tracking()
*/
void GalileoE5aDllPllTrackingFpga::set_channel(unsigned int channel)
{
//printf("blabla channel = %d\n", channel);
channel_ = channel;
//tracking_->set_channel(channel);
tracking_fpga_sc->set_channel(channel);
}
void GalileoE5aDllPllTrackingFpga::set_gnss_synchro(Gnss_Synchro *p_gnss_synchro)
{
//tracking_->set_gnss_synchro(p_gnss_synchro);
tracking_fpga_sc->set_gnss_synchro(p_gnss_synchro);
}
@ -276,13 +222,11 @@ void GalileoE5aDllPllTrackingFpga::disconnect(gr::top_block_sptr top_block)
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

@ -1,19 +1,12 @@
/*!
* \file galileo_e5a_dll_pll_tracking.h
* \file galileo_e5a_dll_pll_tracking_fpga.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>
* tracking block to a TrackingInterface for Galileo E5a signals for the FPGA
* \author Marc Majoral, 2019. mmajoral(at)cttc.cat
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
* Copyright (C) 2010-2019 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
@ -63,10 +56,10 @@ public:
return role_;
}
//! Returns "Galileo_E5a_DLL_PLL_Tracking"
//! Returns "Galileo_E5a_DLL_PLL_Tracking_Fpga"
inline std::string implementation() override
{
return "Galileo_E5a_DLL_PLL_Tracking";
return "Galileo_E5a_DLL_PLL_Tracking_Fpga";
}
inline size_t item_size() override
@ -99,14 +92,14 @@ public:
private:
dll_pll_veml_tracking_fpga_sptr tracking_fpga_sc;
size_t item_size_;
unsigned int channel_;
uint32_t channel_;
std::string role_;
unsigned int in_streams_;
unsigned int out_streams_;
uint32_t in_streams_;
uint32_t out_streams_;
int* d_ca_codes;
int* d_data_codes;
int32_t* d_ca_codes;
int32_t* d_data_codes;
bool d_track_pilot;
};

View File

@ -1,10 +1,8 @@
/*!
* \file gps_l1_ca_dll_pll_tracking_fpga.cc
* \brief Implementation of an adapter of a DLL+PLL tracking loop block
* for GPS L1 C/A to a TrackingInterface that uses the FPGA
* \author Marc Majoral, 2018, mmajoral(at)cttc.es
* Carlos Aviles, 2010. carlos.avilesr(at)googlemail.com
* Javier Arribas, 2011. jarribas(at)cttc.es
* for GPS L1 C/A to a TrackingInterface for the FPGA
* \author Marc Majoral, 2019, mmajoral(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,
@ -13,7 +11,7 @@
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
* Copyright (C) 2010-2019 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
@ -60,10 +58,8 @@ GpsL1CaDllPllTrackingFpga::GpsL1CaDllPllTrackingFpga(
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);
int32_t fs_in_deprecated = configuration->property("GNSS-SDR.internal_fs_hz", 2048000);
int32_t 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;
@ -86,9 +82,9 @@ GpsL1CaDllPllTrackingFpga::GpsL1CaDllPllTrackingFpga(
trk_param_fpga.early_late_space_chips = early_late_space_chips;
float early_late_space_narrow_chips = configuration->property(role + ".early_late_space_narrow_chips", 0.5);
trk_param_fpga.early_late_space_narrow_chips = early_late_space_narrow_chips;
int vector_length = std::round(fs_in / (GPS_L1_CA_CODE_RATE_HZ / GPS_L1_CA_CODE_LENGTH_CHIPS));
int32_t vector_length = std::round(fs_in / (GPS_L1_CA_CODE_RATE_HZ / GPS_L1_CA_CODE_LENGTH_CHIPS));
trk_param_fpga.vector_length = vector_length;
int symbols_extended_correlator = configuration->property(role + ".extend_correlation_symbols", 1);
int32_t symbols_extended_correlator = configuration->property(role + ".extend_correlation_symbols", 1);
if (symbols_extended_correlator < 1)
{
symbols_extended_correlator = 1;
@ -115,13 +111,13 @@ GpsL1CaDllPllTrackingFpga::GpsL1CaDllPllTrackingFpga(
trk_param_fpga.system = 'G';
char sig_[3] = "1C";
std::memcpy(trk_param_fpga.signal, sig_, 3);
int cn0_samples = configuration->property(role + ".cn0_samples", 20);
int32_t 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);
int32_t 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);
int32_t 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);
@ -132,16 +128,15 @@ GpsL1CaDllPllTrackingFpga::GpsL1CaDllPllTrackingFpga(
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);
uint32_t device_base = configuration->property(role + ".device_base", 3);
trk_param_fpga.device_base = device_base;
//unsigned int multicorr_type = configuration->property(role + ".multicorr_type", 0);
trk_param_fpga.multicorr_type = 0; //multicorr_type : 0 -> 3 correlators, 1 -> 5 correlators
//################# PRE-COMPUTE ALL THE CODES #################
d_ca_codes = static_cast<int*>(volk_gnsssdr_malloc(static_cast<int>(GPS_L1_CA_CODE_LENGTH_CHIPS * NUM_PRNs) * sizeof(int), volk_gnsssdr_get_alignment()));
for (unsigned int PRN = 1; PRN <= NUM_PRNs; PRN++)
d_ca_codes = static_cast<int32_t*>(volk_gnsssdr_malloc(static_cast<int32_t>(GPS_L1_CA_CODE_LENGTH_CHIPS * NUM_PRNs) * sizeof(int32_t), volk_gnsssdr_get_alignment()));
for (uint32_t PRN = 1; PRN <= NUM_PRNs; PRN++)
{
gps_l1_ca_code_gen_int(&d_ca_codes[(int(GPS_L1_CA_CODE_LENGTH_CHIPS)) * (PRN - 1)], PRN, 0);
gps_l1_ca_code_gen_int(&d_ca_codes[(int32_t(GPS_L1_CA_CODE_LENGTH_CHIPS)) * (PRN - 1)], PRN, 0);
}
trk_param_fpga.ca_codes = d_ca_codes;
trk_param_fpga.code_length_chips = GPS_L1_CA_CODE_LENGTH_CHIPS;

View File

@ -1,10 +1,8 @@
/*!
* \file gps_l1_ca_dll_pll_tracking_fpga.h
* \brief Interface of an adapter of a DLL+PLL tracking loop block
* for GPS L1 C/A to a TrackingInterface that uses the FPGA
* \author Marc Majoral, 2018. mmajoral(at)cttc.es
* Carlos Aviles, 2010. carlos.avilesr(at)googlemail.com
* Javier Arribas, 2011. jarribas(at)cttc.es
* for GPS L1 C/A to a TrackingInterface for the FPGA
* \author Marc Majoral, 2019, mmajoral(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,
@ -13,7 +11,7 @@
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
* Copyright (C) 2010-2019 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
@ -72,7 +70,7 @@ public:
inline size_t item_size() override
{
return item_size_;
return sizeof(int);
}
void connect(gr::top_block_sptr top_block) override;
@ -100,12 +98,11 @@ public:
private:
dll_pll_veml_tracking_fpga_sptr tracking_fpga_sc;
size_t item_size_;
unsigned int channel_;
uint32_t channel_;
std::string role_;
unsigned int in_streams_;
unsigned int out_streams_;
int* d_ca_codes;
uint32_t in_streams_;
uint32_t out_streams_;
int32_t* d_ca_codes;
};
#endif // GNSS_SDR_GPS_L1_CA_DLL_PLL_TRACKING_FPGA_H_

View File

@ -1,8 +1,8 @@
/*!
* \file gps_l2_m_dll_pll_tracking.cc
* \file gps_l2_m_dll_pll_tracking_fpga.cc
* \brief Implementation of an adapter of a DLL+PLL tracking loop block
* for GPS L1 C/A to a TrackingInterface
* \author Javier Arribas, 2015. jarribas(at)cttc.es
* for GPS L2C to a TrackingInterface
* \author Javier Arribas, 2019. 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,

View File

@ -1,9 +1,8 @@
/*!
* \file gps_l2_m_dll_pll_tracking.h
* \file gps_l2_m_dll_pll_tracking_fpga.h
* \brief Interface of an adapter of a DLL+PLL tracking loop block
* for GPS L1 C/A to a TrackingInterface
* \author Carlos Aviles, 2010. carlos.avilesr(at)googlemail.com
* Javier Arribas, 2011. jarribas(at)cttc.es
* for GPS L2C to a TrackingInterface
* \author Marc Majoral, 2019, mmajoral(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,
@ -63,7 +62,7 @@ public:
return role_;
}
//! Returns "GPS_L2_M_DLL_PLL_Tracking"
//! Returns "GPS_L2_M_DLL_PLL_Tracking_Fpga"
inline std::string implementation() override
{
return "GPS_L2_M_DLL_PLL_Tracking_Fpga";

View File

@ -1,8 +1,9 @@
/*!
* \file gps_l5_dll_pll_tracking.cc
* \file gps_l5_dll_pll_tracking_fpga.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
* \author Marc Majoral, 2019. mmajoral(at)cttc.cat
* Javier Arribas, 2019. 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,
@ -11,7 +12,7 @@
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
* Copyright (C) 2010-2019 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
@ -55,15 +56,11 @@ GpsL5DllPllTrackingFpga::GpsL5DllPllTrackingFpga(
ConfigurationInterface *configuration, const std::string &role,
unsigned int in_streams, unsigned int out_streams) : role_(role), in_streams_(in_streams), out_streams_(out_streams)
{
//printf("L5 TRK CLASS CREATED\n");
//dllpllconf_t trk_param;
Dll_Pll_Conf_Fpga trk_param_fpga = Dll_Pll_Conf_Fpga();
DLOG(INFO) << "role " << role;
//################# CONFIGURATION PARAMETERS ########################
//std::string default_item_type = "gr_complex";
//std::string item_type = configuration->property(role + ".item_type", default_item_type);
int fs_in_deprecated = configuration->property("GNSS-SDR.internal_fs_hz", 2048000);
int fs_in = configuration->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated);
int32_t fs_in_deprecated = configuration->property("GNSS-SDR.internal_fs_hz", 12500000);
int32_t 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;
@ -84,9 +81,9 @@ GpsL5DllPllTrackingFpga::GpsL5DllPllTrackingFpga(
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;
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)));
int32_t 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);
int32_t 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);
@ -112,103 +109,85 @@ GpsL5DllPllTrackingFpga::GpsL5DllPllTrackingFpga(
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);
int32_t 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);
int32_t 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);
int32_t 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);
double carrier_lock_th = configuration->property(role + ".carrier_lock_th", 0.75);
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);
uint32_t device_base = configuration->property(role + ".device_base", 27);
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;
auto code_length_chips = static_cast<unsigned int>(GPS_L5I_CODE_LENGTH_CHIPS);
//printf("TRK code_length_chips = %d\n", code_length_chips);
uint32_t code_samples_per_chip = 1;
auto code_length_chips = static_cast<uint32_t>(GPS_L5I_CODE_LENGTH_CHIPS);
float *tracking_code;
float *data_code;
float *data_code = nullptr;
tracking_code = static_cast<float *>(volk_gnsssdr_malloc(code_length_chips * sizeof(float), volk_gnsssdr_get_alignment()));
if (trk_param_fpga.track_pilot)
if (track_pilot)
{
data_code = static_cast<float *>(volk_gnsssdr_malloc(code_length_chips * sizeof(float), volk_gnsssdr_get_alignment()));
for (uint32_t i = 0; i < code_length_chips; i++)
{
data_code[i] = 0.0;
}
}
d_ca_codes = static_cast<int *>(volk_gnsssdr_malloc(static_cast<int>(code_length_chips * NUM_PRNs) * sizeof(int), volk_gnsssdr_get_alignment()));
d_ca_codes = static_cast<int32_t *>(volk_gnsssdr_malloc(static_cast<int32_t>(code_length_chips * NUM_PRNs) * sizeof(int32_t), volk_gnsssdr_get_alignment()));
if (trk_param_fpga.track_pilot)
if (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()));
d_data_codes = static_cast<int32_t *>(volk_gnsssdr_malloc((static_cast<uint32_t>(code_length_chips)) * NUM_PRNs * sizeof(int32_t), volk_gnsssdr_get_alignment()));
}
//printf("start \n");
for (unsigned int PRN = 1; PRN <= NUM_PRNs; PRN++)
for (uint32_t PRN = 1; PRN <= NUM_PRNs; PRN++)
{
if (track_pilot)
{
gps_l5q_code_gen_float(tracking_code, PRN);
gps_l5i_code_gen_float(data_code, PRN);
for (unsigned int s = 0; s < code_length_chips; s++)
for (uint32_t 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]);
d_ca_codes[static_cast<int32_t>(code_length_chips) * (PRN - 1) + s] = static_cast<int32_t>(tracking_code[s]);
d_data_codes[static_cast<int32_t>(code_length_chips) * (PRN - 1) + s] = static_cast<int32_t>(data_code[s]);
}
}
else
{
gps_l5i_code_gen_float(tracking_code, PRN);
for (unsigned int s = 0; s < code_length_chips; s++)
for (uint32_t 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]);
d_ca_codes[static_cast<int32_t>(code_length_chips) * (PRN - 1) + s] = static_cast<int32_t>(tracking_code[s]);
}
}
}
//printf("end \n");
delete[] tracking_code;
if (trk_param_fpga.track_pilot)
volk_gnsssdr_free(tracking_code);
if (track_pilot)
{
delete[] data_code;
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.";
// }
//printf("call \n");
tracking_fpga_sc = dll_pll_veml_make_tracking_fpga(trk_param_fpga);
//printf("end2 \n");
channel_ = 0;
DLOG(INFO) << "tracking(" << tracking_fpga_sc->unique_id() << ")";
}

View File

@ -1,8 +1,9 @@
/*!
* \file gps_l5_dll_pll_tracking.h
* \file gps_l5_dll_pll_tracking_fpga.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
* \author Marc Majoral, 2019. mmajoral(at)cttc.cat
* Javier Arribas, 2019. 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,
@ -11,7 +12,7 @@
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
* Copyright (C) 2010-2019 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
@ -69,7 +70,7 @@ public:
inline size_t item_size() override
{
return item_size_;
return sizeof(int);
}
void connect(gr::top_block_sptr top_block) override;
@ -95,16 +96,14 @@ public:
void stop_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_;
uint32_t channel_;
std::string role_;
unsigned int in_streams_;
unsigned int out_streams_;
uint32_t in_streams_;
uint32_t out_streams_;
bool d_track_pilot;
int* d_ca_codes;
int* d_data_codes;
int32_t* d_ca_codes;
int32_t* d_data_codes;
};
#endif // GNSS_SDR_GPS_L5_DLL_PLL_TRACKING_FPGA_H_

View File

@ -157,8 +157,8 @@ dll_pll_veml_tracking::dll_pll_veml_tracking(const Dll_Pll_Conf &conf_) : gr::bl
n++;
}
}
d_symbol_history.resize(GPS_CA_PREAMBLE_LENGTH_SYMBOLS); // Change fixed buffer size
d_symbol_history.clear(); // Clear all the elements in the buffer
d_symbol_history.set_capacity(GPS_CA_PREAMBLE_LENGTH_SYMBOLS); // Change fixed buffer size
d_symbol_history.clear(); // Clear all the elements in the buffer
}
else if (signal_type == "2S")
{
@ -425,6 +425,7 @@ dll_pll_veml_tracking::dll_pll_veml_tracking(const Dll_Pll_Conf &conf_) : gr::bl
}
// --- Initializations ---
d_Prompt_circular_buffer.set_capacity(d_secondary_code_length);
multicorrelator_cpu.set_high_dynamics_resampler(trk_parameters.high_dyn);
// Initial code frequency basis of NCO
d_code_freq_chips = d_code_chip_rate;
@ -466,13 +467,13 @@ dll_pll_veml_tracking::dll_pll_veml_tracking(const Dll_Pll_Conf &conf_) : gr::bl
clear_tracking_vars();
if (trk_parameters.smoother_length > 0)
{
d_carr_ph_history.resize(trk_parameters.smoother_length * 2);
d_code_ph_history.resize(trk_parameters.smoother_length * 2);
d_carr_ph_history.set_capacity(trk_parameters.smoother_length * 2);
d_code_ph_history.set_capacity(trk_parameters.smoother_length * 2);
}
else
{
d_carr_ph_history.resize(1);
d_code_ph_history.resize(1);
d_carr_ph_history.set_capacity(1);
d_code_ph_history.set_capacity(1);
}
d_dump = trk_parameters.dump;
@ -668,7 +669,7 @@ void dll_pll_veml_tracking::start_tracking()
n++;
}
}
d_symbol_history.resize(22); // Change fixed buffer size
d_symbol_history.set_capacity(22); // Change fixed buffer size
d_symbol_history.clear();
}
}
@ -710,7 +711,7 @@ void dll_pll_veml_tracking::start_tracking()
// enable tracking pull-in
d_state = 1;
d_cloop = true;
d_Prompt_buffer_deque.clear();
d_Prompt_circular_buffer.clear();
d_last_prompt = gr_complex(0.0, 0.0);
}
@ -771,7 +772,7 @@ bool dll_pll_veml_tracking::acquire_secondary()
int32_t corr_value = 0;
for (uint32_t i = 0; i < d_secondary_code_length; i++)
{
if (d_Prompt_buffer_deque.at(i).real() < 0.0) // symbols clipping
if (d_Prompt_circular_buffer[i].real() < 0.0) // symbols clipping
{
if (d_secondary_code_string->at(i) == '0')
{
@ -927,7 +928,7 @@ void dll_pll_veml_tracking::clear_tracking_vars()
d_code_error_chips = 0.0;
d_code_error_filt_chips = 0.0;
d_current_symbol = 0;
d_Prompt_buffer_deque.clear();
d_Prompt_circular_buffer.clear();
d_last_prompt = gr_complex(0.0, 0.0);
d_carrier_phase_rate_step_rad = 0.0;
d_code_phase_rate_step_chips = 0.0;
@ -963,9 +964,9 @@ void dll_pll_veml_tracking::update_tracking_vars()
double tmp_samples = 0.0;
for (unsigned int k = 0; k < trk_parameters.smoother_length; k++)
{
tmp_cp1 += d_carr_ph_history.at(k).first;
tmp_cp2 += d_carr_ph_history.at(trk_parameters.smoother_length * 2 - k - 1).first;
tmp_samples += d_carr_ph_history.at(trk_parameters.smoother_length * 2 - k - 1).second;
tmp_cp1 += d_carr_ph_history[k].first;
tmp_cp2 += d_carr_ph_history[trk_parameters.smoother_length * 2 - k - 1].first;
tmp_samples += d_carr_ph_history[trk_parameters.smoother_length * 2 - k - 1].second;
}
tmp_cp1 /= static_cast<double>(trk_parameters.smoother_length);
tmp_cp2 /= static_cast<double>(trk_parameters.smoother_length);
@ -977,7 +978,6 @@ void dll_pll_veml_tracking::update_tracking_vars()
d_rem_carr_phase_rad += static_cast<float>(d_carrier_phase_step_rad * static_cast<double>(d_current_prn_length_samples) + 0.5 * d_carrier_phase_rate_step_rad * static_cast<double>(d_current_prn_length_samples) * static_cast<double>(d_current_prn_length_samples));
d_rem_carr_phase_rad = fmod(d_rem_carr_phase_rad, PI_2);
// carrier phase accumulator
//double a = d_carrier_phase_step_rad * static_cast<double>(d_current_prn_length_samples);
//double b = 0.5 * d_carrier_phase_rate_step_rad * static_cast<double>(d_current_prn_length_samples) * static_cast<double>(d_current_prn_length_samples);
@ -997,9 +997,9 @@ void dll_pll_veml_tracking::update_tracking_vars()
double tmp_samples = 0.0;
for (unsigned int k = 0; k < trk_parameters.smoother_length; k++)
{
tmp_cp1 += d_code_ph_history.at(k).first;
tmp_cp2 += d_code_ph_history.at(trk_parameters.smoother_length * 2 - k - 1).first;
tmp_samples += d_code_ph_history.at(trk_parameters.smoother_length * 2 - k - 1).second;
tmp_cp1 += d_code_ph_history[k].first;
tmp_cp2 += d_code_ph_history[trk_parameters.smoother_length * 2 - k - 1].first;
tmp_samples += d_code_ph_history[trk_parameters.smoother_length * 2 - k - 1].second;
}
tmp_cp1 /= static_cast<double>(trk_parameters.smoother_length);
tmp_cp2 /= static_cast<double>(trk_parameters.smoother_length);
@ -1564,8 +1564,8 @@ int dll_pll_veml_tracking::general_work(int noutput_items __attribute__((unused)
if (d_secondary)
{
// ####### SECONDARY CODE LOCK #####
d_Prompt_buffer_deque.push_back(*d_Prompt);
if (d_Prompt_buffer_deque.size() == d_secondary_code_length)
d_Prompt_circular_buffer.push_back(*d_Prompt);
if (d_Prompt_circular_buffer.size() == d_secondary_code_length)
{
next_state = acquire_secondary();
if (next_state)
@ -1575,8 +1575,6 @@ int dll_pll_veml_tracking::general_work(int noutput_items __attribute__((unused)
std::cout << systemName << " " << signal_pretty_name << " secondary code locked in channel " << d_channel
<< " for satellite " << Gnss_Satellite(systemName, d_acquisition_gnss_synchro->PRN) << std::endl;
}
d_Prompt_buffer_deque.pop_front();
}
}
else if (d_symbols_per_bit > 1) //Signal does not have secondary code. Search a bit transition by sign change
@ -1589,9 +1587,10 @@ int dll_pll_veml_tracking::general_work(int noutput_items __attribute__((unused)
int32_t corr_value = 0;
if ((static_cast<int32_t>(d_symbol_history.size()) == d_preamble_length_symbols)) // and (d_make_correlation or !d_flag_frame_sync))
{
for (int32_t i = 0; i < d_preamble_length_symbols; i++)
int i = 0;
for (const auto &iter : d_symbol_history)
{
if (d_symbol_history.at(i) < 0) // symbols clipping
if (iter < 0.0) // symbols clipping
{
corr_value -= d_preambles_symbols[i];
}
@ -1599,6 +1598,7 @@ int dll_pll_veml_tracking::general_work(int noutput_items __attribute__((unused)
{
corr_value += d_preambles_symbols[i];
}
i++;
}
}
if (corr_value == d_preamble_length_symbols)
@ -1667,7 +1667,7 @@ int dll_pll_veml_tracking::general_work(int noutput_items __attribute__((unused)
d_L_accu = gr_complex(0.0, 0.0);
d_VL_accu = gr_complex(0.0, 0.0);
d_last_prompt = gr_complex(0.0, 0.0);
d_Prompt_buffer_deque.clear();
d_Prompt_circular_buffer.clear();
d_current_symbol = 0;
if (d_enable_extended_integration)

View File

@ -92,7 +92,7 @@ private:
uint32_t d_channel;
Gnss_Synchro *d_acquisition_gnss_synchro;
//Signal parameters
// Signal parameters
bool d_secondary;
bool interchange_iq;
double d_signal_carrier_freq;
@ -111,9 +111,10 @@ private:
int32_t d_preamble_length_symbols;
boost::circular_buffer<float> d_symbol_history;
//tracking state machine
// tracking state machine
int32_t d_state;
//Integration period in samples
// Integration period in samples
int32_t d_correlation_length_ms;
int32_t d_n_correlator_taps;
@ -188,11 +189,10 @@ private:
// CN0 estimation and lock detector
int32_t d_cn0_estimation_counter;
int32_t d_carrier_lock_fail_counter;
std::deque<float> d_carrier_lock_detector_queue;
double d_carrier_lock_test;
double d_CN0_SNV_dB_Hz;
double d_carrier_lock_threshold;
std::deque<gr_complex> d_Prompt_buffer_deque;
boost::circular_buffer<gr_complex> d_Prompt_circular_buffer;
gr_complex *d_Prompt_buffer;
// file dump

View File

@ -1,19 +1,12 @@
/*!
* \file gps_l1_ca_dll_pll_tracking_fpga.h
* \brief Interface of a code DLL + carrier PLL tracking block
* \author Marc Majoral, 2018. marc.majoral(at)cttc.es
* Carlos Aviles, 2010. carlos.avilesr(at)googlemail.com
* Javier Arribas, 2011. jarribas(at)cttc.es
* Cillian O'Driscoll, 2017. cillian.odriscoll(at)gmail.com
*
* Code DLL + carrier PLL according to the algorithms described in:
* K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen,
* A Software-Defined GPS and Galileo Receiver. A Single-Frequency Approach,
* Birkhauser, 2007
* \file dll_pll_veml_tracking_fpga.h
* \brief Implementation of a code DLL + carrier PLL tracking block using an FPGA.
* \author Marc Majoral, 2019. marc.majoral(at)cttc.es
* \author Javier Arribas, 2019. jarribas(at)cttc.es
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2015 (see AUTHORS file for a list of contributors)
* Copyright (C) 2010-2019 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
@ -31,7 +24,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNSS-SDR. If not, see <http://www.gnu.org/licenses/>.
* along with GNSS-SDR. If not, see <https://www.gnu.org/licenses/>.
*
* -------------------------------------------------------------------------
*/
@ -49,18 +42,18 @@
#include <fstream>
#include <map>
#include <queue>
#include <string>
#include <utility>
//#include <string>
class dll_pll_veml_tracking_fpga;
typedef boost::shared_ptr<dll_pll_veml_tracking_fpga>
dll_pll_veml_tracking_fpga_sptr;
using dll_pll_veml_tracking_fpga_sptr = boost::shared_ptr<dll_pll_veml_tracking_fpga>;
dll_pll_veml_tracking_fpga_sptr dll_pll_veml_make_tracking_fpga(const Dll_Pll_Conf_Fpga &conf_);
/*!
* \brief This class implements a DLL + PLL tracking loop block
* \brief This class implements a code DLL + carrier PLL tracking block.
*/
class dll_pll_veml_tracking_fpga : public gr::block
{
@ -71,6 +64,7 @@ public:
void set_gnss_synchro(Gnss_Synchro *p_gnss_synchro);
void start_tracking();
void stop_tracking();
int general_work(int noutput_items, gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items, gr_vector_void_star &output_items);
@ -84,6 +78,7 @@ private:
bool cn0_and_tracking_lock_status(double coh_integration_time_s);
bool acquire_secondary();
void do_correlation_step(void);
void run_dll_pll();
void update_tracking_vars();
void clear_tracking_vars();
@ -91,9 +86,10 @@ private:
void log_data(bool integrating);
int32_t save_matfile();
void run_state_2(Gnss_Synchro &current_synchro_data);
// tracking configuration vars
Dll_Pll_Conf_Fpga trk_parameters;
//dllpllconf_fpga_t trk_parameters;
bool d_veml;
bool d_cloop;
uint32_t d_channel;
@ -119,14 +115,20 @@ private:
//tracking state machine
int32_t d_state;
bool d_synchonizing;
//Integration period in samples
int32_t d_correlation_length_ms;
int32_t d_n_correlator_taps;
float *d_tracking_code;
float *d_data_code;
float *d_local_code_shift_chips;
float *d_prompt_data_shift;
std::shared_ptr<fpga_multicorrelator_8sc> multicorrelator_fpga;
std::shared_ptr<Fpga_Multicorrelator_8sc> multicorrelator_fpga;
/* TODO: currently the multicorrelator does not support adding extra correlator
with different local code, thus we need extra multicorrelator instance.
Implement this functionality inside multicorrelator class
as an enhancement to increase the performance
*/
gr_complex *d_correlator_outs;
gr_complex *d_Very_Early;
gr_complex *d_Early;
@ -148,10 +150,14 @@ private:
gr_complex *d_Prompt_Data;
double d_code_phase_step_chips;
double d_code_phase_rate_step_chips;
boost::circular_buffer<std::pair<double, double>> d_code_ph_history;
double d_carrier_phase_step_rad;
double d_carrier_phase_rate_step_rad;
boost::circular_buffer<std::pair<double, double>> d_carr_ph_history;
// remaining code phase and carrier phase between tracking loops
double d_rem_code_phase_samples;
double d_rem_carr_phase_rad;
float d_rem_carr_phase_rad;
// PLL and DLL filter library
Tracking_2nd_DLL_filter d_code_loop_filter;
@ -166,12 +172,10 @@ private:
double d_carr_error_filt_hz;
double d_code_error_chips;
double d_code_error_filt_chips;
double d_K_blk_samples;
double d_code_freq_chips;
double d_carrier_doppler_hz;
double d_acc_carrier_phase_rad;
double d_rem_code_phase_chips;
double d_code_phase_samples;
double T_chip_seconds;
double T_prn_seconds;
double T_prn_samples;
@ -181,11 +185,13 @@ private:
// processing samples counters
uint64_t d_sample_counter;
uint64_t d_acq_sample_stamp;
uint64_t d_absolute_samples_offset;
// CN0 estimation and lock detector
int32_t d_cn0_estimation_counter;
int32_t d_carrier_lock_fail_counter;
std::deque<float> d_carrier_lock_detector_queue;
double d_carrier_lock_test;
double d_CN0_SNV_dB_Hz;
double d_carrier_lock_threshold;
@ -202,7 +208,6 @@ private:
int32_t d_correlation_length_samples;
int32_t d_next_prn_length_samples;
uint64_t d_sample_counter_next;
uint32_t d_pull_in = 0U;
};
#endif //GNSS_SDR_DLL_PLL_VEML_TRACKING_FPGA_H

View File

@ -1,12 +1,13 @@
/*!
* \file dll_pll_conf.cc
* \file dll_pll_conf_fpga.cc
* \brief Class that contains all the configuration parameters for generic
* tracking block based on a DLL and a PLL.
* tracking block based on a DLL and a PLL for the FPGA.
* \author Marc Majoral, 2019. mmajoral(at)cttc.cat
* \author Javier Arribas, 2018. jarribas(at)cttc.es
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2018 (see AUTHORS file for a list of contributors)
* Copyright (C) 2010-2019 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
@ -36,12 +37,14 @@
Dll_Pll_Conf_Fpga::Dll_Pll_Conf_Fpga()
{
/* DLL/PLL tracking configuration */
high_dyn = false;
smoother_length = 10;
fs_in = 0.0;
vector_length = 0U;
dump = false;
dump_mat = true;
dump_filename = std::string("./dll_pll_dump.dat");
pll_bw_hz = 40.0;
pll_bw_hz = 35.0;
dll_bw_hz = 2.0;
pll_bw_narrow_hz = 5.0;
dll_bw_narrow_hz = 0.75;

View File

@ -1,13 +1,15 @@
/*!
* \file dll_pll_conf.h
* \brief Class that contains all the configuration parameters for generic tracking block based on a DLL and a PLL.
* \file dll_pll_conf_fpga.h
* \brief Class that contains all the configuration parameters for generic
* tracking block based on a DLL and a PLL for the FPGA.
* \author Marc Majoral, 2019. mmajoral(at)cttc.cat
* \author Javier Arribas, 2018. jarribas(at)cttc.es
*
* Class that contains all the configuration parameters for generic tracking block based on a DLL and a PLL.
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2018 (see AUTHORS file for a list of contributors)
* Copyright (C) 2010-2019 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
@ -54,9 +56,11 @@ public:
float early_late_space_narrow_chips;
float very_early_late_space_narrow_chips;
int32_t extend_correlation_symbols;
bool high_dyn;
int32_t cn0_samples;
int32_t cn0_min;
int32_t max_lock_fail;
uint32_t smoother_length;
double carrier_lock_th;
bool track_pilot;
char system;

View File

@ -1,17 +1,17 @@
/*!
* \file fpga_multicorrelator_8sc.cc
* \brief High optimized FPGA vector correlator class
* \file fpga_multicorrelator.cc
* \brief FPGA vector correlator class
* \authors <ul>
* <li> Marc Majoral, 2017. mmajoral(at)cttc.cat
* <li> Javier Arribas, 2015. jarribas(at)cttc.es
* <li> Marc Majoral, 2019. mmajoral(at)cttc.cat
* <li> Javier Arribas, 2019. jarribas(at)cttc.es
* </ul>
*
* Class that controls and executes a high optimized vector correlator
* Class that controls and executes a highly optimized vector correlator
* class in the FPGA
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2018 (see AUTHORS file for a list of contributors)
* Copyright (C) 2010-2019 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
@ -35,41 +35,23 @@
*/
#include "fpga_multicorrelator.h"
#include <cmath>
// FPGA stuff
#include <new>
// libraries used by DMA test code and GIPO test code
#include <cerrno>
#include <cstdio>
#include <fcntl.h>
#include <unistd.h>
// libraries used by DMA test code
#include <glog/logging.h>
#include <cassert>
#include <cerrno>
#include <cmath>
#include <csignal>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <fcntl.h>
#include <new>
#include <string>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
// libraries used by GPIO test code
#include <csignal>
#include <cstdlib>
#include <sys/mman.h>
// logging
#include <glog/logging.h>
// string manipulation
#include <string>
#include <utility>
// constants
#include "GPS_L1_CA.h"
//#include "gps_sdr_signal_processing.h"
#define NUM_PRNs 32
// FPGA register access constants
#define PAGE_SIZE 0x10000
#define MAX_LENGTH_DEVICEIO_NAME 50
#define CODE_RESAMPLER_NUM_BITS_PRECISION 20
@ -84,82 +66,23 @@
#define LOCAL_CODE_FPGA_ENABLE_WRITE_MEMORY 0x0C000000
#define TEST_REGISTER_TRACK_WRITEVAL 0x55AA
uint64_t fpga_multicorrelator_8sc::read_sample_counter()
{
uint64_t sample_counter_tmp, sample_counter_msw_tmp;
sample_counter_tmp = d_map_base[d_SAMPLE_COUNTER_REG_ADDR_LSW];
sample_counter_msw_tmp = d_map_base[d_SAMPLE_COUNTER_REG_ADDR_MSW];
sample_counter_msw_tmp = sample_counter_msw_tmp << 32;
sample_counter_tmp = sample_counter_tmp + sample_counter_msw_tmp; // 2^32
//return d_map_base[d_SAMPLE_COUNTER_REG_ADDR];
return sample_counter_tmp;
}
#ifndef TEMP_FAILURE_RETRY
#define TEMP_FAILURE_RETRY(exp) \
({ \
decltype(exp) _rc; \
do \
{ \
_rc = (exp); \
} \
while (_rc == -1 && errno == EINTR); \
_rc; \
})
#endif
void fpga_multicorrelator_8sc::set_initial_sample(uint64_t samples_offset)
{
d_initial_sample_counter = samples_offset;
//printf("www writing d map base %d = d_initial_sample_counter = %d\n", d_INITIAL_COUNTER_VALUE_REG_ADDR, d_initial_sample_counter);
d_map_base[d_INITIAL_COUNTER_VALUE_REG_ADDR_LSW] = (d_initial_sample_counter & 0xFFFFFFFF);
d_map_base[d_INITIAL_COUNTER_VALUE_REG_ADDR_MSW] = (d_initial_sample_counter >> 32) & 0xFFFFFFFF;
}
//void fpga_multicorrelator_8sc::set_local_code_and_taps(int32_t code_length_chips,
// float *shifts_chips, int32_t PRN)
void fpga_multicorrelator_8sc::set_local_code_and_taps(float *shifts_chips, float *prompt_data_shift, int32_t PRN)
{
d_shifts_chips = shifts_chips;
d_prompt_data_shift = prompt_data_shift;
//d_code_length_chips = code_length_chips;
fpga_multicorrelator_8sc::fpga_configure_tracking_gps_local_code(PRN);
}
void fpga_multicorrelator_8sc::set_output_vectors(gr_complex *corr_out, gr_complex *Prompt_Data)
{
d_corr_out = corr_out;
d_Prompt_Data = Prompt_Data;
}
void fpga_multicorrelator_8sc::update_local_code(float rem_code_phase_chips)
{
d_rem_code_phase_chips = rem_code_phase_chips;
//printf("uuuuu d_rem_code_phase_chips = %f\n", d_rem_code_phase_chips);
fpga_multicorrelator_8sc::fpga_compute_code_shift_parameters();
fpga_multicorrelator_8sc::fpga_configure_code_parameters_in_fpga();
}
void fpga_multicorrelator_8sc::Carrier_wipeoff_multicorrelator_resampler(
float rem_carrier_phase_in_rad, float phase_step_rad,
float rem_code_phase_chips, float code_phase_step_chips,
int32_t signal_length_samples)
{
update_local_code(rem_code_phase_chips);
d_rem_carrier_phase_in_rad = rem_carrier_phase_in_rad;
d_code_phase_step_chips = code_phase_step_chips;
d_phase_step_rad = phase_step_rad;
d_correlator_length_samples = signal_length_samples;
fpga_multicorrelator_8sc::fpga_compute_signal_parameters_in_fpga();
fpga_multicorrelator_8sc::fpga_configure_signal_parameters_in_fpga();
fpga_multicorrelator_8sc::fpga_launch_multicorrelator_fpga();
int32_t irq_count;
ssize_t nb;
//printf("$$$$$ waiting for interrupt ... \n");
nb = read(d_device_descriptor, &irq_count, sizeof(irq_count));
//printf("$$$$$ interrupt received ... \n");
if (nb != sizeof(irq_count))
{
printf("Tracking_module Read failed to retrieve 4 bytes!\n");
printf("Tracking_module Interrupt number %d\n", irq_count);
}
fpga_multicorrelator_8sc::read_tracking_gps_results();
}
fpga_multicorrelator_8sc::fpga_multicorrelator_8sc(int32_t n_correlators,
Fpga_Multicorrelator_8sc::Fpga_Multicorrelator_8sc(int32_t n_correlators,
std::string device_name, uint32_t device_base, int32_t *ca_codes, int32_t *data_codes, uint32_t code_length_chips, bool track_pilot,
uint32_t multicorr_type, uint32_t code_samples_per_chip)
{
//printf("tracking fpga class created\n");
d_n_correlators = n_correlators;
d_device_name = std::move(device_name);
d_device_base = device_base;
@ -184,6 +107,7 @@ fpga_multicorrelator_8sc::fpga_multicorrelator_8sc(int32_t n_correlators,
}
d_shifts_chips = nullptr;
d_prompt_data_shift = nullptr;
d_Prompt_Data = nullptr;
d_corr_out = nullptr;
d_code_length_chips = 0;
d_rem_code_phase_chips = 0;
@ -194,112 +118,107 @@ fpga_multicorrelator_8sc::fpga_multicorrelator_8sc(int32_t n_correlators,
d_phase_step_rad_int = 0;
d_initial_sample_counter = 0;
d_channel = 0;
d_correlator_length_samples = 0,
//d_code_length = code_length;
d_code_length_chips = code_length_chips;
d_correlator_length_samples = 0;
d_code_phase_step_chips_num = 0;
d_code_length_chips = code_length_chips;
d_ca_codes = ca_codes;
d_data_codes = data_codes;
d_multicorr_type = multicorr_type;
d_code_samples_per_chip = code_samples_per_chip;
// set up register mapping
// write-only registers
d_CODE_PHASE_STEP_CHIPS_NUM_REG_ADDR = 0;
d_INITIAL_INDEX_REG_BASE_ADDR = 1;
// if (d_multicorr_type == 0)
// {
// // multicorrelator with 3 correlators (16 registers only)
// d_INITIAL_INTERP_COUNTER_REG_BASE_ADDR = 4;
// d_NSAMPLES_MINUS_1_REG_ADDR = 7;
// d_CODE_LENGTH_MINUS_1_REG_ADDR = 8;
// d_REM_CARR_PHASE_RAD_REG_ADDR = 9;
// d_PHASE_STEP_RAD_REG_ADDR = 10;
// d_PROG_MEMS_ADDR = 11;
// d_DROP_SAMPLES_REG_ADDR = 12;
// d_INITIAL_COUNTER_VALUE_REG_ADDR = 13;
// d_START_FLAG_ADDR = 14;
// }
// else
// {
// other types of multicorrelators (32 registers)
d_INITIAL_INTERP_COUNTER_REG_BASE_ADDR = 7;
d_NSAMPLES_MINUS_1_REG_ADDR = 13;
d_CODE_LENGTH_MINUS_1_REG_ADDR = 14;
d_REM_CARR_PHASE_RAD_REG_ADDR = 15;
d_PHASE_STEP_RAD_REG_ADDR = 16;
d_PROG_MEMS_ADDR = 17;
d_DROP_SAMPLES_REG_ADDR = 18;
d_INITIAL_COUNTER_VALUE_REG_ADDR_LSW = 19;
d_INITIAL_COUNTER_VALUE_REG_ADDR_MSW = 20;
d_START_FLAG_ADDR = 30;
// }
//printf("d_n_correlators = %d\n", d_n_correlators);
//printf("d_multicorr_type = %d\n", d_multicorr_type);
// read-write registers
// if (d_multicorr_type == 0)
// {
// // multicorrelator with 3 correlators (16 registers only)
// d_TEST_REG_ADDR = 15;
// }
// else
// {
// other types of multicorrelators (32 registers)
d_TEST_REG_ADDR = 31;
// }
// result 2's complement saturation value
// if (d_multicorr_type == 0)
// {
// // multicorrelator with 3 correlators (16 registers only)
// d_result_SAT_value = 1048576; // 21 bits 2's complement -> 2^20
// }
// else
// {
// // other types of multicorrelators (32 registers)
// d_result_SAT_value = 4194304; // 23 bits 2's complement -> 2^22
// }
// read only registers
d_RESULT_REG_REAL_BASE_ADDR = 1;
// if (d_multicorr_type == 0)
// {
// // multicorrelator with 3 correlators (16 registers only)
// d_RESULT_REG_IMAG_BASE_ADDR = 4;
// d_RESULT_REG_DATA_REAL_BASE_ADDR = 0; // no pilot tracking
// d_RESULT_REG_DATA_IMAG_BASE_ADDR = 0;
// d_SAMPLE_COUNTER_REG_ADDR = 7;
//
// }
// else
// {
// other types of multicorrelators (32 registers)
d_RESULT_REG_IMAG_BASE_ADDR = 7;
d_RESULT_REG_DATA_REAL_BASE_ADDR = 6; // no pilot tracking
d_RESULT_REG_DATA_IMAG_BASE_ADDR = 12;
d_SAMPLE_COUNTER_REG_ADDR_LSW = 13;
d_SAMPLE_COUNTER_REG_ADDR_MSW = 14;
// }
//printf("d_SAMPLE_COUNTER_REG_ADDR = %d\n", d_SAMPLE_COUNTER_REG_ADDR);
//printf("mmmmmmmmmmmmm d_n_correlators = %d\n", d_n_correlators);
DLOG(INFO) << "TRACKING FPGA CLASS CREATED";
}
fpga_multicorrelator_8sc::~fpga_multicorrelator_8sc()
Fpga_Multicorrelator_8sc::~Fpga_Multicorrelator_8sc()
{
//delete[] d_ca_codes;
close_device();
if (d_initial_index != nullptr)
{
volk_gnsssdr_free(d_initial_index);
}
if (d_initial_interp_counter != nullptr)
{
volk_gnsssdr_free(d_initial_interp_counter);
}
}
bool fpga_multicorrelator_8sc::free()
uint64_t Fpga_Multicorrelator_8sc::read_sample_counter()
{
uint64_t sample_counter_tmp, sample_counter_msw_tmp;
sample_counter_tmp = d_map_base[SAMPLE_COUNTER_REG_ADDR_LSW];
sample_counter_msw_tmp = d_map_base[SAMPLE_COUNTER_REG_ADDR_MSW];
sample_counter_msw_tmp = sample_counter_msw_tmp << 32;
sample_counter_tmp = sample_counter_tmp + sample_counter_msw_tmp; // 2^32
return sample_counter_tmp;
}
void Fpga_Multicorrelator_8sc::set_initial_sample(uint64_t samples_offset)
{
d_initial_sample_counter = samples_offset;
d_map_base[INITIAL_COUNTER_VALUE_REG_ADDR_LSW] = (d_initial_sample_counter & 0xFFFFFFFF);
d_map_base[INITIAL_COUNTER_VALUE_REG_ADDR_MSW] = (d_initial_sample_counter >> 32) & 0xFFFFFFFF;
}
void Fpga_Multicorrelator_8sc::set_local_code_and_taps(float *shifts_chips, float *prompt_data_shift, int32_t PRN)
{
d_shifts_chips = shifts_chips;
d_prompt_data_shift = prompt_data_shift;
Fpga_Multicorrelator_8sc::fpga_configure_tracking_gps_local_code(PRN);
}
void Fpga_Multicorrelator_8sc::set_output_vectors(gr_complex *corr_out, gr_complex *Prompt_Data)
{
d_corr_out = corr_out;
d_Prompt_Data = Prompt_Data;
}
void Fpga_Multicorrelator_8sc::update_local_code(float rem_code_phase_chips)
{
d_rem_code_phase_chips = rem_code_phase_chips;
Fpga_Multicorrelator_8sc::fpga_compute_code_shift_parameters();
Fpga_Multicorrelator_8sc::fpga_configure_code_parameters_in_fpga();
}
void Fpga_Multicorrelator_8sc::Carrier_wipeoff_multicorrelator_resampler(
float rem_carrier_phase_in_rad,
float phase_step_rad,
float carrier_phase_rate_step_rad __attribute__((unused)),
float rem_code_phase_chips,
float code_phase_step_chips __attribute__((unused)),
float code_phase_rate_step_chips __attribute__((unused)),
int32_t signal_length_samples)
{
update_local_code(rem_code_phase_chips);
d_rem_carrier_phase_in_rad = rem_carrier_phase_in_rad;
d_code_phase_step_chips = code_phase_step_chips;
d_phase_step_rad = phase_step_rad;
d_correlator_length_samples = signal_length_samples;
Fpga_Multicorrelator_8sc::fpga_compute_signal_parameters_in_fpga();
Fpga_Multicorrelator_8sc::fpga_configure_signal_parameters_in_fpga();
Fpga_Multicorrelator_8sc::fpga_launch_multicorrelator_fpga();
int32_t irq_count;
ssize_t nb;
nb = read(d_device_descriptor, &irq_count, sizeof(irq_count));
if (nb != sizeof(irq_count))
{
std::cout << "Tracking_module Read failed to retrieve 4 bytes!" << std::endl;
std::cout << "Tracking_module Interrupt number " << irq_count << std::endl;
}
Fpga_Multicorrelator_8sc::read_tracking_gps_results();
}
bool Fpga_Multicorrelator_8sc::free()
{
// unlock the channel
fpga_multicorrelator_8sc::unlock_channel();
Fpga_Multicorrelator_8sc::unlock_channel();
// free the FPGA dynamically created variables
if (d_initial_index != nullptr)
@ -318,9 +237,8 @@ bool fpga_multicorrelator_8sc::free()
}
void fpga_multicorrelator_8sc::set_channel(uint32_t channel)
void Fpga_Multicorrelator_8sc::set_channel(uint32_t channel)
{
//printf("www trk set channel\n");
char device_io_name[MAX_LENGTH_DEVICEIO_NAME]; // driver io name
d_channel = channel;
@ -332,20 +250,13 @@ void fpga_multicorrelator_8sc::set_channel(uint32_t channel)
mergedname = d_device_name + devicebasetemp.str();
strcpy(device_io_name, mergedname.c_str());
//printf("ppps opening device %s\n", device_io_name);
std::cout << "trk device_io_name = " << device_io_name << std::endl;
if ((d_device_descriptor = open(device_io_name, O_RDWR | O_SYNC)) == -1)
{
LOG(WARNING) << "Cannot open deviceio" << device_io_name;
std::cout << "Cannot open deviceio" << device_io_name << std::endl;
//printf("error opening device\n");
}
// else
// {
// std::cout << "deviceio" << device_io_name << " opened successfully" << std::endl;
//
// }
d_map_base = reinterpret_cast<volatile uint32_t *>(mmap(nullptr, PAGE_SIZE,
PROT_READ | PROT_WRITE, MAP_SHARED, d_device_descriptor, 0));
@ -354,79 +265,47 @@ void fpga_multicorrelator_8sc::set_channel(uint32_t channel)
LOG(WARNING) << "Cannot map the FPGA tracking module "
<< d_channel << "into user memory";
std::cout << "Cannot map deviceio" << device_io_name << std::endl;
//printf("error mapping registers\n");
}
// else
// {
// std::cout << "deviceio" << device_io_name << "mapped successfully" << std::endl;
// }
// else
// {
// printf("trk mapping registers succes\n"); // this is for debug -- remove !
// }
// sanity check : check test register
uint32_t writeval = TEST_REGISTER_TRACK_WRITEVAL;
uint32_t readval;
readval = fpga_multicorrelator_8sc::fpga_acquisition_test_register(writeval);
readval = Fpga_Multicorrelator_8sc::fpga_acquisition_test_register(writeval);
if (writeval != readval)
{
LOG(WARNING) << "Test register sanity check failed";
printf("tracking test register sanity check failed\n");
//printf("lslslls test sanity check reg failure\n");
std::cout << "tracking test register sanity check failed" << std::endl;
}
else
{
LOG(INFO) << "Test register sanity check success !";
//printf("tracking test register sanity check success\n");
//printf("lslslls test sanity check reg success\n");
}
}
uint32_t fpga_multicorrelator_8sc::fpga_acquisition_test_register(
uint32_t Fpga_Multicorrelator_8sc::fpga_acquisition_test_register(
uint32_t writeval)
{
//printf("d_TEST_REG_ADDR = %d\n", d_TEST_REG_ADDR);
uint32_t readval = 0;
// write value to test register
d_map_base[d_TEST_REG_ADDR] = writeval;
d_map_base[TEST_REG_ADDR] = writeval;
// read value from test register
readval = d_map_base[d_TEST_REG_ADDR];
readval = d_map_base[TEST_REG_ADDR];
// return read value
return readval;
}
void fpga_multicorrelator_8sc::fpga_configure_tracking_gps_local_code(int32_t PRN)
void Fpga_Multicorrelator_8sc::fpga_configure_tracking_gps_local_code(int32_t PRN)
{
uint32_t k;
uint32_t code_chip;
uint32_t select_pilot_corelator = LOCAL_CODE_FPGA_CORRELATOR_SELECT_COUNT;
// select_fpga_correlator = 0;
//printf("kkk d_n_correlators = %x\n", d_n_correlators);
//printf("kkk d_code_length_chips = %d\n", d_code_length_chips);
//printf("programming mems d map base %d\n", d_PROG_MEMS_ADDR);
//FILE *fp;
//char str[80];
//sprintf(str, "generated_code_PRN%d", PRN);
//fp = fopen(str,"w");
// for (s = 0; s < d_n_correlators; s++)
// {
//printf("kkk select_fpga_correlator = %x\n", select_fpga_correlator);
d_map_base[d_PROG_MEMS_ADDR] = LOCAL_CODE_FPGA_CLEAR_ADDRESS_COUNTER;
d_map_base[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)
//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)
if (d_ca_codes[((int32_t(d_code_length_chips)) * d_code_samples_per_chip * (PRN - 1)) + k] == 1)
{
code_chip = 1;
}
@ -436,22 +315,14 @@ void fpga_multicorrelator_8sc::fpga_configure_tracking_gps_local_code(int32_t PR
}
// copy the local code to the FPGA memory one by one
d_map_base[d_PROG_MEMS_ADDR] = LOCAL_CODE_FPGA_ENABLE_WRITE_MEMORY | code_chip; // | select_fpga_correlator;
d_map_base[PROG_MEMS_ADDR] = LOCAL_CODE_FPGA_ENABLE_WRITE_MEMORY | code_chip; // | select_fpga_correlator;
}
// select_fpga_correlator = select_fpga_correlator
// + LOCAL_CODE_FPGA_CORRELATOR_SELECT_COUNT;
// }
//fclose(fp);
//printf("kkk d_track_pilot = %d\n", d_track_pilot);
if (d_track_pilot)
{
//printf("kkk select_fpga_correlator = %x\n", select_fpga_correlator);
d_map_base[d_PROG_MEMS_ADDR] = LOCAL_CODE_FPGA_CLEAR_ADDRESS_COUNTER;
d_map_base[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)
if (d_data_codes[((int32_t(d_code_length_chips)) * d_code_samples_per_chip * (PRN - 1)) + k] == 1)
{
code_chip = 1;
}
@ -459,53 +330,38 @@ void fpga_multicorrelator_8sc::fpga_configure_tracking_gps_local_code(int32_t PR
{
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;
d_map_base[PROG_MEMS_ADDR] = LOCAL_CODE_FPGA_ENABLE_WRITE_MEMORY | code_chip | select_pilot_corelator;
}
}
//printf("\n");
}
void fpga_multicorrelator_8sc::fpga_compute_code_shift_parameters(void)
void Fpga_Multicorrelator_8sc::fpga_compute_code_shift_parameters(void)
{
float temp_calculation;
int32_t i;
//printf("ppp d_rem_code_phase_chips = %f\n", d_rem_code_phase_chips);
for (i = 0; i < d_n_correlators; i++)
{
//printf("ppp d_shifts_chips %d = %f\n", i, d_shifts_chips[i]);
//printf("ppp d_code_samples_per_chip = %d\n", d_code_samples_per_chip);
temp_calculation = floor(
d_shifts_chips[i] - d_rem_code_phase_chips);
//printf("ppp d_rem_code_phase_chips = %f\n", d_rem_code_phase_chips);
//printf("ppp temp calculation %d = %f ================================ \n", i, temp_calculation);
if (temp_calculation < 0)
{
temp_calculation = temp_calculation + (d_code_length_chips * d_code_samples_per_chip); // % operator does not work as in Matlab with negative numbers
}
//printf("ppp d_rem_code_phase_chips = %f\n", d_rem_code_phase_chips);
//printf("ppp temp calculation %d = %f ================================ \n", i, temp_calculation);
d_initial_index[i] = static_cast<uint32_t>((static_cast<int32_t>(temp_calculation)) % (d_code_length_chips * d_code_samples_per_chip));
//printf("ppp d_initial_index %d = %d\n", i, d_initial_index[i]);
temp_calculation = fmod(d_shifts_chips[i] - d_rem_code_phase_chips,
1.0);
//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<uint32_t>(floor(MAX_CODE_RESAMPLER_COUNTER * temp_calculation));
//printf("ppp d_initial_interp_counter %d = %d\n", i, d_initial_interp_counter[i]);
//printf("MAX_CODE_RESAMPLER_COUNTER = %d\n", MAX_CODE_RESAMPLER_COUNTER);
}
if (d_track_pilot)
{
//printf("tracking pilot !!!!!!!!!!!!!!!!\n");
temp_calculation = floor(
d_prompt_data_shift[0] - d_rem_code_phase_chips);
@ -522,47 +378,37 @@ void fpga_multicorrelator_8sc::fpga_compute_code_shift_parameters(void)
}
d_initial_interp_counter[d_n_correlators] = static_cast<uint32_t>(floor(MAX_CODE_RESAMPLER_COUNTER * temp_calculation));
}
//while(1);
}
void fpga_multicorrelator_8sc::fpga_configure_code_parameters_in_fpga(void)
void Fpga_Multicorrelator_8sc::fpga_configure_code_parameters_in_fpga(void)
{
int32_t i;
for (i = 0; i < d_n_correlators; i++)
{
//printf("www writing d map base %d = d_initial_index %d = %d\n", d_INITIAL_INDEX_REG_BASE_ADDR + i, i, d_initial_index[i]);
d_map_base[d_INITIAL_INDEX_REG_BASE_ADDR + i] = d_initial_index[i];
//d_map_base[1 + d_n_correlators + i] = d_initial_interp_counter[i];
//printf("www writing d map base %d = d_initial_interp_counter %d = %d\n", d_INITIAL_INTERP_COUNTER_REG_BASE_ADDR + i, i, d_initial_interp_counter[i]);
d_map_base[d_INITIAL_INTERP_COUNTER_REG_BASE_ADDR + i] = d_initial_interp_counter[i];
d_map_base[INITIAL_INDEX_REG_BASE_ADDR + i] = d_initial_index[i];
d_map_base[INITIAL_INTERP_COUNTER_REG_BASE_ADDR + i] = d_initial_interp_counter[i];
}
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];
d_map_base[INITIAL_INDEX_REG_BASE_ADDR + d_n_correlators] = d_initial_index[d_n_correlators];
d_map_base[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
d_map_base[CODE_LENGTH_MINUS_1_REG_ADDR] = (d_code_length_chips * d_code_samples_per_chip) - 1; // number of samples - 1
}
void fpga_multicorrelator_8sc::fpga_compute_signal_parameters_in_fpga(void)
void Fpga_Multicorrelator_8sc::fpga_compute_signal_parameters_in_fpga(void)
{
float d_rem_carrier_phase_in_rad_temp;
d_code_phase_step_chips_num = static_cast<uint32_t>(roundf(MAX_CODE_RESAMPLER_COUNTER * d_code_phase_step_chips));
if (d_code_phase_step_chips > 1.0)
{
printf("Warning : d_code_phase_step_chips = %f cannot be bigger than one\n", d_code_phase_step_chips);
std::cout << "Warning : d_code_phase_step_chips = " << d_code_phase_step_chips << " cannot be bigger than one" << std::endl;
}
//printf("d_rem_carrier_phase_in_rad = %f\n", d_rem_carrier_phase_in_rad);
if (d_rem_carrier_phase_in_rad > M_PI)
{
d_rem_carrier_phase_in_rad_temp = -2 * M_PI + d_rem_carrier_phase_in_rad;
@ -584,158 +430,81 @@ void fpga_multicorrelator_8sc::fpga_compute_signal_parameters_in_fpga(void)
d_phase_step_rad_int = static_cast<int32_t>(roundf(
(fabs(d_phase_step_rad) / M_PI) * pow(2, PHASE_CARR_NBITS_FRAC))); // the FPGA accepts a range for the phase step between -pi and +pi
//printf("d_phase_step_rad_int = %d\n", d_phase_step_rad_int);
if (d_phase_step_rad < 0)
{
d_phase_step_rad_int = -d_phase_step_rad_int;
}
//printf("d_phase_step_rad_int = %d\n", d_phase_step_rad_int);
}
void fpga_multicorrelator_8sc::fpga_configure_signal_parameters_in_fpga(void)
void Fpga_Multicorrelator_8sc::fpga_configure_signal_parameters_in_fpga(void)
{
//printf("www d map base %d = d_code_phase_step_chips_num = %d\n", d_CODE_PHASE_STEP_CHIPS_NUM_REG_ADDR, d_code_phase_step_chips_num);
d_map_base[d_CODE_PHASE_STEP_CHIPS_NUM_REG_ADDR] = d_code_phase_step_chips_num;
d_map_base[CODE_PHASE_STEP_CHIPS_NUM_REG_ADDR] = d_code_phase_step_chips_num;
//printf("www d map base %d = d_correlator_length_samples - 1 = %d\n", d_NSAMPLES_MINUS_1_REG_ADDR, d_correlator_length_samples - 1);
d_map_base[d_NSAMPLES_MINUS_1_REG_ADDR] = d_correlator_length_samples - 1;
d_map_base[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;
d_map_base[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;
d_map_base[PHASE_STEP_RAD_REG_ADDR] = d_phase_step_rad_int;
}
void fpga_multicorrelator_8sc::fpga_launch_multicorrelator_fpga(void)
void Fpga_Multicorrelator_8sc::fpga_launch_multicorrelator_fpga(void)
{
// enable interrupts
int32_t reenable = 1;
write(d_device_descriptor, reinterpret_cast<void *>(&reenable), sizeof(int32_t));
ssize_t nbytes = TEMP_FAILURE_RETRY(write(d_device_descriptor, reinterpret_cast<void *>(&reenable), sizeof(int32_t)));
if (nbytes != sizeof(int32_t))
{
std::cerr << "Error launching the FPGA multicorrelator" << std::endl;
}
// writing 1 to reg 14 launches the tracking
//printf("www writing 1 to d map base %d = start flag\n", d_START_FLAG_ADDR);
d_map_base[d_START_FLAG_ADDR] = 1;
//while(1);
d_map_base[START_FLAG_ADDR] = 1;
}
void fpga_multicorrelator_8sc::read_tracking_gps_results(void)
void Fpga_Multicorrelator_8sc::read_tracking_gps_results(void)
{
int32_t readval_real;
int32_t readval_imag;
int32_t k;
//printf("www reading trk results\n");
for (k = 0; k < d_n_correlators; k++)
{
readval_real = d_map_base[d_RESULT_REG_REAL_BASE_ADDR + k];
//printf("read real before checking d map base %d = %d\n", d_RESULT_REG_BASE_ADDR + k, readval_real);
//// if (readval_real > debug_max_readval_real[k])
//// {
//// debug_max_readval_real[k] = readval_real;
//// }
// if (readval_real >= d_result_SAT_value) // 0x100000 (21 bits two's complement)
// {
// readval_real = -2*d_result_SAT_value + readval_real;
// }
//// if (readval_real > debug_max_readval_real_after_check[k])
//// {
//// debug_max_readval_real_after_check[k] = readval_real;
//// }
//printf("read real d map base %d = %d\n", d_RESULT_REG_BASE_ADDR + k, readval_real);
readval_imag = d_map_base[d_RESULT_REG_IMAG_BASE_ADDR + k];
//printf("read imag before checking d map base %d = %d\n", d_RESULT_REG_BASE_ADDR + k, readval_imag);
//// if (readval_imag > debug_max_readval_imag[k])
//// {
//// debug_max_readval_imag[k] = readval_imag;
//// }
//
// if (readval_imag >= d_result_SAT_value) // 0x100000 (21 bits two's complement)
// {
// readval_imag = -2*d_result_SAT_value + readval_imag;
// }
//// if (readval_imag > debug_max_readval_imag_after_check[k])
//// {
//// debug_max_readval_imag_after_check[k] = readval_real;
//// }
//printf("read imag d map base %d = %d\n", d_RESULT_REG_BASE_ADDR + k, readval_imag);
readval_real = d_map_base[RESULT_REG_REAL_BASE_ADDR + k];
readval_imag = d_map_base[RESULT_REG_IMAG_BASE_ADDR + k];
d_corr_out[k] = gr_complex(readval_real, readval_imag);
// if (printcounter > 100)
// {
// printcounter = 0;
// for (int32_t ll=0;ll<d_n_correlators;ll++)
// {
// printf("debug_max_readval_real %d = %d\n", ll, debug_max_readval_real[ll]);
// printf("debug_max_readval_imag %d = %d\n", ll, debug_max_readval_imag[ll]);
// printf("debug_max_readval_real_%d after_check = %d\n", ll, debug_max_readval_real_after_check[ll]);
// printf("debug_max_readval_imag_%d after_check = %d\n", ll, debug_max_readval_imag_after_check[ll]);
// }
//
// }
// else
// {
// printcounter = printcounter + 1;
// }
}
if (d_track_pilot)
{
//printf("reading pilot !!!\n");
readval_real = d_map_base[d_RESULT_REG_DATA_REAL_BASE_ADDR];
// if (readval_real >= d_result_SAT_value) // 0x100000 (21 bits two's complement)
// {
// readval_real = -2*d_result_SAT_value + readval_real;
// }
readval_imag = d_map_base[d_RESULT_REG_DATA_IMAG_BASE_ADDR];
// if (readval_imag >= d_result_SAT_value) // 0x100000 (21 bits two's complement)
// {
// readval_imag = -2*d_result_SAT_value + readval_imag;
// }
readval_real = d_map_base[RESULT_REG_REAL_BASE_ADDR + d_n_correlators];
readval_imag = d_map_base[RESULT_REG_IMAG_BASE_ADDR + d_n_correlators];
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
//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
d_map_base[DROP_SAMPLES_REG_ADDR] = 1; // unlock the channel
d_map_base[STOP_TRACKING_REG_ADDR] = 1; // set the tracking module back to idle
}
void fpga_multicorrelator_8sc::close_device()
void Fpga_Multicorrelator_8sc::close_device()
{
auto *aux = const_cast<uint32_t *>(d_map_base);
if (munmap(static_cast<void *>(aux), PAGE_SIZE) == -1)
{
printf("Failed to unmap memory uio\n");
std::cout << "Failed to unmap memory uio" << std::endl;
}
close(d_device_descriptor);
}
void fpga_multicorrelator_8sc::lock_channel(void)
void Fpga_Multicorrelator_8sc::lock_channel(void)
{
// lock the channel for processing
//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
d_map_base[DROP_SAMPLES_REG_ADDR] = 0; // lock the channel
}
//void fpga_multicorrelator_8sc::read_sample_counters(int32_t *sample_counter, int32_t *secondary_sample_counter, int32_t *counter_corr_0_in, int32_t *counter_corr_0_out)
//{
// *sample_counter = d_map_base[11];
// *secondary_sample_counter = d_map_base[8];
// *counter_corr_0_in = d_map_base[10];
// *counter_corr_0_out = d_map_base[9];
//
//}
//void fpga_multicorrelator_8sc::reset_multicorrelator(void)
//{
// d_map_base[14] = 2; // writing a 2 to d_map_base[14] resets the multicorrelator
//}

View File

@ -1,17 +1,17 @@
/*!
* \file fpga_multicorrelator_8sc.h
* \brief High optimized FPGA vector correlator class for lv_16sc_t (short int32_t complex)
* \file fpga_multicorrelator.h
* \brief FPGA vector correlator class
* \authors <ul>
* <li> Marc Majoral, 2017. mmajoral(at)cttc.cat
* <li> Javier Arribas, 2016. jarribas(at)cttc.es
* <li> Marc Majoral, 2019. mmajoral(at)cttc.cat
* <li> Javier Arribas, 2019. jarribas(at)cttc.es
* </ul>
*
* Class that controls and executes a high optimized vector correlator
* Class that controls and executes a highly optimized vector correlator
* class in the FPGA
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2017 (see AUTHORS file for a list of contributors)
* Copyright (C) 2010-2019 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
@ -41,32 +41,49 @@
#include <volk_gnsssdr/volk_gnsssdr.h>
#include <cstdint>
#define MAX_LENGTH_DEVICEIO_NAME 50
// FPGA register addresses
// write addresses
#define CODE_PHASE_STEP_CHIPS_NUM_REG_ADDR 0
#define INITIAL_INDEX_REG_BASE_ADDR 1
#define INITIAL_INTERP_COUNTER_REG_BASE_ADDR 7
#define NSAMPLES_MINUS_1_REG_ADDR 13
#define CODE_LENGTH_MINUS_1_REG_ADDR 14
#define REM_CARR_PHASE_RAD_REG_ADDR 15
#define PHASE_STEP_RAD_REG_ADDR 16
#define PROG_MEMS_ADDR 17
#define DROP_SAMPLES_REG_ADDR 18
#define INITIAL_COUNTER_VALUE_REG_ADDR_LSW 19
#define INITIAL_COUNTER_VALUE_REG_ADDR_MSW 20
#define STOP_TRACKING_REG_ADDR 23
#define START_FLAG_ADDR 30
// read-write addresses
#define TEST_REG_ADDR 31
// read addresses
#define RESULT_REG_REAL_BASE_ADDR 1
#define RESULT_REG_IMAG_BASE_ADDR 7
#define SAMPLE_COUNTER_REG_ADDR_LSW 13
#define SAMPLE_COUNTER_REG_ADDR_MSW 14
/*!
* \brief Class that implements carrier wipe-off and correlators.
*/
class fpga_multicorrelator_8sc
class Fpga_Multicorrelator_8sc
{
public:
fpga_multicorrelator_8sc(int32_t n_correlators, std::string device_name,
Fpga_Multicorrelator_8sc(int32_t n_correlators, std::string device_name,
uint32_t device_base, int32_t *ca_codes, int32_t *data_codes, uint32_t code_length_chips, bool track_pilot, uint32_t multicorr_type, uint32_t code_samples_per_chip);
~fpga_multicorrelator_8sc();
//bool set_output_vectors(gr_complex* corr_out);
~Fpga_Multicorrelator_8sc();
void set_output_vectors(gr_complex *corr_out, gr_complex *Prompt_Data);
// bool set_local_code_and_taps(
// int32_t code_length_chips, const int* local_code_in,
// float *shifts_chips, int32_t PRN);
//bool set_local_code_and_taps(
void set_local_code_and_taps(
// int32_t code_length_chips,
float *shifts_chips, float *prompt_data_shift, int32_t PRN);
//bool set_output_vectors(lv_16sc_t* corr_out);
void update_local_code(float rem_code_phase_chips);
//bool Carrier_wipeoff_multicorrelator_resampler(
void Carrier_wipeoff_multicorrelator_resampler(
float rem_carrier_phase_in_rad, float phase_step_rad,
float carrier_phase_rate_step_rad,
float rem_code_phase_chips, float code_phase_step_chips,
float code_phase_rate_step_chips,
int32_t signal_length_samples);
bool free();
void set_channel(uint32_t channel);
@ -74,16 +91,14 @@ public:
uint64_t read_sample_counter();
void lock_channel(void);
void unlock_channel(void);
//void read_sample_counters(int32_t *sample_counter, int32_t *secondary_sample_counter, int32_t *counter_corr_0_in, int32_t *counter_corr_0_out); // debug
private:
//const int32_t *d_local_code_in;
gr_complex *d_corr_out;
gr_complex *d_Prompt_Data;
float *d_shifts_chips;
float *d_prompt_data_shift;
int32_t d_code_length_chips;
int32_t d_n_correlators;
int32_t d_n_correlators; // number of correlators
// data related to the hardware module and the driver
int32_t d_device_descriptor; // driver descriptor
@ -91,7 +106,6 @@ private:
// configuration data received from the interface
uint32_t d_channel; // channel number
uint32_t d_ncorrelators; // number of correlators
uint32_t d_correlator_length_samples;
float d_rem_code_phase_chips;
float d_code_phase_step_chips;
@ -113,37 +127,11 @@ private:
int32_t *d_ca_codes;
int32_t *d_data_codes;
//uint32_t d_code_length; // nominal number of chips
uint32_t d_code_samples_per_chip;
bool d_track_pilot;
uint32_t d_multicorr_type;
// register addresses
// write-only regs
uint32_t d_CODE_PHASE_STEP_CHIPS_NUM_REG_ADDR;
uint32_t d_INITIAL_INDEX_REG_BASE_ADDR;
uint32_t d_INITIAL_INTERP_COUNTER_REG_BASE_ADDR;
uint32_t d_NSAMPLES_MINUS_1_REG_ADDR;
uint32_t d_CODE_LENGTH_MINUS_1_REG_ADDR;
uint32_t d_REM_CARR_PHASE_RAD_REG_ADDR;
uint32_t d_PHASE_STEP_RAD_REG_ADDR;
uint32_t d_PROG_MEMS_ADDR;
uint32_t d_DROP_SAMPLES_REG_ADDR;
uint32_t d_INITIAL_COUNTER_VALUE_REG_ADDR_LSW;
uint32_t d_INITIAL_COUNTER_VALUE_REG_ADDR_MSW;
uint32_t d_START_FLAG_ADDR;
// read-write regs
uint32_t d_TEST_REG_ADDR;
// read-only regs
uint32_t d_RESULT_REG_REAL_BASE_ADDR;
uint32_t d_RESULT_REG_IMAG_BASE_ADDR;
uint32_t d_RESULT_REG_DATA_REAL_BASE_ADDR;
uint32_t d_RESULT_REG_DATA_IMAG_BASE_ADDR;
uint32_t d_SAMPLE_COUNTER_REG_ADDR_LSW;
uint32_t d_SAMPLE_COUNTER_REG_ADDR_MSW;
// private functions
uint32_t fpga_acquisition_test_register(uint32_t writeval);
void fpga_configure_tracking_gps_local_code(int32_t PRN);
@ -153,17 +141,7 @@ private:
void fpga_configure_signal_parameters_in_fpga(void);
void fpga_launch_multicorrelator_fpga(void);
void read_tracking_gps_results(void);
//void reset_multicorrelator(void);
void close_device(void);
uint32_t d_result_SAT_value;
int32_t debug_max_readval_real[5] = {0, 0, 0, 0, 0};
int32_t debug_max_readval_imag[5] = {0, 0, 0, 0, 0};
int32_t debug_max_readval_real_after_check[5] = {0, 0, 0, 0, 0};
int32_t debug_max_readval_imag_after_check[5] = {0, 0, 0, 0, 0};
int32_t printcounter = 0;
};
#endif /* GNSS_SDR_FPGA_MULTICORRELATOR_H_ */

View File

@ -273,12 +273,11 @@ int ControlThread::run()
cmd_interface_.set_pvt(flowgraph_->get_pvt());
cmd_interface_thread_ = std::thread(&ControlThread::telecommand_listener, this);
bool enable_FPGA = configuration_->property("Channel.enable_FPGA", false);
if (enable_FPGA == true)
{
flowgraph_->start_acquisition_helper();
}
#ifdef ENABLE_FPGA
// Create a task for the acquisition such that id doesn't block the flow of the control thread
fpga_helper_thread_ = boost::thread(&GNSSFlowgraph::start_acquisition_helper,
flowgraph_);
#endif
// Main loop to read and process the control messages
while (flowgraph_->running() && !stop_)
{
@ -294,11 +293,23 @@ int ControlThread::run()
stop_ = true;
flowgraph_->disconnect();
#ifdef ENABLE_FPGA
// trigger a HW reset
// The HW reset causes any HW accelerator module that is waiting for more samples to complete its calculations
// to trigger an interrupt and finish its signal processing tasks immediately. In this way all SW threads that
// are waiting for interrupts in the HW can exit in a normal way.
flowgraph_->perform_hw_reset();
fpga_helper_thread_.try_join_until(boost::chrono::steady_clock::now() + boost::chrono::milliseconds(1000));
#endif
std::this_thread::sleep_for(std::chrono::milliseconds(500));
// Terminate keyboard thread
pthread_t id = keyboard_thread_.native_handle();
keyboard_thread_.detach();
pthread_cancel(id);
LOG(INFO) << "Flowgraph stopped";
if (restart_)
{
return 42; // signal the gnss-sdr-harness.sh to restart the receiver program

View File

@ -95,7 +95,6 @@ public:
*/
void set_control_queue(const gr::msg_queue::sptr control_queue); // NOLINT(performance-unnecessary-value-param)
unsigned int processed_control_messages()
{
return processed_control_messages_;
@ -168,6 +167,9 @@ private:
bool delete_configuration_;
unsigned int processed_control_messages_;
unsigned int applied_actions_;
boost::thread fpga_helper_thread_;
std::thread keyboard_thread_;
std::thread sysv_queue_thread_;
std::thread gps_acq_assist_data_collector_thread_;

View File

@ -11,7 +11,7 @@
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2018 (see AUTHORS file for a list of contributors)
* Copyright (C) 2010-2019 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver

View File

@ -9,7 +9,7 @@
*
* -------------------------------------------------------------------------
*
* Copyright (C) 2010-2018 (see AUTHORS file for a list of contributors)
* Copyright (C) 2010-2019 (see AUTHORS file for a list of contributors)
*
* GNSS-SDR is a software defined Global Navigation
* Satellite Systems receiver
@ -50,6 +50,7 @@
#include <exception>
#include <iostream>
#include <set>
#include <thread>
#include <utility>
#ifdef GR_GREATER_38
#include <gnuradio/filter/fir_filter_blk.h>
@ -123,6 +124,7 @@ void GNSSFlowgraph::connect()
return;
}
#ifndef ENABLE_FPGA
for (int i = 0; i < sources_count_; i++)
{
if (configuration_->property(sig_source_.at(i)->role() + ".enable_FPGA", false) == false)
@ -141,6 +143,7 @@ void GNSSFlowgraph::connect()
}
}
// Signal Source > Signal conditioner >
for (unsigned int i = 0; i < sig_conditioner_.size(); i++)
{
@ -159,7 +162,7 @@ void GNSSFlowgraph::connect()
}
}
}
#endif
for (unsigned int i = 0; i < channels_count_; i++)
{
try
@ -205,78 +208,78 @@ void GNSSFlowgraph::connect()
int RF_Channels = 0;
int signal_conditioner_ID = 0;
#ifndef ENABLE_FPGA
for (int i = 0; i < sources_count_; i++)
{
//FPGA Accelerators do not need signal sources or conditioners
//as the samples are feed directly to the FPGA fabric, so, if enabled, do not connect any source
if (configuration_->property(sig_source_.at(i)->role() + ".enable_FPGA", false) == false)
try
{
try
//TODO: Remove this array implementation and create generic multistream connector
//(if a signal source has more than 1 stream, then connect it to the multistream signal conditioner)
if (sig_source_.at(i)->implementation() == "Raw_Array_Signal_Source")
{
//TODO: Remove this array implementation and create generic multistream connector
//(if a signal source has more than 1 stream, then connect it to the multistream signal conditioner)
if (sig_source_.at(i)->implementation() == "Raw_Array_Signal_Source")
//Multichannel Array
std::cout << "ARRAY MODE" << std::endl;
for (int j = 0; j < GNSS_SDR_ARRAY_SIGNAL_CONDITIONER_CHANNELS; j++)
{
//Multichannel Array
std::cout << "ARRAY MODE" << std::endl;
for (int j = 0; j < GNSS_SDR_ARRAY_SIGNAL_CONDITIONER_CHANNELS; j++)
{
std::cout << "connecting ch " << j << std::endl;
top_block_->connect(sig_source_.at(i)->get_right_block(), j, sig_conditioner_.at(i)->get_left_block(), j);
}
std::cout << "connecting ch " << j << std::endl;
top_block_->connect(sig_source_.at(i)->get_right_block(), j, sig_conditioner_.at(i)->get_left_block(), j);
}
else
}
else
{
//TODO: Create a class interface for SignalSources, derived from GNSSBlockInterface.
//Include GetRFChannels in the interface to avoid read config parameters here
//read the number of RF channels for each front-end
RF_Channels = configuration_->property(sig_source_.at(i)->role() + ".RF_channels", 1);
for (int j = 0; j < RF_Channels; j++)
{
//TODO: Create a class interface for SignalSources, derived from GNSSBlockInterface.
//Include GetRFChannels in the interface to avoid read config parameters here
//read the number of RF channels for each front-end
RF_Channels = configuration_->property(sig_source_.at(i)->role() + ".RF_channels", 1);
//Connect the multichannel signal source to multiple signal conditioners
// GNURADIO max_streams=-1 means infinite ports!
LOG(INFO) << "sig_source_.at(i)->get_right_block()->output_signature()->max_streams()=" << sig_source_.at(i)->get_right_block()->output_signature()->max_streams();
LOG(INFO) << "sig_conditioner_.at(signal_conditioner_ID)->get_left_block()->input_signature()=" << sig_conditioner_.at(signal_conditioner_ID)->get_left_block()->input_signature()->max_streams();
for (int j = 0; j < RF_Channels; j++)
if (sig_source_.at(i)->get_right_block()->output_signature()->max_streams() > 1)
{
//Connect the multichannel signal source to multiple signal conditioners
// GNURADIO max_streams=-1 means infinite ports!
LOG(INFO) << "sig_source_.at(i)->get_right_block()->output_signature()->max_streams()=" << sig_source_.at(i)->get_right_block()->output_signature()->max_streams();
LOG(INFO) << "sig_conditioner_.at(signal_conditioner_ID)->get_left_block()->input_signature()=" << sig_conditioner_.at(signal_conditioner_ID)->get_left_block()->input_signature()->max_streams();
if (sig_source_.at(i)->get_right_block()->output_signature()->max_streams() > 1)
LOG(INFO) << "connecting sig_source_ " << i << " stream " << j << " to conditioner " << j;
top_block_->connect(sig_source_.at(i)->get_right_block(), j, sig_conditioner_.at(signal_conditioner_ID)->get_left_block(), 0);
}
else
{
if (j == 0)
{
LOG(INFO) << "connecting sig_source_ " << i << " stream " << j << " to conditioner " << j;
top_block_->connect(sig_source_.at(i)->get_right_block(), j, sig_conditioner_.at(signal_conditioner_ID)->get_left_block(), 0);
// RF_channel 0 backward compatibility with single channel sources
LOG(INFO) << "connecting sig_source_ " << i << " stream " << 0 << " to conditioner " << j;
top_block_->connect(sig_source_.at(i)->get_right_block(), 0, sig_conditioner_.at(signal_conditioner_ID)->get_left_block(), 0);
}
else
{
if (j == 0)
{
// RF_channel 0 backward compatibility with single channel sources
LOG(INFO) << "connecting sig_source_ " << i << " stream " << 0 << " to conditioner " << j;
top_block_->connect(sig_source_.at(i)->get_right_block(), 0, sig_conditioner_.at(signal_conditioner_ID)->get_left_block(), 0);
}
else
{
// Multiple channel sources using multiple output blocks of single channel (requires RF_channel selector in call)
LOG(INFO) << "connecting sig_source_ " << i << " stream " << j << " to conditioner " << j;
top_block_->connect(sig_source_.at(i)->get_right_block(j), 0, sig_conditioner_.at(signal_conditioner_ID)->get_left_block(), 0);
}
// Multiple channel sources using multiple output blocks of single channel (requires RF_channel selector in call)
LOG(INFO) << "connecting sig_source_ " << i << " stream " << j << " to conditioner " << j;
top_block_->connect(sig_source_.at(i)->get_right_block(j), 0, sig_conditioner_.at(signal_conditioner_ID)->get_left_block(), 0);
}
signal_conditioner_ID++;
}
signal_conditioner_ID++;
}
}
catch (const std::exception& e)
{
LOG(WARNING) << "Can't connect signal source " << i << " to signal conditioner " << i;
LOG(ERROR) << e.what();
top_block_->disconnect_all();
return;
}
}
catch (const std::exception& e)
{
LOG(WARNING) << "Can't connect signal source " << i << " to signal conditioner " << i;
LOG(ERROR) << e.what();
top_block_->disconnect_all();
return;
}
}
DLOG(INFO) << "Signal source connected to signal conditioner";
bool FPGA_enabled = configuration_->property(sig_source_.at(0)->role() + ".enable_FPGA", false);
#endif
#if ENABLE_FPGA
if (FPGA_enabled == false)
if (configuration_->property(sig_source_.at(0)->role() + ".enable_FPGA", false) == false)
{
//connect the signal source to sample counter
//connect the sample counter to Observables
@ -352,13 +355,15 @@ void GNSSFlowgraph::connect()
return;
}
#endif
// Signal conditioner (selected_signal_source) >> channels (i) (dependent of their associated SignalSource_ID)
int selected_signal_conditioner_ID = 0;
bool use_acq_resampler = configuration_->property("GNSS-SDR.use_acquisition_resampler", false);
uint32_t fs = configuration_->property("GNSS-SDR.internal_fs_sps", 0);
for (unsigned int i = 0; i < channels_count_; i++)
{
if (FPGA_enabled == false)
#ifndef ENABLE_FPGA
if (configuration_->property(sig_source_.at(0)->role() + ".enable_FPGA", false) == false)
{
try
{
@ -500,6 +505,7 @@ void GNSSFlowgraph::connect()
DLOG(INFO) << "signal conditioner " << selected_signal_conditioner_ID << " connected to channel " << i;
}
#endif
// Signal Source > Signal conditioner >> Channels >> Observables
try
{
@ -664,16 +670,15 @@ void GNSSFlowgraph::connect()
}
}
#ifndef ENABLE_FPGA
// Activate acquisition in enabled channels
for (unsigned int i = 0; i < channels_count_; i++)
{
LOG(INFO) << "Channel " << i << " assigned to " << channels_.at(i)->get_signal();
if (channels_state_[i] == 1)
{
if (FPGA_enabled == false)
{
channels_.at(i)->start_acquisition();
}
channels_.at(i)->start_acquisition();
LOG(INFO) << "Channel " << i << " connected to observables and ready for acquisition";
}
else
@ -681,6 +686,7 @@ void GNSSFlowgraph::connect()
LOG(INFO) << "Channel " << i << " connected to observables in standby mode";
}
}
#endif
connected_ = true;
LOG(INFO) << "Flowgraph connected";
@ -702,6 +708,66 @@ void GNSSFlowgraph::disconnect()
int RF_Channels = 0;
int signal_conditioner_ID = 0;
#ifdef ENABLE_FPGA
if (configuration_->property(sig_source_.at(0)->role() + ".enable_FPGA", false) == false)
{
for (int i = 0; i < sources_count_; i++)
{
try
{
// TODO: Remove this array implementation and create generic multistream connector
// (if a signal source has more than 1 stream, then connect it to the multistream signal conditioner)
if (sig_source_.at(i)->implementation() == "Raw_Array_Signal_Source")
{
//Multichannel Array
for (int j = 0; j < GNSS_SDR_ARRAY_SIGNAL_CONDITIONER_CHANNELS; j++)
{
top_block_->disconnect(sig_source_.at(i)->get_right_block(), j, sig_conditioner_.at(i)->get_left_block(), j);
}
}
else
{
// TODO: Create a class interface for SignalSources, derived from GNSSBlockInterface.
// Include GetRFChannels in the interface to avoid read config parameters here
// read the number of RF channels for each front-end
RF_Channels = configuration_->property(sig_source_.at(i)->role() + ".RF_channels", 1);
for (int j = 0; j < RF_Channels; j++)
{
if (sig_source_.at(i)->get_right_block()->output_signature()->max_streams() > 1)
{
top_block_->disconnect(sig_source_.at(i)->get_right_block(), j, sig_conditioner_.at(signal_conditioner_ID)->get_left_block(), 0);
}
else
{
if (j == 0)
{
// RF_channel 0 backward compatibility with single channel sources
top_block_->disconnect(sig_source_.at(i)->get_right_block(), 0, sig_conditioner_.at(signal_conditioner_ID)->get_left_block(), 0);
}
else
{
// Multiple channel sources using multiple output blocks of single channel (requires RF_channel selector in call)
top_block_->disconnect(sig_source_.at(i)->get_right_block(j), 0, sig_conditioner_.at(signal_conditioner_ID)->get_left_block(), 0);
}
}
signal_conditioner_ID++;
}
}
}
catch (const std::exception& e)
{
LOG(INFO) << "Can't disconnect signal source " << i << " to signal conditioner " << i << ": " << e.what();
top_block_->disconnect_all();
return;
}
}
}
#else
for (int i = 0; i < sources_count_; i++)
{
try
@ -753,10 +819,10 @@ void GNSSFlowgraph::disconnect()
return;
}
}
#endif
#if ENABLE_FPGA
bool FPGA_enabled = configuration_->property(sig_source_.at(0)->role() + ".enable_FPGA", false);
if (FPGA_enabled == false)
#ifdef ENABLE_FPGA
if (configuration_->property(sig_source_.at(0)->role() + ".enable_FPGA", false) == false)
{
// disconnect the signal source to sample counter
// disconnect the sample counter to Observables
@ -817,6 +883,7 @@ void GNSSFlowgraph::disconnect()
top_block_->disconnect_all();
return;
}
#ifndef ENABLE_FPGA
try
{
top_block_->disconnect(sig_conditioner_.at(selected_signal_conditioner_ID)->get_right_block(), 0,
@ -828,7 +895,7 @@ void GNSSFlowgraph::disconnect()
top_block_->disconnect_all();
return;
}
#endif
// Signal Source > Signal conditioner >> Channels >> Observables
try
{
@ -1075,7 +1142,14 @@ void GNSSFlowgraph::apply_action(unsigned int who, unsigned int what)
}
acq_channels_count_++;
DLOG(INFO) << "Channel " << ch_index << " Starting acquisition " << channels_[ch_index]->get_signal().get_satellite() << ", Signal " << channels_[ch_index]->get_signal().get_signal_str();
#ifndef ENABLE_FPGA
channels_[ch_index]->start_acquisition();
#else
// create a task for the FPGA such that it doesn't stop the flow
std::thread tmp_thread(&ChannelInterface::start_acquisition, channels_[ch_index]);
tmp_thread.detach();
#endif
}
DLOG(INFO) << "Channel " << ch_index << " in state " << channels_state_[ch_index];
}
@ -1150,7 +1224,13 @@ void GNSSFlowgraph::apply_action(unsigned int who, unsigned int what)
}
acq_channels_count_++;
DLOG(INFO) << "Channel " << i << " Starting acquisition " << channels_[i]->get_signal().get_satellite() << ", Signal " << channels_[i]->get_signal().get_signal_str();
#ifndef ENABLE_FPGA
channels_[i]->start_acquisition();
#else
// create a task for the FPGA such that it doesn't stop the flow
std::thread tmp_thread(&ChannelInterface::start_acquisition, channels_[i]);
tmp_thread.detach();
#endif
}
DLOG(INFO) << "Channel " << i << " in state " << channels_state_[i];
}
@ -1165,7 +1245,13 @@ void GNSSFlowgraph::apply_action(unsigned int who, unsigned int what)
channels_state_[who] = 1;
acq_channels_count_++;
LOG(INFO) << "Channel " << who << " Starting acquisition " << channels_[who]->get_signal().get_satellite() << ", Signal " << channels_[who]->get_signal().get_signal_str();
#ifndef ENABLE_FPGA
channels_[who]->start_acquisition();
#else
// create a task for the FPGA such that it doesn't stop the flow
std::thread tmp_thread(&ChannelInterface::start_acquisition, channels_[who]);
tmp_thread.detach();
#endif
}
else
{
@ -1309,7 +1395,13 @@ void GNSSFlowgraph::apply_action(unsigned int who, unsigned int what)
}
acq_channels_count_++;
DLOG(INFO) << "Channel " << ch_index << " Starting acquisition " << channels_[ch_index]->get_signal().get_satellite() << ", Signal " << channels_[ch_index]->get_signal().get_signal_str();
#ifndef ENABLE_FPGA
channels_[ch_index]->start_acquisition();
#else
// create a task for the FPGA such that it doesn't stop the flow
std::thread tmp_thread(&ChannelInterface::start_acquisition, channels_[ch_index]);
tmp_thread.detach();
#endif
}
DLOG(INFO) << "Channel " << ch_index << " in state " << channels_state_[ch_index];
}
@ -1337,7 +1429,13 @@ void GNSSFlowgraph::apply_action(unsigned int who, unsigned int what)
}
acq_channels_count_++;
DLOG(INFO) << "Channel " << ch_index << " Starting acquisition " << channels_[ch_index]->get_signal().get_satellite() << ", Signal " << channels_[ch_index]->get_signal().get_signal_str();
#ifndef ENABLE_FPGA
channels_[ch_index]->start_acquisition();
#else
// create a task for the FPGA such that it doesn't stop the flow
std::thread tmp_thread(&ChannelInterface::start_acquisition, channels_[ch_index]);
tmp_thread.detach();
#endif
}
DLOG(INFO) << "Channel " << ch_index << " in state " << channels_state_[ch_index];
}
@ -1366,7 +1464,13 @@ void GNSSFlowgraph::apply_action(unsigned int who, unsigned int what)
}
acq_channels_count_++;
DLOG(INFO) << "Channel " << ch_index << " Starting acquisition " << channels_[ch_index]->get_signal().get_satellite() << ", Signal " << channels_[ch_index]->get_signal().get_signal_str();
#ifndef ENABLE_FPGA
channels_[ch_index]->start_acquisition();
#else
// create a task for the FPGA such that it doesn't stop the flow
std::thread tmp_thread(&ChannelInterface::start_acquisition, channels_[ch_index]);
tmp_thread.detach();
#endif
}
DLOG(INFO) << "Channel " << ch_index << " in state " << channels_state_[ch_index];
}
@ -1446,6 +1550,7 @@ void GNSSFlowgraph::set_configuration(std::shared_ptr<ConfigurationInterface> co
configuration_ = std::move(configuration);
}
#ifdef ENABLE_FPGA
void GNSSFlowgraph::start_acquisition_helper()
{
@ -1459,6 +1564,16 @@ void GNSSFlowgraph::start_acquisition_helper()
}
void GNSSFlowgraph::perform_hw_reset()
{
// a stop acquisition command causes the SW to reset the HW
std::shared_ptr<Channel> channel_ptr;
channel_ptr = std::dynamic_pointer_cast<Channel>(channels_.at(0));
channel_ptr->acquisition()->stop_acquisition();
}
#endif
void GNSSFlowgraph::init()
{
/*

View File

@ -95,9 +95,11 @@ public:
void disconnect();
void wait();
#ifdef ENABLE_FPGA
void start_acquisition_helper();
void perform_hw_reset();
#endif
/*!
* \brief Applies an action to the flow graph
*

View File

@ -343,18 +343,11 @@ bool Galileo_Navigation_Message::read_navigation_bool(std::bitset<GALILEO_DATA_J
void Galileo_Navigation_Message::split_page(std::string page_string, int32_t flag_even_word)
{
// ToDo: Clean all the tests and create an independent google test code for the telemetry decoder.
//char correct_tail[7]="011110"; //the viterbi decoder output change the tail to this value (why?)
//char correct_tail[7]="000000";
int32_t Page_type = 0;
// std::cout << "Start decoding Galileo I/NAV " << std::endl;
if (page_string.at(0) == '1') // if page is odd
{
// std::cout<< "page_string.at(0) split page="<<page_string.at(0) << std::endl;
const std::string& page_Odd = page_string;
// std::cout<<"Page odd string in split page"<< std::endl << page_Odd << std::endl;
if (flag_even_word == 1) // An odd page has been received but the previous even page is kept in memory and it is considered to join pages
{
@ -364,10 +357,6 @@ void Galileo_Navigation_Message::split_page(std::string page_string, int32_t fla
std::string Page_type_even = page_INAV.substr(1, 1);
std::string nominal = "0";
//if (Page_type_even.compare(nominal) != 0)
// std::cout << "Alert frame "<< std::endl;
//else std::cout << "Nominal Page" << std::endl;
std::string Data_k = page_INAV.substr(2, 112);
std::string Odd_bit = page_INAV.substr(114, 1);
std::string Page_type_Odd = page_INAV.substr(115, 1);
@ -388,10 +377,6 @@ void Galileo_Navigation_Message::split_page(std::string page_string, int32_t fla
std::bitset<GALILEO_DATA_FRAME_BITS> TLM_word_for_CRC_bits(TLM_word_for_CRC);
std::bitset<24> checksum(CRC_data);
//if (Tail_odd.compare(correct_tail) != 0)
// std::cout << "Tail odd is not correct!" << std::endl;
//else std::cout<<"Tail odd is correct!"<<std::endl;
if (CRC_test(TLM_word_for_CRC_bits, checksum.to_ulong()) == true)
{
flag_CRC_test = true;
@ -414,10 +399,6 @@ void Galileo_Navigation_Message::split_page(std::string page_string, int32_t fla
{
page_Even = page_string.substr(0, 114);
std::string tail_Even = page_string.substr(114, 6);
//std::cout << "tail_even_string: " << tail_Even <<std::endl;
//if (tail_Even.compare(correct_tail) != 0)
// std::cout << "Tail even is not correct!" << std::endl;
//else std::cout<<"Tail even is correct!"<< std::endl;
}
}
@ -429,14 +410,14 @@ bool Galileo_Navigation_Message::have_new_ephemeris() // Check if we have a new
// if all ephemeris pages have the same IOD, then they belong to the same block
if ((IOD_nav_1 == IOD_nav_2) and (IOD_nav_3 == IOD_nav_4) and (IOD_nav_1 == IOD_nav_3))
{
std::cout << "Ephemeris (1, 2, 3, 4) have been received and belong to the same batch" << std::endl;
DLOG(INFO) << "Ephemeris (1, 2, 3, 4) have been received and belong to the same batch";
flag_ephemeris_1 = false; // clear the flag
flag_ephemeris_2 = false; // clear the flag
flag_ephemeris_3 = false; // clear the flag
flag_ephemeris_4 = false; // clear the flag
flag_all_ephemeris = true;
IOD_ephemeris = IOD_nav_1;
std::cout << "Batch number: " << IOD_ephemeris << std::endl;
DLOG(INFO) << "Batch number: " << IOD_ephemeris;
return true;
}
}
@ -646,7 +627,7 @@ int32_t Galileo_Navigation_Message::page_jk_decoder(const char* data_jk)
std::bitset<GALILEO_DATA_JK_BITS> data_jk_bits(data_jk_string);
page_number = static_cast<int32_t>(read_navigation_unsigned(data_jk_bits, PAGE_TYPE_BIT));
LOG(INFO) << "Page number = " << page_number;
DLOG(INFO) << "Page number = " << page_number;
switch (page_number)
{

View File

@ -123,7 +123,7 @@ int main(int argc, char** argv)
boost::system::error_code ec;
if (!boost::filesystem::create_directory(p, ec))
{
std::cout << "Could not create the " << FLAGS_log_dir << " folder. GNSS-SDR program ended." << std::endl;
std::cerr << "Could not create the " << FLAGS_log_dir << " folder. GNSS-SDR program ended." << std::endl;
google::ShutDownCommandLineFlags();
return 1;
}
@ -144,8 +144,9 @@ int main(int argc, char** argv)
}
catch (const boost::thread_resource_error& e)
{
std::cout << "Failed to create boost thread." << std::endl;
std::cerr << "Failed to create boost thread." << std::endl;
google::ShutDownCommandLineFlags();
std::cout << "GNSS-SDR program ended." << std::endl;
return 1;
}
catch (const boost::exception& e)
@ -153,12 +154,14 @@ int main(int argc, char** argv)
if (GOOGLE_STRIP_LOG == 0)
{
LOG(WARNING) << "Boost exception: " << boost::diagnostic_information(e);
std::cerr << boost::diagnostic_information(e) << std::endl;
}
else
{
std::cerr << "Boost exception: " << boost::diagnostic_information(e) << std::endl;
}
google::ShutDownCommandLineFlags();
std::cout << "GNSS-SDR program ended." << std::endl;
return 1;
}
catch (const std::exception& ex)
@ -166,12 +169,14 @@ int main(int argc, char** argv)
if (GOOGLE_STRIP_LOG == 0)
{
LOG(WARNING) << "C++ Standard Library exception: " << ex.what();
std::cerr << ex.what() << std::endl;
}
else
{
std::cerr << "C++ Standard Library exception: " << ex.what() << std::endl;
}
google::ShutDownCommandLineFlags();
std::cout << "GNSS-SDR program ended." << std::endl;
return 1;
}
catch (...)
@ -179,12 +184,14 @@ int main(int argc, char** argv)
if (GOOGLE_STRIP_LOG == 0)
{
LOG(WARNING) << "Unexpected catch. This should not happen.";
std::cerr << "Unexpected error." << std::endl;
}
else
{
std::cerr << "Unexpected catch. This should not happen." << std::endl;
}
google::ShutDownCommandLineFlags();
std::cout << "GNSS-SDR program ended." << std::endl;
return 1;
}

View File

@ -64,17 +64,15 @@ using google::LogMessage;
DECLARE_string(log_dir);
#if UNIT_TESTING_MINIMAL
#include "unit-tests/arithmetic/matio_test.cc"
#if EXTRA_TESTS
#include "unit-tests/signal-processing-blocks/acquisition/acq_performance_test.cc"
#include "unit-tests/signal-processing-blocks/tracking/tracking_pull-in_test.cc"
#if ENABLE_FPGA
#if FPGA_BLOCKS_TEST
#include "unit-tests/signal-processing-blocks/tracking/tracking_pull-in_test_fpga.cc"
#endif
#endif // FPGA_BLOCKS_TEST
#include "unit-tests/signal-processing-blocks/observables/hybrid_observables_test.cc"
#endif
#endif // EXTRA_TESTS
#else
@ -160,12 +158,15 @@ DECLARE_string(log_dir);
#include "unit-tests/signal-processing-blocks/tracking/gps_l1_ca_kf_tracking_test.cc"
#include "unit-tests/signal-processing-blocks/tracking/gps_l2_m_dll_pll_tracking_test.cc"
#include "unit-tests/signal-processing-blocks/tracking/tracking_pull-in_test.cc"
#if ENABLE_FPGA
#if FPGA_BLOCKS_TEST
#include "unit-tests/signal-processing-blocks/tracking/tracking_pull-in_test_fpga.cc"
#endif
#endif // FPGA_BLOCKS_TEST
#include "unit-tests/signal-processing-blocks/observables/hybrid_observables_test.cc"
#if FPGA_BLOCKS_TEST
#include "unit-tests/signal-processing-blocks/observables/hybrid_observables_test_fpga.cc"
#endif // FPGA_BLOCKS_TEST
#include "unit-tests/signal-processing-blocks/telemetry_decoder/gps_l1_ca_telemetry_decoder_test.cc"
#endif
#endif // EXTRA_TESTS
#endif // UNIT_TESTING_MINIMAL

View File

@ -94,7 +94,7 @@ DEFINE_bool(acq_test_dump, false, "Dump the results of an acquisition block into
// ######## GNURADIO BLOCK MESSAGE RECEVER #########
class AcqPerfTest_msg_rx;
typedef boost::shared_ptr<AcqPerfTest_msg_rx> AcqPerfTest_msg_rx_sptr;
using AcqPerfTest_msg_rx_sptr = boost::shared_ptr<AcqPerfTest_msg_rx>;
AcqPerfTest_msg_rx_sptr AcqPerfTest_msg_rx_make(Concurrent_Queue<int>& queue);

View File

@ -57,7 +57,7 @@
// ######## GNURADIO BLOCK MESSAGE RECEVER #########
class GlonassL1CaPcpsAcquisitionTest_msg_rx;
typedef boost::shared_ptr<GlonassL1CaPcpsAcquisitionTest_msg_rx> GlonassL1CaPcpsAcquisitionTest_msg_rx_sptr;
using GlonassL1CaPcpsAcquisitionTest_msg_rx_sptr = boost::shared_ptr<GlonassL1CaPcpsAcquisitionTest_msg_rx>;
GlonassL1CaPcpsAcquisitionTest_msg_rx_sptr GlonassL1CaPcpsAcquisitionTest_msg_rx_make();

View File

@ -102,7 +102,11 @@ void thread_acquisition_send_rx_samples(gr::top_block_sptr top_block,
pointer_float = (float *)&buffer_float[0];
for (int k = 0; k < file_length; k = k + FLOAT_SIZE)
{
fread(buffer_float, FLOAT_SIZE, 1, rx_signal_file);
size_t result = fread(buffer_float, FLOAT_SIZE, 1, rx_signal_file);
if (result != FLOAT_SIZE)
{
std::cerr << "Error reading buffer" << std::endl;
}
if (fabs(pointer_float[0]) > max)
{
@ -152,7 +156,11 @@ void thread_acquisition_send_rx_samples(gr::top_block_sptr top_block,
for (int t = 0; t < transfer_size; t++)
{
fread(buffer_float, FLOAT_SIZE, 1, rx_signal_file);
size_t result = fread(buffer_float, FLOAT_SIZE, 1, rx_signal_file);
if (result != FLOAT_SIZE)
{
std::cerr << "Error reading buffer" << std::endl;
}
// specify (float) (int) for a quantization maximizing the dynamic range
buffer_DMA[t] = static_cast<signed char>((pointer_float[0] * (RX_SIGNAL_MAX_VALUE - 1) / max));
@ -176,7 +184,7 @@ void thread_acquisition_send_rx_samples(gr::top_block_sptr top_block,
// ######## GNURADIO BLOCK MESSAGE RECEVER #########
class GpsL1CaPcpsAcquisitionTestFpga_msg_rx;
typedef boost::shared_ptr<GpsL1CaPcpsAcquisitionTestFpga_msg_rx> GpsL1CaPcpsAcquisitionTest_msg_fpga_rx_sptr;
using GpsL1CaPcpsAcquisitionTest_msg_fpga_rx_sptr = boost::shared_ptr<GpsL1CaPcpsAcquisitionTestFpga_msg_rx>;
GpsL1CaPcpsAcquisitionTest_msg_fpga_rx_sptr GpsL1CaPcpsAcquisitionTestFpga_msg_rx_make();

View File

@ -63,7 +63,7 @@
// ######## GNURADIO BLOCK MESSAGE RECEVER #########
class GpsL2MPcpsAcquisitionTest_msg_rx;
typedef boost::shared_ptr<GpsL2MPcpsAcquisitionTest_msg_rx> GpsL2MPcpsAcquisitionTest_msg_rx_sptr;
using GpsL2MPcpsAcquisitionTest_msg_rx_sptr = boost::shared_ptr<GpsL2MPcpsAcquisitionTest_msg_rx>;
GpsL2MPcpsAcquisitionTest_msg_rx_sptr GpsL2MPcpsAcquisitionTest_msg_rx_make();

View File

@ -91,7 +91,7 @@
// ######## GNURADIO BLOCK MESSAGE RECEVER FOR TRACKING MESSAGES #########
class HybridObservablesTest_msg_rx;
typedef boost::shared_ptr<HybridObservablesTest_msg_rx> HybridObservablesTest_msg_rx_sptr;
using HybridObservablesTest_msg_rx_sptr = boost::shared_ptr<HybridObservablesTest_msg_rx>;
HybridObservablesTest_msg_rx_sptr HybridObservablesTest_msg_rx_make();
@ -142,7 +142,7 @@ HybridObservablesTest_msg_rx::~HybridObservablesTest_msg_rx() = default;
// ######## GNURADIO BLOCK MESSAGE RECEVER FOR TLM MESSAGES #########
class HybridObservablesTest_tlm_msg_rx;
typedef boost::shared_ptr<HybridObservablesTest_tlm_msg_rx> HybridObservablesTest_tlm_msg_rx_sptr;
using HybridObservablesTest_tlm_msg_rx_sptr = boost::shared_ptr<HybridObservablesTest_tlm_msg_rx>;
HybridObservablesTest_tlm_msg_rx_sptr HybridObservablesTest_tlm_msg_rx_make();

View File

@ -67,7 +67,7 @@
// ######## GNURADIO BLOCK MESSAGE RECEVER FOR TRACKING MESSAGES #########
class GpsL1CADllPllTelemetryDecoderTest_msg_rx;
typedef boost::shared_ptr<GpsL1CADllPllTelemetryDecoderTest_msg_rx> GpsL1CADllPllTelemetryDecoderTest_msg_rx_sptr;
using GpsL1CADllPllTelemetryDecoderTest_msg_rx_sptr = boost::shared_ptr<GpsL1CADllPllTelemetryDecoderTest_msg_rx>;
GpsL1CADllPllTelemetryDecoderTest_msg_rx_sptr GpsL1CADllPllTelemetryDecoderTest_msg_rx_make();
@ -118,7 +118,7 @@ GpsL1CADllPllTelemetryDecoderTest_msg_rx::~GpsL1CADllPllTelemetryDecoderTest_msg
// ######## GNURADIO BLOCK MESSAGE RECEVER FOR TLM MESSAGES #########
class GpsL1CADllPllTelemetryDecoderTest_tlm_msg_rx;
typedef boost::shared_ptr<GpsL1CADllPllTelemetryDecoderTest_tlm_msg_rx> GpsL1CADllPllTelemetryDecoderTest_tlm_msg_rx_sptr;
using GpsL1CADllPllTelemetryDecoderTest_tlm_msg_rx_sptr = boost::shared_ptr<GpsL1CADllPllTelemetryDecoderTest_tlm_msg_rx>;
GpsL1CADllPllTelemetryDecoderTest_tlm_msg_rx_sptr GpsL1CADllPllTelemetryDecoderTest_tlm_msg_rx_make();

View File

@ -63,7 +63,7 @@
// ######## GNURADIO BLOCK MESSAGE RECEVER #########
class GpsL1CADllPllTrackingTest_msg_rx;
typedef boost::shared_ptr<GpsL1CADllPllTrackingTest_msg_rx> GpsL1CADllPllTrackingTest_msg_rx_sptr;
using GpsL1CADllPllTrackingTest_msg_rx_sptr = boost::shared_ptr<GpsL1CADllPllTrackingTest_msg_rx>;
GpsL1CADllPllTrackingTest_msg_rx_sptr GpsL1CADllPllTrackingTest_msg_rx_make();

View File

@ -102,7 +102,11 @@ void send_tracking_gps_input_samples(FILE *rx_signal_file,
}
if (num_remaining_samples > DMA_TRACK_TRANSFER_SIZE)
{
fread(buffer_DMA, DMA_TRACK_TRANSFER_SIZE, 1, rx_signal_file);
size_t result = fread(buffer_DMA, DMA_TRACK_TRANSFER_SIZE, 1, rx_signal_file);
if (result != DMA_TRACK_TRANSFER_SIZE)
{
std::cerr << "Error reading from DMA" << std::endl;
}
assert(DMA_TRACK_TRANSFER_SIZE == write(dma_descr, &buffer_DMA[0], DMA_TRACK_TRANSFER_SIZE));
num_remaining_samples = num_remaining_samples - DMA_TRACK_TRANSFER_SIZE;
@ -110,8 +114,11 @@ void send_tracking_gps_input_samples(FILE *rx_signal_file,
}
else
{
fread(buffer_DMA, num_remaining_samples, 1, rx_signal_file);
size_t result = fread(buffer_DMA, num_remaining_samples, 1, rx_signal_file);
if (static_cast<int>(result) != num_remaining_samples)
{
std::cerr << "Error reading from DMA" << std::endl;
}
assert(num_remaining_samples == write(dma_descr, &buffer_DMA[0], num_remaining_samples));
num_samples_transferred = num_samples_transferred + num_remaining_samples;
num_remaining_samples = 0;

View File

@ -65,7 +65,7 @@ DEFINE_bool(plot_gps_l1_kf_tracking_test, false, "Plots results of GpsL1CAKfTrac
// ######## GNURADIO BLOCK MESSAGE RECEVER #########
class GpsL1CAKfTrackingTest_msg_rx;
typedef boost::shared_ptr<GpsL1CAKfTrackingTest_msg_rx> GpsL1CAKfTrackingTest_msg_rx_sptr;
using GpsL1CAKfTrackingTest_msg_rx_sptr = boost::shared_ptr<GpsL1CAKfTrackingTest_msg_rx>;
GpsL1CAKfTrackingTest_msg_rx_sptr GpsL1CAKfTrackingTest_msg_rx_make();

View File

@ -57,7 +57,7 @@
// ######## GNURADIO BLOCK MESSAGE RECEVER #########
class GpsL2MDllPllTrackingTest_msg_rx;
typedef boost::shared_ptr<GpsL2MDllPllTrackingTest_msg_rx> GpsL2MDllPllTrackingTest_msg_rx_sptr;
using GpsL2MDllPllTrackingTest_msg_rx_sptr = boost::shared_ptr<GpsL2MDllPllTrackingTest_msg_rx>;
GpsL2MDllPllTrackingTest_msg_rx_sptr GpsL2MDllPllTrackingTest_msg_rx_make();

View File

@ -79,7 +79,7 @@
// ######## GNURADIO TRACKING BLOCK MESSAGE RECEVER #########
class TrackingPullInTest_msg_rx;
typedef boost::shared_ptr<TrackingPullInTest_msg_rx> TrackingPullInTest_msg_rx_sptr;
using TrackingPullInTest_msg_rx_sptr = boost::shared_ptr<TrackingPullInTest_msg_rx>;
TrackingPullInTest_msg_rx_sptr TrackingPullInTest_msg_rx_make();