1
0
mirror of https://github.com/gnss-sdr/gnss-sdr synced 2024-12-15 20:50:33 +00:00

Merge branch 'next' of https://github.com/gnss-sdr/gnss-sdr into next

This commit is contained in:
Carles Fernandez 2019-04-17 09:24:47 +02:00
commit 0bbd8608ab
96 changed files with 1910 additions and 1257 deletions

View File

@ -578,7 +578,7 @@ $ sudo port install doxygen +docs
You also might need to activate a Python installation. The list of installed versions can be retrieved with:
~~~~~~
$ port select list python
$ port select --list python
~~~~~~
and you can activate a certain version by typing:

View File

@ -100,6 +100,13 @@ else()
gnsssdr_python_check_module("mako >= ${GNSSSDR_MAKO_MIN_VERSION}" mako "mako.__version__ >= '${GNSSSDR_MAKO_MIN_VERSION}'" MAKO_FOUND)
gnsssdr_python_check_module("six - python 2 and 3 compatibility library" six "True" SIX_FOUND)
endif()
if(NOT MAKO_FOUND OR NOT SIX_FOUND)
unset(PYTHON_EXECUTABLE)
find_package(PythonInterp ${GNSSSDR_PYTHON_MIN_VERSION})
gnsssdr_python_check_module("python >= ${GNSSSDR_PYTHON_MIN_VERSION}" sys "sys.version.split()[0] >= '${GNSSSDR_PYTHON_MIN_VERSION}'" PYTHON_MIN_VER_FOUND)
gnsssdr_python_check_module("mako >= ${GNSSSDR_MAKO_MIN_VERSION}" mako "mako.__version__ >= '${GNSSSDR_MAKO_MIN_VERSION}'" MAKO_FOUND)
gnsssdr_python_check_module("six - python 2 and 3 compatibility library" six "True" SIX_FOUND)
endif()
endif()
endif()

View File

@ -123,7 +123,7 @@ BeidouB1iPcpsAcquisition::BeidouB1iPcpsAcquisition(
threshold_ = 0.0;
doppler_step_ = 0;
gnss_synchro_ = nullptr;
channel_fsm_ = nullptr;
if (in_streams_ > 1)
{
LOG(ERROR) << "This implementation only supports one input stream";

View File

@ -102,7 +102,7 @@ public:
/*!
* \brief Set channel fsm associated to this acquisition instance
*/
inline void set_channel_fsm(std::shared_ptr<ChannelFsm> channel_fsm) override
inline void set_channel_fsm(std::weak_ptr<ChannelFsm> channel_fsm) override
{
channel_fsm_ = channel_fsm;
acquisition_->set_channel_fsm(channel_fsm);
@ -173,7 +173,7 @@ private:
bool bit_transition_flag_;
bool use_CFAR_algorithm_flag_;
uint32_t channel_;
std::shared_ptr<ChannelFsm> channel_fsm_;
std::weak_ptr<ChannelFsm> channel_fsm_;
float threshold_;
uint32_t doppler_max_;
uint32_t doppler_step_;

View File

@ -121,7 +121,7 @@ BeidouB3iPcpsAcquisition::BeidouB3iPcpsAcquisition(
threshold_ = 0.0;
doppler_step_ = 0;
gnss_synchro_ = nullptr;
channel_fsm_ = nullptr;
if (in_streams_ > 1)
{
LOG(ERROR) << "This implementation only supports one input stream";

View File

@ -101,7 +101,7 @@ public:
/*!
* \brief Set channel fsm associated to this acquisition instance
*/
inline void set_channel_fsm(std::shared_ptr<ChannelFsm> channel_fsm) override
inline void set_channel_fsm(std::weak_ptr<ChannelFsm> channel_fsm) override
{
channel_fsm_ = channel_fsm;
acquisition_->set_channel_fsm(channel_fsm);
@ -172,7 +172,7 @@ private:
bool bit_transition_flag_;
bool use_CFAR_algorithm_flag_;
unsigned int channel_;
std::shared_ptr<ChannelFsm> channel_fsm_;
std::weak_ptr<ChannelFsm> channel_fsm_;
float threshold_;
unsigned int doppler_max_;
unsigned int doppler_step_;

View File

@ -110,7 +110,7 @@ GalileoE1Pcps8msAmbiguousAcquisition::GalileoE1Pcps8msAmbiguousAcquisition(
threshold_ = 0.0;
doppler_step_ = 0;
gnss_synchro_ = nullptr;
channel_fsm_ = nullptr;
if (in_streams_ > 1)
{
LOG(ERROR) << "This implementation only supports one input stream";

View File

@ -96,7 +96,7 @@ public:
/*!
* \brief Set channel fsm associated to this acquisition instance
*/
inline void set_channel_fsm(std::shared_ptr<ChannelFsm> channel_fsm) override
inline void set_channel_fsm(std::weak_ptr<ChannelFsm> channel_fsm) override
{
channel_fsm_ = channel_fsm;
acquisition_cc_->set_channel_fsm(channel_fsm);
@ -156,7 +156,7 @@ private:
unsigned int vector_length_;
unsigned int code_length_;
unsigned int channel_;
std::shared_ptr<ChannelFsm> channel_fsm_;
std::weak_ptr<ChannelFsm> channel_fsm_;
float threshold_;
unsigned int doppler_max_;
unsigned int doppler_step_;

View File

@ -154,7 +154,7 @@ GalileoE1PcpsAmbiguousAcquisition::GalileoE1PcpsAmbiguousAcquisition(
threshold_ = 0.0;
doppler_step_ = 0;
gnss_synchro_ = nullptr;
channel_fsm_ = nullptr;
if (in_streams_ > 1)
{
LOG(ERROR) << "This implementation only supports one input stream";

View File

@ -100,7 +100,7 @@ public:
/*!
* \brief Set channel fsm associated to this acquisition instance
*/
inline void set_channel_fsm(std::shared_ptr<ChannelFsm> channel_fsm) override
inline void set_channel_fsm(std::weak_ptr<ChannelFsm> channel_fsm) override
{
channel_fsm_ = channel_fsm;
acquisition_->set_channel_fsm(channel_fsm);
@ -171,7 +171,7 @@ private:
bool use_CFAR_algorithm_flag_;
bool acquire_pilot_;
unsigned int channel_;
std::shared_ptr<ChannelFsm> channel_fsm_;
std::weak_ptr<ChannelFsm> channel_fsm_;
float threshold_;
unsigned int doppler_max_;
unsigned int doppler_step_;

View File

@ -44,6 +44,13 @@
#include <complex> // for complex
#include <cstring> // for memcpy
// the following flags are FPGA-specific and they are using arrange the values of the fft of the local code in the way the FPGA
// expects. This arrangement is done in the initialisation to avoid consuming unnecessary clock cycles during tracking.
#define QUANT_BITS_LOCAL_CODE 16
#define SELECT_LSBits 0x0000FFFF // Select the 10 LSbits out of a 20-bit word
#define SELECT_MSBbits 0xFFFF0000 // Select the 10 MSbits out of a 20-bit word
#define SELECT_ALL_CODE_BITS 0xFFFFFFFF // Select a 20 bit word
#define SHL_CODE_BITS 65536 // shift left by 10 bits
GalileoE1PcpsAmbiguousAcquisitionFpga::GalileoE1PcpsAmbiguousAcquisitionFpga(
ConfigurationInterface* configuration,
@ -67,7 +74,7 @@ GalileoE1PcpsAmbiguousAcquisitionFpga::GalileoE1PcpsAmbiguousAcquisitionFpga(
acq_parameters.repeat_satellite = configuration_->property(role + ".repeat_satellite", false);
DLOG(INFO) << role << " satellite repeat = " << acq_parameters.repeat_satellite;
float downsampling_factor = configuration_->property(role + ".downsampling_factor", 4.0);
uint32_t downsampling_factor = configuration_->property(role + ".downsampling_factor", 4);
acq_parameters.downsampling_factor = downsampling_factor;
fs_in = fs_in / downsampling_factor;
@ -97,15 +104,16 @@ GalileoE1PcpsAmbiguousAcquisitionFpga::GalileoE1PcpsAmbiguousAcquisitionFpga(
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));
acq_parameters.excludelimit = static_cast<unsigned int>(1 + ceil((1.0 / GALILEO_E1_CODE_CHIP_RATE_HZ) * static_cast<float>(fs_in)));
// 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
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 * GALILEO_E1_NUMBER_OF_CODES]; // memory containing all the possible fft codes for PRN 0 to 32
float max; // temporary maxima search
d_all_fft_codes_ = new uint32_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
int32_t tmp, tmp2, local_code, fft_data;
for (uint32_t PRN = 1; PRN <= GALILEO_E1_NUMBER_OF_CODES; PRN++)
{
@ -153,24 +161,33 @@ GalileoE1PcpsAmbiguousAcquisitionFpga::GalileoE1PcpsAmbiguousAcquisitionFpga(
max = std::abs(fft_codes_padded[i].imag());
}
}
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
// map the FFT to the dynamic range of the fixed point values an copy to buffer containing all FFTs
// and package codes in a format that is ready to be written to the FPGA
for (uint32_t i = 0; i < nsamples_total; i++)
{
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)));
tmp = static_cast<int32_t>(floor(fft_codes_padded[i].real() * (pow(2, QUANT_BITS_LOCAL_CODE - 1) - 1) / max));
tmp2 = static_cast<int32_t>(floor(fft_codes_padded[i].imag() * (pow(2, QUANT_BITS_LOCAL_CODE - 1) - 1) / max));
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_all_fft_codes_[i + (nsamples_total * (PRN - 1))] = fft_data;
}
}
acq_parameters.all_fft_codes = d_all_fft_codes_;
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);
acq_parameters.max_num_acqs = configuration_->property(role + ".max_num_acqs", 2);
// reference for the FPGA FFT-IFFT attenuation factor
acq_parameters.total_block_exp = configuration_->property(role + ".total_block_exp", 14);
acq_parameters.total_block_exp = configuration_->property(role + ".total_block_exp", 13);
acquisition_fpga_ = pcps_make_acquisition_fpga(acq_parameters);
channel_ = 0;
doppler_step_ = 0;
gnss_synchro_ = nullptr;
channel_fsm_ = nullptr;
// temporary buffers that we can delete
delete[] code;
delete fft_if;

View File

@ -99,7 +99,7 @@ public:
/*!
* \brief Set channel fsm associated to this acquisition instance
*/
inline void set_channel_fsm(std::shared_ptr<ChannelFsm> channel_fsm) override
inline void set_channel_fsm(std::weak_ptr<ChannelFsm> channel_fsm) override
{
channel_fsm_ = channel_fsm;
acquisition_fpga_->set_channel_fsm(channel_fsm);
@ -157,7 +157,7 @@ private:
pcps_acquisition_fpga_sptr acquisition_fpga_;
bool acquire_pilot_;
uint32_t channel_;
std::shared_ptr<ChannelFsm> channel_fsm_;
std::weak_ptr<ChannelFsm> channel_fsm_;
uint32_t doppler_max_;
uint32_t doppler_step_;
std::string dump_filename_;
@ -166,7 +166,7 @@ private:
unsigned int in_streams_;
unsigned int out_streams_;
lv_16sc_t* d_all_fft_codes_; // memory that contains all the code ffts
uint32_t* d_all_fft_codes_; // memory that contains all the code ffts
};
#endif /* GNSS_SDR_GALILEO_E1_PCPS_AMBIGUOUS_ACQUISITION_FPGA_H_ */

View File

@ -111,7 +111,7 @@ GalileoE1PcpsCccwsrAmbiguousAcquisition::GalileoE1PcpsCccwsrAmbiguousAcquisition
threshold_ = 0.0;
doppler_step_ = 0;
gnss_synchro_ = nullptr;
channel_fsm_ = nullptr;
if (in_streams_ > 1)
{
LOG(ERROR) << "This implementation only supports one input stream";

View File

@ -96,7 +96,7 @@ public:
/*!
* \brief Set channel fsm associated to this acquisition instance
*/
inline void set_channel_fsm(std::shared_ptr<ChannelFsm> channel_fsm) override
inline void set_channel_fsm(std::weak_ptr<ChannelFsm> channel_fsm) override
{
channel_fsm_ = channel_fsm;
acquisition_cc_->set_channel_fsm(channel_fsm);
@ -155,7 +155,7 @@ private:
unsigned int code_length_;
//unsigned int satellite_;
unsigned int channel_;
std::shared_ptr<ChannelFsm> channel_fsm_;
std::weak_ptr<ChannelFsm> channel_fsm_;
float threshold_;
unsigned int doppler_max_;
unsigned int doppler_step_;

View File

@ -144,7 +144,7 @@ GalileoE1PcpsQuickSyncAmbiguousAcquisition::GalileoE1PcpsQuickSyncAmbiguousAcqui
threshold_ = 0.0;
doppler_step_ = 0;
gnss_synchro_ = nullptr;
channel_fsm_ = nullptr;
if (in_streams_ > 1)
{
LOG(ERROR) << "This implementation only supports one input stream";

View File

@ -97,7 +97,7 @@ public:
/*!
* \brief Set channel fsm associated to this acquisition instance
*/
inline void set_channel_fsm(std::shared_ptr<ChannelFsm> channel_fsm) override
inline void set_channel_fsm(std::weak_ptr<ChannelFsm> channel_fsm) override
{
channel_fsm_ = channel_fsm;
acquisition_cc_->set_channel_fsm(channel_fsm);
@ -159,7 +159,7 @@ private:
unsigned int code_length_;
bool bit_transition_flag_;
unsigned int channel_;
std::shared_ptr<ChannelFsm> channel_fsm_;
std::weak_ptr<ChannelFsm> channel_fsm_;
float threshold_;
unsigned int doppler_max_;
unsigned int doppler_step_;

View File

@ -114,7 +114,7 @@ GalileoE1PcpsTongAmbiguousAcquisition::GalileoE1PcpsTongAmbiguousAcquisition(
threshold_ = 0.0;
doppler_step_ = 0;
gnss_synchro_ = nullptr;
channel_fsm_ = nullptr;
if (in_streams_ > 1)
{
LOG(ERROR) << "This implementation only supports one input stream";

View File

@ -96,7 +96,7 @@ public:
/*!
* \brief Set channel fsm associated to this acquisition instance
*/
inline void set_channel_fsm(std::shared_ptr<ChannelFsm> channel_fsm) override
inline void set_channel_fsm(std::weak_ptr<ChannelFsm> channel_fsm) override
{
channel_fsm_ = channel_fsm;
acquisition_cc_->set_channel_fsm(channel_fsm);
@ -157,7 +157,7 @@ private:
unsigned int vector_length_;
unsigned int code_length_;
unsigned int channel_;
std::shared_ptr<ChannelFsm> channel_fsm_;
std::weak_ptr<ChannelFsm> channel_fsm_;
float threshold_;
unsigned int doppler_max_;
unsigned int doppler_step_;

View File

@ -119,7 +119,7 @@ GalileoE5aNoncoherentIQAcquisitionCaf::GalileoE5aNoncoherentIQAcquisitionCaf(
threshold_ = 0.0;
doppler_step_ = 0;
gnss_synchro_ = nullptr;
channel_fsm_ = nullptr;
if (in_streams_ > 1)
{
LOG(ERROR) << "This implementation only supports one input stream";

View File

@ -97,7 +97,7 @@ public:
/*!
* \brief Set channel fsm associated to this acquisition instance
*/
inline void set_channel_fsm(std::shared_ptr<ChannelFsm> channel_fsm) override
inline void set_channel_fsm(std::weak_ptr<ChannelFsm> channel_fsm) override
{
channel_fsm_ = channel_fsm;
acquisition_cc_->set_channel_fsm(channel_fsm);
@ -160,7 +160,7 @@ private:
unsigned int code_length_;
bool bit_transition_flag_;
unsigned int channel_;
std::shared_ptr<ChannelFsm> channel_fsm_;
std::weak_ptr<ChannelFsm> channel_fsm_;
float threshold_;
unsigned int doppler_max_;
unsigned int doppler_step_;

View File

@ -152,7 +152,7 @@ GalileoE5aPcpsAcquisition::GalileoE5aPcpsAcquisition(ConfigurationInterface* con
threshold_ = 0.0;
doppler_step_ = 0;
gnss_synchro_ = nullptr;
channel_fsm_ = nullptr;
if (in_streams_ > 1)
{
LOG(ERROR) << "This implementation only supports one input stream";

View File

@ -88,7 +88,7 @@ public:
/*!
* \brief Set channel fsm associated to this acquisition instance
*/
inline void set_channel_fsm(std::shared_ptr<ChannelFsm> channel_fsm) override
inline void set_channel_fsm(std::weak_ptr<ChannelFsm> channel_fsm) override
{
channel_fsm_ = channel_fsm;
acquisition_->set_channel_fsm(channel_fsm);
@ -169,7 +169,7 @@ private:
unsigned int vector_length_;
unsigned int code_length_;
unsigned int channel_;
std::shared_ptr<ChannelFsm> channel_fsm_;
std::weak_ptr<ChannelFsm> channel_fsm_;
unsigned int doppler_max_;
unsigned int doppler_step_;
unsigned int sampled_ms_;

View File

@ -44,6 +44,13 @@
#include <complex> // for complex
#include <cstring> // for strcpy, memcpy
// the following flags are FPGA-specific and they are using arrange the values of the fft of the local code in the way the FPGA
// expects. This arrangement is done in the initialisation to avoid consuming unnecessary clock cycles during tracking.
#define QUANT_BITS_LOCAL_CODE 16
#define SELECT_LSBits 0x0000FFFF // Select the 10 LSbits out of a 20-bit word
#define SELECT_MSBbits 0xFFFF0000 // Select the 10 MSbits out of a 20-bit word
#define SELECT_ALL_CODE_BITS 0xFFFFFFFF // Select a 20 bit word
#define SHL_CODE_BITS 65536 // shift left by 10 bits
GalileoE5aPcpsAcquisitionFpga::GalileoE5aPcpsAcquisitionFpga(ConfigurationInterface* configuration,
const std::string& role,
@ -64,7 +71,7 @@ GalileoE5aPcpsAcquisitionFpga::GalileoE5aPcpsAcquisitionFpga(ConfigurationInterf
acq_parameters.repeat_satellite = configuration_->property(role + ".repeat_satellite", false);
DLOG(INFO) << role << " satellite repeat = " << acq_parameters.repeat_satellite;
float downsampling_factor = configuration_->property(role + ".downsampling_factor", 1.0);
uint32_t downsampling_factor = configuration_->property(role + ".downsampling_factor", 1);
acq_parameters.downsampling_factor = downsampling_factor;
fs_in = fs_in / downsampling_factor;
@ -98,15 +105,17 @@ GalileoE5aPcpsAcquisitionFpga::GalileoE5aPcpsAcquisitionFpga(ConfigurationInterf
acq_parameters.samples_per_ms = nsamples_total / sampled_ms;
acq_parameters.samples_per_code = nsamples_total;
acq_parameters.excludelimit = static_cast<uint32_t>(ceil((1.0 / GALILEO_E5A_CODE_CHIP_RATE_HZ) * static_cast<float>(acq_parameters.fs_in)));
acq_parameters.excludelimit = static_cast<unsigned int>(1 + ceil((1.0 / GALILEO_E5A_CODE_CHIP_RATE_HZ) * static_cast<float>(fs_in)));
// 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
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 * GALILEO_E5A_NUMBER_OF_CODES]; // memory containing all the possible fft codes for PRN 0 to 32
float max; // temporary maxima search
d_all_fft_codes_ = new uint32_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
int32_t tmp, tmp2, local_code, fft_data;
for (uint32_t PRN = 1; PRN <= GALILEO_E5A_NUMBER_OF_CODES; PRN++)
{
@ -154,24 +163,33 @@ GalileoE5aPcpsAcquisitionFpga::GalileoE5aPcpsAcquisitionFpga(ConfigurationInterf
max = std::abs(fft_codes_padded[i].imag());
}
}
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
// map the FFT to the dynamic range of the fixed point values an copy to buffer containing all FFTs
// and package codes in a format that is ready to be written to the FPGA
for (uint32_t i = 0; i < nsamples_total; i++)
{
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)));
tmp = static_cast<int32_t>(floor(fft_codes_padded[i].real() * (pow(2, QUANT_BITS_LOCAL_CODE - 1) - 1) / max));
tmp2 = static_cast<int32_t>(floor(fft_codes_padded[i].imag() * (pow(2, QUANT_BITS_LOCAL_CODE - 1) - 1) / max));
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_all_fft_codes_[i + (nsamples_total * (PRN - 1))] = fft_data;
}
}
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);
acq_parameters.total_block_exp = configuration_->property(role + ".total_block_exp", 13);
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);
acq_parameters.max_num_acqs = configuration_->property(role + ".max_num_acqs", 2);
acquisition_fpga_ = pcps_make_acquisition_fpga(acq_parameters);
channel_ = 0;
doppler_step_ = 0;
gnss_synchro_ = nullptr;
channel_fsm_ = nullptr;
// temporary buffers that we can delete
delete[] code;
delete fft_if;

View File

@ -101,7 +101,7 @@ public:
/*!
* \brief Set channel fsm associated to this acquisition instance
*/
inline void set_channel_fsm(std::shared_ptr<ChannelFsm> channel_fsm) override
inline void set_channel_fsm(std::weak_ptr<ChannelFsm> channel_fsm) override
{
channel_fsm_ = channel_fsm;
acquisition_fpga_->set_channel_fsm(channel_fsm);
@ -176,7 +176,7 @@ private:
bool acq_iq_;
uint32_t channel_;
std::shared_ptr<ChannelFsm> channel_fsm_;
std::weak_ptr<ChannelFsm> channel_fsm_;
uint32_t doppler_max_;
uint32_t doppler_step_;
unsigned int in_streams_;
@ -184,7 +184,7 @@ private:
Gnss_Synchro* gnss_synchro_;
lv_16sc_t* d_all_fft_codes_; // memory that contains all the code ffts
uint32_t* d_all_fft_codes_; // memory that contains all the code ffts
};
#endif /* GNSS_SDR_GALILEO_E5A_PCPS_ACQUISITION_FPGA_H_ */

View File

@ -125,7 +125,7 @@ GlonassL1CaPcpsAcquisition::GlonassL1CaPcpsAcquisition(
threshold_ = 0.0;
doppler_step_ = 0;
gnss_synchro_ = nullptr;
channel_fsm_ = nullptr;
if (in_streams_ > 1)
{
LOG(ERROR) << "This implementation only supports one input stream";

View File

@ -98,7 +98,7 @@ public:
/*!
* \brief Set channel fsm associated to this acquisition instance
*/
inline void set_channel_fsm(std::shared_ptr<ChannelFsm> channel_fsm) override
inline void set_channel_fsm(std::weak_ptr<ChannelFsm> channel_fsm) override
{
channel_fsm_ = channel_fsm;
acquisition_->set_channel_fsm(channel_fsm);
@ -162,7 +162,7 @@ private:
bool bit_transition_flag_;
bool use_CFAR_algorithm_flag_;
unsigned int channel_;
std::shared_ptr<ChannelFsm> channel_fsm_;
std::weak_ptr<ChannelFsm> channel_fsm_;
float threshold_;
unsigned int doppler_max_;
unsigned int doppler_step_;

View File

@ -124,7 +124,7 @@ GlonassL2CaPcpsAcquisition::GlonassL2CaPcpsAcquisition(
threshold_ = 0.0;
doppler_step_ = 0;
gnss_synchro_ = nullptr;
channel_fsm_ = nullptr;
if (in_streams_ > 1)
{
LOG(ERROR) << "This implementation only supports one input stream";

View File

@ -98,7 +98,7 @@ public:
/*!
* \brief Set channel fsm associated to this acquisition instance
*/
inline void set_channel_fsm(std::shared_ptr<ChannelFsm> channel_fsm) override
inline void set_channel_fsm(std::weak_ptr<ChannelFsm> channel_fsm) override
{
channel_fsm_ = channel_fsm;
acquisition_->set_channel_fsm(channel_fsm);
@ -162,7 +162,7 @@ private:
bool bit_transition_flag_;
bool use_CFAR_algorithm_flag_;
unsigned int channel_;
std::shared_ptr<ChannelFsm> channel_fsm_;
std::weak_ptr<ChannelFsm> channel_fsm_;
float threshold_;
unsigned int doppler_max_;
unsigned int doppler_step_;

View File

@ -147,7 +147,7 @@ GpsL1CaPcpsAcquisition::GpsL1CaPcpsAcquisition(
threshold_ = 0.0;
doppler_step_ = 0;
gnss_synchro_ = nullptr;
channel_fsm_ = nullptr;
if (in_streams_ > 1)
{
LOG(ERROR) << "This implementation only supports one input stream";

View File

@ -104,7 +104,7 @@ public:
/*!
* \brief Set channel fsm associated to this acquisition instance
*/
inline void set_channel_fsm(std::shared_ptr<ChannelFsm> channel_fsm) override
inline void set_channel_fsm(std::weak_ptr<ChannelFsm> channel_fsm) override
{
channel_fsm_ = channel_fsm;
acquisition_->set_channel_fsm(channel_fsm);
@ -174,7 +174,7 @@ private:
bool bit_transition_flag_;
bool use_CFAR_algorithm_flag_;
unsigned int channel_;
std::shared_ptr<ChannelFsm> channel_fsm_;
std::weak_ptr<ChannelFsm> channel_fsm_;
float threshold_;
unsigned int doppler_max_;
unsigned int doppler_step_;

View File

@ -97,7 +97,7 @@ GpsL1CaPcpsAcquisitionFineDoppler::GpsL1CaPcpsAcquisitionFineDoppler(
threshold_ = 0.0;
doppler_step_ = 0;
gnss_synchro_ = nullptr;
channel_fsm_ = nullptr;
if (in_streams_ > 1)
{
LOG(ERROR) << "This implementation only supports one input stream";

View File

@ -97,7 +97,7 @@ public:
/*!
* \brief Set channel fsm associated to this acquisition instance
*/
inline void set_channel_fsm(std::shared_ptr<ChannelFsm> channel_fsm) override
inline void set_channel_fsm(std::weak_ptr<ChannelFsm> channel_fsm) override
{
channel_fsm_ = channel_fsm;
acquisition_cc_->set_channel_fsm(channel_fsm);
@ -152,7 +152,7 @@ private:
std::string item_type_;
unsigned int vector_length_;
unsigned int channel_;
std::shared_ptr<ChannelFsm> channel_fsm_;
std::weak_ptr<ChannelFsm> channel_fsm_;
float threshold_;
int doppler_max_;
unsigned int doppler_step_;

View File

@ -47,9 +47,15 @@
#include <complex> // for complex
#include <cstring> // for memcpy
#define NUM_PRNs 32
// the following flags are FPGA-specific and they are using arrange the values of the fft of the local code in the way the FPGA
// expects. This arrangement is done in the initialisation to avoid consuming unnecessary clock cycles during tracking.
#define QUANT_BITS_LOCAL_CODE 16
#define SELECT_LSBits 0x0000FFFF // Select the 10 LSbits out of a 20-bit word
#define SELECT_MSBbits 0xFFFF0000 // Select the 10 MSbits out of a 20-bit word
#define SELECT_ALL_CODE_BITS 0xFFFFFFFF // Select a 20 bit word
#define SHL_CODE_BITS 65536 // shift left by 10 bits
GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga(
ConfigurationInterface* configuration,
@ -71,9 +77,8 @@ GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga(
acq_parameters.repeat_satellite = configuration_->property(role + ".repeat_satellite", false);
DLOG(INFO) << role << " satellite repeat = " << acq_parameters.repeat_satellite;
float downsampling_factor = configuration_->property(role + ".downsampling_factor", 4.0);
uint32_t downsampling_factor = configuration_->property(role + ".downsampling_factor", 4);
acq_parameters.downsampling_factor = downsampling_factor;
fs_in = fs_in / downsampling_factor;
acq_parameters.fs_in = fs_in;
@ -94,7 +99,7 @@ GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga(
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));
acq_parameters.excludelimit = static_cast<unsigned int>(1 + ceil(GPS_L1_CA_CHIP_PERIOD * static_cast<float>(fs_in)));
// 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)
@ -102,8 +107,10 @@ GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga(
// 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
d_all_fft_codes_ = new uint32_t[(nsamples_total * NUM_PRNs)]; // memory containing all the possible fft codes for PRN 0 to 32
float max;
int32_t tmp, tmp2, local_code, fft_data;
// temporary maxima search
for (uint32_t PRN = 1; PRN <= NUM_PRNs; PRN++)
{
gps_l1_ca_code_gen_complex_sampled(code, PRN, fs_in, 0); // generate PRN code
@ -135,10 +142,15 @@ GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga(
max = std::abs(fft_codes_padded[i].imag());
}
}
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
// map the FFT to the dynamic range of the fixed point values an copy to buffer containing all FFTs
// and package codes in a format that is ready to be written to the FPGA
for (uint32_t i = 0; i < nsamples_total; i++)
{
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)));
tmp = static_cast<int32_t>(floor(fft_codes_padded[i].real() * (pow(2, QUANT_BITS_LOCAL_CODE - 1) - 1) / max));
tmp2 = static_cast<int32_t>(floor(fft_codes_padded[i].imag() * (pow(2, QUANT_BITS_LOCAL_CODE - 1) - 1) / max));
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_all_fft_codes_[i + (nsamples_total * (PRN - 1))] = fft_data;
}
}
@ -146,14 +158,18 @@ GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga(
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);
acq_parameters.total_block_exp = configuration_->property(role + ".total_block_exp", 10);
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);
acq_parameters.max_num_acqs = configuration_->property(role + ".max_num_acqs", 2);
acquisition_fpga_ = pcps_make_acquisition_fpga(acq_parameters);
channel_ = 0;
doppler_step_ = 0;
gnss_synchro_ = nullptr;
channel_fsm_ = nullptr;
// temporary buffers that we can delete
delete[] code;
delete fft_if;

View File

@ -35,6 +35,7 @@
#ifndef GNSS_SDR_GPS_L1_CA_PCPS_ACQUISITION_FPGA_H_
#define GNSS_SDR_GPS_L1_CA_PCPS_ACQUISITION_FPGA_H_
#include "channel_fsm.h"
#include "pcps_acquisition_fpga.h"
#include <gnuradio/runtime_types.h> // for basic_block_sptr, top_block_sptr
@ -100,9 +101,9 @@ public:
}
/*!
* \brief Set channel fsm associated to this acquisition instance
*/
inline void set_channel_fsm(std::shared_ptr<ChannelFsm> channel_fsm) override
* \brief Set channel fsm associated to this acquisition instance
*/
inline void set_channel_fsm(std::weak_ptr<ChannelFsm> channel_fsm) override
{
channel_fsm_ = channel_fsm;
acquisition_fpga_->set_channel_fsm(channel_fsm);
@ -159,14 +160,14 @@ private:
ConfigurationInterface* configuration_;
pcps_acquisition_fpga_sptr acquisition_fpga_;
uint32_t channel_;
std::shared_ptr<ChannelFsm> channel_fsm_;
std::weak_ptr<ChannelFsm> channel_fsm_;
uint32_t doppler_max_;
uint32_t doppler_step_;
Gnss_Synchro* gnss_synchro_;
std::string role_;
unsigned int in_streams_;
unsigned int out_streams_;
lv_16sc_t* d_all_fft_codes_; // memory that contains all the code ffts
uint32_t* d_all_fft_codes_; // memory that contains all the code ffts
};
#endif /* GNSS_SDR_GPS_L1_CA_PCPS_ACQUISITION_FPGA_H_ */

View File

@ -89,7 +89,7 @@ GpsL1CaPcpsAssistedAcquisition::GpsL1CaPcpsAssistedAcquisition(
threshold_ = 0.0;
doppler_step_ = 0;
gnss_synchro_ = nullptr;
channel_fsm_ = nullptr;
if (in_streams_ > 1)
{
LOG(ERROR) << "This implementation only supports one input stream";

View File

@ -97,7 +97,7 @@ public:
/*!
* \brief Set channel fsm associated to this acquisition instance
*/
inline void set_channel_fsm(std::shared_ptr<ChannelFsm> channel_fsm) override
inline void set_channel_fsm(std::weak_ptr<ChannelFsm> channel_fsm) override
{
channel_fsm_ = channel_fsm;
acquisition_cc_->set_channel_fsm(channel_fsm);
@ -149,7 +149,7 @@ private:
unsigned int vector_length_;
//unsigned int satellite_;
unsigned int channel_;
std::shared_ptr<ChannelFsm> channel_fsm_;
std::weak_ptr<ChannelFsm> channel_fsm_;
float threshold_;
int doppler_max_;
unsigned int doppler_step_;

View File

@ -105,7 +105,7 @@ GpsL1CaPcpsOpenClAcquisition::GpsL1CaPcpsOpenClAcquisition(
threshold_ = 0.0;
doppler_step_ = 0;
gnss_synchro_ = nullptr;
channel_fsm_ = nullptr;
if (in_streams_ > 1)
{
LOG(ERROR) << "This implementation only supports one input stream";

View File

@ -96,7 +96,7 @@ public:
/*!
* \brief Set channel fsm associated to this acquisition instance
*/
inline void set_channel_fsm(std::shared_ptr<ChannelFsm> channel_fsm) override
inline void set_channel_fsm(std::weak_ptr<ChannelFsm> channel_fsm) override
{
channel_fsm_ = channel_fsm;
acquisition_cc_->set_channel_fsm(channel_fsm);
@ -154,7 +154,7 @@ private:
unsigned int code_length_;
bool bit_transition_flag_;
unsigned int channel_;
std::shared_ptr<ChannelFsm> channel_fsm_;
std::weak_ptr<ChannelFsm> channel_fsm_;
float threshold_;
unsigned int doppler_max_;
unsigned int doppler_step_;

View File

@ -137,7 +137,7 @@ GpsL1CaPcpsQuickSyncAcquisition::GpsL1CaPcpsQuickSyncAcquisition(
threshold_ = 0.0;
doppler_step_ = 0;
gnss_synchro_ = nullptr;
channel_fsm_ = nullptr;
if (in_streams_ > 1)
{
LOG(ERROR) << "This implementation only supports one input stream";

View File

@ -98,7 +98,7 @@ public:
/*!
* \brief Set channel fsm associated to this acquisition instance
*/
inline void set_channel_fsm(std::shared_ptr<ChannelFsm> channel_fsm) override
inline void set_channel_fsm(std::weak_ptr<ChannelFsm> channel_fsm) override
{
channel_fsm_ = channel_fsm;
acquisition_cc_->set_channel_fsm(channel_fsm);
@ -160,7 +160,7 @@ private:
unsigned int code_length_;
bool bit_transition_flag_;
unsigned int channel_;
std::shared_ptr<ChannelFsm> channel_fsm_;
std::weak_ptr<ChannelFsm> channel_fsm_;
float threshold_;
unsigned int doppler_max_;
unsigned int doppler_step_;

View File

@ -99,7 +99,7 @@ GpsL1CaPcpsTongAcquisition::GpsL1CaPcpsTongAcquisition(
threshold_ = 0.0;
doppler_step_ = 0;
gnss_synchro_ = nullptr;
channel_fsm_ = nullptr;
if (in_streams_ > 1)
{
LOG(ERROR) << "This implementation only supports one input stream";

View File

@ -97,7 +97,7 @@ public:
/*!
* \brief Set channel fsm associated to this acquisition instance
*/
inline void set_channel_fsm(std::shared_ptr<ChannelFsm> channel_fsm) override
inline void set_channel_fsm(std::weak_ptr<ChannelFsm> channel_fsm) override
{
channel_fsm_ = channel_fsm;
acquisition_cc_->set_channel_fsm(channel_fsm);
@ -158,7 +158,7 @@ private:
unsigned int vector_length_;
unsigned int code_length_;
unsigned int channel_;
std::shared_ptr<ChannelFsm> channel_fsm_;
std::weak_ptr<ChannelFsm> channel_fsm_;
float threshold_;
unsigned int doppler_max_;
unsigned int doppler_step_;

View File

@ -151,7 +151,7 @@ GpsL2MPcpsAcquisition::GpsL2MPcpsAcquisition(
threshold_ = 0.0;
doppler_step_ = 0;
gnss_synchro_ = nullptr;
channel_fsm_ = nullptr;
num_codes_ = acq_parameters_.sampled_ms / acq_parameters_.ms_per_code;
if (in_streams_ > 1)
{

View File

@ -101,7 +101,7 @@ public:
/*!
* \brief Set channel fsm associated to this acquisition instance
*/
inline void set_channel_fsm(std::shared_ptr<ChannelFsm> channel_fsm) override
inline void set_channel_fsm(std::weak_ptr<ChannelFsm> channel_fsm) override
{
channel_fsm_ = channel_fsm;
acquisition_->set_channel_fsm(channel_fsm);
@ -171,7 +171,7 @@ private:
bool bit_transition_flag_;
bool use_CFAR_algorithm_flag_;
unsigned int channel_;
std::shared_ptr<ChannelFsm> channel_fsm_;
std::weak_ptr<ChannelFsm> channel_fsm_;
float threshold_;
unsigned int doppler_max_;
unsigned int doppler_step_;

View File

@ -47,7 +47,11 @@
#include <cstring> // for memcpy
#define NUM_PRNs 32
#define QUANT_BITS_LOCAL_CODE 16
#define SELECT_LSBits 0x0000FFFF // Select the 10 LSbits out of a 20-bit word
#define SELECT_MSBbits 0xFFFF0000 // Select the 10 MSbits out of a 20-bit word
#define SELECT_ALL_CODE_BITS 0xFFFFFFFF // Select a 20 bit word
#define SHL_CODE_BITS 65536 // shift left by 10 bits
GpsL2MPcpsAcquisitionFpga::GpsL2MPcpsAcquisitionFpga(
ConfigurationInterface* configuration,
@ -102,8 +106,11 @@ GpsL2MPcpsAcquisitionFpga::GpsL2MPcpsAcquisitionFpga(
// 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
//d_all_fft_codes_ = new lv_16sc_t[nsamples_total * NUM_PRNs]; // memory containing all the possible fft codes for PRN 0 to 32
d_all_fft_codes_ = new uint32_t[(nsamples_total * NUM_PRNs)]; // memory containing all the possible fft codes for PRN 0 to 32
float max; // temporary maxima search
int32_t tmp, tmp2, local_code, fft_data;
for (unsigned int PRN = 1; PRN <= NUM_PRNs; PRN++)
{
gps_l2c_m_code_gen_complex_sampled(code, PRN, fs_in_);
@ -127,10 +134,18 @@ GpsL2MPcpsAcquisitionFpga::GpsL2MPcpsAcquisitionFpga(
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
// map the FFT to the dynamic range of the fixed point values an copy to buffer containing all FFTs
// and package codes in a format that is ready to be written to the FPGA
for (uint32_t i = 0; i < nsamples_total; i++)
{
d_all_fft_codes_[i + nsamples_total * (PRN - 1)] = lv_16sc_t(static_cast<int>(floor(fft_codes_padded[i].real() * (pow(2, 7) - 1) / max)),
static_cast<int>(floor(fft_codes_padded[i].imag() * (pow(2, 7) - 1) / max)));
tmp = static_cast<int32_t>(floor(fft_codes_padded[i].real() * (pow(2, QUANT_BITS_LOCAL_CODE - 1) - 1) / max));
tmp2 = static_cast<int32_t>(floor(fft_codes_padded[i].imag() * (pow(2, QUANT_BITS_LOCAL_CODE - 1) - 1) / max));
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_all_fft_codes_[i + (nsamples_total * (PRN - 1))] = fft_data;
// d_all_fft_codes_[i + nsamples_total * (PRN - 1)] = lv_16sc_t(static_cast<int32_t>(floor(fft_codes_padded[i].real() * (pow(2, QUANT_BITS_LOCAL_CODE - 1) - 1) / max)),
// static_cast<int32_t>(floor(fft_codes_padded[i].imag() * (pow(2, QUANT_BITS_LOCAL_CODE - 1) - 1) / max)));
}
}
@ -146,7 +161,7 @@ GpsL2MPcpsAcquisitionFpga::GpsL2MPcpsAcquisitionFpga(
channel_ = 0;
doppler_step_ = 0;
gnss_synchro_ = nullptr;
channel_fsm_ = nullptr;
threshold_ = 0.0;
}

View File

@ -100,7 +100,7 @@ public:
/*!
* \brief Set channel fsm associated to this acquisition instance
*/
inline void set_channel_fsm(std::shared_ptr<ChannelFsm> channel_fsm) override
inline void set_channel_fsm(std::weak_ptr<ChannelFsm> channel_fsm) override
{
channel_fsm_ = channel_fsm;
acquisition_fpga_->set_channel_fsm(channel_fsm);
@ -158,7 +158,7 @@ private:
pcps_acquisition_fpga_sptr acquisition_fpga_;
std::string item_type_;
unsigned int channel_;
std::shared_ptr<ChannelFsm> channel_fsm_;
std::weak_ptr<ChannelFsm> channel_fsm_;
float threshold_;
unsigned int doppler_max_;
unsigned int doppler_step_;
@ -169,7 +169,7 @@ private:
unsigned int in_streams_;
unsigned int out_streams_;
lv_16sc_t* d_all_fft_codes_; // memory that contains all the code ffts
uint32_t* d_all_fft_codes_; // memory that contains all the code ffts
//float calculate_threshold(float pfa);
};

View File

@ -147,7 +147,7 @@ GpsL5iPcpsAcquisition::GpsL5iPcpsAcquisition(
threshold_ = 0.0;
doppler_step_ = 0;
gnss_synchro_ = nullptr;
channel_fsm_ = nullptr;
if (in_streams_ > 1)
{
LOG(ERROR) << "This implementation only supports one input stream";

View File

@ -101,7 +101,7 @@ public:
/*!
* \brief Set channel fsm associated to this acquisition instance
*/
inline void set_channel_fsm(std::shared_ptr<ChannelFsm> channel_fsm) override
inline void set_channel_fsm(std::weak_ptr<ChannelFsm> channel_fsm) override
{
channel_fsm_ = channel_fsm;
acquisition_->set_channel_fsm(channel_fsm);
@ -170,7 +170,7 @@ private:
bool bit_transition_flag_;
bool use_CFAR_algorithm_flag_;
unsigned int channel_;
std::shared_ptr<ChannelFsm> channel_fsm_;
std::weak_ptr<ChannelFsm> channel_fsm_;
float threshold_;
unsigned int doppler_max_;
unsigned int doppler_step_;

View File

@ -49,6 +49,14 @@
#define NUM_PRNs 32
// the following flags are FPGA-specific and they are using arrange the values of the fft of the local code in the way the FPGA
// expects. This arrangement is done in the initialisation to avoid consuming unnecessary clock cycles during tracking.
#define QUANT_BITS_LOCAL_CODE 16
#define SELECT_LSBits 0x0000FFFF // Select the 10 LSbits out of a 20-bit word
#define SELECT_MSBbits 0xFFFF0000 // Select the 10 MSbits out of a 20-bit word
#define SELECT_ALL_CODE_BITS 0xFFFFFFFF // Select a 20 bit word
#define SHL_CODE_BITS 65536 // shift left by 10 bits
GpsL5iPcpsAcquisitionFpga::GpsL5iPcpsAcquisitionFpga(
ConfigurationInterface* configuration,
@ -70,7 +78,7 @@ GpsL5iPcpsAcquisitionFpga::GpsL5iPcpsAcquisitionFpga(
acq_parameters.repeat_satellite = configuration_->property(role + ".repeat_satellite", false);
DLOG(INFO) << role << " satellite repeat = " << acq_parameters.repeat_satellite;
float downsampling_factor = configuration_->property(role + ".downsampling_factor", 1.0);
uint32_t downsampling_factor = configuration_->property(role + ".downsampling_factor", 1);
acq_parameters.downsampling_factor = downsampling_factor;
fs_in = fs_in / downsampling_factor;
@ -96,16 +104,18 @@ GpsL5iPcpsAcquisitionFpga::GpsL5iPcpsAcquisitionFpga(
acq_parameters.samples_per_ms = nsamples_total / sampled_ms;
acq_parameters.samples_per_code = nsamples_total;
acq_parameters.excludelimit = static_cast<uint32_t>(ceil((1.0 / GPS_L5I_CODE_RATE_HZ) * static_cast<float>(acq_parameters.fs_in)));
acq_parameters.excludelimit = static_cast<unsigned int>(1 + ceil((1.0 / GPS_L5I_CODE_RATE_HZ) * static_cast<float>(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(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()));
d_all_fft_codes_ = new lv_16sc_t[nsamples_total * NUM_PRNs]; // memory containing all the possible fft codes for PRN 0 to 32
d_all_fft_codes_ = new uint32_t[(nsamples_total * NUM_PRNs)]; // memory containing all the possible fft codes for PRN 0 to 32
float max; // temporary maxima search
int32_t tmp, tmp2, local_code, fft_data;
for (uint32_t PRN = 1; PRN <= NUM_PRNs; PRN++)
{
gps_l5i_code_gen_complex_sampled(code, PRN, fs_in);
@ -136,24 +146,33 @@ GpsL5iPcpsAcquisitionFpga::GpsL5iPcpsAcquisitionFpga(
max = std::abs(fft_codes_padded[i].imag());
}
}
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
// map the FFT to the dynamic range of the fixed point values an copy to buffer containing all FFTs
// and package codes in a format that is ready to be written to the FPGA
for (uint32_t i = 0; i < nsamples_total; i++)
{
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)));
tmp = static_cast<int32_t>(floor(fft_codes_padded[i].real() * (pow(2, QUANT_BITS_LOCAL_CODE - 1) - 1) / max));
tmp2 = static_cast<int32_t>(floor(fft_codes_padded[i].imag() * (pow(2, QUANT_BITS_LOCAL_CODE - 1) - 1) / max));
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_all_fft_codes_[i + (nsamples_total * (PRN - 1))] = fft_data;
}
}
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);
acq_parameters.total_block_exp = configuration_->property(role + ".total_block_exp", 13);
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);
acq_parameters.max_num_acqs = configuration_->property(role + ".max_num_acqs", 2);
acquisition_fpga_ = pcps_make_acquisition_fpga(acq_parameters);
channel_ = 0;
doppler_step_ = 0;
gnss_synchro_ = nullptr;
channel_fsm_ = nullptr;
// temporary buffers that we can delete
delete[] code;
delete fft_if;

View File

@ -101,11 +101,12 @@ public:
/*!
* \brief Set channel fsm associated to this acquisition instance
*/
inline void set_channel_fsm(std::shared_ptr<ChannelFsm> channel_fsm) override
inline void set_channel_fsm(std::weak_ptr<ChannelFsm> channel_fsm) override
{
channel_fsm_ = channel_fsm;
acquisition_fpga_->set_channel_fsm(channel_fsm);
}
/*!
* \brief Set statistics threshold of PCPS algorithm
*/
@ -158,7 +159,7 @@ private:
pcps_acquisition_fpga_sptr acquisition_fpga_;
std::string item_type_;
uint32_t channel_;
std::shared_ptr<ChannelFsm> channel_fsm_;
std::weak_ptr<ChannelFsm> channel_fsm_;
uint32_t doppler_max_;
uint32_t doppler_step_;
std::string dump_filename_;
@ -167,7 +168,7 @@ private:
unsigned int in_streams_;
unsigned int out_streams_;
lv_16sc_t* d_all_fft_codes_; // memory that contains all the code ffts
uint32_t* d_all_fft_codes_; // memory that contains all the code ffts
float calculate_threshold(float pfa);
};

View File

@ -100,7 +100,7 @@ private:
int doppler_offset);
float estimate_input_power(gr_complex* in);
std::shared_ptr<ChannelFsm> d_channel_fsm;
std::weak_ptr<ChannelFsm> d_channel_fsm;
int64_t d_fs_in;
int d_samples_per_ms;
int d_sampled_ms;
@ -216,7 +216,7 @@ public:
/*!
* \brief Set channel fsm associated to this acquisition instance
*/
inline void set_channel_fsm(std::shared_ptr<ChannelFsm> channel_fsm)
inline void set_channel_fsm(std::weak_ptr<ChannelFsm> channel_fsm)
{
d_channel_fsm = channel_fsm;
}

View File

@ -118,7 +118,7 @@ private:
int32_t d_state;
bool d_dump;
uint32_t d_channel;
std::shared_ptr<ChannelFsm> d_channel_fsm;
std::weak_ptr<ChannelFsm> d_channel_fsm;
std::string d_dump_filename;
public:
@ -186,7 +186,7 @@ public:
/*!
* \brief Set channel fsm associated to this acquisition instance
*/
inline void set_channel_fsm(std::shared_ptr<ChannelFsm> channel_fsm)
inline void set_channel_fsm(std::weak_ptr<ChannelFsm> channel_fsm)
{
d_channel_fsm = channel_fsm;
}

View File

@ -429,10 +429,11 @@ void pcps_acquisition::send_positive_acquisition()
<< ", magnitude " << d_mag
<< ", input signal power " << d_input_power;
d_positive_acq = 1;
if (d_channel_fsm)
if (!d_channel_fsm.expired())
{
//the channel FSM is set, so, notify it directly the positive acquisition to minimize delays
d_channel_fsm->Event_valid_acquisition();
d_channel_fsm.lock()->Event_valid_acquisition();
}
else
{

View File

@ -124,7 +124,7 @@ private:
int64_t d_old_freq;
int32_t d_state;
uint32_t d_channel;
std::shared_ptr<ChannelFsm> d_channel_fsm;
std::weak_ptr<ChannelFsm> d_channel_fsm;
uint32_t d_doppler_step;
float d_doppler_center_step_two;
uint32_t d_num_noncoherent_integrations_counter;
@ -213,7 +213,7 @@ public:
/*!
* \brief Set channel fsm associated to this acquisition instance
*/
inline void set_channel_fsm(std::shared_ptr<ChannelFsm> channel_fsm)
inline void set_channel_fsm(std::weak_ptr<ChannelFsm> channel_fsm)
{
d_channel_fsm = channel_fsm;
}

View File

@ -122,7 +122,7 @@ private:
int d_n_samples_in_buffer;
bool d_dump;
unsigned int d_channel;
std::shared_ptr<ChannelFsm> d_channel_fsm;
std::weak_ptr<ChannelFsm> d_channel_fsm;
std::string d_dump_filename;
@ -189,7 +189,7 @@ public:
/*!
* \brief Set channel fsm associated to this acquisition instance
*/
inline void set_channel_fsm(std::shared_ptr<ChannelFsm> channel_fsm)
inline void set_channel_fsm(std::weak_ptr<ChannelFsm> channel_fsm)
{
d_channel_fsm = channel_fsm;
}

View File

@ -34,6 +34,7 @@
#include "pcps_acquisition_fpga.h"
#include "gnss_synchro.h"
//#include <boost/chrono.hpp>
#include <glog/logging.h>
#include <cmath> // for ceil
#include <iostream> // for operator<<
@ -42,7 +43,6 @@
#define AQ_DOWNSAMPLING_DELAY 40 // delay due to the downsampling filter in the acquisition
pcps_acquisition_fpga_sptr pcps_make_acquisition_fpga(pcpsconf_fpga_t conf_)
{
return pcps_acquisition_fpga_sptr(new pcps_acquisition_fpga(std::move(conf_)));
@ -52,7 +52,7 @@ pcps_acquisition_fpga_sptr pcps_make_acquisition_fpga(pcpsconf_fpga_t conf_)
pcps_acquisition_fpga::pcps_acquisition_fpga(pcpsconf_fpga_t conf_)
{
acq_parameters = std::move(conf_);
d_sample_counter = 0ULL; // SAMPLE COUNTER
d_sample_counter = 0ULL; // Sample Counter
d_active = false;
d_state = 0;
d_fft_size = acq_parameters.samples_per_code;
@ -71,16 +71,21 @@ pcps_acquisition_fpga::pcps_acquisition_fpga(pcpsconf_fpga_t conf_)
d_total_block_exp = acq_parameters.total_block_exp;
d_make_2_steps = acq_parameters.make_2_steps;
d_num_doppler_bins_step2 = acq_parameters.num_doppler_bins_step2;
d_doppler_step2 = acq_parameters.doppler_step2;
d_doppler_center_step_two = 0.0;
d_doppler_max = acq_parameters.doppler_max;
d_max_num_acqs = acq_parameters.max_num_acqs;
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()
{
acquisition_fpga->free();
}
pcps_acquisition_fpga::~pcps_acquisition_fpga() = default;
void pcps_acquisition_fpga::set_local_code()
{
@ -100,9 +105,7 @@ void pcps_acquisition_fpga::init()
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))) + 1;
acquisition_fpga->init();
d_num_doppler_bins = static_cast<uint32_t>(std::ceil(static_cast<double>(static_cast<int32_t>(d_doppler_max) - static_cast<int32_t>(-d_doppler_max)) / static_cast<double>(d_doppler_step))) + 1;
}
@ -144,7 +147,7 @@ void pcps_acquisition_fpga::send_positive_acquisition()
<< ", input signal power " << d_input_power;
//the channel FSM is set, so, notify it directly the positive acquisition to minimize delays
d_channel_fsm->Event_valid_acquisition();
d_channel_fsm.lock()->Event_valid_acquisition();
}
@ -163,65 +166,60 @@ void pcps_acquisition_fpga::send_negative_acquisition()
if (acq_parameters.repeat_satellite == true)
{
d_channel_fsm->Event_failed_acquisition_repeat();
d_channel_fsm.lock()->Event_failed_acquisition_repeat();
}
else
{
d_channel_fsm->Event_failed_acquisition_no_repeat();
d_channel_fsm.lock()->Event_failed_acquisition_no_repeat();
}
}
void pcps_acquisition_fpga::set_active(bool active)
void pcps_acquisition_fpga::acquisition_core(uint32_t num_doppler_bins, uint32_t doppler_step, int32_t doppler_min)
{
d_active = active;
// initialize acquisition algorithm
uint32_t indext = 0U;
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: "
<< d_threshold << ", doppler_max: " << acq_parameters.doppler_max
<< ", doppler_step: " << d_doppler_step
// no CFAR algorithm in the FPGA
<< ", use_CFAR_algorithm_flag: false";
uint64_t initial_sample;
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);
int32_t doppler;
acquisition_fpga->set_doppler_sweep(num_doppler_bins, doppler_step, doppler_min);
acquisition_fpga->run_acquisition();
acquisition_fpga->read_acquisition_results(&indext, &firstpeak, &secondpeak, &initial_sample, &d_input_power, &d_doppler_index, &total_block_exp);
acquisition_fpga->read_acquisition_results(&indext,
&firstpeak,
&secondpeak,
&initial_sample,
&d_input_power,
&d_doppler_index,
&total_block_exp);
doppler = static_cast<int32_t>(doppler_min) + doppler_step * (d_doppler_index - 1);
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;
}
doppler = -static_cast<int32_t>(acq_parameters.doppler_max) + d_doppler_step * (d_doppler_index - 1);
if (secondpeak > 0)
{
d_test_statistics = firstpeak / secondpeak;
d_test_statistics = 0;
}
else
{
d_test_statistics = 0.0;
if (secondpeak > 0)
{
d_test_statistics = firstpeak / secondpeak;
}
else
{
d_test_statistics = 0.0;
}
}
// debug
// if (d_test_statistics > d_threshold)
// {
// printf("firstpeak = %f, secondpeak = %f, test_statistics = %f reported block exp = %d PRN = %d inext = %d, initial_sample = %ld doppler = %d\n", firstpeak, secondpeak, d_test_statistics, (int)total_block_exp, (int)d_gnss_synchro->PRN, (int)indext, (long int)initial_sample, (int)doppler);
// printf("doppler_min = %d doppler_step = %d num_doppler_bins = %d\n", (int)doppler_min, (int)doppler_step, (int)num_doppler_bins);
// }
d_gnss_synchro->Acq_doppler_hz = static_cast<double>(doppler);
d_sample_counter = initial_sample;
@ -230,7 +228,7 @@ void pcps_acquisition_fpga::set_active(bool active)
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
d_gnss_synchro->Acq_samplestamp_samples = d_downsampling_factor * static_cast<uint64_t>(d_sample_counter) - static_cast<uint64_t>(44); //33; //41; //+ 81*0.5; // delay due to the downsampling filter in the acquisition
}
else
{
@ -243,18 +241,82 @@ void pcps_acquisition_fpga::set_active(bool active)
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)
void pcps_acquisition_fpga::set_active(bool active)
{
d_active = active;
d_input_power = 0.0;
d_mag = 0.0;
DLOG(INFO) << "Channel: " << d_channel
<< " , doing acquisition of satellite: " << d_gnss_synchro->System << " " << d_gnss_synchro->PRN
<< " ,sample stamp: " << d_sample_counter << ", threshold: "
<< d_threshold << ", doppler_max: " << d_doppler_max
<< ", doppler_step: " << d_doppler_step
// no CFAR algorithm in the FPGA
<< ", use_CFAR_algorithm_flag: false";
acquisition_fpga->open_device();
acquisition_fpga->configure_acquisition();
acquisition_fpga->write_local_code();
acquisition_fpga->set_block_exp(d_total_block_exp);
acquisition_core(d_num_doppler_bins, d_doppler_step, -d_doppler_max);
if (!d_make_2_steps)
{
d_active = false;
send_positive_acquisition();
d_state = 0; // Positive acquisition
acquisition_fpga->close_device();
if (d_test_statistics > d_threshold)
{
d_active = false;
send_positive_acquisition();
d_state = 0; // Positive acquisition
}
else
{
d_state = 0;
d_active = false;
send_negative_acquisition();
}
}
else
{
d_state = 0;
d_active = false;
send_negative_acquisition();
if (d_test_statistics > d_threshold)
{
d_doppler_center_step_two = static_cast<float>(d_gnss_synchro->Acq_doppler_hz);
uint32_t num_second_acq = 1;
while (num_second_acq < d_max_num_acqs)
{
acquisition_core(d_num_doppler_bins_step2, d_doppler_step2, d_doppler_center_step_two - static_cast<float>(floor(d_num_doppler_bins_step2 / 2.0)) * d_doppler_step2);
if (d_test_statistics > d_threshold)
{
d_active = false;
send_positive_acquisition();
d_state = 0; // Positive acquisition
break;
}
num_second_acq = num_second_acq + 1;
}
acquisition_fpga->close_device();
if (d_test_statistics <= d_threshold)
{
d_state = 0;
d_active = false;
send_negative_acquisition();
}
}
else
{
acquisition_fpga->close_device();
d_state = 0;
d_active = false;
send_negative_acquisition();
}
}
}
@ -262,11 +324,7 @@ void pcps_acquisition_fpga::set_active(bool active)
void pcps_acquisition_fpga::reset_acquisition(void)
{
// this function triggers a HW reset of the FPGA PL.
acquisition_fpga->open_device();
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);
acquisition_fpga->close_device();
}

View File

@ -62,11 +62,16 @@ typedef struct
int32_t code_length;
uint32_t select_queue_Fpga;
std::string device_name;
lv_16sc_t* all_fft_codes; // memory that contains all the code ffts
float downsampling_factor;
uint32_t* all_fft_codes; // pointer to memory that contains all the code ffts
//float downsampling_factor;
uint32_t downsampling_factor;
uint32_t total_block_exp;
uint32_t excludelimit;
bool make_2_steps;
uint32_t num_doppler_bins_step2;
float doppler_step2;
bool repeat_satellite;
uint32_t max_num_acqs;
} pcpsconf_fpga_t;
class pcps_acquisition_fpga;
@ -95,6 +100,8 @@ private:
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);
void acquisition_core(uint32_t num_doppler_bins, uint32_t doppler_step, int32_t doppler_max);
pcpsconf_fpga_t acq_parameters;
bool d_active;
float d_threshold;
@ -104,19 +111,27 @@ private:
float d_test_statistics;
int32_t d_state;
uint32_t d_channel;
std::shared_ptr<ChannelFsm> d_channel_fsm;
std::weak_ptr<ChannelFsm> d_channel_fsm;
uint32_t d_doppler_step;
uint32_t d_doppler_max;
uint32_t d_fft_size;
uint32_t d_num_doppler_bins;
uint64_t d_sample_counter;
Gnss_Synchro* d_gnss_synchro;
std::shared_ptr<Fpga_Acquisition> acquisition_fpga;
float d_downsampling_factor;
//float d_downsampling_factor;
uint32_t d_downsampling_factor;
uint32_t d_select_queue_Fpga;
uint32_t d_total_block_exp;
bool d_make_2_steps;
uint32_t d_num_doppler_bins_step2;
float d_doppler_step2;
float d_doppler_center_step_two;
uint32_t d_max_num_acqs;
public:
~pcps_acquisition_fpga();
@ -172,11 +187,10 @@ public:
d_channel = channel;
}
/*!
* \brief Set channel fsm associated to this acquisition instance
*/
inline void set_channel_fsm(std::shared_ptr<ChannelFsm> channel_fsm)
* \brief Set channel fsm associated to this acquisition instance
*/
inline void set_channel_fsm(std::weak_ptr<ChannelFsm> channel_fsm)
{
d_channel_fsm = channel_fsm;
}
@ -197,7 +211,7 @@ public:
*/
inline void set_doppler_max(uint32_t doppler_max)
{
acq_parameters.doppler_max = doppler_max;
d_doppler_max = doppler_max;
acquisition_fpga->set_doppler_max(doppler_max);
}
@ -215,11 +229,6 @@ public:
* \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

@ -138,7 +138,7 @@ private:
int32_t d_well_count;
bool d_dump;
uint32_t d_channel;
std::shared_ptr<ChannelFsm> d_channel_fsm;
std::weak_ptr<ChannelFsm> d_channel_fsm;
std::string d_dump_filename;
public:
@ -199,7 +199,7 @@ public:
/*!
* \brief Set channel fsm associated to this acquisition instance
*/
inline void set_channel_fsm(std::shared_ptr<ChannelFsm> channel_fsm)
inline void set_channel_fsm(std::weak_ptr<ChannelFsm> channel_fsm)
{
d_channel_fsm = channel_fsm;
}

View File

@ -117,7 +117,7 @@ private:
int32_t d_state;
bool d_dump;
uint32_t d_channel;
std::shared_ptr<ChannelFsm> d_channel_fsm;
std::weak_ptr<ChannelFsm> d_channel_fsm;
std::string d_dump_filename;
public:
@ -186,7 +186,7 @@ public:
/*!
* \brief Set channel fsm associated to this acquisition instance
*/
inline void set_channel_fsm(std::shared_ptr<ChannelFsm> channel_fsm)
inline void set_channel_fsm(std::weak_ptr<ChannelFsm> channel_fsm)
{
d_channel_fsm = channel_fsm;
}

View File

@ -162,7 +162,7 @@ private:
cl::CommandQueue* d_cl_queue;
clFFT_Plan d_cl_fft_plan;
cl_int d_cl_fft_batch_size;
std::shared_ptr<ChannelFsm> d_channel_fsm;
std::weak_ptr<ChannelFsm> d_channel_fsm;
int d_opencl;
public:
@ -230,7 +230,7 @@ public:
/*!
* \brief Set channel fsm associated to this acquisition instance
*/
inline void set_channel_fsm(std::shared_ptr<ChannelFsm> channel_fsm)
inline void set_channel_fsm(std::weak_ptr<ChannelFsm> channel_fsm)
{
d_channel_fsm = channel_fsm;
}

View File

@ -151,7 +151,7 @@ private:
int32_t d_state;
bool d_dump;
uint32_t d_channel;
std::shared_ptr<ChannelFsm> d_channel_fsm;
std::weak_ptr<ChannelFsm> d_channel_fsm;
std::string d_dump_filename;
public:
@ -219,7 +219,7 @@ public:
/*!
* \brief Set channel fsm associated to this acquisition instance
*/
inline void set_channel_fsm(std::shared_ptr<ChannelFsm> channel_fsm)
inline void set_channel_fsm(std::weak_ptr<ChannelFsm> channel_fsm)
{
d_channel_fsm = channel_fsm;
}

View File

@ -134,7 +134,7 @@ private:
int32_t d_state;
bool d_dump;
uint32_t d_channel;
std::shared_ptr<ChannelFsm> d_channel_fsm;
std::weak_ptr<ChannelFsm> d_channel_fsm;
std::string d_dump_filename;
public:
@ -202,7 +202,7 @@ public:
/*!
* \brief Set channel fsm associated to this acquisition instance
*/
inline void set_channel_fsm(std::shared_ptr<ChannelFsm> channel_fsm)
inline void set_channel_fsm(std::weak_ptr<ChannelFsm> channel_fsm)
{
d_channel_fsm = channel_fsm;
}

View File

@ -45,23 +45,21 @@
// 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
#define LAUNCH_ACQUISITION 1 // command to launch the multicorrelator
#define TEST_REG_SANITY_CHECK 0x55AA // value to check the presence of the test register (to detect the hw)
#define LOCAL_CODE_CLEAR_MEM 0x10000000 // command to clear the internal memory of the multicorrelator
#define MEM_LOCAL_CODE_WR_ENABLE 0x0C000000 // command to enable the ENA and WR pins of the internal memory of the multicorrelator
#define POW_2_2 4 // 2^2 (used for the conversion of floating point numbers to integers)
#define POW_2_29 536870912 // 2^29 (used for the conversion of floating point numbers to integers)
#define SELECT_LSB 0x00FF // value to select the least significant byte
#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
#define PAGE_SIZE 0x10000 // default page size for the multicorrelator memory map
#define RESET_ACQUISITION 2 // command to reset the multicorrelator
#define LAUNCH_ACQUISITION 1 // command to launch the multicorrelator
#define TEST_REG_SANITY_CHECK 0x55AA // value to check the presence of the test register (to detect the hw)
#define LOCAL_CODE_CLEAR_MEM 0x10000000 // command to clear the internal memory of the multicorrelator
#define MEM_LOCAL_CODE_WR_ENABLE 0x0C000000 // command to enable the ENA and WR pins of the internal memory of the multicorrelator
#define POW_2_2 4 // 2^2 (used for the conversion of floating point numbers to integers)
#define POW_2_31 2147483648 // 2^31 (used for the conversion of floating point numbers to integers)
#define ENABLE_INT_ON_RESET 2 // flag that causes the acquisition to trigger an interrupt when it is reset.
#define SELECT_LSBits 0x0000FFFF // Select the 10 LSbits out of a 20-bit word
#define SELECT_MSBbits 0xFFFF0000 // Select the 10 MSbits out of a 20-bit word
#define SELECT_ALL_CODE_BITS 0xFFFFFFFF // Select a 20 bit word
#define SHL_CODE_BITS 65536 // shift left by 10 bits
#ifndef TEMP_FAILURE_RETRY
#define TEMP_FAILURE_RETRY(exp) \
@ -84,7 +82,8 @@ Fpga_Acquisition::Fpga_Acquisition(std::string device_name,
int64_t fs_in,
uint32_t sampled_ms __attribute__((unused)),
uint32_t select_queue,
lv_16sc_t *all_fft_codes,
//lv_16sc_t *all_fft_codes,
uint32_t *all_fft_codes,
uint32_t excludelimit)
{
uint32_t vector_length = nsamples_total;
@ -102,12 +101,10 @@ Fpga_Acquisition::Fpga_Acquisition(std::string device_name,
d_fd = 0; // driver descriptor
d_map_base = nullptr; // driver memory map
d_all_fft_codes = all_fft_codes;
Fpga_Acquisition::reset_acquisition();
Fpga_Acquisition::open_device();
Fpga_Acquisition::reset_acquisition();
Fpga_Acquisition::fpga_acquisition_test_register();
Fpga_Acquisition::close_device();
d_PRN = 0;
DLOG(INFO) << "Acquisition FPGA class created";
}
@ -116,12 +113,6 @@ Fpga_Acquisition::Fpga_Acquisition(std::string device_name,
Fpga_Acquisition::~Fpga_Acquisition() = default;
bool Fpga_Acquisition::init()
{
return true;
}
bool Fpga_Acquisition::set_local_code(uint32_t PRN)
{
// select the code with the chosen PRN
@ -132,8 +123,12 @@ bool Fpga_Acquisition::set_local_code(uint32_t PRN)
void Fpga_Acquisition::write_local_code()
{
Fpga_Acquisition::fpga_configure_acquisition_local_code(
&d_all_fft_codes[d_nsamples_total * (d_PRN - 1)]);
d_map_base[9] = LOCAL_CODE_CLEAR_MEM;
// write local code
for (uint32_t k = 0; k < d_vector_length; k++)
{
d_map_base[6] = d_all_fft_codes[d_nsamples_total * (d_PRN - 1) + k];
}
}
@ -156,12 +151,6 @@ void Fpga_Acquisition::open_device()
}
bool Fpga_Acquisition::free()
{
return true;
}
void Fpga_Acquisition::fpga_acquisition_test_register()
{
// sanity check : check test register
@ -184,31 +173,11 @@ void Fpga_Acquisition::fpga_acquisition_test_register()
}
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;
d_map_base[9] = LOCAL_CODE_CLEAR_MEM;
// write local code
for (k = 0; k < d_vector_length; k++)
{
tmp = fft_local_code[k].real();
tmp2 = fft_local_code[k].imag();
local_code = (tmp & SELECT_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;
}
}
void Fpga_Acquisition::run_acquisition(void)
{
// enable interrupts
int32_t reenable = 1;
int32_t disable_int = 0;
//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))
{
@ -228,11 +197,11 @@ void Fpga_Acquisition::run_acquisition(void)
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;
}
// 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;
// }
}
@ -241,47 +210,30 @@ 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)
void Fpga_Acquisition::set_doppler_sweep(uint32_t num_sweeps, uint32_t doppler_step, int32_t doppler_min)
{
float phase_step_rad_real;
float phase_step_rad_int_temp;
int32_t phase_step_rad_int;
auto doppler = static_cast<int32_t>(-d_doppler_max);
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)
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)
if (phase_step_rad_real >= 1.0)
{
phase_step_rad_real = MAX_PHASE_STEP_RAD;
}
phase_step_rad_int_temp = phase_step_rad_real * POW_2_2; // * 2^2
phase_step_rad_int = 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
phase_step_rad_real = 2.0 * (doppler_min) / static_cast<float>(d_fs_in);
phase_step_rad_int = static_cast<int32_t>(phase_step_rad_real * (POW_2_31));
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);
if (phase_step_rad_real >= 1.0)
{
phase_step_rad_real = MAX_PHASE_STEP_RAD;
}
phase_step_rad_int_temp = phase_step_rad_real * POW_2_2; // * 2^2
phase_step_rad_int = 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
phase_step_rad_real = 2.0 * (doppler_step) / static_cast<float>(d_fs_in);
phase_step_rad_int = static_cast<int32_t>(phase_step_rad_real * (POW_2_31)); // * 2^29 (in total it makes x2^31 in two steps to avoid the warnings
d_map_base[4] = phase_step_rad_int;
// write number of doppler sweeps
d_map_base[5] = num_sweeps;
}
void Fpga_Acquisition::configure_acquisition()
{
Fpga_Acquisition::open_device();
//Fpga_Acquisition::open_device();
d_map_base[0] = d_select_queue;
d_map_base[1] = d_vector_length;
@ -291,30 +243,6 @@ void Fpga_Acquisition::configure_acquisition()
}
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 * (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)
if (phase_step_rad_real >= 1.0)
{
phase_step_rad_real = MAX_PHASE_STEP_RAD;
}
phase_step_rad_int_temp = phase_step_rad_real * POW_2_2; // * 2^2
phase_step_rad_int = 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
d_map_base[3] = phase_step_rad_int;
}
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)
{
@ -323,35 +251,31 @@ void Fpga_Acquisition::read_acquisition_results(uint32_t *max_index,
uint64_t readval_long = 0;
uint64_t readval_long_shifted = 0;
readval = d_map_base[1];
readval = d_map_base[1]; // read sample counter (LSW)
initial_sample_tmp = readval;
readval_long = d_map_base[2];
readval_long = d_map_base[2]; // read sample counter (MSW)
readval_long_shifted = readval_long << 32; // 2^32
initial_sample_tmp = initial_sample_tmp + readval_long_shifted; // 2^32
*initial_sample = initial_sample_tmp;
readval = d_map_base[3];
readval = d_map_base[3]; // read first peak value
*firstpeak = static_cast<float>(readval);
readval = d_map_base[4];
readval = d_map_base[4]; // read second peak value
*secondpeak = static_cast<float>(readval);
readval = d_map_base[5];
readval = d_map_base[5]; // read max index position
*max_index = readval;
*power_sum = 0;
readval = d_map_base[8];
*total_blk_exp = readval;
*power_sum = 0; // power sum is not used
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();
readval = d_map_base[8]; // read FFT block exponent
*total_blk_exp = readval;
}
@ -380,9 +304,9 @@ void Fpga_Acquisition::close_device()
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();
d_map_base[8] = RESET_ACQUISITION; // writing a 2 to d_map_base[8] resets the acquisition. This causes a reset of all
// the FPGA HW modules including the multicorrelators
d_map_base[14] = ENABLE_INT_ON_RESET; // enable int on reset
}
@ -392,8 +316,7 @@ void Fpga_Acquisition::read_fpga_total_scale_factor(uint32_t *total_scale_factor
uint32_t readval = 0;
readval = d_map_base[8];
*total_scale_factor = readval;
//readval = d_map_base[8];
// only the total scale factor is used for the tests (fw scale factor to be removed)
*fw_scale_factor = 0;
}

View File

@ -53,16 +53,14 @@ public:
int64_t fs_in,
uint32_t sampled_ms,
uint32_t select_queue,
lv_16sc_t *all_fft_codes,
uint32_t *all_fft_codes,
uint32_t excludelimit);
~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(uint32_t num_sweeps, uint32_t doppler_step, int32_t doppler_min);
void run_acquisition(void);
void set_phase_step(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();
@ -110,7 +108,7 @@ private:
// data related to the hardware module and the driver
int32_t d_fd; // driver descriptor
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_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_excludelimit;
uint32_t d_nsamples_total; // number of samples including padding
@ -122,7 +120,6 @@ private:
uint32_t d_PRN; // PRN
// FPGA private functions
void fpga_acquisition_test_register(void);
void fpga_configure_acquisition_local_code(lv_16sc_t fft_local_code[]);
void read_result_valid(uint32_t *result_valid);
};

View File

@ -218,7 +218,6 @@ void Channel::set_signal(const Gnss_Signal& gnss_signal)
acq_->set_local_code();
if (flag_enable_fpga)
{
//set again the gnss_synchro pointer to trigger the preloading of the current PRN code to the FPGA fabric
trk_->set_gnss_synchro(&gnss_synchro_);
}
nav_->set_satellite(gnss_signal_.get_satellite());

View File

@ -20,53 +20,6 @@ if(DEFINED __INCLUDED_VOLK_PYTHON_CMAKE)
endif()
set(__INCLUDED_VOLK_PYTHON_CMAKE TRUE)
########################################################################
# Setup the python interpreter:
# This allows the user to specify a specific interpreter,
# or finds the interpreter via the built-in cmake module.
########################################################################
set(VOLK_PYTHON_MIN_VERSION "2.7")
set(VOLK_PYTHON3_MIN_VERSION "3.4")
if(CMAKE_VERSION VERSION_LESS 3.12)
if(PYTHON_EXECUTABLE)
message(STATUS "User set python executable ${PYTHON_EXECUTABLE}")
find_package(PythonInterp ${VOLK_PYTHON_MIN_VERSION} REQUIRED)
else()
message(STATUS "PYTHON_EXECUTABLE not set - using default python2")
message(STATUS "Use -DPYTHON_EXECUTABLE=/path/to/python3 to build for python3.")
find_package(PythonInterp ${VOLK_PYTHON_MIN_VERSION})
if(NOT PYTHONINTERP_FOUND)
message(STATUS "python2 not found - using python3")
find_package(PythonInterp ${VOLK_PYTHON3_MIN_VERSION} REQUIRED)
endif()
endif()
else()
if(PYTHON_EXECUTABLE)
message(STATUS "User set python executable ${PYTHON_EXECUTABLE}")
find_package(PythonInterp ${VOLK_PYTHON_MIN_VERSION} REQUIRED)
else()
find_package(Python3 COMPONENTS Interpreter)
if(Python3_FOUND)
set(PYTHON_EXECUTABLE ${Python3_EXECUTABLE})
set(PYTHON_VERSION_MAJOR ${Python3_VERSION_MAJOR})
endif()
if(NOT Python3_FOUND OR NOT MAKO_FOUND OR NOT SIX_FOUND)
find_package(Python2 COMPONENTS Interpreter)
if(Python2_FOUND)
set(PYTHON_EXECUTABLE ${Python2_EXECUTABLE})
set(PYTHON_VERSION_MAJOR ${Python2_VERSION_MAJOR})
endif()
endif()
endif()
endif()
if(${PYTHON_VERSION_MAJOR} VERSION_EQUAL 3)
set(PYTHON3 TRUE)
endif()
########################################################################
# Check for the existence of a python module:
# - desc a string description of the check
@ -102,6 +55,61 @@ except: pass
"${have}")
endmacro()
########################################################################
# Setup the python interpreter:
# This allows the user to specify a specific interpreter,
# or finds the interpreter via the built-in cmake module.
########################################################################
set(VOLK_PYTHON_MIN_VERSION "2.7")
set(VOLK_PYTHON3_MIN_VERSION "3.4")
if(CMAKE_VERSION VERSION_LESS 3.12)
if(PYTHON_EXECUTABLE)
message(STATUS "User set python executable ${PYTHON_EXECUTABLE}")
find_package(PythonInterp ${VOLK_PYTHON_MIN_VERSION} REQUIRED)
else()
message(STATUS "PYTHON_EXECUTABLE not set - using default python2")
message(STATUS "Use -DPYTHON_EXECUTABLE=/path/to/python3 to build for python3.")
find_package(PythonInterp ${VOLK_PYTHON_MIN_VERSION})
if(NOT PYTHONINTERP_FOUND)
message(STATUS "python2 not found - using python3")
find_package(PythonInterp ${VOLK_PYTHON3_MIN_VERSION} REQUIRED)
endif()
endif()
else()
if(PYTHON_EXECUTABLE)
message(STATUS "User set python executable ${PYTHON_EXECUTABLE}")
find_package(PythonInterp ${VOLK_PYTHON_MIN_VERSION} REQUIRED)
else()
find_package(Python3 COMPONENTS Interpreter)
if(Python3_FOUND)
set(PYTHON_EXECUTABLE ${Python3_EXECUTABLE})
set(PYTHON_VERSION_MAJOR ${Python3_VERSION_MAJOR})
volk_python_check_module("mako >= 0.4.2" mako "mako.__version__ >= '0.4.2'" MAKO_FOUND)
volk_python_check_module("six - python 2 and 3 compatibility library" six "True" SIX_FOUND)
endif()
if(NOT Python3_FOUND OR NOT MAKO_FOUND OR NOT SIX_FOUND)
find_package(Python2 COMPONENTS Interpreter)
if(Python2_FOUND)
set(PYTHON_EXECUTABLE ${Python2_EXECUTABLE})
set(PYTHON_VERSION_MAJOR ${Python2_VERSION_MAJOR})
volk_python_check_module("mako >= 0.4.2" mako "mako.__version__ >= '0.4.2'" MAKO_FOUND)
volk_python_check_module("six - python 2 and 3 compatibility library" six "True" SIX_FOUND)
endif()
if(NOT MAKO_FOUND OR NOT SIX_FOUND)
unset(PYTHON_EXECUTABLE)
find_package(PythonInterp ${VOLK_PYTHON_MIN_VERSION})
endif()
endif()
endif()
endif()
if(${PYTHON_VERSION_MAJOR} VERSION_EQUAL 3)
set(PYTHON3 TRUE)
endif()
########################################################################
# Sets the python installation directory VOLK_PYTHON_DIR
########################################################################

View File

@ -114,7 +114,7 @@ hybrid_observables_gs::hybrid_observables_gs(uint32_t nchannels_in,
}
}
T_rx_TOW_ms = 0U;
T_rx_TOW_offset_ms = 0U;
T_rx_step_ms = 20; //read from config at the adapter GNSS-SDR.observable_interval_ms!!
T_rx_TOW_set = false;
// rework
@ -443,38 +443,39 @@ void hybrid_observables_gs::update_TOW(const std::vector<Gnss_Synchro> &data)
//2. If the TOW is set, it must be incremented by the desired receiver time step.
// the time step must match the observables timer block (connected to the las input channel)
std::vector<Gnss_Synchro>::const_iterator it;
// if (!T_rx_TOW_set)
// {
//uint32_t TOW_ref = std::numeric_limits<uint32_t>::max();
uint32_t TOW_ref = 0U;
for (it = data.cbegin(); it != data.cend(); it++)
if (!T_rx_TOW_set)
{
if (it->Flag_valid_word)
//uint32_t TOW_ref = std::numeric_limits<uint32_t>::max();
uint32_t TOW_ref = 0U;
for (it = data.cbegin(); it != data.cend(); it++)
{
if (it->TOW_at_current_symbol_ms > TOW_ref)
if (it->Flag_valid_word)
{
TOW_ref = it->TOW_at_current_symbol_ms;
T_rx_TOW_set = true;
if (it->TOW_at_current_symbol_ms > TOW_ref)
{
TOW_ref = it->TOW_at_current_symbol_ms;
T_rx_TOW_set = true;
}
}
}
T_rx_TOW_ms = TOW_ref - (TOW_ref % 20);
}
else
{
T_rx_TOW_ms += T_rx_step_ms; //the tow time step increment must match the ref time channel step
//todo: check what happens during the week rollover
if (T_rx_TOW_ms >= 604800000)
{
T_rx_TOW_ms = T_rx_TOW_ms % 604800000;
}
}
T_rx_TOW_ms = TOW_ref;
//}
// else
// {
// T_rx_TOW_ms += T_rx_step_ms;
// //todo: check what happens during the week rollover
// if (T_rx_TOW_ms >= 604800000)
// {
// T_rx_TOW_ms = T_rx_TOW_ms % 604800000;
// }
// }
// std::cout << "T_rx_TOW_ms: " << T_rx_TOW_ms << std::endl;
}
void hybrid_observables_gs::compute_pranges(std::vector<Gnss_Synchro> &data)
{
// std::cout.precision(17);
// std::cout << " T_rx_TOW_ms: " << static_cast<double>(T_rx_TOW_ms) << std::endl;
std::vector<Gnss_Synchro>::iterator it;
for (it = data.begin(); it != data.end(); it++)
{
@ -486,13 +487,21 @@ void hybrid_observables_gs::compute_pranges(std::vector<Gnss_Synchro> &data)
it->Pseudorange_m = traveltime_s * SPEED_OF_LIGHT;
it->Flag_valid_pseudorange = true;
// debug code
// std::cout.precision(17);
// std::cout << "[" << it->Channel_ID << "] interp_TOW_ms: " << it->interp_TOW_ms << std::endl;
// std::cout << "[" << it->Channel_ID << "] Diff T_rx_TOW_ms - interp_TOW_ms: " << static_cast<double>(T_rx_TOW_ms) - it->interp_TOW_ms << std::endl;
// std::cout << "[" << it->Channel_ID << "] Pseudorange_m: " << it->Pseudorange_m << std::endl;
//
// std::cout << "[" << it->Channel_ID << "] interp_TOW_ms: " << it->interp_TOW_ms << std::endl;
// std::cout << "[" << it->Channel_ID << "] Diff T_rx_TOW_ms - interp_TOW_ms: " << static_cast<double>(T_rx_TOW_ms) - it->interp_TOW_ms << std::endl;
}
}
// usleep(1000);
// for (it = data.begin(); it != data.end(); it++)
// {
// if (it->Flag_valid_word)
// {
// std::cout << "[" << it->Channel_ID << "] Pseudorange_m: " << it->Pseudorange_m << std::endl;
// }
// }
// std::cout << std::endl;
// usleep(1000);
}
@ -548,7 +557,7 @@ int hybrid_observables_gs::general_work(int noutput_items __attribute__((unused)
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))
if (!interp_trk_obs(interpolated_gnss_synchro, n, d_Rx_clock_buffer.front()))
{
// Produce an empty observation
interpolated_gnss_synchro = Gnss_Synchro();
@ -564,49 +573,10 @@ int hybrid_observables_gs::general_work(int noutput_items __attribute__((unused)
}
epoch_data.push_back(interpolated_gnss_synchro);
}
if (n_valid > 0)
{
update_TOW(epoch_data);
int tow_inc_loop_count = 0;
while (T_rx_TOW_ms % 20 != 0 and tow_inc_loop_count < 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;
}
}
if (n_valid > 0)
{
update_TOW(epoch_data);
compute_pranges(epoch_data);
}

View File

@ -83,7 +83,7 @@ private:
//rx time follow GPST
bool T_rx_TOW_set;
uint32_t T_rx_TOW_ms;
uint32_t T_rx_TOW_offset_ms;
uint32_t T_rx_step_ms;
bool d_dump;
bool d_dump_mat;
uint32_t d_nchannels_in;

View File

@ -53,10 +53,10 @@ Ad9361FpgaSignalSource::Ad9361FpgaSignalSource(ConfigurationInterface* configura
std::string default_item_type = "gr_complex";
std::string default_dump_file = "./data/signal_source.dat";
freq_ = configuration->property(role + ".freq", GPS_L1_FREQ_HZ);
sample_rate_ = configuration->property(role + ".sampling_frequency", 2600000);
bandwidth_ = configuration->property(role + ".bandwidth", 2000000);
sample_rate_ = configuration->property(role + ".sampling_frequency", 12500000);
bandwidth_ = configuration->property(role + ".bandwidth", 12500000);
rx1_en_ = configuration->property(role + ".rx1_enable", true);
rx2_en_ = configuration->property(role + ".rx2_enable", false);
rx2_en_ = configuration->property(role + ".rx2_enable", true);
buffer_size_ = configuration->property(role + ".buffer_size", 0xA0000);
quadrature_ = configuration->property(role + ".quadrature", true);
rf_dc_ = configuration->property(role + ".rf_dc", true);

View File

@ -40,21 +40,20 @@ LabsatSignalSource::LabsatSignalSource(ConfigurationInterface* configuration,
const std::string& role, unsigned int in_stream, unsigned int out_stream, gr::msg_queue::sptr queue) : role_(role), in_stream_(in_stream), out_stream_(out_stream), queue_(std::move(queue))
{
std::string default_item_type = "gr_complex";
std::string default_dump_file = "./data/source.bin";
std::string default_dump_file = "./labsat_output.dat";
item_type_ = configuration->property(role + ".item_type", default_item_type);
dump_ = configuration->property(role + ".dump", false);
dump_filename_ = configuration->property(role + ".dump_filename", default_dump_file);
int channel_selector = configuration->property(role + ".selected_channel", 1);
std::string default_filename = "./example_capture.LS3";
samples_ = configuration->property(role + ".samples", 0);
std::string default_filename = "./example_capture.LS3";
filename_ = configuration->property(role + ".filename", default_filename);
if (item_type_ == "gr_complex")
{
item_size_ = sizeof(gr_complex);
labsat23_source_ = labsat23_make_source(filename_.c_str(), channel_selector);
labsat23_source_ = labsat23_make_source_sptr(filename_.c_str(), channel_selector, queue_);
DLOG(INFO) << "Item size " << item_size_;
DLOG(INFO) << "labsat23_source_(" << labsat23_source_->unique_id() << ")";
}

View File

@ -81,7 +81,6 @@ private:
unsigned int out_stream_;
std::string item_type_;
size_t item_size_;
uint64_t samples_;
std::string filename_;
bool dump_;
std::string dump_filename_;

View File

@ -64,6 +64,7 @@ target_link_libraries(signal_source_gr_blocks
Gnuradio::runtime
signal_source_libs
PRIVATE
core_receiver
Gflags::gflags
Glog::glog
)

View File

@ -30,30 +30,25 @@
#include "labsat23_source.h"
#include "control_message_factory.h"
#include <gnuradio/io_signature.h>
#include <exception>
#include <iostream>
#include <sstream>
labsat23_source_sptr labsat23_make_source(const char *signal_file_basename, int channel_selector)
labsat23_source_sptr labsat23_make_source_sptr(const char *signal_file_basename, int channel_selector, gr::msg_queue::sptr queue)
{
return labsat23_source_sptr(new labsat23_source(signal_file_basename, channel_selector));
}
std::string labsat23_source::generate_filename()
{
std::ostringstream ss;
ss << std::setw(4) << std::setfill('0') << d_current_file_number;
return d_signal_file_basename + "_" + ss.str() + ".LS3";
return labsat23_source_sptr(new labsat23_source(signal_file_basename, channel_selector, queue));
}
labsat23_source::labsat23_source(const char *signal_file_basename,
int channel_selector) : gr::block("labsat23_source",
gr::io_signature::make(0, 0, 0),
gr::io_signature::make(1, 1, sizeof(gr_complex)))
int channel_selector,
gr::msg_queue::sptr queue) : gr::block("labsat23_source",
gr::io_signature::make(0, 0, 0),
gr::io_signature::make(1, 1, sizeof(gr_complex))),
d_queue(queue)
{
if (channel_selector < 1 or channel_selector > 2)
{
@ -108,6 +103,25 @@ labsat23_source::~labsat23_source()
}
std::string labsat23_source::generate_filename()
{
if (d_signal_file_basename.substr(d_signal_file_basename.length() - 4, 4) == ".ls2" or d_signal_file_basename.substr(d_signal_file_basename.length() - 4, 4) == ".LS2")
{
if (d_current_file_number == 0)
{
return d_signal_file_basename;
}
else
{
return std::string("donotexist"); // just to stop processing
}
}
std::ostringstream ss;
ss << std::setw(4) << std::setfill('0') << d_current_file_number;
return d_signal_file_basename + "_" + ss.str() + ".LS3";
}
int labsat23_source::getBit(uint8_t byte, int position)
{
return (byte >> position) & 0x01;
@ -120,7 +134,7 @@ void labsat23_source::decode_samples_one_channel(int16_t input_short, gr_complex
switch (type)
{
case 2:
//two bits per sample, 8 samples per int16
// two bits per sample, 8 samples per int16
for (int i = 0; i < 8; i++)
{
out[i] = gr_complex(static_cast<float>(bs[15 - (2 * i)]),
@ -129,45 +143,45 @@ void labsat23_source::decode_samples_one_channel(int16_t input_short, gr_complex
}
break;
case 4:
//four bits per sample, 4 samples per int16
// bits per sample, 4 samples per int16
for (int i = 0; i < 4; i++)
{
out[i] = gr_complex(0.0, 0.0);
//In-Phase
// In-Phase
if (bs[15 - 4 * i])
{
if (bs[13 - 4 * i]) //11
if (bs[13 - 4 * i]) // 11
{
out[i] += gr_complex(-1, 0);
}
else //10
else // 10
{
out[i] += gr_complex(-2, 0);
}
}
else
{
if (bs[13 - 4 * i]) //01
if (bs[13 - 4 * i]) // 01
{
out[i] += gr_complex(1, 0);
}
}
//Quadrature
// Quadrature
if (bs[14 - 4 * i])
{
if (bs[12 - 4 * i]) //11
if (bs[12 - 4 * i]) // 11
{
out[i] += gr_complex(0, -1);
}
else //10
else // 10
{
out[i] += gr_complex(0, -2);
}
}
else
{
if (bs[12 - 4 * i]) //01
if (bs[12 - 4 * i]) // 01
{
out[i] += gr_complex(0, 1);
}
@ -192,8 +206,8 @@ int labsat23_source::general_work(int noutput_items,
{
char memblock[1024];
binary_input_file->read(memblock, 1024);
//parse Labsat header
//check preamble
// parse Labsat header
// check preamble
int byte_counter = 0;
bool preamble_ok = true;
for (int i = 0; i < 8; i++)
@ -388,7 +402,6 @@ int labsat23_source::general_work(int noutput_items,
return -1;
}
// ready to start reading samples
switch (d_bits_per_sample)
{
@ -419,8 +432,10 @@ int labsat23_source::general_work(int noutput_items,
}
// trigger the read of the next file in the sequence
std::cout << "End of current file, reading the next Labsat file in sequence: " << generate_filename() << std::endl;
if (d_labsat_version == 3)
{
std::cout << "End of current file, reading the next Labsat file in sequence: " << generate_filename() << std::endl;
}
d_current_file_number++;
binary_input_file->close();
binary_input_file->open(generate_filename().c_str(), std::ios::in | std::ios::binary);
@ -430,7 +445,17 @@ int labsat23_source::general_work(int noutput_items,
}
else
{
std::cout << "Last file reached, LabSat source stop" << std::endl;
if (d_labsat_version == 3)
{
std::cout << "Last file reached, LabSat source stop" << std::endl;
}
else
{
std::cout << "End of file reached, LabSat source stop" << std::endl;
}
auto *cmf = new ControlMessageFactory();
d_queue->handle(cmf->GetQueueMessage(200, 0));
delete cmf;
return -1;
}
}
@ -468,8 +493,10 @@ int labsat23_source::general_work(int noutput_items,
}
// trigger the read of the next file in the sequence
std::cout << "End of current file, reading the next Labsat file in sequence: " << generate_filename() << std::endl;
if (d_labsat_version == 3)
{
std::cout << "End of current file, reading the next Labsat file in sequence: " << generate_filename() << std::endl;
}
d_current_file_number++;
binary_input_file->close();
binary_input_file->open(generate_filename().c_str(), std::ios::in | std::ios::binary);
@ -479,7 +506,17 @@ int labsat23_source::general_work(int noutput_items,
}
else
{
std::cout << "Last file reached, LabSat source stop" << std::endl;
if (d_labsat_version == 3)
{
std::cout << "Last file reached, LabSat source stop" << std::endl;
}
else
{
std::cout << "End of file reached, LabSat source stop" << std::endl;
}
auto *cmf = new ControlMessageFactory();
d_queue->handle(cmf->GetQueueMessage(200, 0));
delete cmf;
return -1;
}
}

View File

@ -32,6 +32,7 @@
#define GNSS_SDR_LABSAT23_SOURCE_H
#include <gnuradio/block.h>
#include <gnuradio/msg_queue.h> // for msg_queue, msg_queue::sptr
#include <cstdint>
#include <fstream>
#include <string>
@ -41,7 +42,7 @@ class labsat23_source;
using labsat23_source_sptr = boost::shared_ptr<labsat23_source>;
labsat23_source_sptr labsat23_make_source(const char *signal_file_basename, int channel_selector);
labsat23_source_sptr labsat23_make_source_sptr(const char *signal_file_basename, int channel_selector, gr::msg_queue::sptr queue);
/*!
* \brief This class implements conversion between Labsat2 and 3 format byte packet samples to gr_complex
@ -49,7 +50,8 @@ labsat23_source_sptr labsat23_make_source(const char *signal_file_basename, int
class labsat23_source : public gr::block
{
private:
friend labsat23_source_sptr labsat23_make_source_sptr(const char *signal_file_basename, int channel_selector);
friend labsat23_source_sptr labsat23_make_source_sptr(const char *signal_file_basename, int channel_selector, gr::msg_queue::sptr queue);
labsat23_source(const char *signal_file_basename, int channel_selector, gr::msg_queue::sptr queue);
std::string generate_filename();
void decode_samples_one_channel(int16_t input_short, gr_complex *out, int type);
int getBit(uint8_t byte, int position);
@ -62,9 +64,9 @@ private:
std::ifstream *binary_input_file;
uint8_t d_ref_clock;
uint8_t d_bits_per_sample;
gr::msg_queue::sptr d_queue;
public:
labsat23_source(const char *signal_file_basename, int channel_selector);
~labsat23_source();
int general_work(int noutput_items,
gr_vector_int &ninput_items,

View File

@ -215,7 +215,7 @@ galileo_telemetry_decoder_gs::galileo_telemetry_decoder_gs(
d_flag_preamble = false;
d_channel = 0;
flag_TOW_set = false;
flag_PLL_180_deg_phase_locked = false;
d_symbol_history.set_capacity(d_required_symbols + 1);
// vars for Viterbi decoder
@ -488,9 +488,6 @@ void galileo_telemetry_decoder_gs::set_channel(int32_t channel)
int galileo_telemetry_decoder_gs::general_work(int noutput_items __attribute__((unused)), gr_vector_int &ninput_items __attribute__((unused)),
gr_vector_const_void_star &input_items, gr_vector_void_star &output_items)
{
int32_t corr_value = 0;
int32_t preamble_diff = 0;
auto **out = reinterpret_cast<Gnss_Synchro **>(&output_items[0]); // Get the output buffer pointer
const auto **in = reinterpret_cast<const Gnss_Synchro **>(&input_items[0]); // Get the input buffer pointer
@ -513,27 +510,29 @@ int galileo_telemetry_decoder_gs::general_work(int noutput_items __attribute__((
d_sent_tlm_failed_msg = true;
}
}
if (d_symbol_history.size() > d_required_symbols)
{
// ******* preamble correlation ********
for (int32_t i = 0; i < d_samples_per_preamble; i++)
{
if (d_symbol_history[i] < 0.0) // symbols clipping
{
corr_value -= d_preamble_samples[i];
}
else
{
corr_value += d_preamble_samples[i];
}
}
}
// ******* frame sync ******************
switch (d_stat)
{
case 0: // no preamble information
{
//correlate with preamble
int32_t corr_value = 0;
if (d_symbol_history.size() > d_required_symbols)
{
// ******* preamble correlation ********
for (int32_t i = 0; i < d_samples_per_preamble; i++)
{
if (d_symbol_history[i] < 0.0) // symbols clipping
{
corr_value -= d_preamble_samples[i];
}
else
{
corr_value += d_preamble_samples[i];
}
}
}
if (abs(corr_value) >= d_samples_per_preamble)
{
d_preamble_index = d_sample_counter; // record the preamble sample stamp
@ -544,6 +543,24 @@ int galileo_telemetry_decoder_gs::general_work(int noutput_items __attribute__((
}
case 1: // possible preamble lock
{
//correlate with preamble
int32_t corr_value = 0;
int32_t preamble_diff = 0;
if (d_symbol_history.size() > d_required_symbols)
{
// ******* preamble correlation ********
for (int32_t i = 0; i < d_samples_per_preamble; i++)
{
if (d_symbol_history[i] < 0.0) // symbols clipping
{
corr_value -= d_preamble_samples[i];
}
else
{
corr_value += d_preamble_samples[i];
}
}
}
if (abs(corr_value) >= d_samples_per_preamble)
{
// check preamble separation
@ -554,6 +571,7 @@ int galileo_telemetry_decoder_gs::general_work(int noutput_items __attribute__((
DLOG(INFO) << "Starting page decoder for Galileo satellite " << this->d_satellite;
d_preamble_index = d_sample_counter; // record the preamble sample stamp
d_CRC_error_counter = 0;
if (corr_value < 0) flag_PLL_180_deg_phase_locked = true;
d_stat = 2;
}
else
@ -576,7 +594,7 @@ int galileo_telemetry_decoder_gs::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 (flag_PLL_180_deg_phase_locked == false) // normal PLL lock
{
for (uint32_t i = 0; i < d_frame_length_symbols; i++)
{
@ -595,7 +613,7 @@ int galileo_telemetry_decoder_gs::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 (flag_PLL_180_deg_phase_locked == false) // normal PLL lock
{
int k = 0;
for (uint32_t i = 0; i < d_frame_length_symbols; i++)

View File

@ -102,6 +102,7 @@ private:
bool d_sent_tlm_failed_msg;
uint32_t d_stat;
bool d_flag_frame_sync;
bool flag_PLL_180_deg_phase_locked;
bool d_flag_parity;
bool d_flag_preamble;

View File

@ -68,55 +68,66 @@ gps_l1_ca_telemetry_decoder_gs::gps_l1_ca_telemetry_decoder_gs(
this->message_port_register_out(pmt::mp("telemetry_to_trk"));
d_last_valid_preamble = 0;
d_sent_tlm_failed_msg = false;
d_max_symbols_without_valid_frame = GPS_SUBFRAME_BITS * GPS_CA_TELEMETRY_SYMBOLS_PER_BIT * 5; //rise alarm if 5 consecutive subframes have no valid CRC
// initialize internal vars
d_dump = dump;
d_satellite = Gnss_Satellite(satellite.get_system(), satellite.get_PRN());
DLOG(INFO) << "Initializing GPS L1 TELEMETRY DECODER";
d_bits_per_preamble = GPS_CA_PREAMBLE_LENGTH_BITS;
d_samples_per_preamble = d_bits_per_preamble * GPS_CA_TELEMETRY_SYMBOLS_PER_BIT;
d_preamble_period_symbols = GPS_SUBFRAME_BITS * GPS_CA_TELEMETRY_SYMBOLS_PER_BIT;
// set the preamble
uint16_t preambles_bits[GPS_CA_PREAMBLE_LENGTH_BITS] = GPS_PREAMBLE;
d_required_symbols = GPS_SUBFRAME_BITS * GPS_CA_TELEMETRY_SYMBOLS_PER_BIT;
// preamble bits to sampled symbols
d_preambles_symbols = static_cast<int32_t *>(volk_gnsssdr_malloc(GPS_CA_PREAMBLE_LENGTH_SYMBOLS * sizeof(int32_t), volk_gnsssdr_get_alignment()));
d_preamble_samples = static_cast<int32_t *>(volk_gnsssdr_malloc(d_samples_per_preamble * sizeof(int32_t), volk_gnsssdr_get_alignment()));
d_frame_length_symbols = GPS_SUBFRAME_BITS * GPS_CA_TELEMETRY_SYMBOLS_PER_BIT;
d_max_symbols_without_valid_frame = d_required_symbols * 10; //rise alarm 1 minute without valid tlm
d_page_part_symbols = static_cast<double *>(volk_gnsssdr_malloc(d_frame_length_symbols * sizeof(double), volk_gnsssdr_get_alignment()));
int32_t n = 0;
for (uint16_t preambles_bit : preambles_bits)
for (int32_t i = 0; i < d_bits_per_preamble; i++)
{
for (uint32_t j = 0; j < GPS_CA_TELEMETRY_SYMBOLS_PER_BIT; j++)
if (GPS_CA_PREAMBLE.at(i) == '1')
{
if (preambles_bit == 1)
for (uint32_t j = 0; j < GPS_CA_TELEMETRY_SYMBOLS_PER_BIT; j++)
{
d_preambles_symbols[n] = 1;
d_preamble_samples[n] = 1;
n++;
}
else
}
else
{
for (uint32_t j = 0; j < GPS_CA_TELEMETRY_SYMBOLS_PER_BIT; j++)
{
d_preambles_symbols[n] = -1;
d_preamble_samples[n] = -1;
n++;
}
n++;
}
}
d_stat = 0U;
d_sample_counter = 0ULL;
d_stat = 0;
d_preamble_index = 0ULL;
d_flag_frame_sync = false;
d_prev_GPS_frame_4bytes = 0;
d_TOW_at_Preamble_ms = 0;
flag_TOW_set = false;
d_flag_preamble = false;
d_flag_new_tow_available = false;
d_channel = 0;
flag_PLL_180_deg_phase_locked = false;
d_preamble_time_samples = 0ULL;
d_flag_parity = false;
d_TOW_at_current_symbol_ms = 0;
d_symbol_history.set_capacity(GPS_CA_PREAMBLE_LENGTH_SYMBOLS);
d_crc_error_synchronization_counter = 0;
d_current_subframe_symbol = 0;
d_sample_counter = 0;
d_TOW_at_Preamble_ms = 0;
d_CRC_error_counter = 0;
d_flag_preamble = false;
d_channel = 0;
flag_TOW_set = false;
flag_PLL_180_deg_phase_locked = false;
d_prev_GPS_frame_4bytes = 0;
d_symbol_history.set_capacity(d_required_symbols);
}
gps_l1_ca_telemetry_decoder_gs::~gps_l1_ca_telemetry_decoder_gs()
{
volk_gnsssdr_free(d_preambles_symbols);
d_symbol_history.clear();
volk_gnsssdr_free(d_preamble_samples);
volk_gnsssdr_free(d_page_part_symbols);
if (d_dump_file.is_open() == true)
{
try
@ -209,11 +220,11 @@ bool gps_l1_ca_telemetry_decoder_gs::decode_subframe()
bool subframe_synchro_confirmation = false;
bool CRC_ok = true;
for (float d_subframe_symbol : d_subframe_symbols)
for (float subframe_symbol : d_symbol_history)
{
// ******* SYMBOL TO BIT *******
// extended correlation to bit period is enabled in tracking!
symbol_accumulator += d_subframe_symbol; // accumulate the input value in d_symbol_accumulator
symbol_accumulator += subframe_symbol; // accumulate the input value in d_symbol_accumulator
symbol_accumulator_counter++;
if (symbol_accumulator_counter == 20)
{
@ -221,6 +232,11 @@ bool gps_l1_ca_telemetry_decoder_gs::decode_subframe()
if (symbol_accumulator > 0)
{
GPS_frame_4bytes += 1; // insert the telemetry bit in LSB
//std::cout << "1";
}
else
{
//std::cout << "0";
}
symbol_accumulator = 0;
symbol_accumulator_counter = 0;
@ -276,7 +292,7 @@ bool gps_l1_ca_telemetry_decoder_gs::decode_subframe()
// NEW GPS SUBFRAME HAS ARRIVED!
if (CRC_ok)
{
int32_t subframe_ID = d_nav.subframe_decoder(subframe); //d ecode the subframe
int32_t subframe_ID = d_nav.subframe_decoder(subframe); //decode the subframe
if (subframe_ID > 0 and subframe_ID < 6)
{
std::cout << "New GPS NAV message received in channel " << this->d_channel << ": "
@ -313,7 +329,6 @@ bool gps_l1_ca_telemetry_decoder_gs::decode_subframe()
default:
break;
}
d_flag_new_tow_available = true;
}
else
{
@ -336,30 +351,18 @@ void gps_l1_ca_telemetry_decoder_gs::reset()
int gps_l1_ca_telemetry_decoder_gs::general_work(int noutput_items __attribute__((unused)), gr_vector_int &ninput_items __attribute__((unused)),
gr_vector_const_void_star &input_items, gr_vector_void_star &output_items)
{
int32_t preamble_diff_ms = 0;
auto **out = reinterpret_cast<Gnss_Synchro **>(&output_items[0]); // Get the output buffer pointer
const auto **in = reinterpret_cast<const Gnss_Synchro **>(&input_items[0]); // Get the input buffer pointer
Gnss_Synchro current_symbol{}; // structure to save the synchronization information and send the output object to the next block
// 1. Copy the current tracking output
current_symbol = in[0][0];
// record the oldest subframe symbol before inserting a new symbol into the circular buffer
if (d_current_subframe_symbol < GPS_SUBFRAME_MS and !d_symbol_history.empty())
{
d_subframe_symbols[d_current_subframe_symbol] = d_symbol_history[0].Prompt_I;
d_current_subframe_symbol++;
}
d_symbol_history.push_back(current_symbol); // add new symbol to the symbol queue
consume_each(1);
d_flag_preamble = false;
// check if there is a problem with the telemetry of the current satellite
Gnss_Synchro current_symbol = in[0][0];
// add new symbol to the symbol queue
d_symbol_history.push_back(current_symbol.Prompt_I);
d_sample_counter++; // count for the processed symbols
if (d_sent_tlm_failed_msg == false)
consume_each(1);
d_flag_preamble = false;
// check if there is a problem with the telemetry of the current satellite
if (d_stat < 2 and d_sent_tlm_failed_msg == false)
{
if ((d_sample_counter - d_last_valid_preamble) > d_max_symbols_without_valid_frame)
{
@ -369,108 +372,123 @@ int gps_l1_ca_telemetry_decoder_gs::general_work(int noutput_items __attribute__
}
}
// ******* preamble correlation ********
int32_t corr_value = 0;
if ((d_symbol_history.size() == GPS_CA_PREAMBLE_LENGTH_SYMBOLS))
{
int i = 0;
for (const auto &iter : d_symbol_history)
{
if (iter.Flag_valid_symbol_output == true)
{
if (iter.Prompt_I < 0.0) // symbols clipping
{
corr_value -= d_preambles_symbols[i];
}
else
{
corr_value += d_preambles_symbols[i];
}
}
i++;
}
}
// ******* frame sync ******************
if (std::abs(corr_value) == GPS_CA_PREAMBLE_LENGTH_SYMBOLS)
switch (d_stat)
{
//TODO: Rewrite with state machine
if (d_stat == 0)
{
// record the preamble sample stamp
d_preamble_time_samples = d_symbol_history[0].Tracking_sample_counter; // record the preamble sample stamp
DLOG(INFO) << "Preamble detection for SAT " << this->d_satellite << "d_symbol_history[0].Tracking_sample_counter=" << d_symbol_history[0].Tracking_sample_counter;
d_stat = 1; // enter into frame pre-detection status
}
else if (d_stat == 1) // check 6 seconds of preamble separation
{
preamble_diff_ms = std::round(((static_cast<double>(d_symbol_history[0].Tracking_sample_counter) - static_cast<double>(d_preamble_time_samples)) / static_cast<double>(d_symbol_history[0].fs)) * 1000.0);
if (std::abs(preamble_diff_ms - GPS_SUBFRAME_MS) % GPS_SUBFRAME_MS == 0)
{
DLOG(INFO) << "Preamble confirmation for SAT " << this->d_satellite;
d_flag_preamble = true;
d_preamble_time_samples = d_symbol_history[0].Tracking_sample_counter; // record the PRN start sample index associated to the preamble
if (!d_flag_frame_sync)
{
d_flag_frame_sync = true;
if (corr_value < 0)
{
flag_PLL_180_deg_phase_locked = true; // PLL is locked to opposite phase!
DLOG(INFO) << " PLL in opposite phase for Sat " << this->d_satellite.get_PRN();
}
else
{
flag_PLL_180_deg_phase_locked = false;
}
DLOG(INFO) << " Frame sync SAT " << this->d_satellite << " with preamble start at "
<< static_cast<double>(d_preamble_time_samples) / static_cast<double>(d_symbol_history[0].fs) << " [s]";
}
case 0: // no preamble information
{
//correlate with preamble
int32_t corr_value = 0;
if (d_symbol_history.size() >= GPS_CA_PREAMBLE_LENGTH_SYMBOLS)
{
// ******* preamble correlation ********
for (int32_t i = 0; i < GPS_CA_PREAMBLE_LENGTH_SYMBOLS; i++)
{
if (d_symbol_history[i] < 0.0) // symbols clipping
{
corr_value -= d_preamble_samples[i];
}
else
{
corr_value += d_preamble_samples[i];
}
}
}
if (abs(corr_value) >= d_samples_per_preamble)
{
d_preamble_index = d_sample_counter; // record the preamble sample stamp
DLOG(INFO) << "Preamble detection for GPS L1 satellite " << this->d_satellite;
d_stat = 1; // enter into frame pre-detection status
}
break;
}
case 1: // possible preamble lock
{
//correlate with preamble
int32_t corr_value = 0;
int32_t preamble_diff = 0;
if (d_symbol_history.size() >= GPS_CA_PREAMBLE_LENGTH_SYMBOLS)
{
// ******* preamble correlation ********
for (int32_t i = 0; i < GPS_CA_PREAMBLE_LENGTH_SYMBOLS; i++)
{
if (d_symbol_history[i] < 0.0) // symbols clipping
{
corr_value -= d_preamble_samples[i];
}
else
{
corr_value += d_preamble_samples[i];
}
}
}
if (abs(corr_value) >= d_samples_per_preamble)
{
// check preamble separation
preamble_diff = static_cast<int32_t>(d_sample_counter - d_preamble_index);
if (abs(preamble_diff - d_preamble_period_symbols) == 0)
{
DLOG(INFO) << "Preamble confirmation for SAT " << this->d_satellite;
d_preamble_index = d_sample_counter; // record the preamble sample stamp
if (corr_value < 0) flag_PLL_180_deg_phase_locked = true;
d_stat = 2;
}
else
{
if (preamble_diff > d_preamble_period_symbols)
{
d_stat = 0; // start again
}
}
}
break;
}
case 2: // preamble acquired
{
if (d_sample_counter >= d_preamble_index + static_cast<uint64_t>(d_preamble_period_symbols))
{
DLOG(INFO) << "Preamble received for SAT " << this->d_satellite << "d_sample_counter=" << d_sample_counter << "\n";
// call the decoder
// 0. fetch the symbols into an array
d_preamble_index = d_sample_counter; // record the preamble sample stamp (t_P)
// try to decode the subframe:
if (decode_subframe() == false)
{
d_crc_error_synchronization_counter++;
if (d_crc_error_synchronization_counter > 3)
{
DLOG(INFO) << "TOO MANY CRC ERRORS: Lost of frame sync SAT " << this->d_satellite << std::endl;
d_stat = 0; // lost of frame sync
d_flag_frame_sync = false;
flag_TOW_set = false;
d_crc_error_synchronization_counter = 0;
}
}
d_current_subframe_symbol = 0;
}
}
}
else
{
if (d_stat == 1)
{
preamble_diff_ms = round(((static_cast<double>(d_symbol_history[0].Tracking_sample_counter) - static_cast<double>(d_preamble_time_samples)) / static_cast<double>(d_symbol_history[0].fs)) * 1000.0);
if (preamble_diff_ms > GPS_SUBFRAME_MS)
{
DLOG(INFO) << "Lost of frame sync SAT " << this->d_satellite << " preamble_diff= " << preamble_diff_ms;
// std::cout << "Lost of frame sync SAT " << this->d_satellite << " preamble_diff= " << preamble_diff_ms << std::endl;
d_stat = 0; // lost of frame sync
d_flag_frame_sync = false;
flag_TOW_set = false;
d_current_subframe_symbol = 0;
d_crc_error_synchronization_counter = 0;
d_TOW_at_current_symbol_ms = 0;
}
}
if (decode_subframe())
{
d_CRC_error_counter = 0;
d_flag_preamble = true; // valid preamble indicator (initialized to false every work())
d_last_valid_preamble = d_sample_counter;
if (!d_flag_frame_sync)
{
d_flag_frame_sync = true;
DLOG(INFO) << " Frame sync SAT " << this->d_satellite;
}
}
else
{
d_CRC_error_counter++;
d_preamble_index = d_sample_counter; // record the preamble sample stamp
if (d_CRC_error_counter > 2)
{
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;
d_TOW_at_Preamble_ms = 0;
d_CRC_error_counter = 0;
flag_TOW_set = false;
}
}
}
break;
}
}
// 2. Add the telemetry decoder information
if (this->d_flag_preamble == true and d_flag_new_tow_available == true)
if (d_flag_preamble == true)
{
d_TOW_at_current_symbol_ms = static_cast<uint32_t>(d_nav.d_TOW * 1000.0) + GPS_CA_PREAMBLE_DURATION_MS;
d_TOW_at_current_symbol_ms = static_cast<uint32_t>(d_nav.d_TOW * 1000.0);
d_TOW_at_Preamble_ms = static_cast<uint32_t>(d_nav.d_TOW * 1000.0);
flag_TOW_set = true;
d_flag_new_tow_available = false;
d_last_valid_preamble = d_sample_counter;
}
else
{

View File

@ -73,46 +73,45 @@ private:
gps_l1_ca_make_telemetry_decoder_gs(const Gnss_Satellite &satellite, bool dump);
gps_l1_ca_telemetry_decoder_gs(const Gnss_Satellite &satellite, bool dump);
bool gps_word_parityCheck(uint32_t gpsword);
bool decode_subframe();
bool new_decoder();
int d_crc_error_synchronization_counter;
// new
int32_t d_bits_per_preamble;
int32_t d_samples_per_preamble;
int32_t d_preamble_period_symbols;
int32_t *d_preamble_samples;
uint32_t d_required_symbols;
uint32_t d_frame_length_symbols;
double *d_page_part_symbols;
bool flag_PLL_180_deg_phase_locked;
// navigation message vars
Gps_Navigation_Message d_nav;
uint32_t d_prev_GPS_frame_4bytes;
boost::circular_buffer<float> d_symbol_history;
uint64_t d_sample_counter;
bool d_sent_tlm_failed_msg;
uint64_t d_preamble_index;
uint64_t d_last_valid_preamble;
uint32_t d_max_symbols_without_valid_frame;
int *d_preambles_symbols;
bool d_sent_tlm_failed_msg;
uint32_t d_stat;
bool d_flag_frame_sync;
// symbols
boost::circular_buffer<Gnss_Synchro> d_symbol_history;
float d_subframe_symbols[GPS_SUBFRAME_MS]{}; // symbols per subframe
int d_current_subframe_symbol;
// bits and frame
uint32_t d_prev_GPS_frame_4bytes;
bool d_flag_parity;
bool d_flag_preamble;
bool d_flag_new_tow_available;
int32_t d_CRC_error_counter;
// navigation message vars
Gps_Navigation_Message d_nav;
bool d_dump;
Gnss_Satellite d_satellite;
int d_channel;
uint64_t d_preamble_time_samples;
int32_t d_channel;
uint32_t d_TOW_at_Preamble_ms;
uint32_t d_TOW_at_current_symbol_ms;
bool flag_TOW_set;
bool flag_PLL_180_deg_phase_locked;
bool d_dump;
std::string d_dump_filename;
std::ofstream d_dump_file;
};

View File

@ -48,6 +48,11 @@
#include <cstring> // for memcpy
#include <iostream> // for operator<<,
// the following flags are FPGA-specific and they are using arrange the values of the local code in the way the FPGA
// expects. This arrangement is done in the initialisation to avoid consuming unnecessary clock cycles during tracking.
#define LOCAL_CODE_FPGA_ENABLE_WRITE_MEMORY 0x0C000000 // flag that enables WE (Write Enable) of the local code FPGA
#define LOCAL_CODE_FPGA_CORRELATOR_SELECT_COUNT 0x20000000 // flag that selects the writing of the pilot code in the FPGA (as opposed to the data code)
GalileoE1DllPllVemlTrackingFpga::GalileoE1DllPllVemlTrackingFpga(
ConfigurationInterface* configuration, const std::string& role,
@ -56,8 +61,6 @@ GalileoE1DllPllVemlTrackingFpga::GalileoE1DllPllVemlTrackingFpga(
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);
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;
@ -68,16 +71,76 @@ GalileoE1DllPllVemlTrackingFpga::GalileoE1DllPllVemlTrackingFpga(
trk_param_fpga.dump_filename = dump_filename;
bool dump_mat = configuration->property(role + ".dump_mat", true);
trk_param_fpga.dump_mat = dump_mat;
trk_param_fpga.high_dyn = configuration->property(role + ".high_dyn", false);
if (configuration->property(role + ".smoother_length", 10) < 1)
{
trk_param_fpga.smoother_length = 1;
std::cout << TEXT_RED << "WARNING: Gal. E1. smoother_length must be bigger than 0. It has been set to 1" << TEXT_RESET << std::endl;
}
else
{
trk_param_fpga.smoother_length = configuration->property(role + ".smoother_length", 10);
}
float pll_bw_hz = configuration->property(role + ".pll_bw_hz", 5.0);
if (FLAGS_pll_bw_hz != 0.0) pll_bw_hz = static_cast<float>(FLAGS_pll_bw_hz);
if (FLAGS_pll_bw_hz != 0.0)
{
pll_bw_hz = static_cast<float>(FLAGS_pll_bw_hz);
}
trk_param_fpga.pll_bw_hz = pll_bw_hz;
float dll_bw_hz = configuration->property(role + ".dll_bw_hz", 0.5);
if (FLAGS_dll_bw_hz != 0.0) dll_bw_hz = static_cast<float>(FLAGS_dll_bw_hz);
if (FLAGS_dll_bw_hz != 0.0)
{
dll_bw_hz = static_cast<float>(FLAGS_dll_bw_hz);
}
trk_param_fpga.dll_bw_hz = dll_bw_hz;
float pll_bw_narrow_hz = configuration->property(role + ".pll_bw_narrow_hz", 2.0);
trk_param_fpga.pll_bw_narrow_hz = pll_bw_narrow_hz;
float dll_bw_narrow_hz = configuration->property(role + ".dll_bw_narrow_hz", 0.25);
trk_param_fpga.dll_bw_narrow_hz = dll_bw_narrow_hz;
int dll_filter_order = configuration->property(role + ".dll_filter_order", 2);
if (dll_filter_order < 1)
{
LOG(WARNING) << "dll_filter_order parameter must be 1, 2 or 3. Set to 1.";
dll_filter_order = 1;
}
if (dll_filter_order > 3)
{
LOG(WARNING) << "dll_filter_order parameter must be 1, 2 or 3. Set to 3.";
dll_filter_order = 3;
}
trk_param_fpga.dll_filter_order = dll_filter_order;
int pll_filter_order = configuration->property(role + ".pll_filter_order", 3);
if (pll_filter_order < 2)
{
LOG(WARNING) << "pll_filter_order parameter must be 2 or 3. Set to 2.";
pll_filter_order = 2;
}
if (pll_filter_order > 3)
{
LOG(WARNING) << "pll_filter_order parameter must be 2 or 3. Set to 3.";
pll_filter_order = 3;
}
trk_param_fpga.pll_filter_order = pll_filter_order;
if (pll_filter_order == 2)
{
trk_param_fpga.fll_filter_order = 1;
}
if (pll_filter_order == 3)
{
trk_param_fpga.fll_filter_order = 2;
}
bool enable_fll_pull_in = configuration->property(role + ".enable_fll_pull_in", false);
trk_param_fpga.enable_fll_pull_in = enable_fll_pull_in;
float fll_bw_hz = configuration->property(role + ".fll_bw_hz", 35.0);
trk_param_fpga.fll_bw_hz = fll_bw_hz;
float pull_in_time_s = configuration->property(role + ".pull_in_time_s", 2.0);
trk_param_fpga.pull_in_time_s = pull_in_time_s;
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;
@ -111,16 +174,29 @@ GalileoE1DllPllVemlTrackingFpga::GalileoE1DllPllVemlTrackingFpga(
char sig_[3] = "1B";
std::memcpy(trk_param_fpga.signal, sig_, 3);
int32_t cn0_samples = configuration->property(role + ".cn0_samples", 20);
if (FLAGS_cn0_samples != 20) cn0_samples = FLAGS_cn0_samples;
if (FLAGS_cn0_samples != 20)
{
cn0_samples = FLAGS_cn0_samples;
}
trk_param_fpga.cn0_samples = cn0_samples;
int32_t cn0_min = configuration->property(role + ".cn0_min", 25);
if (FLAGS_cn0_min != 25) cn0_min = FLAGS_cn0_min;
if (FLAGS_cn0_min != 25)
{
cn0_min = FLAGS_cn0_min;
}
trk_param_fpga.cn0_min = cn0_min;
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;
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;
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
@ -158,19 +234,39 @@ GalileoE1DllPllVemlTrackingFpga::GalileoE1DllPllVemlTrackingFpga(
galileo_e1_code_gen_sinboc11_float(ca_codes_f, pilot_signal, PRN);
galileo_e1_code_gen_sinboc11_float(data_codes_f, data_signal, PRN);
// The code is generated as a series of 1s and -1s. In order to store the values using only one bit, a -1 is stored as a 0 in the FPGA
for (uint32_t s = 0; s < 2 * GALILEO_E1_B_CODE_LENGTH_CHIPS; 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]);
int32_t tmp_value = static_cast<int32_t>(ca_codes_f[s]);
if (tmp_value < 0)
{
tmp_value = 0;
}
tmp_value = tmp_value | LOCAL_CODE_FPGA_ENABLE_WRITE_MEMORY;
d_ca_codes[static_cast<int32_t>(GALILEO_E1_B_CODE_LENGTH_CHIPS) * 2 * (PRN - 1) + s] = tmp_value;
tmp_value = static_cast<int32_t>(data_codes_f[s]);
if (tmp_value < 0)
{
tmp_value = 0;
}
tmp_value = tmp_value | LOCAL_CODE_FPGA_ENABLE_WRITE_MEMORY | LOCAL_CODE_FPGA_CORRELATOR_SELECT_COUNT;
d_data_codes[static_cast<int32_t>(GALILEO_E1_B_CODE_LENGTH_CHIPS) * 2 * (PRN - 1) + s] = tmp_value;
}
}
else
{
galileo_e1_code_gen_sinboc11_float(ca_codes_f, data_signal, PRN);
// The code is generated as a series of 1s and -1s. In order to store the values using only one bit, a -1 is stored as a 0 in the FPGA
for (uint32_t s = 0; s < 2 * GALILEO_E1_B_CODE_LENGTH_CHIPS; 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]);
int32_t tmp_value = static_cast<int32_t>(ca_codes_f[s]);
if (tmp_value < 0)
{
tmp_value = 0;
}
tmp_value = tmp_value | LOCAL_CODE_FPGA_ENABLE_WRITE_MEMORY;
d_ca_codes[static_cast<int32_t>(GALILEO_E1_B_CODE_LENGTH_CHIPS) * 2 * (PRN - 1) + s] = tmp_value;
}
}
}

View File

@ -45,6 +45,11 @@
#include <cstring> // for memcpy
#include <iostream>
// the following flags are FPGA-specific and they are using arrange the values of the local code in the way the FPGA
// expects. This arrangement is done in the initialisation to avoid consuming unnecessary clock cycles during tracking.
#define LOCAL_CODE_FPGA_ENABLE_WRITE_MEMORY 0x0C000000 // flag that enables WE (Write Enable) of the local code FPGA
#define LOCAL_CODE_FPGA_CORRELATOR_SELECT_COUNT 0x20000000 // flag that selects the writing of the pilot code in the FPGA (as opposed to the data code)
GalileoE5aDllPllTrackingFpga::GalileoE5aDllPllTrackingFpga(
ConfigurationInterface *configuration, const std::string &role,
@ -53,8 +58,6 @@ GalileoE5aDllPllTrackingFpga::GalileoE5aDllPllTrackingFpga(
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);
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;
@ -65,12 +68,71 @@ GalileoE5aDllPllTrackingFpga::GalileoE5aDllPllTrackingFpga(
trk_param_fpga.dump_filename = dump_filename;
bool dump_mat = configuration->property(role + ".dump_mat", true);
trk_param_fpga.dump_mat = dump_mat;
trk_param_fpga.high_dyn = configuration->property(role + ".high_dyn", false);
if (configuration->property(role + ".smoother_length", 10) < 1)
{
trk_param_fpga.smoother_length = 1;
std::cout << TEXT_RED << "WARNING: Gal. E5a. smoother_length must be bigger than 0. It has been set to 1" << TEXT_RESET << std::endl;
}
else
{
trk_param_fpga.smoother_length = configuration->property(role + ".smoother_length", 10);
}
float pll_bw_hz = configuration->property(role + ".pll_bw_hz", 20.0);
if (FLAGS_pll_bw_hz != 0.0) pll_bw_hz = static_cast<float>(FLAGS_pll_bw_hz);
if (FLAGS_pll_bw_hz != 0.0)
{
pll_bw_hz = static_cast<float>(FLAGS_pll_bw_hz);
}
trk_param_fpga.pll_bw_hz = pll_bw_hz;
float dll_bw_hz = configuration->property(role + ".dll_bw_hz", 20.0);
if (FLAGS_dll_bw_hz != 0.0) dll_bw_hz = static_cast<float>(FLAGS_dll_bw_hz);
if (FLAGS_dll_bw_hz != 0.0)
{
dll_bw_hz = static_cast<float>(FLAGS_dll_bw_hz);
}
trk_param_fpga.dll_bw_hz = dll_bw_hz;
int dll_filter_order = configuration->property(role + ".dll_filter_order", 2);
if (dll_filter_order < 1)
{
LOG(WARNING) << "dll_filter_order parameter must be 1, 2 or 3. Set to 1.";
dll_filter_order = 1;
}
if (dll_filter_order > 3)
{
LOG(WARNING) << "dll_filter_order parameter must be 1, 2 or 3. Set to 3.";
dll_filter_order = 3;
}
trk_param_fpga.dll_filter_order = dll_filter_order;
int pll_filter_order = configuration->property(role + ".pll_filter_order", 3);
if (pll_filter_order < 2)
{
LOG(WARNING) << "pll_filter_order parameter must be 2 or 3. Set to 2.";
pll_filter_order = 2;
}
if (pll_filter_order > 3)
{
LOG(WARNING) << "pll_filter_order parameter must be 2 or 3. Set to 3.";
pll_filter_order = 3;
}
trk_param_fpga.pll_filter_order = pll_filter_order;
if (pll_filter_order == 2)
{
trk_param_fpga.fll_filter_order = 1;
}
if (pll_filter_order == 3)
{
trk_param_fpga.fll_filter_order = 2;
}
bool enable_fll_pull_in = configuration->property(role + ".enable_fll_pull_in", false);
trk_param_fpga.enable_fll_pull_in = enable_fll_pull_in;
float fll_bw_hz = configuration->property(role + ".fll_bw_hz", 35.0);
trk_param_fpga.fll_bw_hz = fll_bw_hz;
float pull_in_time_s = configuration->property(role + ".pull_in_time_s", 2.0);
trk_param_fpga.pull_in_time_s = pull_in_time_s;
float pll_bw_narrow_hz = configuration->property(role + ".pll_bw_narrow_hz", 5.0);
trk_param_fpga.pll_bw_narrow_hz = pll_bw_narrow_hz;
float dll_bw_narrow_hz = configuration->property(role + ".dll_bw_narrow_hz", 2.0);
@ -106,17 +168,30 @@ GalileoE5aDllPllTrackingFpga::GalileoE5aDllPllTrackingFpga(
char sig_[3] = "5X";
std::memcpy(trk_param_fpga.signal, sig_, 3);
int32_t cn0_samples = configuration->property(role + ".cn0_samples", 20);
if (FLAGS_cn0_samples != 20) cn0_samples = FLAGS_cn0_samples;
if (FLAGS_cn0_samples != 20)
{
cn0_samples = FLAGS_cn0_samples;
}
trk_param_fpga.cn0_samples = cn0_samples;
int32_t cn0_min = configuration->property(role + ".cn0_min", 25);
if (FLAGS_cn0_min != 25) cn0_min = FLAGS_cn0_min;
if (FLAGS_cn0_min != 25)
{
cn0_min = FLAGS_cn0_min;
}
trk_param_fpga.cn0_min = cn0_min;
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;
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;
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
@ -143,19 +218,41 @@ GalileoE5aDllPllTrackingFpga::GalileoE5aDllPllTrackingFpga(
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 *>(sig_));
if (trk_param_fpga.track_pilot)
{
// The code is generated as a series of 1s and -1s. In order to store the values using only one bit, a -1 is stored as a 0 in the FPGA
for (uint32_t s = 0; s < code_length_chips; 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());
int32_t tmp_value = static_cast<int32_t>(aux_code[s].imag());
if (tmp_value < 0)
{
tmp_value = 0;
}
tmp_value = tmp_value | LOCAL_CODE_FPGA_ENABLE_WRITE_MEMORY;
d_ca_codes[static_cast<int32_t>(code_length_chips) * (PRN - 1) + s] = tmp_value;
tmp_value = static_cast<int32_t>(aux_code[s].real());
if (tmp_value < 0)
{
tmp_value = 0;
}
tmp_value = tmp_value | LOCAL_CODE_FPGA_ENABLE_WRITE_MEMORY | LOCAL_CODE_FPGA_CORRELATOR_SELECT_COUNT;
d_data_codes[static_cast<int32_t>(code_length_chips) * (PRN - 1) + s] = tmp_value;
}
}
else
{
// The code is generated as a series of 1s and -1s. In order to store the values using only one bit, a -1 is stored as a 0 in the FPGA
for (uint32_t s = 0; s < code_length_chips; s++)
{
d_ca_codes[static_cast<int32_t>(code_length_chips) * (PRN - 1) + s] = static_cast<int32_t>(aux_code[s].real());
int32_t tmp_value = static_cast<int32_t>(aux_code[s].real());
if (tmp_value < 0)
{
tmp_value = 0;
}
tmp_value = tmp_value | LOCAL_CODE_FPGA_ENABLE_WRITE_MEMORY;
d_ca_codes[static_cast<int32_t>(code_length_chips) * (PRN - 1) + s] = tmp_value;
}
}
}

View File

@ -99,7 +99,6 @@ private:
std::string role_;
uint32_t in_streams_;
uint32_t out_streams_;
int32_t* d_ca_codes;
int32_t* d_data_codes;
bool d_track_pilot;

View File

@ -48,8 +48,11 @@
#include <cstring> // for memcpy
#include <iostream>
#define NUM_PRNs 32
#define NUM_PRNs 32 // total number of PRNs
// the following flag is FPGA-specific and they are using arrange the values of the local code in the way the FPGA
// expects. This arrangement is done in the initialisation to avoid consuming unnecessary clock cycles during tracking.
#define LOCAL_CODE_FPGA_ENABLE_WRITE_MEMORY 0x0C000000 // flag that enables WE (Write Enable) of the local code FPGA
GpsL1CaDllPllTrackingFpga::GpsL1CaDllPllTrackingFpga(
ConfigurationInterface* configuration, const std::string& role,
@ -62,6 +65,17 @@ GpsL1CaDllPllTrackingFpga::GpsL1CaDllPllTrackingFpga(
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;
trk_param_fpga.high_dyn = configuration->property(role + ".high_dyn", false);
if (configuration->property(role + ".smoother_length", 10) < 1)
{
trk_param_fpga.smoother_length = 1;
std::cout << TEXT_RED << "WARNING: GPS L1 C/A. smoother_length must be bigger than 0. It has been set to 1" << TEXT_RESET << std::endl;
}
else
{
trk_param_fpga.smoother_length = configuration->property(role + ".smoother_length", 10);
}
bool dump = configuration->property(role + ".dump", false);
trk_param_fpga.dump = dump;
std::string default_dump_filename = "./track_ch";
@ -70,15 +84,64 @@ GpsL1CaDllPllTrackingFpga::GpsL1CaDllPllTrackingFpga(
bool dump_mat = configuration->property(role + ".dump_mat", true);
trk_param_fpga.dump_mat = dump_mat;
float pll_bw_hz = configuration->property(role + ".pll_bw_hz", 50.0);
if (FLAGS_pll_bw_hz != 0.0) pll_bw_hz = static_cast<float>(FLAGS_pll_bw_hz);
if (FLAGS_pll_bw_hz != 0.0)
{
pll_bw_hz = static_cast<float>(FLAGS_pll_bw_hz);
}
trk_param_fpga.pll_bw_hz = pll_bw_hz;
float pll_bw_narrow_hz = configuration->property(role + ".pll_bw_narrow_hz", 20.0);
trk_param_fpga.pll_bw_narrow_hz = pll_bw_narrow_hz;
float dll_bw_narrow_hz = configuration->property(role + ".dll_bw_narrow_hz", 2.0);
trk_param_fpga.dll_bw_narrow_hz = dll_bw_narrow_hz;
float dll_bw_hz = configuration->property(role + ".dll_bw_hz", 2.0);
if (FLAGS_dll_bw_hz != 0.0) dll_bw_hz = static_cast<float>(FLAGS_dll_bw_hz);
if (FLAGS_dll_bw_hz != 0.0)
{
dll_bw_hz = static_cast<float>(FLAGS_dll_bw_hz);
}
trk_param_fpga.dll_bw_hz = dll_bw_hz;
int dll_filter_order = configuration->property(role + ".dll_filter_order", 2);
if (dll_filter_order < 1)
{
LOG(WARNING) << "dll_filter_order parameter must be 1, 2 or 3. Set to 1.";
dll_filter_order = 1;
}
if (dll_filter_order > 3)
{
LOG(WARNING) << "dll_filter_order parameter must be 1, 2 or 3. Set to 3.";
dll_filter_order = 3;
}
trk_param_fpga.dll_filter_order = dll_filter_order;
int pll_filter_order = configuration->property(role + ".pll_filter_order", 3);
if (pll_filter_order < 2)
{
LOG(WARNING) << "pll_filter_order parameter must be 2 or 3. Set to 2.";
pll_filter_order = 2;
}
if (pll_filter_order > 3)
{
LOG(WARNING) << "pll_filter_order parameter must be 2 or 3. Set to 3.";
pll_filter_order = 3;
}
trk_param_fpga.pll_filter_order = pll_filter_order;
if (pll_filter_order == 2)
{
trk_param_fpga.fll_filter_order = 1;
}
if (pll_filter_order == 3)
{
trk_param_fpga.fll_filter_order = 2;
}
bool enable_fll_pull_in = configuration->property(role + ".enable_fll_pull_in", false);
trk_param_fpga.enable_fll_pull_in = enable_fll_pull_in;
float fll_bw_hz = configuration->property(role + ".fll_bw_hz", 35.0);
trk_param_fpga.fll_bw_hz = fll_bw_hz;
float pull_in_time_s = configuration->property(role + ".pull_in_time_s", 2.0);
trk_param_fpga.pull_in_time_s = pull_in_time_s;
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;
float early_late_space_narrow_chips = configuration->property(role + ".early_late_space_narrow_chips", 0.5);
@ -113,16 +176,28 @@ GpsL1CaDllPllTrackingFpga::GpsL1CaDllPllTrackingFpga(
char sig_[3] = "1C";
std::memcpy(trk_param_fpga.signal, sig_, 3);
int32_t cn0_samples = configuration->property(role + ".cn0_samples", 20);
if (FLAGS_cn0_samples != 20) cn0_samples = FLAGS_cn0_samples;
if (FLAGS_cn0_samples != 20)
{
cn0_samples = FLAGS_cn0_samples;
}
trk_param_fpga.cn0_samples = cn0_samples;
int32_t cn0_min = configuration->property(role + ".cn0_min", 25);
if (FLAGS_cn0_min != 25) cn0_min = FLAGS_cn0_min;
int32_t cn0_min = configuration->property(role + ".cn0_min", 30);
if (FLAGS_cn0_min != 25)
{
cn0_min = FLAGS_cn0_min;
}
trk_param_fpga.cn0_min = cn0_min;
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;
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;
double carrier_lock_th = configuration->property(role + ".carrier_lock_th", 0.80);
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
@ -138,6 +213,18 @@ GpsL1CaDllPllTrackingFpga::GpsL1CaDllPllTrackingFpga(
for (uint32_t PRN = 1; PRN <= NUM_PRNs; PRN++)
{
gps_l1_ca_code_gen_int(&d_ca_codes[(int32_t(GPS_L1_CA_CODE_LENGTH_CHIPS)) * (PRN - 1)], PRN, 0);
// The code is generated as a series of 1s and -1s. In order to store the values using only one bit, a -1 is stored as a 0 in the FPGA
for (uint32_t k = 0; k < GPS_L1_CA_CODE_LENGTH_CHIPS; k++)
{
int32_t tmp_value = d_ca_codes[(int32_t(GPS_L1_CA_CODE_LENGTH_CHIPS)) * (PRN - 1) + k];
if (tmp_value < 0)
{
tmp_value = 0;
}
tmp_value = tmp_value | LOCAL_CODE_FPGA_ENABLE_WRITE_MEMORY;
d_ca_codes[(int32_t(GPS_L1_CA_CODE_LENGTH_CHIPS)) * (PRN - 1) + k] = tmp_value;
}
}
trk_param_fpga.ca_codes = d_ca_codes;
trk_param_fpga.code_length_chips = GPS_L1_CA_CODE_LENGTH_CHIPS;

View File

@ -50,7 +50,12 @@
#include <cstring> // for memcpy
#include <iostream>
#define NUM_PRNs 32
#define NUM_PRNs 32 // number of PRNS
// the following flags are FPGA-specific and they are using arrange the values of the local code in the way the FPGA
// expects. This arrangement is done in the initialisation to avoid consuming unnecessary clock cycles during tracking.
#define LOCAL_CODE_FPGA_ENABLE_WRITE_MEMORY 0x0C000000 // flag that enables WE (Write Enable) of the local code FPGA
#define LOCAL_CODE_FPGA_CORRELATOR_SELECT_COUNT 0x20000000 // flag that selects the writing of the pilot code in the FPGA (as opposed to the data code)
GpsL5DllPllTrackingFpga::GpsL5DllPllTrackingFpga(
@ -70,11 +75,27 @@ GpsL5DllPllTrackingFpga::GpsL5DllPllTrackingFpga(
trk_param_fpga.dump_filename = dump_filename;
bool dump_mat = configuration->property(role + ".dump_mat", true);
trk_param_fpga.dump_mat = dump_mat;
trk_param_fpga.high_dyn = configuration->property(role + ".high_dyn", false);
if (configuration->property(role + ".smoother_length", 10) < 1)
{
trk_param_fpga.smoother_length = 1;
std::cout << TEXT_RED << "WARNING: GPS L5. smoother_length must be bigger than 0. It has been set to 1" << TEXT_RESET << std::endl;
}
else
{
trk_param_fpga.smoother_length = configuration->property(role + ".smoother_length", 10);
}
float pll_bw_hz = configuration->property(role + ".pll_bw_hz", 50.0);
if (FLAGS_pll_bw_hz != 0.0) pll_bw_hz = static_cast<float>(FLAGS_pll_bw_hz);
if (FLAGS_pll_bw_hz != 0.0)
{
pll_bw_hz = static_cast<float>(FLAGS_pll_bw_hz);
}
trk_param_fpga.pll_bw_hz = pll_bw_hz;
float dll_bw_hz = configuration->property(role + ".dll_bw_hz", 2.0);
if (FLAGS_dll_bw_hz != 0.0) dll_bw_hz = static_cast<float>(FLAGS_dll_bw_hz);
if (FLAGS_dll_bw_hz != 0.0)
{
dll_bw_hz = static_cast<float>(FLAGS_dll_bw_hz);
}
trk_param_fpga.dll_bw_hz = dll_bw_hz;
float pll_bw_narrow_hz = configuration->property(role + ".pll_bw_narrow_hz", 2.0);
trk_param_fpga.pll_bw_narrow_hz = pll_bw_narrow_hz;
@ -82,6 +103,49 @@ 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 dll_filter_order = configuration->property(role + ".dll_filter_order", 2);
if (dll_filter_order < 1)
{
LOG(WARNING) << "dll_filter_order parameter must be 1, 2 or 3. Set to 1.";
dll_filter_order = 1;
}
if (dll_filter_order > 3)
{
LOG(WARNING) << "dll_filter_order parameter must be 1, 2 or 3. Set to 3.";
dll_filter_order = 3;
}
trk_param_fpga.dll_filter_order = dll_filter_order;
int pll_filter_order = configuration->property(role + ".pll_filter_order", 3);
if (pll_filter_order < 2)
{
LOG(WARNING) << "pll_filter_order parameter must be 2 or 3. Set to 2.";
pll_filter_order = 2;
}
if (pll_filter_order > 3)
{
LOG(WARNING) << "pll_filter_order parameter must be 2 or 3. Set to 3.";
pll_filter_order = 3;
}
trk_param_fpga.pll_filter_order = pll_filter_order;
if (pll_filter_order == 2)
{
trk_param_fpga.fll_filter_order = 1;
}
if (pll_filter_order == 3)
{
trk_param_fpga.fll_filter_order = 2;
}
bool enable_fll_pull_in = configuration->property(role + ".enable_fll_pull_in", false);
trk_param_fpga.enable_fll_pull_in = enable_fll_pull_in;
float fll_bw_hz = configuration->property(role + ".fll_bw_hz", 35.0);
trk_param_fpga.fll_bw_hz = fll_bw_hz;
float pull_in_time_s = configuration->property(role + ".pull_in_time_s", 2.0);
trk_param_fpga.pull_in_time_s = pull_in_time_s;
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;
int32_t extend_correlation_symbols = configuration->property(role + ".extend_correlation_symbols", 1);
@ -111,16 +175,28 @@ GpsL5DllPllTrackingFpga::GpsL5DllPllTrackingFpga(
char sig_[3] = "L5";
std::memcpy(trk_param_fpga.signal, sig_, 3);
int32_t cn0_samples = configuration->property(role + ".cn0_samples", 20);
if (FLAGS_cn0_samples != 20) cn0_samples = FLAGS_cn0_samples;
if (FLAGS_cn0_samples != 20)
{
cn0_samples = FLAGS_cn0_samples;
}
trk_param_fpga.cn0_samples = cn0_samples;
int32_t cn0_min = configuration->property(role + ".cn0_min", 25);
if (FLAGS_cn0_min != 25) cn0_min = FLAGS_cn0_min;
if (FLAGS_cn0_min != 25)
{
cn0_min = FLAGS_cn0_min;
}
trk_param_fpga.cn0_min = cn0_min;
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;
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.75);
if (FLAGS_carrier_lock_th != 0.85) carrier_lock_th = FLAGS_carrier_lock_th;
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
@ -163,18 +239,40 @@ GpsL5DllPllTrackingFpga::GpsL5DllPllTrackingFpga(
gps_l5q_code_gen_float(tracking_code, PRN);
gps_l5i_code_gen_float(data_code, PRN);
// The code is generated as a series of 1s and -1s. In order to store the values using only one bit, a -1 is stored as a 0 in the FPGA
for (uint32_t s = 0; s < code_length_chips; 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]);
int32_t tmp_value = static_cast<int32_t>(tracking_code[s]);
if (tmp_value < 0)
{
tmp_value = 0;
}
tmp_value = tmp_value | LOCAL_CODE_FPGA_ENABLE_WRITE_MEMORY;
d_ca_codes[static_cast<int32_t>(code_length_chips) * (PRN - 1) + s] = tmp_value;
tmp_value = static_cast<int32_t>(data_code[s]);
if (tmp_value < 0)
{
tmp_value = 0;
}
tmp_value = tmp_value | LOCAL_CODE_FPGA_ENABLE_WRITE_MEMORY | LOCAL_CODE_FPGA_CORRELATOR_SELECT_COUNT;
d_data_codes[static_cast<int32_t>(code_length_chips) * (PRN - 1) + s] = tmp_value;
}
}
else
{
gps_l5i_code_gen_float(tracking_code, PRN);
// The code is generated as a series of 1s and -1s. In order to store the values using only one bit, a -1 is stored as a 0 in the FPGA
for (uint32_t s = 0; s < code_length_chips; s++)
{
d_ca_codes[static_cast<int32_t>(code_length_chips) * (PRN - 1) + s] = static_cast<int32_t>(tracking_code[s]);
int32_t tmp_value = static_cast<int32_t>(tracking_code[s]);
if (tmp_value < 0)
{
tmp_value = 0;
}
tmp_value = tmp_value | LOCAL_CODE_FPGA_ENABLE_WRITE_MEMORY;
d_ca_codes[static_cast<int32_t>(code_length_chips) * (PRN - 1) + s] = tmp_value;
}
}
}

View File

@ -560,9 +560,6 @@ void dll_pll_veml_tracking::start_tracking()
d_carrier_phase_rate_step_rad = 0.0;
d_carr_ph_history.clear();
d_code_ph_history.clear();
// DLL/PLL filter initialization
d_carrier_loop_filter.initialize(static_cast<float>(d_acq_carrier_doppler_hz)); // initialize the carrier filter
d_code_loop_filter.initialize(); // initialize the code filter
if (systemName == "GPS" and signal_type == "1C")
{
@ -732,8 +729,13 @@ void dll_pll_veml_tracking::start_tracking()
d_current_correlation_time_s = d_code_period;
// Initialize tracking ==========================================
d_carrier_loop_filter.set_params(trk_parameters.fll_bw_hz, trk_parameters.pll_bw_hz, trk_parameters.pll_filter_order);
d_code_loop_filter.set_noise_bandwidth(trk_parameters.dll_bw_hz);
d_code_loop_filter.set_update_interval(d_code_period);
// DLL/PLL filter initialization
d_carrier_loop_filter.initialize(static_cast<float>(d_acq_carrier_doppler_hz)); // initialize the carrier filter
d_code_loop_filter.initialize(); // initialize the code filter
// DEBUG OUTPUT
std::cout << "Tracking of " << systemName << " " << signal_pretty_name << " signal started on channel " << d_channel << " for satellite " << Gnss_Satellite(systemName, d_acquisition_gnss_synchro->PRN) << std::endl;
@ -1541,6 +1543,7 @@ void dll_pll_veml_tracking::stop_tracking()
d_state = 0;
}
int dll_pll_veml_tracking::general_work(int noutput_items __attribute__((unused)), gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items, gr_vector_void_star &output_items)
{
@ -1572,10 +1575,6 @@ int dll_pll_veml_tracking::general_work(int noutput_items __attribute__((unused)
double acq_trk_diff_seconds = static_cast<double>(acq_trk_diff_samples) / trk_parameters.fs_in;
double delta_trk_to_acq_prn_start_samples = static_cast<double>(acq_trk_diff_samples) - d_acq_code_phase_samples;
// Doppler effect Fd = (C / (C + Vr)) * F
double radial_velocity = (d_signal_carrier_freq + d_acq_carrier_doppler_hz) / d_signal_carrier_freq;
// new chip and PRN sequence periods based on acq Doppler
d_code_freq_chips = radial_velocity * d_code_chip_rate;
d_code_freq_chips = d_code_chip_rate;
d_code_phase_step_chips = d_code_freq_chips / trk_parameters.fs_in;
d_code_phase_rate_step_chips = 0.0;

View File

@ -33,20 +33,20 @@
#define GNSS_SDR_DLL_PLL_VEML_TRACKING_FPGA_H
#include "dll_pll_conf_fpga.h"
#include "tracking_2nd_DLL_filter.h"
#include "tracking_2nd_PLL_filter.h"
#include "tracking_FLL_PLL_filter.h" // for PLL/FLL filter
#include "tracking_loop_filter.h" // for DLL filter
#include <boost/circular_buffer.hpp>
#include <boost/shared_ptr.hpp>
#include <gnuradio/block.h>
#include <boost/shared_ptr.hpp> // for boost::shared_ptr
#include <gnuradio/block.h> // for block
#include <gnuradio/gr_complex.h> // for gr_complex
#include <gnuradio/types.h> // for gr_vector_const_void_star
#include <gnuradio/types.h> // for gr_vector_int, gr_vector...
#include <pmt/pmt.h> // for pmt_t
#include <cstdint>
#include <deque> // for deque
#include <fstream> // for ofstream
#include <memory> // for shared_ptr
#include <cstdint> // for int32_t
#include <deque> // for deque
#include <fstream> // for string, ofstream
#include <memory> // for shared_ptr
#include <string>
#include <utility>
#include <utility> // for pair
class Fpga_Multicorrelator_8sc;
class Gnss_Synchro;
@ -77,7 +77,7 @@ public:
private:
friend dll_pll_veml_tracking_fpga_sptr dll_pll_veml_make_tracking_fpga(const Dll_Pll_Conf_Fpga &conf_);
void msg_handler_telemetry_to_trk(const pmt::pmt_t &msg);
dll_pll_veml_tracking_fpga(const Dll_Pll_Conf_Fpga &conf_);
void msg_handler_preamble_index(pmt::pmt_t msg);
@ -91,7 +91,7 @@ private:
void log_data(bool integrating);
int32_t save_matfile();
void run_state_2(Gnss_Synchro &current_synchro_data);
//void run_state_2(Gnss_Synchro &current_synchro_data);
// tracking configuration vars
Dll_Pll_Conf_Fpga trk_parameters;
@ -115,23 +115,20 @@ private:
std::string *d_secondary_code_string;
std::string signal_pretty_name;
int32_t *d_gps_l1ca_preambles_symbols;
int32_t *d_preambles_symbols;
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;
float *d_local_code_shift_chips;
float *d_prompt_data_shift;
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;
@ -146,9 +143,9 @@ private:
gr_complex d_VE_accu;
gr_complex d_E_accu;
gr_complex d_P_accu;
gr_complex d_P_accu_old;
gr_complex d_L_accu;
gr_complex d_VL_accu;
gr_complex d_last_prompt;
gr_complex *d_Prompt_Data;
@ -163,15 +160,18 @@ private:
float d_rem_carr_phase_rad;
// PLL and DLL filter library
Tracking_2nd_DLL_filter d_code_loop_filter;
Tracking_2nd_PLL_filter d_carrier_loop_filter;
Tracking_loop_filter d_code_loop_filter;
Tracking_FLL_PLL_filter d_carrier_loop_filter;
// acquisition
double d_acq_code_phase_samples;
double d_acq_carrier_doppler_hz;
// tracking vars
double d_carr_error_hz;
bool d_pull_in_transitory;
double d_current_correlation_time_s;
double d_carr_phase_error_hz;
double d_carr_freq_error_hz;
double d_carr_error_filt_hz;
double d_code_error_chips;
double d_code_error_filt_chips;
@ -194,11 +194,12 @@ 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;
//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;
//std::deque<gr_complex> d_Prompt_buffer_deque;
gr_complex *d_Prompt_buffer;
// file dump

View File

@ -44,6 +44,15 @@ Dll_Pll_Conf_Fpga::Dll_Pll_Conf_Fpga()
dump = false;
dump_mat = true;
dump_filename = std::string("./dll_pll_dump.dat");
enable_fll_pull_in = false;
enable_fll_steady_state = false;
pull_in_time_s = 2;
fll_filter_order = 1;
pll_filter_order = 3;
dll_filter_order = 2;
fll_bw_hz = 35.0;
pll_pull_in_bw_hz = 50.0;
dll_pull_in_bw_hz = 3.0;
pll_bw_hz = 35.0;
dll_bw_hz = 2.0;
pll_bw_narrow_hz = 5.0;

View File

@ -42,11 +42,22 @@ class Dll_Pll_Conf_Fpga
{
public:
/* DLL/PLL tracking configuration */
int fll_filter_order;
bool enable_fll_pull_in;
bool enable_fll_steady_state;
unsigned int pull_in_time_s; // signed integer, when pull in time is not yet reached it has to be compared against a negative number
int pll_filter_order;
int dll_filter_order;
double fs_in;
uint32_t vector_length;
bool dump;
bool dump_mat;
std::string dump_filename;
float pll_pull_in_bw_hz;
float dll_pull_in_bw_hz;
float fll_bw_hz;
float pll_bw_hz;
float dll_bw_hz;
float pll_bw_narrow_hz;

View File

@ -51,14 +51,15 @@
#define CODE_PHASE_STEP_CHIPS_NUM_NBITS CODE_RESAMPLER_NUM_BITS_PRECISION
#define pwrtwo(x) (1 << (x))
#define MAX_CODE_RESAMPLER_COUNTER pwrtwo(CODE_PHASE_STEP_CHIPS_NUM_NBITS) // 2^CODE_PHASE_STEP_CHIPS_NUM_NBITS
#define PHASE_CARR_NBITS 32
#define PHASE_CARR_NBITS_INT 1
#define PHASE_CARR_NBITS_FRAC PHASE_CARR_NBITS - PHASE_CARR_NBITS_INT
#define PHASE_CARR_MAX 2147483648 // 2^(31) The phase is represented as a 32-bit vector in 1.31 format
#define PHASE_CARR_MAX_div_PI 683565275.5764316 // 2^(31)/pi
#define TWO_PI 6.283185307179586
#define LOCAL_CODE_FPGA_CORRELATOR_SELECT_COUNT 0x20000000
#define LOCAL_CODE_FPGA_CLEAR_ADDRESS_COUNTER 0x10000000
#define LOCAL_CODE_FPGA_ENABLE_WRITE_MEMORY 0x0C000000
#define TEST_REGISTER_TRACK_WRITEVAL 0x55AA
#define ENABLE_TRK_INT_ON_RESET 1 /* flag that causes the tracking HW accelerator to trigger an interrupt when it is reset. It is used \
to avoid a potential deadlock caused by the SW waiting for an interrupt from the FPGA when the HW is reset */
#ifndef TEMP_FAILURE_RETRY
#define TEMP_FAILURE_RETRY(exp) \
({ \
@ -118,6 +119,7 @@ Fpga_Multicorrelator_8sc::Fpga_Multicorrelator_8sc(int32_t n_correlators,
d_data_codes = data_codes;
d_multicorr_type = multicorr_type;
d_code_samples_per_chip = code_samples_per_chip;
d_code_length_samples = d_code_length_chips * d_code_samples_per_chip;
DLOG(INFO) << "TRACKING FPGA CLASS CREATED";
}
@ -171,28 +173,30 @@ void Fpga_Multicorrelator_8sc::set_output_vectors(gr_complex *corr_out, gr_compl
}
void Fpga_Multicorrelator_8sc::update_local_code(float rem_code_phase_chips)
void Fpga_Multicorrelator_8sc::update_local_code()
{
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)
float rem_carrier_phase_in_rad, // nco phase initial position
float phase_step_rad, // nco phase step
float carrier_phase_rate_step_rad __attribute__((unused)), // nco phase step rate change
float rem_code_phase_chips, // code resampler initial position
float code_phase_step_chips __attribute__((unused)), // code resampler step
float code_phase_rate_step_chips __attribute__((unused)), // code resampler step rate
int32_t signal_length_samples) // number of 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;
d_rem_carrier_phase_in_rad = rem_carrier_phase_in_rad; // nco phase initial position
d_phase_step_rad = phase_step_rad; // nco phase step
d_carrier_phase_rate_step_rad = carrier_phase_rate_step_rad; // nco phase step rate
d_rem_code_phase_chips = rem_code_phase_chips; // code resampler initial position
d_code_phase_step_chips = code_phase_step_chips; // code resampler step
d_code_phase_rate_step_chips = code_phase_rate_step_chips; // code resampler step rate
d_correlator_length_samples = signal_length_samples; // number of samples
Fpga_Multicorrelator_8sc::update_local_code();
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();
@ -279,6 +283,16 @@ void Fpga_Multicorrelator_8sc::set_channel(uint32_t channel)
{
LOG(INFO) << "Test register sanity check success !";
}
d_map_base[INT_ON_RST_REG_ADDR] = ENABLE_TRK_INT_ON_RESET; // enable interrupts on reset to prevent deadlock
// enable interrupts
int32_t reenable = 1;
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;
}
}
@ -298,88 +312,72 @@ uint32_t Fpga_Multicorrelator_8sc::fpga_acquisition_test_register(
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;
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++)
for (k = 0; k < d_code_length_samples; k++)
{
if (d_ca_codes[((int32_t(d_code_length_chips)) * d_code_samples_per_chip * (PRN - 1)) + k] == 1)
{
code_chip = 1;
}
else
{
code_chip = 0;
}
// copy the local code to the FPGA memory one by one
d_map_base[PROG_MEMS_ADDR] = LOCAL_CODE_FPGA_ENABLE_WRITE_MEMORY | code_chip; // | select_fpga_correlator;
d_map_base[PROG_MEMS_ADDR] = d_ca_codes[(d_code_length_samples * (PRN - 1)) + k];
}
if (d_track_pilot)
{
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++)
for (k = 0; k < d_code_length_samples; k++)
{
if (d_data_codes[((int32_t(d_code_length_chips)) * d_code_samples_per_chip * (PRN - 1)) + k] == 1)
{
code_chip = 1;
}
else
{
code_chip = 0;
}
d_map_base[PROG_MEMS_ADDR] = LOCAL_CODE_FPGA_ENABLE_WRITE_MEMORY | code_chip | select_pilot_corelator;
d_map_base[PROG_MEMS_ADDR] = d_data_codes[(d_code_length_samples * (PRN - 1)) + k];
}
}
d_map_base[CODE_LENGTH_MINUS_1_REG_ADDR] = (d_code_length_samples)-1; // number of samples - 1
}
void Fpga_Multicorrelator_8sc::fpga_compute_code_shift_parameters(void)
{
float temp_calculation;
int32_t i;
float frac_part; // decimal part
int32_t dec_part; // fractional part
for (i = 0; i < d_n_correlators; i++)
for (uint32_t i = 0; i < d_n_correlators; i++)
{
temp_calculation = floor(d_shifts_chips[i] - d_rem_code_phase_chips);
dec_part = floor(d_shifts_chips[i] - d_rem_code_phase_chips);
if (temp_calculation < 0)
if (dec_part < 0)
{
temp_calculation = temp_calculation + (d_code_length_chips * d_code_samples_per_chip); // % operator does not work as in Matlab with negative numbers
dec_part = dec_part + d_code_length_samples; // % operator does not work as in Matlab with negative numbers
}
d_initial_index[i] = static_cast<uint32_t>((static_cast<int32_t>(temp_calculation)) % (d_code_length_chips * d_code_samples_per_chip));
temp_calculation = fmod(d_shifts_chips[i] - d_rem_code_phase_chips, 1.0);
if (temp_calculation < 0)
d_initial_index[i] = dec_part;
frac_part = fmod(d_shifts_chips[i] - d_rem_code_phase_chips, 1.0);
if (frac_part < 0)
{
temp_calculation = temp_calculation + 1.0; // fmod operator does not work as in Matlab with negative numbers
frac_part = frac_part + 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));
d_initial_interp_counter[i] = static_cast<uint32_t>(floor(MAX_CODE_RESAMPLER_COUNTER * frac_part));
}
if (d_track_pilot)
{
temp_calculation = floor(d_prompt_data_shift[0] - d_rem_code_phase_chips);
dec_part = floor(d_prompt_data_shift[0] - d_rem_code_phase_chips);
if (temp_calculation < 0)
if (dec_part < 0)
{
temp_calculation = temp_calculation + (d_code_length_chips * d_code_samples_per_chip); // % operator does not work as in Matlab with negative numbers
dec_part = dec_part + d_code_length_samples; // % operator does not work as in Matlab with negative numbers
}
d_initial_index[d_n_correlators] = static_cast<uint32_t>((static_cast<int32_t>(temp_calculation)) % (d_code_length_chips * d_code_samples_per_chip));
temp_calculation = fmod(d_prompt_data_shift[0] - d_rem_code_phase_chips, 1.0);
if (temp_calculation < 0)
d_initial_index[d_n_correlators] = dec_part;
frac_part = fmod(d_prompt_data_shift[0] - d_rem_code_phase_chips, 1.0);
if (frac_part < 0)
{
temp_calculation = temp_calculation + 1.0; // fmod operator does not work as in Matlab with negative numbers
frac_part = frac_part + 1.0; // fmod operator does not work as in Matlab with negative numbers
}
d_initial_interp_counter[d_n_correlators] = static_cast<uint32_t>(floor(MAX_CODE_RESAMPLER_COUNTER * temp_calculation));
d_initial_interp_counter[d_n_correlators] = static_cast<uint32_t>(floor(MAX_CODE_RESAMPLER_COUNTER * frac_part));
}
}
void Fpga_Multicorrelator_8sc::fpga_configure_code_parameters_in_fpga(void)
{
int32_t i;
for (i = 0; i < d_n_correlators; i++)
for (uint32_t i = 0; i < d_n_correlators; 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];
@ -389,8 +387,6 @@ void Fpga_Multicorrelator_8sc::fpga_configure_code_parameters_in_fpga(void)
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];
}
d_map_base[CODE_LENGTH_MINUS_1_REG_ADDR] = (d_code_length_chips * d_code_samples_per_chip) - 1; // number of samples - 1
}
@ -399,58 +395,52 @@ 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)
{
std::cout << "Warning : d_code_phase_step_chips = " << d_code_phase_step_chips << " cannot be bigger than one" << std::endl;
}
d_code_phase_rate_step_chips_num = static_cast<uint32_t>(roundf(MAX_CODE_RESAMPLER_COUNTER * d_code_phase_rate_step_chips));
if (d_rem_carrier_phase_in_rad > M_PI)
{
d_rem_carrier_phase_in_rad_temp = -2 * M_PI + d_rem_carrier_phase_in_rad;
d_rem_carrier_phase_in_rad_temp = -TWO_PI + d_rem_carrier_phase_in_rad;
}
else if (d_rem_carrier_phase_in_rad < -M_PI)
{
d_rem_carrier_phase_in_rad_temp = 2 * M_PI + d_rem_carrier_phase_in_rad;
d_rem_carrier_phase_in_rad_temp = TWO_PI + d_rem_carrier_phase_in_rad;
}
else
{
d_rem_carrier_phase_in_rad_temp = d_rem_carrier_phase_in_rad;
}
d_rem_carr_phase_rad_int = static_cast<int32_t>(roundf((fabs(d_rem_carrier_phase_in_rad_temp) / M_PI) * pow(2, PHASE_CARR_NBITS_FRAC)));
if (d_rem_carrier_phase_in_rad_temp < 0)
{
d_rem_carr_phase_rad_int = -d_rem_carr_phase_rad_int;
}
d_phase_step_rad_int = static_cast<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
if (d_phase_step_rad < 0)
{
d_phase_step_rad_int = -d_phase_step_rad_int;
}
d_rem_carr_phase_rad_int = static_cast<int32_t>(roundf((d_rem_carrier_phase_in_rad_temp)*PHASE_CARR_MAX_div_PI));
d_phase_step_rad_int = static_cast<int32_t>(roundf((d_phase_step_rad)*PHASE_CARR_MAX_div_PI)); // the FPGA accepts a range for the phase step between -pi and +pi
d_carrier_phase_rate_step_rad_int = static_cast<int32_t>(roundf((d_carrier_phase_rate_step_rad)*PHASE_CARR_MAX_div_PI));
}
void Fpga_Multicorrelator_8sc::fpga_configure_signal_parameters_in_fpga(void)
{
d_map_base[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; // code phase step
d_map_base[NSAMPLES_MINUS_1_REG_ADDR] = d_correlator_length_samples - 1;
d_map_base[CODE_PHASE_STEP_CHIPS_RATE] = d_code_phase_rate_step_chips_num; // code phase step rate
d_map_base[REM_CARR_PHASE_RAD_REG_ADDR] = d_rem_carr_phase_rad_int;
d_map_base[NSAMPLES_MINUS_1_REG_ADDR] = d_correlator_length_samples - 1; // number of samples
d_map_base[PHASE_STEP_RAD_REG_ADDR] = d_phase_step_rad_int;
d_map_base[REM_CARR_PHASE_RAD_REG_ADDR] = d_rem_carr_phase_rad_int; // initial nco phase
d_map_base[PHASE_STEP_RAD_REG_ADDR] = d_phase_step_rad_int; // nco phase step
d_map_base[PHASE_STEP_RATE_REG_ADDR] = d_carrier_phase_rate_step_rad_int; // nco phase step rate
}
void Fpga_Multicorrelator_8sc::fpga_launch_multicorrelator_fpga(void)
{
// enable interrupts
int32_t reenable = 1;
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;
}
// // enable interrupts
// int32_t reenable = 1;
// 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
d_map_base[START_FLAG_ADDR] = 1;
}
@ -460,9 +450,8 @@ void Fpga_Multicorrelator_8sc::read_tracking_gps_results(void)
{
int32_t readval_real;
int32_t readval_imag;
int32_t k;
for (k = 0; k < d_n_correlators; k++)
for (uint32_t k = 0; k < d_n_correlators; k++)
{
readval_real = d_map_base[RESULT_REG_REAL_BASE_ADDR + k];
readval_imag = d_map_base[RESULT_REG_IMAG_BASE_ADDR + k];

View File

@ -54,7 +54,10 @@
#define DROP_SAMPLES_REG_ADDR 18
#define INITIAL_COUNTER_VALUE_REG_ADDR_LSW 19
#define INITIAL_COUNTER_VALUE_REG_ADDR_MSW 20
#define CODE_PHASE_STEP_CHIPS_RATE 21
#define PHASE_STEP_RATE_REG_ADDR 22
#define STOP_TRACKING_REG_ADDR 23
#define INT_ON_RST_REG_ADDR 24 // cause interrupt on reset to prevent deadlock
#define START_FLAG_ADDR 30
// read-write addresses
#define TEST_REG_ADDR 31
@ -77,7 +80,7 @@ public:
void set_output_vectors(gr_complex *corr_out, gr_complex *Prompt_Data);
void set_local_code_and_taps(
float *shifts_chips, float *prompt_data_shift, int32_t PRN);
void update_local_code(float rem_code_phase_chips);
void update_local_code();
void Carrier_wipeoff_multicorrelator_resampler(
float rem_carrier_phase_in_rad, float phase_step_rad,
float carrier_phase_rate_step_rad,
@ -96,27 +99,32 @@ private:
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; // number of correlators
uint32_t d_code_length_chips;
uint32_t d_code_length_samples;
uint32_t d_n_correlators; // number of correlators
// data related to the hardware module and the driver
int32_t d_device_descriptor; // driver descriptor
volatile uint32_t *d_map_base; // driver memory map
// configuration data received from the interface
uint32_t d_channel; // channel number
uint32_t d_channel; // channel number
uint32_t d_correlator_length_samples;
float d_rem_code_phase_chips;
float d_code_phase_step_chips;
float d_code_phase_rate_step_chips;
float d_rem_carrier_phase_in_rad;
float d_phase_step_rad;
float d_carrier_phase_rate_step_rad;
// configuration data computed in the format that the FPGA expects
uint32_t *d_initial_index;
uint32_t *d_initial_interp_counter;
uint32_t d_code_phase_step_chips_num;
uint32_t d_code_phase_rate_step_chips_num;
int32_t d_rem_carr_phase_rad_int;
int32_t d_phase_step_rad_int;
int32_t d_carrier_phase_rate_step_rad_int;
uint64_t d_initial_sample_counter;
// driver

View File

@ -58,7 +58,7 @@ class AcquisitionInterface : public GNSSBlockInterface
public:
virtual void set_gnss_synchro(Gnss_Synchro* gnss_synchro) = 0;
virtual void set_channel(unsigned int channel_id) = 0;
virtual void set_channel_fsm(std::shared_ptr<ChannelFsm> channel_fsm) = 0;
virtual void set_channel_fsm(std::weak_ptr<ChannelFsm> channel_fsm) = 0;
virtual void set_threshold(float threshold) = 0;
virtual void set_doppler_max(unsigned int doppler_max) = 0;
virtual void set_doppler_step(unsigned int doppler_step) = 0;

View File

@ -2,11 +2,12 @@
* \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
* \author Marc Majoral 2019. mmajoral(at)cttc.es
* \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
@ -69,19 +70,17 @@ gnss_sdr_fpga_sample_counter::gnss_sdr_fpga_sample_counter(
interval_ms = _interval_ms;
fs = _fs;
samples_per_output = std::round(fs * static_cast<double>(interval_ms) / 1e3);
//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;
last_sample_counter = 0ULL;
current_T_rx_ms = 0;
current_s = 0;
current_m = 0;
current_h = 0;
current_days = 0;
report_interval_ms = 1000; // default reporting 1 second
report_interval_ms = 1000; // default reporting 1 second
samples_per_report = std::round(fs * static_cast<double>(report_interval_ms) / 1e3);
flag_enable_send_msg = false; // enable it for reporting time with asynchronous message
flag_m = false;
flag_h = false;
@ -105,11 +104,9 @@ gnss_sdr_fpga_sample_counter::~gnss_sdr_fpga_sample_counter()
}
// Called by gnuradio to enable drivers, etc for i/o devices.
// Called by GNU Radio to enable drivers, etc for i/o devices.
bool gnss_sdr_fpga_sample_counter::start()
{
//todo: place here the RE-INITIALIZATION routines. This function will be called by GNURadio at every start of the flowgraph.
// configure the number of samples per output in the FPGA and enable the interrupts
configure_samples_per_output(samples_per_output);
@ -118,11 +115,9 @@ bool gnss_sdr_fpga_sample_counter::start()
}
// Called by GNURadio to disable drivers, etc for i/o devices.
// Called by GNU Radio to disable drivers, etc for i/o devices.
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;
@ -194,65 +189,31 @@ void gnss_sdr_fpga_sample_counter::close_device()
}
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,
gr_vector_void_star &output_items)
{
//todo: Call here a function that waits for an interrupt. Do not open a thread,
//it must be a simple call to a BLOCKING function.
// The function will return the actual absolute sample count of the internal counter of the timmer.
// store the sample count in class member sample_counter
// Possible problem: what happen if the PS is overloaded and gnuradio does not call this function
// with the sufficient rate to catch all the interrupts in the counter. To be evaluated later.
wait_for_interrupt();
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
// 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
// variable number).
uint64_t sample_counter_tmp, sample_counter_msw_tmp;
sample_counter_tmp = map_base[0];
sample_counter_msw_tmp = map_base[1];
sample_counter_msw_tmp = sample_counter_msw_tmp << 32;
sample_counter_tmp = sample_counter_tmp + sample_counter_msw_tmp; // 2^32
sample_counter = sample_counter_tmp;
sample_counter = sample_counter + samples_passed; //samples_per_output;
auto *out = reinterpret_cast<Gnss_Synchro *>(output_items[0]);
out[0] = Gnss_Synchro();
out[0].Flag_valid_symbol_output = false;
out[0].Flag_valid_word = false;
out[0].Channel_ID = -1;
out[0].fs = fs;
if ((current_T_rx_ms % report_interval_ms) == 0)
if ((sample_counter - last_sample_counter) > samples_per_report)
{
last_sample_counter = sample_counter;
current_s++;
if ((current_s % 60) == 0)
{
@ -310,7 +271,25 @@ int gnss_sdr_fpga_sample_counter::general_work(int noutput_items __attribute__((
}
}
out[0].Tracking_sample_counter = sample_counter;
//current_T_rx_ms = (sample_counter * 1000) / samples_per_output;
current_T_rx_ms = interval_ms * (sample_counter) / samples_per_output;
return 1;
}
void gnss_sdr_fpga_sample_counter::wait_for_interrupt()
{
int32_t irq_count;
ssize_t nb;
// enable interrupts
int32_t reenable = 1;
write(fd, reinterpret_cast<void *>(&reenable), sizeof(int32_t));
// 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;
}
}

View File

@ -55,11 +55,15 @@ private:
void close_device(void);
void open_device(void);
bool start();
bool stop();
uint32_t wait_for_interrupt_and_read_counter(void);
void wait_for_interrupt(void);
uint32_t samples_per_output;
uint32_t samples_per_report;
double fs;
uint64_t sample_counter;
uint64_t last_sample_counter;
uint32_t interval_ms;
uint64_t current_T_rx_ms; // Receiver time in ms since the beginning of the run
uint32_t current_s; // Receiver time in seconds, modulo 60
@ -70,6 +74,7 @@ private:
bool flag_days; // True if the receiver has been running for at least 1 day
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

View File

@ -246,8 +246,8 @@ void GNSSFlowgraph::connect()
{
// 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();
DLOG(INFO) << "sig_source_.at(i)->get_right_block()->output_signature()->max_streams()=" << sig_source_.at(i)->get_right_block()->output_signature()->max_streams();
DLOG(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)
{
@ -443,10 +443,26 @@ void GNSSFlowgraph::connect()
{
// create a FIR low pass filter
std::vector<float> taps;
// float beta = 7.0;
// float halfband = 0.5;
// float fractional_bw = 0.4;
// float rate = 1.0 / static_cast<float>(decimation);
//
// float trans_width = rate * (halfband - fractional_bw);
// float mid_transition_band = rate * halfband - trans_width / 2.0;
//
// taps = gr::filter::firdes::low_pass(1.0,
// 1.0,
// mid_transition_band,
// trans_width,
// gr::filter::firdes::win_type::WIN_KAISER,
// beta);
taps = gr::filter::firdes::low_pass(1.0,
fs,
acq_fs / 2.1,
acq_fs / 10,
acq_fs / 2,
gr::filter::firdes::win_type::WIN_HAMMING);
gr::basic_block_sptr fir_filter_ccf_ = gr::filter::fir_filter_ccf::make(decimation, taps);

View File

@ -83,6 +83,7 @@ const int32_t GPS_L1_CA_HISTORY_DEEP = 100;
{ \
1, 0, 0, 0, 1, 0, 1, 1 \
}
const std::string GPS_CA_PREAMBLE = {"10001011"};
const int32_t GPS_CA_PREAMBLE_LENGTH_BITS = 8;
const int32_t GPS_CA_PREAMBLE_LENGTH_SYMBOLS = 160;
const double GPS_CA_PREAMBLE_DURATION_S = 0.160;

View File

@ -63,7 +63,13 @@ for channelNr = channelList
%% Plot all figures =======================================================
timeAxisInSeconds = (1:4:settings.msToProcess)/1000;
if isfield(trackResults(channelNr), 'prn_start_time_s')
timeAxis=trackResults(channelNr).prn_start_time_s;
time_label='RX Time (s)';
else
timeAxis = (1:length(trackResults(channelNr).PRN));
time_label='Epoch';
end
%----- Discrete-Time Scatter Plot ---------------------------------
plot(handles(1, 1), trackResults(channelNr).data_I,...
@ -77,29 +83,26 @@ for channelNr = channelList
ylabel(handles(1, 1), 'Q prompt');
%----- Nav bits ---------------------------------------------------
t = (1:length(trackResults(channelNr).data_I));
plot (handles(1, 2), t, ...
plot (handles(1, 2), timeAxis, ...
trackResults(channelNr).data_I);
grid (handles(1, 2));
title (handles(1, 2), 'Bits of the navigation message');
xlabel(handles(1, 2), 'Time (s)');
xlabel(handles(1, 2), time_label);
axis (handles(1, 2), 'tight');
%----- PLL discriminator unfiltered--------------------------------
t = (1:length(trackResults(channelNr).pllDiscr));
plot (handles(2, 1), t, ...
plot (handles(2, 1), timeAxis, ...
trackResults(channelNr).pllDiscr, 'r');
grid (handles(2, 1));
axis (handles(2, 1), 'tight');
xlabel(handles(2, 1), 'Time (s)');
xlabel(handles(2, 1), time_label);
ylabel(handles(2, 1), 'Amplitude');
title (handles(2, 1), 'Raw PLL discriminator');
%----- Correlation ------------------------------------------------
t = (1:length(trackResults(channelNr).I_VE));
plot(handles(2, 2), t, ...
plot(handles(2, 2), timeAxis, ...
[sqrt(trackResults(channelNr).I_VE.^2 + ...
trackResults(channelNr).Q_VE.^2)', ...
sqrt(trackResults(channelNr).I_E.^2 + ...
@ -114,7 +117,7 @@ for channelNr = channelList
grid (handles(2, 2));
title (handles(2, 2), 'Correlation results');
xlabel(handles(2, 2), 'Time (s)');
xlabel(handles(2, 2), time_label);
axis (handles(2, 2), 'tight');
hLegend = legend(handles(2, 2), '$\sqrt{I_{VE}^2 + Q_{VE}^2}$', ...
@ -127,35 +130,32 @@ for channelNr = channelList
set(hLegend, 'Interpreter', 'Latex');
%----- PLL discriminator filtered----------------------------------
t = (1:length(trackResults(channelNr).pllDiscrFilt));
plot (handles(3, 1), t, ...
plot (handles(3, 1), timeAxis, ...
trackResults(channelNr).pllDiscrFilt, 'b');
grid (handles(3, 1));
axis (handles(3, 1), 'tight');
xlabel(handles(3, 1), 'Time (s)');
xlabel(handles(3, 1), time_label);
ylabel(handles(3, 1), 'Amplitude');
title (handles(3, 1), 'Filtered PLL discriminator');
%----- DLL discriminator unfiltered--------------------------------
t = (1:length(trackResults(channelNr).dllDiscr));
plot (handles(3, 2), t, ...
plot (handles(3, 2), timeAxis, ...
trackResults(channelNr).dllDiscr, 'r');
grid (handles(3, 2));
axis (handles(3, 2), 'tight');
xlabel(handles(3, 2), 'Time (s)');
xlabel(handles(3, 2), time_label);
ylabel(handles(3, 2), 'Amplitude');
title (handles(3, 2), 'Raw DLL discriminator');
%----- DLL discriminator filtered----------------------------------
t = (1:length(trackResults(channelNr).dllDiscrFilt));
plot (handles(3, 3), t, ...
plot (handles(3, 3), timeAxis, ...
trackResults(channelNr).dllDiscrFilt, 'b');
grid (handles(3, 3));
axis (handles(3, 3), 'tight');
xlabel(handles(3, 3), 'Time (s)');
xlabel(handles(3, 3), time_label);
ylabel(handles(3, 3), 'Amplitude');
title (handles(3, 3), 'Filtered DLL discriminator');