mirror of
https://github.com/gnss-sdr/gnss-sdr
synced 2024-12-16 05:00:35 +00:00
Merge branch 'next' of https://github.com/gnss-sdr/gnss-sdr into next
This commit is contained in:
commit
0bbd8608ab
@ -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:
|
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:
|
and you can activate a certain version by typing:
|
||||||
|
@ -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("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)
|
gnsssdr_python_check_module("six - python 2 and 3 compatibility library" six "True" SIX_FOUND)
|
||||||
endif()
|
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()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -123,7 +123,7 @@ BeidouB1iPcpsAcquisition::BeidouB1iPcpsAcquisition(
|
|||||||
threshold_ = 0.0;
|
threshold_ = 0.0;
|
||||||
doppler_step_ = 0;
|
doppler_step_ = 0;
|
||||||
gnss_synchro_ = nullptr;
|
gnss_synchro_ = nullptr;
|
||||||
channel_fsm_ = nullptr;
|
|
||||||
if (in_streams_ > 1)
|
if (in_streams_ > 1)
|
||||||
{
|
{
|
||||||
LOG(ERROR) << "This implementation only supports one input stream";
|
LOG(ERROR) << "This implementation only supports one input stream";
|
||||||
|
@ -102,7 +102,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
* \brief Set channel fsm associated to this acquisition instance
|
* \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;
|
channel_fsm_ = channel_fsm;
|
||||||
acquisition_->set_channel_fsm(channel_fsm);
|
acquisition_->set_channel_fsm(channel_fsm);
|
||||||
@ -173,7 +173,7 @@ private:
|
|||||||
bool bit_transition_flag_;
|
bool bit_transition_flag_;
|
||||||
bool use_CFAR_algorithm_flag_;
|
bool use_CFAR_algorithm_flag_;
|
||||||
uint32_t channel_;
|
uint32_t channel_;
|
||||||
std::shared_ptr<ChannelFsm> channel_fsm_;
|
std::weak_ptr<ChannelFsm> channel_fsm_;
|
||||||
float threshold_;
|
float threshold_;
|
||||||
uint32_t doppler_max_;
|
uint32_t doppler_max_;
|
||||||
uint32_t doppler_step_;
|
uint32_t doppler_step_;
|
||||||
|
@ -121,7 +121,7 @@ BeidouB3iPcpsAcquisition::BeidouB3iPcpsAcquisition(
|
|||||||
threshold_ = 0.0;
|
threshold_ = 0.0;
|
||||||
doppler_step_ = 0;
|
doppler_step_ = 0;
|
||||||
gnss_synchro_ = nullptr;
|
gnss_synchro_ = nullptr;
|
||||||
channel_fsm_ = nullptr;
|
|
||||||
if (in_streams_ > 1)
|
if (in_streams_ > 1)
|
||||||
{
|
{
|
||||||
LOG(ERROR) << "This implementation only supports one input stream";
|
LOG(ERROR) << "This implementation only supports one input stream";
|
||||||
|
@ -101,7 +101,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
* \brief Set channel fsm associated to this acquisition instance
|
* \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;
|
channel_fsm_ = channel_fsm;
|
||||||
acquisition_->set_channel_fsm(channel_fsm);
|
acquisition_->set_channel_fsm(channel_fsm);
|
||||||
@ -172,7 +172,7 @@ private:
|
|||||||
bool bit_transition_flag_;
|
bool bit_transition_flag_;
|
||||||
bool use_CFAR_algorithm_flag_;
|
bool use_CFAR_algorithm_flag_;
|
||||||
unsigned int channel_;
|
unsigned int channel_;
|
||||||
std::shared_ptr<ChannelFsm> channel_fsm_;
|
std::weak_ptr<ChannelFsm> channel_fsm_;
|
||||||
float threshold_;
|
float threshold_;
|
||||||
unsigned int doppler_max_;
|
unsigned int doppler_max_;
|
||||||
unsigned int doppler_step_;
|
unsigned int doppler_step_;
|
||||||
|
@ -110,7 +110,7 @@ GalileoE1Pcps8msAmbiguousAcquisition::GalileoE1Pcps8msAmbiguousAcquisition(
|
|||||||
threshold_ = 0.0;
|
threshold_ = 0.0;
|
||||||
doppler_step_ = 0;
|
doppler_step_ = 0;
|
||||||
gnss_synchro_ = nullptr;
|
gnss_synchro_ = nullptr;
|
||||||
channel_fsm_ = nullptr;
|
|
||||||
if (in_streams_ > 1)
|
if (in_streams_ > 1)
|
||||||
{
|
{
|
||||||
LOG(ERROR) << "This implementation only supports one input stream";
|
LOG(ERROR) << "This implementation only supports one input stream";
|
||||||
|
@ -96,7 +96,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
* \brief Set channel fsm associated to this acquisition instance
|
* \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;
|
channel_fsm_ = channel_fsm;
|
||||||
acquisition_cc_->set_channel_fsm(channel_fsm);
|
acquisition_cc_->set_channel_fsm(channel_fsm);
|
||||||
@ -156,7 +156,7 @@ private:
|
|||||||
unsigned int vector_length_;
|
unsigned int vector_length_;
|
||||||
unsigned int code_length_;
|
unsigned int code_length_;
|
||||||
unsigned int channel_;
|
unsigned int channel_;
|
||||||
std::shared_ptr<ChannelFsm> channel_fsm_;
|
std::weak_ptr<ChannelFsm> channel_fsm_;
|
||||||
float threshold_;
|
float threshold_;
|
||||||
unsigned int doppler_max_;
|
unsigned int doppler_max_;
|
||||||
unsigned int doppler_step_;
|
unsigned int doppler_step_;
|
||||||
|
@ -154,7 +154,7 @@ GalileoE1PcpsAmbiguousAcquisition::GalileoE1PcpsAmbiguousAcquisition(
|
|||||||
threshold_ = 0.0;
|
threshold_ = 0.0;
|
||||||
doppler_step_ = 0;
|
doppler_step_ = 0;
|
||||||
gnss_synchro_ = nullptr;
|
gnss_synchro_ = nullptr;
|
||||||
channel_fsm_ = nullptr;
|
|
||||||
if (in_streams_ > 1)
|
if (in_streams_ > 1)
|
||||||
{
|
{
|
||||||
LOG(ERROR) << "This implementation only supports one input stream";
|
LOG(ERROR) << "This implementation only supports one input stream";
|
||||||
|
@ -100,7 +100,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
* \brief Set channel fsm associated to this acquisition instance
|
* \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;
|
channel_fsm_ = channel_fsm;
|
||||||
acquisition_->set_channel_fsm(channel_fsm);
|
acquisition_->set_channel_fsm(channel_fsm);
|
||||||
@ -171,7 +171,7 @@ private:
|
|||||||
bool use_CFAR_algorithm_flag_;
|
bool use_CFAR_algorithm_flag_;
|
||||||
bool acquire_pilot_;
|
bool acquire_pilot_;
|
||||||
unsigned int channel_;
|
unsigned int channel_;
|
||||||
std::shared_ptr<ChannelFsm> channel_fsm_;
|
std::weak_ptr<ChannelFsm> channel_fsm_;
|
||||||
float threshold_;
|
float threshold_;
|
||||||
unsigned int doppler_max_;
|
unsigned int doppler_max_;
|
||||||
unsigned int doppler_step_;
|
unsigned int doppler_step_;
|
||||||
|
@ -44,6 +44,13 @@
|
|||||||
#include <complex> // for complex
|
#include <complex> // for complex
|
||||||
#include <cstring> // for memcpy
|
#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(
|
GalileoE1PcpsAmbiguousAcquisitionFpga::GalileoE1PcpsAmbiguousAcquisitionFpga(
|
||||||
ConfigurationInterface* configuration,
|
ConfigurationInterface* configuration,
|
||||||
@ -67,7 +74,7 @@ GalileoE1PcpsAmbiguousAcquisitionFpga::GalileoE1PcpsAmbiguousAcquisitionFpga(
|
|||||||
acq_parameters.repeat_satellite = configuration_->property(role + ".repeat_satellite", false);
|
acq_parameters.repeat_satellite = configuration_->property(role + ".repeat_satellite", false);
|
||||||
DLOG(INFO) << role << " satellite repeat = " << acq_parameters.repeat_satellite;
|
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;
|
acq_parameters.downsampling_factor = downsampling_factor;
|
||||||
|
|
||||||
fs_in = fs_in / downsampling_factor;
|
fs_in = fs_in / downsampling_factor;
|
||||||
@ -97,15 +104,16 @@ GalileoE1PcpsAmbiguousAcquisitionFpga::GalileoE1PcpsAmbiguousAcquisitionFpga(
|
|||||||
acq_parameters.device_name = device_name;
|
acq_parameters.device_name = device_name;
|
||||||
acq_parameters.samples_per_ms = nsamples_total / sampled_ms;
|
acq_parameters.samples_per_ms = nsamples_total / sampled_ms;
|
||||||
acq_parameters.samples_per_code = nsamples_total;
|
acq_parameters.samples_per_code = nsamples_total;
|
||||||
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
|
// 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)
|
// a channel is assigned)
|
||||||
auto* fft_if = new gr::fft::fft_complex(nsamples_total, true); // Direct FFT
|
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* 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()));
|
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
|
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
|
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++)
|
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());
|
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)),
|
tmp = 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, 9) - 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.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
|
// 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);
|
acquisition_fpga_ = pcps_make_acquisition_fpga(acq_parameters);
|
||||||
|
|
||||||
channel_ = 0;
|
channel_ = 0;
|
||||||
doppler_step_ = 0;
|
doppler_step_ = 0;
|
||||||
gnss_synchro_ = nullptr;
|
gnss_synchro_ = nullptr;
|
||||||
channel_fsm_ = nullptr;
|
|
||||||
// temporary buffers that we can delete
|
// temporary buffers that we can delete
|
||||||
delete[] code;
|
delete[] code;
|
||||||
delete fft_if;
|
delete fft_if;
|
||||||
|
@ -99,7 +99,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
* \brief Set channel fsm associated to this acquisition instance
|
* \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;
|
channel_fsm_ = channel_fsm;
|
||||||
acquisition_fpga_->set_channel_fsm(channel_fsm);
|
acquisition_fpga_->set_channel_fsm(channel_fsm);
|
||||||
@ -157,7 +157,7 @@ private:
|
|||||||
pcps_acquisition_fpga_sptr acquisition_fpga_;
|
pcps_acquisition_fpga_sptr acquisition_fpga_;
|
||||||
bool acquire_pilot_;
|
bool acquire_pilot_;
|
||||||
uint32_t channel_;
|
uint32_t channel_;
|
||||||
std::shared_ptr<ChannelFsm> channel_fsm_;
|
std::weak_ptr<ChannelFsm> channel_fsm_;
|
||||||
uint32_t doppler_max_;
|
uint32_t doppler_max_;
|
||||||
uint32_t doppler_step_;
|
uint32_t doppler_step_;
|
||||||
std::string dump_filename_;
|
std::string dump_filename_;
|
||||||
@ -166,7 +166,7 @@ private:
|
|||||||
unsigned int in_streams_;
|
unsigned int in_streams_;
|
||||||
unsigned int out_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_ */
|
#endif /* GNSS_SDR_GALILEO_E1_PCPS_AMBIGUOUS_ACQUISITION_FPGA_H_ */
|
||||||
|
@ -111,7 +111,7 @@ GalileoE1PcpsCccwsrAmbiguousAcquisition::GalileoE1PcpsCccwsrAmbiguousAcquisition
|
|||||||
threshold_ = 0.0;
|
threshold_ = 0.0;
|
||||||
doppler_step_ = 0;
|
doppler_step_ = 0;
|
||||||
gnss_synchro_ = nullptr;
|
gnss_synchro_ = nullptr;
|
||||||
channel_fsm_ = nullptr;
|
|
||||||
if (in_streams_ > 1)
|
if (in_streams_ > 1)
|
||||||
{
|
{
|
||||||
LOG(ERROR) << "This implementation only supports one input stream";
|
LOG(ERROR) << "This implementation only supports one input stream";
|
||||||
|
@ -96,7 +96,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
* \brief Set channel fsm associated to this acquisition instance
|
* \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;
|
channel_fsm_ = channel_fsm;
|
||||||
acquisition_cc_->set_channel_fsm(channel_fsm);
|
acquisition_cc_->set_channel_fsm(channel_fsm);
|
||||||
@ -155,7 +155,7 @@ private:
|
|||||||
unsigned int code_length_;
|
unsigned int code_length_;
|
||||||
//unsigned int satellite_;
|
//unsigned int satellite_;
|
||||||
unsigned int channel_;
|
unsigned int channel_;
|
||||||
std::shared_ptr<ChannelFsm> channel_fsm_;
|
std::weak_ptr<ChannelFsm> channel_fsm_;
|
||||||
float threshold_;
|
float threshold_;
|
||||||
unsigned int doppler_max_;
|
unsigned int doppler_max_;
|
||||||
unsigned int doppler_step_;
|
unsigned int doppler_step_;
|
||||||
|
@ -144,7 +144,7 @@ GalileoE1PcpsQuickSyncAmbiguousAcquisition::GalileoE1PcpsQuickSyncAmbiguousAcqui
|
|||||||
threshold_ = 0.0;
|
threshold_ = 0.0;
|
||||||
doppler_step_ = 0;
|
doppler_step_ = 0;
|
||||||
gnss_synchro_ = nullptr;
|
gnss_synchro_ = nullptr;
|
||||||
channel_fsm_ = nullptr;
|
|
||||||
if (in_streams_ > 1)
|
if (in_streams_ > 1)
|
||||||
{
|
{
|
||||||
LOG(ERROR) << "This implementation only supports one input stream";
|
LOG(ERROR) << "This implementation only supports one input stream";
|
||||||
|
@ -97,7 +97,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
* \brief Set channel fsm associated to this acquisition instance
|
* \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;
|
channel_fsm_ = channel_fsm;
|
||||||
acquisition_cc_->set_channel_fsm(channel_fsm);
|
acquisition_cc_->set_channel_fsm(channel_fsm);
|
||||||
@ -159,7 +159,7 @@ private:
|
|||||||
unsigned int code_length_;
|
unsigned int code_length_;
|
||||||
bool bit_transition_flag_;
|
bool bit_transition_flag_;
|
||||||
unsigned int channel_;
|
unsigned int channel_;
|
||||||
std::shared_ptr<ChannelFsm> channel_fsm_;
|
std::weak_ptr<ChannelFsm> channel_fsm_;
|
||||||
float threshold_;
|
float threshold_;
|
||||||
unsigned int doppler_max_;
|
unsigned int doppler_max_;
|
||||||
unsigned int doppler_step_;
|
unsigned int doppler_step_;
|
||||||
|
@ -114,7 +114,7 @@ GalileoE1PcpsTongAmbiguousAcquisition::GalileoE1PcpsTongAmbiguousAcquisition(
|
|||||||
threshold_ = 0.0;
|
threshold_ = 0.0;
|
||||||
doppler_step_ = 0;
|
doppler_step_ = 0;
|
||||||
gnss_synchro_ = nullptr;
|
gnss_synchro_ = nullptr;
|
||||||
channel_fsm_ = nullptr;
|
|
||||||
if (in_streams_ > 1)
|
if (in_streams_ > 1)
|
||||||
{
|
{
|
||||||
LOG(ERROR) << "This implementation only supports one input stream";
|
LOG(ERROR) << "This implementation only supports one input stream";
|
||||||
|
@ -96,7 +96,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
* \brief Set channel fsm associated to this acquisition instance
|
* \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;
|
channel_fsm_ = channel_fsm;
|
||||||
acquisition_cc_->set_channel_fsm(channel_fsm);
|
acquisition_cc_->set_channel_fsm(channel_fsm);
|
||||||
@ -157,7 +157,7 @@ private:
|
|||||||
unsigned int vector_length_;
|
unsigned int vector_length_;
|
||||||
unsigned int code_length_;
|
unsigned int code_length_;
|
||||||
unsigned int channel_;
|
unsigned int channel_;
|
||||||
std::shared_ptr<ChannelFsm> channel_fsm_;
|
std::weak_ptr<ChannelFsm> channel_fsm_;
|
||||||
float threshold_;
|
float threshold_;
|
||||||
unsigned int doppler_max_;
|
unsigned int doppler_max_;
|
||||||
unsigned int doppler_step_;
|
unsigned int doppler_step_;
|
||||||
|
@ -119,7 +119,7 @@ GalileoE5aNoncoherentIQAcquisitionCaf::GalileoE5aNoncoherentIQAcquisitionCaf(
|
|||||||
threshold_ = 0.0;
|
threshold_ = 0.0;
|
||||||
doppler_step_ = 0;
|
doppler_step_ = 0;
|
||||||
gnss_synchro_ = nullptr;
|
gnss_synchro_ = nullptr;
|
||||||
channel_fsm_ = nullptr;
|
|
||||||
if (in_streams_ > 1)
|
if (in_streams_ > 1)
|
||||||
{
|
{
|
||||||
LOG(ERROR) << "This implementation only supports one input stream";
|
LOG(ERROR) << "This implementation only supports one input stream";
|
||||||
|
@ -97,7 +97,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
* \brief Set channel fsm associated to this acquisition instance
|
* \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;
|
channel_fsm_ = channel_fsm;
|
||||||
acquisition_cc_->set_channel_fsm(channel_fsm);
|
acquisition_cc_->set_channel_fsm(channel_fsm);
|
||||||
@ -160,7 +160,7 @@ private:
|
|||||||
unsigned int code_length_;
|
unsigned int code_length_;
|
||||||
bool bit_transition_flag_;
|
bool bit_transition_flag_;
|
||||||
unsigned int channel_;
|
unsigned int channel_;
|
||||||
std::shared_ptr<ChannelFsm> channel_fsm_;
|
std::weak_ptr<ChannelFsm> channel_fsm_;
|
||||||
float threshold_;
|
float threshold_;
|
||||||
unsigned int doppler_max_;
|
unsigned int doppler_max_;
|
||||||
unsigned int doppler_step_;
|
unsigned int doppler_step_;
|
||||||
|
@ -152,7 +152,7 @@ GalileoE5aPcpsAcquisition::GalileoE5aPcpsAcquisition(ConfigurationInterface* con
|
|||||||
threshold_ = 0.0;
|
threshold_ = 0.0;
|
||||||
doppler_step_ = 0;
|
doppler_step_ = 0;
|
||||||
gnss_synchro_ = nullptr;
|
gnss_synchro_ = nullptr;
|
||||||
channel_fsm_ = nullptr;
|
|
||||||
if (in_streams_ > 1)
|
if (in_streams_ > 1)
|
||||||
{
|
{
|
||||||
LOG(ERROR) << "This implementation only supports one input stream";
|
LOG(ERROR) << "This implementation only supports one input stream";
|
||||||
|
@ -88,7 +88,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
* \brief Set channel fsm associated to this acquisition instance
|
* \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;
|
channel_fsm_ = channel_fsm;
|
||||||
acquisition_->set_channel_fsm(channel_fsm);
|
acquisition_->set_channel_fsm(channel_fsm);
|
||||||
@ -169,7 +169,7 @@ private:
|
|||||||
unsigned int vector_length_;
|
unsigned int vector_length_;
|
||||||
unsigned int code_length_;
|
unsigned int code_length_;
|
||||||
unsigned int channel_;
|
unsigned int channel_;
|
||||||
std::shared_ptr<ChannelFsm> channel_fsm_;
|
std::weak_ptr<ChannelFsm> channel_fsm_;
|
||||||
unsigned int doppler_max_;
|
unsigned int doppler_max_;
|
||||||
unsigned int doppler_step_;
|
unsigned int doppler_step_;
|
||||||
unsigned int sampled_ms_;
|
unsigned int sampled_ms_;
|
||||||
|
@ -44,6 +44,13 @@
|
|||||||
#include <complex> // for complex
|
#include <complex> // for complex
|
||||||
#include <cstring> // for strcpy, memcpy
|
#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,
|
GalileoE5aPcpsAcquisitionFpga::GalileoE5aPcpsAcquisitionFpga(ConfigurationInterface* configuration,
|
||||||
const std::string& role,
|
const std::string& role,
|
||||||
@ -64,7 +71,7 @@ GalileoE5aPcpsAcquisitionFpga::GalileoE5aPcpsAcquisitionFpga(ConfigurationInterf
|
|||||||
acq_parameters.repeat_satellite = configuration_->property(role + ".repeat_satellite", false);
|
acq_parameters.repeat_satellite = configuration_->property(role + ".repeat_satellite", false);
|
||||||
DLOG(INFO) << role << " satellite repeat = " << acq_parameters.repeat_satellite;
|
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;
|
acq_parameters.downsampling_factor = downsampling_factor;
|
||||||
fs_in = fs_in / 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_ms = nsamples_total / sampled_ms;
|
||||||
acq_parameters.samples_per_code = nsamples_total;
|
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
|
// 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)
|
// a channel is assigned)
|
||||||
auto* fft_if = new gr::fft::fft_complex(nsamples_total, true); // Direct FFT
|
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* 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()));
|
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
|
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
|
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++)
|
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());
|
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)),
|
tmp = 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, 9) - 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.all_fft_codes = d_all_fft_codes_;
|
||||||
|
|
||||||
// reference for the FPGA FFT-IFFT attenuation factor
|
// 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);
|
acquisition_fpga_ = pcps_make_acquisition_fpga(acq_parameters);
|
||||||
|
|
||||||
channel_ = 0;
|
channel_ = 0;
|
||||||
doppler_step_ = 0;
|
doppler_step_ = 0;
|
||||||
gnss_synchro_ = nullptr;
|
gnss_synchro_ = nullptr;
|
||||||
channel_fsm_ = nullptr;
|
|
||||||
// temporary buffers that we can delete
|
// temporary buffers that we can delete
|
||||||
delete[] code;
|
delete[] code;
|
||||||
delete fft_if;
|
delete fft_if;
|
||||||
|
@ -101,7 +101,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
* \brief Set channel fsm associated to this acquisition instance
|
* \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;
|
channel_fsm_ = channel_fsm;
|
||||||
acquisition_fpga_->set_channel_fsm(channel_fsm);
|
acquisition_fpga_->set_channel_fsm(channel_fsm);
|
||||||
@ -176,7 +176,7 @@ private:
|
|||||||
bool acq_iq_;
|
bool acq_iq_;
|
||||||
|
|
||||||
uint32_t channel_;
|
uint32_t channel_;
|
||||||
std::shared_ptr<ChannelFsm> channel_fsm_;
|
std::weak_ptr<ChannelFsm> channel_fsm_;
|
||||||
uint32_t doppler_max_;
|
uint32_t doppler_max_;
|
||||||
uint32_t doppler_step_;
|
uint32_t doppler_step_;
|
||||||
unsigned int in_streams_;
|
unsigned int in_streams_;
|
||||||
@ -184,7 +184,7 @@ private:
|
|||||||
|
|
||||||
Gnss_Synchro* gnss_synchro_;
|
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_ */
|
#endif /* GNSS_SDR_GALILEO_E5A_PCPS_ACQUISITION_FPGA_H_ */
|
||||||
|
@ -125,7 +125,7 @@ GlonassL1CaPcpsAcquisition::GlonassL1CaPcpsAcquisition(
|
|||||||
threshold_ = 0.0;
|
threshold_ = 0.0;
|
||||||
doppler_step_ = 0;
|
doppler_step_ = 0;
|
||||||
gnss_synchro_ = nullptr;
|
gnss_synchro_ = nullptr;
|
||||||
channel_fsm_ = nullptr;
|
|
||||||
if (in_streams_ > 1)
|
if (in_streams_ > 1)
|
||||||
{
|
{
|
||||||
LOG(ERROR) << "This implementation only supports one input stream";
|
LOG(ERROR) << "This implementation only supports one input stream";
|
||||||
|
@ -98,7 +98,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
* \brief Set channel fsm associated to this acquisition instance
|
* \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;
|
channel_fsm_ = channel_fsm;
|
||||||
acquisition_->set_channel_fsm(channel_fsm);
|
acquisition_->set_channel_fsm(channel_fsm);
|
||||||
@ -162,7 +162,7 @@ private:
|
|||||||
bool bit_transition_flag_;
|
bool bit_transition_flag_;
|
||||||
bool use_CFAR_algorithm_flag_;
|
bool use_CFAR_algorithm_flag_;
|
||||||
unsigned int channel_;
|
unsigned int channel_;
|
||||||
std::shared_ptr<ChannelFsm> channel_fsm_;
|
std::weak_ptr<ChannelFsm> channel_fsm_;
|
||||||
float threshold_;
|
float threshold_;
|
||||||
unsigned int doppler_max_;
|
unsigned int doppler_max_;
|
||||||
unsigned int doppler_step_;
|
unsigned int doppler_step_;
|
||||||
|
@ -124,7 +124,7 @@ GlonassL2CaPcpsAcquisition::GlonassL2CaPcpsAcquisition(
|
|||||||
threshold_ = 0.0;
|
threshold_ = 0.0;
|
||||||
doppler_step_ = 0;
|
doppler_step_ = 0;
|
||||||
gnss_synchro_ = nullptr;
|
gnss_synchro_ = nullptr;
|
||||||
channel_fsm_ = nullptr;
|
|
||||||
if (in_streams_ > 1)
|
if (in_streams_ > 1)
|
||||||
{
|
{
|
||||||
LOG(ERROR) << "This implementation only supports one input stream";
|
LOG(ERROR) << "This implementation only supports one input stream";
|
||||||
|
@ -98,7 +98,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
* \brief Set channel fsm associated to this acquisition instance
|
* \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;
|
channel_fsm_ = channel_fsm;
|
||||||
acquisition_->set_channel_fsm(channel_fsm);
|
acquisition_->set_channel_fsm(channel_fsm);
|
||||||
@ -162,7 +162,7 @@ private:
|
|||||||
bool bit_transition_flag_;
|
bool bit_transition_flag_;
|
||||||
bool use_CFAR_algorithm_flag_;
|
bool use_CFAR_algorithm_flag_;
|
||||||
unsigned int channel_;
|
unsigned int channel_;
|
||||||
std::shared_ptr<ChannelFsm> channel_fsm_;
|
std::weak_ptr<ChannelFsm> channel_fsm_;
|
||||||
float threshold_;
|
float threshold_;
|
||||||
unsigned int doppler_max_;
|
unsigned int doppler_max_;
|
||||||
unsigned int doppler_step_;
|
unsigned int doppler_step_;
|
||||||
|
@ -147,7 +147,7 @@ GpsL1CaPcpsAcquisition::GpsL1CaPcpsAcquisition(
|
|||||||
threshold_ = 0.0;
|
threshold_ = 0.0;
|
||||||
doppler_step_ = 0;
|
doppler_step_ = 0;
|
||||||
gnss_synchro_ = nullptr;
|
gnss_synchro_ = nullptr;
|
||||||
channel_fsm_ = nullptr;
|
|
||||||
if (in_streams_ > 1)
|
if (in_streams_ > 1)
|
||||||
{
|
{
|
||||||
LOG(ERROR) << "This implementation only supports one input stream";
|
LOG(ERROR) << "This implementation only supports one input stream";
|
||||||
|
@ -104,7 +104,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
* \brief Set channel fsm associated to this acquisition instance
|
* \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;
|
channel_fsm_ = channel_fsm;
|
||||||
acquisition_->set_channel_fsm(channel_fsm);
|
acquisition_->set_channel_fsm(channel_fsm);
|
||||||
@ -174,7 +174,7 @@ private:
|
|||||||
bool bit_transition_flag_;
|
bool bit_transition_flag_;
|
||||||
bool use_CFAR_algorithm_flag_;
|
bool use_CFAR_algorithm_flag_;
|
||||||
unsigned int channel_;
|
unsigned int channel_;
|
||||||
std::shared_ptr<ChannelFsm> channel_fsm_;
|
std::weak_ptr<ChannelFsm> channel_fsm_;
|
||||||
float threshold_;
|
float threshold_;
|
||||||
unsigned int doppler_max_;
|
unsigned int doppler_max_;
|
||||||
unsigned int doppler_step_;
|
unsigned int doppler_step_;
|
||||||
|
@ -97,7 +97,7 @@ GpsL1CaPcpsAcquisitionFineDoppler::GpsL1CaPcpsAcquisitionFineDoppler(
|
|||||||
threshold_ = 0.0;
|
threshold_ = 0.0;
|
||||||
doppler_step_ = 0;
|
doppler_step_ = 0;
|
||||||
gnss_synchro_ = nullptr;
|
gnss_synchro_ = nullptr;
|
||||||
channel_fsm_ = nullptr;
|
|
||||||
if (in_streams_ > 1)
|
if (in_streams_ > 1)
|
||||||
{
|
{
|
||||||
LOG(ERROR) << "This implementation only supports one input stream";
|
LOG(ERROR) << "This implementation only supports one input stream";
|
||||||
|
@ -97,7 +97,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
* \brief Set channel fsm associated to this acquisition instance
|
* \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;
|
channel_fsm_ = channel_fsm;
|
||||||
acquisition_cc_->set_channel_fsm(channel_fsm);
|
acquisition_cc_->set_channel_fsm(channel_fsm);
|
||||||
@ -152,7 +152,7 @@ private:
|
|||||||
std::string item_type_;
|
std::string item_type_;
|
||||||
unsigned int vector_length_;
|
unsigned int vector_length_;
|
||||||
unsigned int channel_;
|
unsigned int channel_;
|
||||||
std::shared_ptr<ChannelFsm> channel_fsm_;
|
std::weak_ptr<ChannelFsm> channel_fsm_;
|
||||||
float threshold_;
|
float threshold_;
|
||||||
int doppler_max_;
|
int doppler_max_;
|
||||||
unsigned int doppler_step_;
|
unsigned int doppler_step_;
|
||||||
|
@ -47,9 +47,15 @@
|
|||||||
#include <complex> // for complex
|
#include <complex> // for complex
|
||||||
#include <cstring> // for memcpy
|
#include <cstring> // for memcpy
|
||||||
|
|
||||||
|
|
||||||
#define NUM_PRNs 32
|
#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(
|
GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga(
|
||||||
ConfigurationInterface* configuration,
|
ConfigurationInterface* configuration,
|
||||||
@ -71,9 +77,8 @@ GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga(
|
|||||||
acq_parameters.repeat_satellite = configuration_->property(role + ".repeat_satellite", false);
|
acq_parameters.repeat_satellite = configuration_->property(role + ".repeat_satellite", false);
|
||||||
DLOG(INFO) << role << " satellite repeat = " << acq_parameters.repeat_satellite;
|
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;
|
acq_parameters.downsampling_factor = downsampling_factor;
|
||||||
|
|
||||||
fs_in = fs_in / downsampling_factor;
|
fs_in = fs_in / downsampling_factor;
|
||||||
|
|
||||||
acq_parameters.fs_in = fs_in;
|
acq_parameters.fs_in = fs_in;
|
||||||
@ -94,7 +99,7 @@ GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga(
|
|||||||
acq_parameters.device_name = device_name;
|
acq_parameters.device_name = device_name;
|
||||||
acq_parameters.samples_per_ms = nsamples_total / sampled_ms;
|
acq_parameters.samples_per_ms = nsamples_total / sampled_ms;
|
||||||
acq_parameters.samples_per_code = nsamples_total;
|
acq_parameters.samples_per_code = nsamples_total;
|
||||||
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
|
// 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)
|
// a channel is assigned)
|
||||||
@ -102,8 +107,10 @@ GpsL1CaPcpsAcquisitionFpga::GpsL1CaPcpsAcquisitionFpga(
|
|||||||
// allocate memory to compute all the PRNs and compute all the possible codes
|
// 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* 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()));
|
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
|
float max;
|
||||||
|
int32_t tmp, tmp2, local_code, fft_data;
|
||||||
|
// temporary maxima search
|
||||||
for (uint32_t PRN = 1; PRN <= NUM_PRNs; PRN++)
|
for (uint32_t PRN = 1; PRN <= NUM_PRNs; PRN++)
|
||||||
{
|
{
|
||||||
gps_l1_ca_code_gen_complex_sampled(code, PRN, fs_in, 0); // generate PRN code
|
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());
|
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)),
|
tmp = 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, 9) - 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_;
|
acq_parameters.all_fft_codes = d_all_fft_codes_;
|
||||||
|
|
||||||
// reference for the FPGA FFT-IFFT attenuation factor
|
// 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);
|
acquisition_fpga_ = pcps_make_acquisition_fpga(acq_parameters);
|
||||||
|
|
||||||
channel_ = 0;
|
channel_ = 0;
|
||||||
doppler_step_ = 0;
|
doppler_step_ = 0;
|
||||||
gnss_synchro_ = nullptr;
|
gnss_synchro_ = nullptr;
|
||||||
channel_fsm_ = nullptr;
|
|
||||||
// temporary buffers that we can delete
|
// temporary buffers that we can delete
|
||||||
delete[] code;
|
delete[] code;
|
||||||
delete fft_if;
|
delete fft_if;
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
#ifndef GNSS_SDR_GPS_L1_CA_PCPS_ACQUISITION_FPGA_H_
|
#ifndef GNSS_SDR_GPS_L1_CA_PCPS_ACQUISITION_FPGA_H_
|
||||||
#define GNSS_SDR_GPS_L1_CA_PCPS_ACQUISITION_FPGA_H_
|
#define GNSS_SDR_GPS_L1_CA_PCPS_ACQUISITION_FPGA_H_
|
||||||
|
|
||||||
|
|
||||||
#include "channel_fsm.h"
|
#include "channel_fsm.h"
|
||||||
#include "pcps_acquisition_fpga.h"
|
#include "pcps_acquisition_fpga.h"
|
||||||
#include <gnuradio/runtime_types.h> // for basic_block_sptr, top_block_sptr
|
#include <gnuradio/runtime_types.h> // for basic_block_sptr, top_block_sptr
|
||||||
@ -102,7 +103,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
* \brief Set channel fsm associated to this acquisition instance
|
* \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;
|
channel_fsm_ = channel_fsm;
|
||||||
acquisition_fpga_->set_channel_fsm(channel_fsm);
|
acquisition_fpga_->set_channel_fsm(channel_fsm);
|
||||||
@ -159,14 +160,14 @@ private:
|
|||||||
ConfigurationInterface* configuration_;
|
ConfigurationInterface* configuration_;
|
||||||
pcps_acquisition_fpga_sptr acquisition_fpga_;
|
pcps_acquisition_fpga_sptr acquisition_fpga_;
|
||||||
uint32_t channel_;
|
uint32_t channel_;
|
||||||
std::shared_ptr<ChannelFsm> channel_fsm_;
|
std::weak_ptr<ChannelFsm> channel_fsm_;
|
||||||
uint32_t doppler_max_;
|
uint32_t doppler_max_;
|
||||||
uint32_t doppler_step_;
|
uint32_t doppler_step_;
|
||||||
Gnss_Synchro* gnss_synchro_;
|
Gnss_Synchro* gnss_synchro_;
|
||||||
std::string role_;
|
std::string role_;
|
||||||
unsigned int in_streams_;
|
unsigned int in_streams_;
|
||||||
unsigned int out_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_ */
|
#endif /* GNSS_SDR_GPS_L1_CA_PCPS_ACQUISITION_FPGA_H_ */
|
||||||
|
@ -89,7 +89,7 @@ GpsL1CaPcpsAssistedAcquisition::GpsL1CaPcpsAssistedAcquisition(
|
|||||||
threshold_ = 0.0;
|
threshold_ = 0.0;
|
||||||
doppler_step_ = 0;
|
doppler_step_ = 0;
|
||||||
gnss_synchro_ = nullptr;
|
gnss_synchro_ = nullptr;
|
||||||
channel_fsm_ = nullptr;
|
|
||||||
if (in_streams_ > 1)
|
if (in_streams_ > 1)
|
||||||
{
|
{
|
||||||
LOG(ERROR) << "This implementation only supports one input stream";
|
LOG(ERROR) << "This implementation only supports one input stream";
|
||||||
|
@ -97,7 +97,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
* \brief Set channel fsm associated to this acquisition instance
|
* \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;
|
channel_fsm_ = channel_fsm;
|
||||||
acquisition_cc_->set_channel_fsm(channel_fsm);
|
acquisition_cc_->set_channel_fsm(channel_fsm);
|
||||||
@ -149,7 +149,7 @@ private:
|
|||||||
unsigned int vector_length_;
|
unsigned int vector_length_;
|
||||||
//unsigned int satellite_;
|
//unsigned int satellite_;
|
||||||
unsigned int channel_;
|
unsigned int channel_;
|
||||||
std::shared_ptr<ChannelFsm> channel_fsm_;
|
std::weak_ptr<ChannelFsm> channel_fsm_;
|
||||||
float threshold_;
|
float threshold_;
|
||||||
int doppler_max_;
|
int doppler_max_;
|
||||||
unsigned int doppler_step_;
|
unsigned int doppler_step_;
|
||||||
|
@ -105,7 +105,7 @@ GpsL1CaPcpsOpenClAcquisition::GpsL1CaPcpsOpenClAcquisition(
|
|||||||
threshold_ = 0.0;
|
threshold_ = 0.0;
|
||||||
doppler_step_ = 0;
|
doppler_step_ = 0;
|
||||||
gnss_synchro_ = nullptr;
|
gnss_synchro_ = nullptr;
|
||||||
channel_fsm_ = nullptr;
|
|
||||||
if (in_streams_ > 1)
|
if (in_streams_ > 1)
|
||||||
{
|
{
|
||||||
LOG(ERROR) << "This implementation only supports one input stream";
|
LOG(ERROR) << "This implementation only supports one input stream";
|
||||||
|
@ -96,7 +96,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
* \brief Set channel fsm associated to this acquisition instance
|
* \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;
|
channel_fsm_ = channel_fsm;
|
||||||
acquisition_cc_->set_channel_fsm(channel_fsm);
|
acquisition_cc_->set_channel_fsm(channel_fsm);
|
||||||
@ -154,7 +154,7 @@ private:
|
|||||||
unsigned int code_length_;
|
unsigned int code_length_;
|
||||||
bool bit_transition_flag_;
|
bool bit_transition_flag_;
|
||||||
unsigned int channel_;
|
unsigned int channel_;
|
||||||
std::shared_ptr<ChannelFsm> channel_fsm_;
|
std::weak_ptr<ChannelFsm> channel_fsm_;
|
||||||
float threshold_;
|
float threshold_;
|
||||||
unsigned int doppler_max_;
|
unsigned int doppler_max_;
|
||||||
unsigned int doppler_step_;
|
unsigned int doppler_step_;
|
||||||
|
@ -137,7 +137,7 @@ GpsL1CaPcpsQuickSyncAcquisition::GpsL1CaPcpsQuickSyncAcquisition(
|
|||||||
threshold_ = 0.0;
|
threshold_ = 0.0;
|
||||||
doppler_step_ = 0;
|
doppler_step_ = 0;
|
||||||
gnss_synchro_ = nullptr;
|
gnss_synchro_ = nullptr;
|
||||||
channel_fsm_ = nullptr;
|
|
||||||
if (in_streams_ > 1)
|
if (in_streams_ > 1)
|
||||||
{
|
{
|
||||||
LOG(ERROR) << "This implementation only supports one input stream";
|
LOG(ERROR) << "This implementation only supports one input stream";
|
||||||
|
@ -98,7 +98,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
* \brief Set channel fsm associated to this acquisition instance
|
* \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;
|
channel_fsm_ = channel_fsm;
|
||||||
acquisition_cc_->set_channel_fsm(channel_fsm);
|
acquisition_cc_->set_channel_fsm(channel_fsm);
|
||||||
@ -160,7 +160,7 @@ private:
|
|||||||
unsigned int code_length_;
|
unsigned int code_length_;
|
||||||
bool bit_transition_flag_;
|
bool bit_transition_flag_;
|
||||||
unsigned int channel_;
|
unsigned int channel_;
|
||||||
std::shared_ptr<ChannelFsm> channel_fsm_;
|
std::weak_ptr<ChannelFsm> channel_fsm_;
|
||||||
float threshold_;
|
float threshold_;
|
||||||
unsigned int doppler_max_;
|
unsigned int doppler_max_;
|
||||||
unsigned int doppler_step_;
|
unsigned int doppler_step_;
|
||||||
|
@ -99,7 +99,7 @@ GpsL1CaPcpsTongAcquisition::GpsL1CaPcpsTongAcquisition(
|
|||||||
threshold_ = 0.0;
|
threshold_ = 0.0;
|
||||||
doppler_step_ = 0;
|
doppler_step_ = 0;
|
||||||
gnss_synchro_ = nullptr;
|
gnss_synchro_ = nullptr;
|
||||||
channel_fsm_ = nullptr;
|
|
||||||
if (in_streams_ > 1)
|
if (in_streams_ > 1)
|
||||||
{
|
{
|
||||||
LOG(ERROR) << "This implementation only supports one input stream";
|
LOG(ERROR) << "This implementation only supports one input stream";
|
||||||
|
@ -97,7 +97,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
* \brief Set channel fsm associated to this acquisition instance
|
* \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;
|
channel_fsm_ = channel_fsm;
|
||||||
acquisition_cc_->set_channel_fsm(channel_fsm);
|
acquisition_cc_->set_channel_fsm(channel_fsm);
|
||||||
@ -158,7 +158,7 @@ private:
|
|||||||
unsigned int vector_length_;
|
unsigned int vector_length_;
|
||||||
unsigned int code_length_;
|
unsigned int code_length_;
|
||||||
unsigned int channel_;
|
unsigned int channel_;
|
||||||
std::shared_ptr<ChannelFsm> channel_fsm_;
|
std::weak_ptr<ChannelFsm> channel_fsm_;
|
||||||
float threshold_;
|
float threshold_;
|
||||||
unsigned int doppler_max_;
|
unsigned int doppler_max_;
|
||||||
unsigned int doppler_step_;
|
unsigned int doppler_step_;
|
||||||
|
@ -151,7 +151,7 @@ GpsL2MPcpsAcquisition::GpsL2MPcpsAcquisition(
|
|||||||
threshold_ = 0.0;
|
threshold_ = 0.0;
|
||||||
doppler_step_ = 0;
|
doppler_step_ = 0;
|
||||||
gnss_synchro_ = nullptr;
|
gnss_synchro_ = nullptr;
|
||||||
channel_fsm_ = nullptr;
|
|
||||||
num_codes_ = acq_parameters_.sampled_ms / acq_parameters_.ms_per_code;
|
num_codes_ = acq_parameters_.sampled_ms / acq_parameters_.ms_per_code;
|
||||||
if (in_streams_ > 1)
|
if (in_streams_ > 1)
|
||||||
{
|
{
|
||||||
|
@ -101,7 +101,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
* \brief Set channel fsm associated to this acquisition instance
|
* \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;
|
channel_fsm_ = channel_fsm;
|
||||||
acquisition_->set_channel_fsm(channel_fsm);
|
acquisition_->set_channel_fsm(channel_fsm);
|
||||||
@ -171,7 +171,7 @@ private:
|
|||||||
bool bit_transition_flag_;
|
bool bit_transition_flag_;
|
||||||
bool use_CFAR_algorithm_flag_;
|
bool use_CFAR_algorithm_flag_;
|
||||||
unsigned int channel_;
|
unsigned int channel_;
|
||||||
std::shared_ptr<ChannelFsm> channel_fsm_;
|
std::weak_ptr<ChannelFsm> channel_fsm_;
|
||||||
float threshold_;
|
float threshold_;
|
||||||
unsigned int doppler_max_;
|
unsigned int doppler_max_;
|
||||||
unsigned int doppler_step_;
|
unsigned int doppler_step_;
|
||||||
|
@ -47,7 +47,11 @@
|
|||||||
#include <cstring> // for memcpy
|
#include <cstring> // for memcpy
|
||||||
|
|
||||||
#define NUM_PRNs 32
|
#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(
|
GpsL2MPcpsAcquisitionFpga::GpsL2MPcpsAcquisitionFpga(
|
||||||
ConfigurationInterface* configuration,
|
ConfigurationInterface* configuration,
|
||||||
@ -102,8 +106,11 @@ GpsL2MPcpsAcquisitionFpga::GpsL2MPcpsAcquisitionFpga(
|
|||||||
// allocate memory to compute all the PRNs and compute all the possible codes
|
// 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* 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()));
|
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 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
|
float max; // temporary maxima search
|
||||||
|
int32_t tmp, tmp2, local_code, fft_data;
|
||||||
|
|
||||||
for (unsigned int PRN = 1; PRN <= NUM_PRNs; PRN++)
|
for (unsigned int PRN = 1; PRN <= NUM_PRNs; PRN++)
|
||||||
{
|
{
|
||||||
gps_l2c_m_code_gen_complex_sampled(code, PRN, fs_in_);
|
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());
|
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)),
|
tmp = static_cast<int32_t>(floor(fft_codes_padded[i].real() * (pow(2, QUANT_BITS_LOCAL_CODE - 1) - 1) / max));
|
||||||
static_cast<int>(floor(fft_codes_padded[i].imag() * (pow(2, 7) - 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;
|
channel_ = 0;
|
||||||
doppler_step_ = 0;
|
doppler_step_ = 0;
|
||||||
gnss_synchro_ = nullptr;
|
gnss_synchro_ = nullptr;
|
||||||
channel_fsm_ = nullptr;
|
|
||||||
|
|
||||||
threshold_ = 0.0;
|
threshold_ = 0.0;
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
* \brief Set channel fsm associated to this acquisition instance
|
* \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;
|
channel_fsm_ = channel_fsm;
|
||||||
acquisition_fpga_->set_channel_fsm(channel_fsm);
|
acquisition_fpga_->set_channel_fsm(channel_fsm);
|
||||||
@ -158,7 +158,7 @@ private:
|
|||||||
pcps_acquisition_fpga_sptr acquisition_fpga_;
|
pcps_acquisition_fpga_sptr acquisition_fpga_;
|
||||||
std::string item_type_;
|
std::string item_type_;
|
||||||
unsigned int channel_;
|
unsigned int channel_;
|
||||||
std::shared_ptr<ChannelFsm> channel_fsm_;
|
std::weak_ptr<ChannelFsm> channel_fsm_;
|
||||||
float threshold_;
|
float threshold_;
|
||||||
unsigned int doppler_max_;
|
unsigned int doppler_max_;
|
||||||
unsigned int doppler_step_;
|
unsigned int doppler_step_;
|
||||||
@ -169,7 +169,7 @@ private:
|
|||||||
unsigned int in_streams_;
|
unsigned int in_streams_;
|
||||||
unsigned int out_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);
|
//float calculate_threshold(float pfa);
|
||||||
};
|
};
|
||||||
|
@ -147,7 +147,7 @@ GpsL5iPcpsAcquisition::GpsL5iPcpsAcquisition(
|
|||||||
threshold_ = 0.0;
|
threshold_ = 0.0;
|
||||||
doppler_step_ = 0;
|
doppler_step_ = 0;
|
||||||
gnss_synchro_ = nullptr;
|
gnss_synchro_ = nullptr;
|
||||||
channel_fsm_ = nullptr;
|
|
||||||
if (in_streams_ > 1)
|
if (in_streams_ > 1)
|
||||||
{
|
{
|
||||||
LOG(ERROR) << "This implementation only supports one input stream";
|
LOG(ERROR) << "This implementation only supports one input stream";
|
||||||
|
@ -101,7 +101,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
* \brief Set channel fsm associated to this acquisition instance
|
* \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;
|
channel_fsm_ = channel_fsm;
|
||||||
acquisition_->set_channel_fsm(channel_fsm);
|
acquisition_->set_channel_fsm(channel_fsm);
|
||||||
@ -170,7 +170,7 @@ private:
|
|||||||
bool bit_transition_flag_;
|
bool bit_transition_flag_;
|
||||||
bool use_CFAR_algorithm_flag_;
|
bool use_CFAR_algorithm_flag_;
|
||||||
unsigned int channel_;
|
unsigned int channel_;
|
||||||
std::shared_ptr<ChannelFsm> channel_fsm_;
|
std::weak_ptr<ChannelFsm> channel_fsm_;
|
||||||
float threshold_;
|
float threshold_;
|
||||||
unsigned int doppler_max_;
|
unsigned int doppler_max_;
|
||||||
unsigned int doppler_step_;
|
unsigned int doppler_step_;
|
||||||
|
@ -49,6 +49,14 @@
|
|||||||
|
|
||||||
#define NUM_PRNs 32
|
#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(
|
GpsL5iPcpsAcquisitionFpga::GpsL5iPcpsAcquisitionFpga(
|
||||||
ConfigurationInterface* configuration,
|
ConfigurationInterface* configuration,
|
||||||
@ -70,7 +78,7 @@ GpsL5iPcpsAcquisitionFpga::GpsL5iPcpsAcquisitionFpga(
|
|||||||
acq_parameters.repeat_satellite = configuration_->property(role + ".repeat_satellite", false);
|
acq_parameters.repeat_satellite = configuration_->property(role + ".repeat_satellite", false);
|
||||||
DLOG(INFO) << role << " satellite repeat = " << acq_parameters.repeat_satellite;
|
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;
|
acq_parameters.downsampling_factor = downsampling_factor;
|
||||||
|
|
||||||
fs_in = fs_in / 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_ms = nsamples_total / sampled_ms;
|
||||||
acq_parameters.samples_per_code = nsamples_total;
|
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
|
// 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)
|
// a channel is assigned)
|
||||||
auto* fft_if = new gr::fft::fft_complex(nsamples_total, true); // Direct FFT
|
auto* fft_if = new gr::fft::fft_complex(nsamples_total, true); // Direct FFT
|
||||||
auto* code = new gr_complex[nsamples_total];
|
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()));
|
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
|
float max; // temporary maxima search
|
||||||
|
int32_t tmp, tmp2, local_code, fft_data;
|
||||||
|
|
||||||
for (uint32_t PRN = 1; PRN <= NUM_PRNs; PRN++)
|
for (uint32_t PRN = 1; PRN <= NUM_PRNs; PRN++)
|
||||||
{
|
{
|
||||||
gps_l5i_code_gen_complex_sampled(code, PRN, fs_in);
|
gps_l5i_code_gen_complex_sampled(code, PRN, fs_in);
|
||||||
@ -136,24 +146,33 @@ GpsL5iPcpsAcquisitionFpga::GpsL5iPcpsAcquisitionFpga(
|
|||||||
max = std::abs(fft_codes_padded[i].imag());
|
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)),
|
tmp = 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, 9) - 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.all_fft_codes = d_all_fft_codes_;
|
||||||
|
|
||||||
// reference for the FPGA FFT-IFFT attenuation factor
|
// 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);
|
acquisition_fpga_ = pcps_make_acquisition_fpga(acq_parameters);
|
||||||
|
|
||||||
channel_ = 0;
|
channel_ = 0;
|
||||||
doppler_step_ = 0;
|
doppler_step_ = 0;
|
||||||
gnss_synchro_ = nullptr;
|
gnss_synchro_ = nullptr;
|
||||||
channel_fsm_ = nullptr;
|
|
||||||
// temporary buffers that we can delete
|
// temporary buffers that we can delete
|
||||||
delete[] code;
|
delete[] code;
|
||||||
delete fft_if;
|
delete fft_if;
|
||||||
|
@ -101,11 +101,12 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
* \brief Set channel fsm associated to this acquisition instance
|
* \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;
|
channel_fsm_ = channel_fsm;
|
||||||
acquisition_fpga_->set_channel_fsm(channel_fsm);
|
acquisition_fpga_->set_channel_fsm(channel_fsm);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Set statistics threshold of PCPS algorithm
|
* \brief Set statistics threshold of PCPS algorithm
|
||||||
*/
|
*/
|
||||||
@ -158,7 +159,7 @@ private:
|
|||||||
pcps_acquisition_fpga_sptr acquisition_fpga_;
|
pcps_acquisition_fpga_sptr acquisition_fpga_;
|
||||||
std::string item_type_;
|
std::string item_type_;
|
||||||
uint32_t channel_;
|
uint32_t channel_;
|
||||||
std::shared_ptr<ChannelFsm> channel_fsm_;
|
std::weak_ptr<ChannelFsm> channel_fsm_;
|
||||||
uint32_t doppler_max_;
|
uint32_t doppler_max_;
|
||||||
uint32_t doppler_step_;
|
uint32_t doppler_step_;
|
||||||
std::string dump_filename_;
|
std::string dump_filename_;
|
||||||
@ -167,7 +168,7 @@ private:
|
|||||||
unsigned int in_streams_;
|
unsigned int in_streams_;
|
||||||
unsigned int out_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);
|
float calculate_threshold(float pfa);
|
||||||
};
|
};
|
||||||
|
@ -100,7 +100,7 @@ private:
|
|||||||
int doppler_offset);
|
int doppler_offset);
|
||||||
float estimate_input_power(gr_complex* in);
|
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;
|
int64_t d_fs_in;
|
||||||
int d_samples_per_ms;
|
int d_samples_per_ms;
|
||||||
int d_sampled_ms;
|
int d_sampled_ms;
|
||||||
@ -216,7 +216,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
* \brief Set channel fsm associated to this acquisition instance
|
* \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;
|
d_channel_fsm = channel_fsm;
|
||||||
}
|
}
|
||||||
|
@ -118,7 +118,7 @@ private:
|
|||||||
int32_t d_state;
|
int32_t d_state;
|
||||||
bool d_dump;
|
bool d_dump;
|
||||||
uint32_t d_channel;
|
uint32_t d_channel;
|
||||||
std::shared_ptr<ChannelFsm> d_channel_fsm;
|
std::weak_ptr<ChannelFsm> d_channel_fsm;
|
||||||
std::string d_dump_filename;
|
std::string d_dump_filename;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -186,7 +186,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
* \brief Set channel fsm associated to this acquisition instance
|
* \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;
|
d_channel_fsm = channel_fsm;
|
||||||
}
|
}
|
||||||
|
@ -429,10 +429,11 @@ void pcps_acquisition::send_positive_acquisition()
|
|||||||
<< ", magnitude " << d_mag
|
<< ", magnitude " << d_mag
|
||||||
<< ", input signal power " << d_input_power;
|
<< ", input signal power " << d_input_power;
|
||||||
d_positive_acq = 1;
|
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
|
//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
|
else
|
||||||
{
|
{
|
||||||
|
@ -124,7 +124,7 @@ private:
|
|||||||
int64_t d_old_freq;
|
int64_t d_old_freq;
|
||||||
int32_t d_state;
|
int32_t d_state;
|
||||||
uint32_t d_channel;
|
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_step;
|
||||||
float d_doppler_center_step_two;
|
float d_doppler_center_step_two;
|
||||||
uint32_t d_num_noncoherent_integrations_counter;
|
uint32_t d_num_noncoherent_integrations_counter;
|
||||||
@ -213,7 +213,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
* \brief Set channel fsm associated to this acquisition instance
|
* \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;
|
d_channel_fsm = channel_fsm;
|
||||||
}
|
}
|
||||||
|
@ -122,7 +122,7 @@ private:
|
|||||||
int d_n_samples_in_buffer;
|
int d_n_samples_in_buffer;
|
||||||
bool d_dump;
|
bool d_dump;
|
||||||
unsigned int d_channel;
|
unsigned int d_channel;
|
||||||
std::shared_ptr<ChannelFsm> d_channel_fsm;
|
std::weak_ptr<ChannelFsm> d_channel_fsm;
|
||||||
|
|
||||||
std::string d_dump_filename;
|
std::string d_dump_filename;
|
||||||
|
|
||||||
@ -189,7 +189,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
* \brief Set channel fsm associated to this acquisition instance
|
* \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;
|
d_channel_fsm = channel_fsm;
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
|
|
||||||
#include "pcps_acquisition_fpga.h"
|
#include "pcps_acquisition_fpga.h"
|
||||||
#include "gnss_synchro.h"
|
#include "gnss_synchro.h"
|
||||||
|
//#include <boost/chrono.hpp>
|
||||||
#include <glog/logging.h>
|
#include <glog/logging.h>
|
||||||
#include <cmath> // for ceil
|
#include <cmath> // for ceil
|
||||||
#include <iostream> // for operator<<
|
#include <iostream> // for operator<<
|
||||||
@ -42,7 +43,6 @@
|
|||||||
|
|
||||||
#define AQ_DOWNSAMPLING_DELAY 40 // delay due to the downsampling filter in the acquisition
|
#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_)
|
pcps_acquisition_fpga_sptr pcps_make_acquisition_fpga(pcpsconf_fpga_t conf_)
|
||||||
{
|
{
|
||||||
return pcps_acquisition_fpga_sptr(new pcps_acquisition_fpga(std::move(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_)
|
pcps_acquisition_fpga::pcps_acquisition_fpga(pcpsconf_fpga_t conf_)
|
||||||
{
|
{
|
||||||
acq_parameters = std::move(conf_);
|
acq_parameters = std::move(conf_);
|
||||||
d_sample_counter = 0ULL; // SAMPLE COUNTER
|
d_sample_counter = 0ULL; // Sample Counter
|
||||||
d_active = false;
|
d_active = false;
|
||||||
d_state = 0;
|
d_state = 0;
|
||||||
d_fft_size = acq_parameters.samples_per_code;
|
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_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,
|
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);
|
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()
|
pcps_acquisition_fpga::~pcps_acquisition_fpga() = default;
|
||||||
{
|
|
||||||
acquisition_fpga->free();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void pcps_acquisition_fpga::set_local_code()
|
void pcps_acquisition_fpga::set_local_code()
|
||||||
{
|
{
|
||||||
@ -100,9 +105,7 @@ void pcps_acquisition_fpga::init()
|
|||||||
d_mag = 0.0;
|
d_mag = 0.0;
|
||||||
d_input_power = 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;
|
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;
|
||||||
|
|
||||||
acquisition_fpga->init();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -144,7 +147,7 @@ void pcps_acquisition_fpga::send_positive_acquisition()
|
|||||||
<< ", input signal power " << d_input_power;
|
<< ", input signal power " << d_input_power;
|
||||||
|
|
||||||
//the channel FSM is set, so, notify it directly the positive acquisition to minimize delays
|
//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,56 +166,43 @@ void pcps_acquisition_fpga::send_negative_acquisition()
|
|||||||
|
|
||||||
if (acq_parameters.repeat_satellite == true)
|
if (acq_parameters.repeat_satellite == true)
|
||||||
{
|
{
|
||||||
d_channel_fsm->Event_failed_acquisition_repeat();
|
d_channel_fsm.lock()->Event_failed_acquisition_repeat();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
d_channel_fsm->Event_failed_acquisition_no_repeat();
|
d_channel_fsm.lock()->Event_failed_acquisition_no_repeat();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pcps_acquisition_fpga::acquisition_core(uint32_t num_doppler_bins, uint32_t doppler_step, int32_t doppler_min)
|
||||||
void pcps_acquisition_fpga::set_active(bool active)
|
|
||||||
{
|
{
|
||||||
d_active = active;
|
|
||||||
|
|
||||||
// initialize acquisition algorithm
|
|
||||||
uint32_t indext = 0U;
|
uint32_t indext = 0U;
|
||||||
float firstpeak = 0.0;
|
float firstpeak = 0.0;
|
||||||
float secondpeak = 0.0;
|
float secondpeak = 0.0;
|
||||||
uint32_t total_block_exp;
|
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;
|
uint64_t initial_sample;
|
||||||
|
int32_t doppler;
|
||||||
acquisition_fpga->configure_acquisition();
|
acquisition_fpga->set_doppler_sweep(num_doppler_bins, doppler_step, doppler_min);
|
||||||
acquisition_fpga->set_doppler_sweep(d_num_doppler_bins);
|
|
||||||
acquisition_fpga->write_local_code();
|
|
||||||
acquisition_fpga->set_block_exp(d_total_block_exp);
|
|
||||||
acquisition_fpga->run_acquisition();
|
acquisition_fpga->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 (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
|
// 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;
|
std::cout << "changing blk exp..... d_total_block_exp = " << d_total_block_exp << " total_block_exp = " << total_block_exp << " chan = " << d_channel << std::endl;
|
||||||
d_total_block_exp = total_block_exp;
|
d_total_block_exp = total_block_exp;
|
||||||
|
d_test_statistics = 0;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
doppler = -static_cast<int32_t>(acq_parameters.doppler_max) + d_doppler_step * (d_doppler_index - 1);
|
{
|
||||||
|
|
||||||
if (secondpeak > 0)
|
if (secondpeak > 0)
|
||||||
{
|
{
|
||||||
d_test_statistics = firstpeak / secondpeak;
|
d_test_statistics = firstpeak / secondpeak;
|
||||||
@ -221,6 +211,14 @@ void pcps_acquisition_fpga::set_active(bool active)
|
|||||||
{
|
{
|
||||||
d_test_statistics = 0.0;
|
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_gnss_synchro->Acq_doppler_hz = static_cast<double>(doppler);
|
||||||
d_sample_counter = initial_sample;
|
d_sample_counter = initial_sample;
|
||||||
@ -230,7 +228,7 @@ void pcps_acquisition_fpga::set_active(bool active)
|
|||||||
if (d_downsampling_factor > 1)
|
if (d_downsampling_factor > 1)
|
||||||
{
|
{
|
||||||
d_gnss_synchro->Acq_delay_samples = static_cast<double>(d_downsampling_factor * (indext));
|
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
|
else
|
||||||
{
|
{
|
||||||
@ -243,7 +241,34 @@ void pcps_acquisition_fpga::set_active(bool active)
|
|||||||
d_gnss_synchro->Acq_delay_samples = static_cast<double>(indext);
|
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
|
d_gnss_synchro->Acq_samplestamp_samples = d_sample_counter; // delay due to the downsampling filter in the acquisition
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
acquisition_fpga->close_device();
|
||||||
if (d_test_statistics > d_threshold)
|
if (d_test_statistics > d_threshold)
|
||||||
{
|
{
|
||||||
d_active = false;
|
d_active = false;
|
||||||
@ -256,17 +281,50 @@ void pcps_acquisition_fpga::set_active(bool active)
|
|||||||
d_active = false;
|
d_active = false;
|
||||||
send_negative_acquisition();
|
send_negative_acquisition();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void pcps_acquisition_fpga::reset_acquisition(void)
|
void pcps_acquisition_fpga::reset_acquisition(void)
|
||||||
{
|
{
|
||||||
// this function triggers a HW reset of the FPGA PL.
|
// this function triggers a HW reset of the FPGA PL.
|
||||||
|
acquisition_fpga->open_device();
|
||||||
acquisition_fpga->reset_acquisition();
|
acquisition_fpga->reset_acquisition();
|
||||||
}
|
acquisition_fpga->close_device();
|
||||||
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
@ -62,11 +62,16 @@ typedef struct
|
|||||||
int32_t code_length;
|
int32_t code_length;
|
||||||
uint32_t select_queue_Fpga;
|
uint32_t select_queue_Fpga;
|
||||||
std::string device_name;
|
std::string device_name;
|
||||||
lv_16sc_t* all_fft_codes; // memory that contains all the code ffts
|
uint32_t* all_fft_codes; // pointer to memory that contains all the code ffts
|
||||||
float downsampling_factor;
|
//float downsampling_factor;
|
||||||
|
uint32_t downsampling_factor;
|
||||||
uint32_t total_block_exp;
|
uint32_t total_block_exp;
|
||||||
uint32_t excludelimit;
|
uint32_t excludelimit;
|
||||||
|
bool make_2_steps;
|
||||||
|
uint32_t num_doppler_bins_step2;
|
||||||
|
float doppler_step2;
|
||||||
bool repeat_satellite;
|
bool repeat_satellite;
|
||||||
|
uint32_t max_num_acqs;
|
||||||
} pcpsconf_fpga_t;
|
} pcpsconf_fpga_t;
|
||||||
|
|
||||||
class pcps_acquisition_fpga;
|
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);
|
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;
|
pcpsconf_fpga_t acq_parameters;
|
||||||
bool d_active;
|
bool d_active;
|
||||||
float d_threshold;
|
float d_threshold;
|
||||||
@ -104,19 +111,27 @@ private:
|
|||||||
float d_test_statistics;
|
float d_test_statistics;
|
||||||
int32_t d_state;
|
int32_t d_state;
|
||||||
uint32_t d_channel;
|
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_step;
|
||||||
|
uint32_t d_doppler_max;
|
||||||
uint32_t d_fft_size;
|
uint32_t d_fft_size;
|
||||||
uint32_t d_num_doppler_bins;
|
uint32_t d_num_doppler_bins;
|
||||||
uint64_t d_sample_counter;
|
uint64_t d_sample_counter;
|
||||||
Gnss_Synchro* d_gnss_synchro;
|
Gnss_Synchro* d_gnss_synchro;
|
||||||
std::shared_ptr<Fpga_Acquisition> acquisition_fpga;
|
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_select_queue_Fpga;
|
||||||
|
|
||||||
uint32_t d_total_block_exp;
|
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:
|
public:
|
||||||
~pcps_acquisition_fpga();
|
~pcps_acquisition_fpga();
|
||||||
|
|
||||||
@ -172,11 +187,10 @@ public:
|
|||||||
d_channel = channel;
|
d_channel = channel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Set channel fsm associated to this acquisition instance
|
* \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;
|
d_channel_fsm = channel_fsm;
|
||||||
}
|
}
|
||||||
@ -197,7 +211,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
inline void set_doppler_max(uint32_t doppler_max)
|
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);
|
acquisition_fpga->set_doppler_max(doppler_max);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -215,11 +229,6 @@ public:
|
|||||||
* \brief This funciton triggers a HW reset of the FPGA PL.
|
* \brief This funciton triggers a HW reset of the FPGA PL.
|
||||||
*/
|
*/
|
||||||
void reset_acquisition(void);
|
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_*/
|
#endif /* GNSS_SDR_PCPS_ACQUISITION_FPGA_H_*/
|
||||||
|
@ -138,7 +138,7 @@ private:
|
|||||||
int32_t d_well_count;
|
int32_t d_well_count;
|
||||||
bool d_dump;
|
bool d_dump;
|
||||||
uint32_t d_channel;
|
uint32_t d_channel;
|
||||||
std::shared_ptr<ChannelFsm> d_channel_fsm;
|
std::weak_ptr<ChannelFsm> d_channel_fsm;
|
||||||
std::string d_dump_filename;
|
std::string d_dump_filename;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -199,7 +199,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
* \brief Set channel fsm associated to this acquisition instance
|
* \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;
|
d_channel_fsm = channel_fsm;
|
||||||
}
|
}
|
||||||
|
@ -117,7 +117,7 @@ private:
|
|||||||
int32_t d_state;
|
int32_t d_state;
|
||||||
bool d_dump;
|
bool d_dump;
|
||||||
uint32_t d_channel;
|
uint32_t d_channel;
|
||||||
std::shared_ptr<ChannelFsm> d_channel_fsm;
|
std::weak_ptr<ChannelFsm> d_channel_fsm;
|
||||||
std::string d_dump_filename;
|
std::string d_dump_filename;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -186,7 +186,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
* \brief Set channel fsm associated to this acquisition instance
|
* \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;
|
d_channel_fsm = channel_fsm;
|
||||||
}
|
}
|
||||||
|
@ -162,7 +162,7 @@ private:
|
|||||||
cl::CommandQueue* d_cl_queue;
|
cl::CommandQueue* d_cl_queue;
|
||||||
clFFT_Plan d_cl_fft_plan;
|
clFFT_Plan d_cl_fft_plan;
|
||||||
cl_int d_cl_fft_batch_size;
|
cl_int d_cl_fft_batch_size;
|
||||||
std::shared_ptr<ChannelFsm> d_channel_fsm;
|
std::weak_ptr<ChannelFsm> d_channel_fsm;
|
||||||
int d_opencl;
|
int d_opencl;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -230,7 +230,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
* \brief Set channel fsm associated to this acquisition instance
|
* \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;
|
d_channel_fsm = channel_fsm;
|
||||||
}
|
}
|
||||||
|
@ -151,7 +151,7 @@ private:
|
|||||||
int32_t d_state;
|
int32_t d_state;
|
||||||
bool d_dump;
|
bool d_dump;
|
||||||
uint32_t d_channel;
|
uint32_t d_channel;
|
||||||
std::shared_ptr<ChannelFsm> d_channel_fsm;
|
std::weak_ptr<ChannelFsm> d_channel_fsm;
|
||||||
std::string d_dump_filename;
|
std::string d_dump_filename;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -219,7 +219,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
* \brief Set channel fsm associated to this acquisition instance
|
* \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;
|
d_channel_fsm = channel_fsm;
|
||||||
}
|
}
|
||||||
|
@ -134,7 +134,7 @@ private:
|
|||||||
int32_t d_state;
|
int32_t d_state;
|
||||||
bool d_dump;
|
bool d_dump;
|
||||||
uint32_t d_channel;
|
uint32_t d_channel;
|
||||||
std::shared_ptr<ChannelFsm> d_channel_fsm;
|
std::weak_ptr<ChannelFsm> d_channel_fsm;
|
||||||
std::string d_dump_filename;
|
std::string d_dump_filename;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -202,7 +202,7 @@ public:
|
|||||||
/*!
|
/*!
|
||||||
* \brief Set channel fsm associated to this acquisition instance
|
* \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;
|
d_channel_fsm = channel_fsm;
|
||||||
}
|
}
|
||||||
|
@ -46,22 +46,20 @@
|
|||||||
|
|
||||||
// FPGA register parameters
|
// FPGA register parameters
|
||||||
#define PAGE_SIZE 0x10000 // default page size for the multicorrelator memory map
|
#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 RESET_ACQUISITION 2 // command to reset the multicorrelator
|
||||||
#define LAUNCH_ACQUISITION 1 // command to launch 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 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 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 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_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 POW_2_31 2147483648 // 2^31 (used for the conversion of floating point numbers to integers)
|
||||||
#define SELECT_LSB 0x00FF // value to select the least significant byte
|
#define ENABLE_INT_ON_RESET 2 // flag that causes the acquisition to trigger an interrupt when it is reset.
|
||||||
#define SELECT_MSB 0XFF00 // value to select the most significant byte
|
|
||||||
#define SELECT_16_BITS 0xFFFF // value to select 16 bits
|
#define SELECT_LSBits 0x0000FFFF // Select the 10 LSbits out of a 20-bit word
|
||||||
#define SHL_8_BITS 256 // value used to shift a value 8 bits to the left
|
#define SELECT_MSBbits 0xFFFF0000 // Select the 10 MSbits out of a 20-bit word
|
||||||
#define SELECT_LSBits 0x000003FF // Select the 10 LSbits out of a 20-bit word
|
#define SELECT_ALL_CODE_BITS 0xFFFFFFFF // Select a 20 bit word
|
||||||
#define SELECT_MSBbits 0x000FFC00 // Select the 10 MSbits out of a 20-bit word
|
#define SHL_CODE_BITS 65536 // shift left by 10 bits
|
||||||
#define SELECT_ALL_CODE_BITS 0x000FFFFF // Select a 20 bit word
|
|
||||||
#define SHL_CODE_BITS 1024 // shift left by 10 bits
|
|
||||||
|
|
||||||
#ifndef TEMP_FAILURE_RETRY
|
#ifndef TEMP_FAILURE_RETRY
|
||||||
#define TEMP_FAILURE_RETRY(exp) \
|
#define TEMP_FAILURE_RETRY(exp) \
|
||||||
@ -84,7 +82,8 @@ Fpga_Acquisition::Fpga_Acquisition(std::string device_name,
|
|||||||
int64_t fs_in,
|
int64_t fs_in,
|
||||||
uint32_t sampled_ms __attribute__((unused)),
|
uint32_t sampled_ms __attribute__((unused)),
|
||||||
uint32_t select_queue,
|
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 excludelimit)
|
||||||
{
|
{
|
||||||
uint32_t vector_length = nsamples_total;
|
uint32_t vector_length = nsamples_total;
|
||||||
@ -102,12 +101,10 @@ Fpga_Acquisition::Fpga_Acquisition(std::string device_name,
|
|||||||
d_fd = 0; // driver descriptor
|
d_fd = 0; // driver descriptor
|
||||||
d_map_base = nullptr; // driver memory map
|
d_map_base = nullptr; // driver memory map
|
||||||
d_all_fft_codes = all_fft_codes;
|
d_all_fft_codes = all_fft_codes;
|
||||||
|
|
||||||
Fpga_Acquisition::reset_acquisition();
|
|
||||||
Fpga_Acquisition::open_device();
|
Fpga_Acquisition::open_device();
|
||||||
|
Fpga_Acquisition::reset_acquisition();
|
||||||
Fpga_Acquisition::fpga_acquisition_test_register();
|
Fpga_Acquisition::fpga_acquisition_test_register();
|
||||||
Fpga_Acquisition::close_device();
|
Fpga_Acquisition::close_device();
|
||||||
|
|
||||||
d_PRN = 0;
|
d_PRN = 0;
|
||||||
DLOG(INFO) << "Acquisition FPGA class created";
|
DLOG(INFO) << "Acquisition FPGA class created";
|
||||||
}
|
}
|
||||||
@ -116,12 +113,6 @@ Fpga_Acquisition::Fpga_Acquisition(std::string device_name,
|
|||||||
Fpga_Acquisition::~Fpga_Acquisition() = default;
|
Fpga_Acquisition::~Fpga_Acquisition() = default;
|
||||||
|
|
||||||
|
|
||||||
bool Fpga_Acquisition::init()
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool Fpga_Acquisition::set_local_code(uint32_t PRN)
|
bool Fpga_Acquisition::set_local_code(uint32_t PRN)
|
||||||
{
|
{
|
||||||
// select the code with the chosen PRN
|
// 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()
|
void Fpga_Acquisition::write_local_code()
|
||||||
{
|
{
|
||||||
Fpga_Acquisition::fpga_configure_acquisition_local_code(
|
d_map_base[9] = LOCAL_CODE_CLEAR_MEM;
|
||||||
&d_all_fft_codes[d_nsamples_total * (d_PRN - 1)]);
|
// 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()
|
void Fpga_Acquisition::fpga_acquisition_test_register()
|
||||||
{
|
{
|
||||||
// sanity check : check 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)
|
void Fpga_Acquisition::run_acquisition(void)
|
||||||
{
|
{
|
||||||
// enable interrupts
|
// enable interrupts
|
||||||
int32_t reenable = 1;
|
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)));
|
ssize_t nbytes = TEMP_FAILURE_RETRY(write(d_fd, reinterpret_cast<void *>(&reenable), sizeof(int32_t)));
|
||||||
if (nbytes != 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;
|
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)));
|
// nbytes = TEMP_FAILURE_RETRY(write(d_fd, reinterpret_cast<void *>(&disable_int), sizeof(int32_t)));
|
||||||
if (nbytes != sizeof(int32_t))
|
// if (nbytes != sizeof(int32_t))
|
||||||
{
|
// {
|
||||||
std::cerr << "Error disabling interruptions in the FPGA." << std::endl;
|
// 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;
|
d_map_base[11] = total_block_exp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Fpga_Acquisition::set_doppler_sweep(uint32_t num_sweeps, uint32_t doppler_step, int32_t doppler_min)
|
||||||
void Fpga_Acquisition::set_doppler_sweep(uint32_t num_sweeps)
|
|
||||||
{
|
{
|
||||||
float phase_step_rad_real;
|
float phase_step_rad_real;
|
||||||
float phase_step_rad_int_temp;
|
|
||||||
int32_t phase_step_rad_int;
|
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 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 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 = 2.0 * (doppler_min) / static_cast<float>(d_fs_in);
|
||||||
phase_step_rad_real = phase_step_rad / (GPS_TWO_PI / 2);
|
phase_step_rad_int = static_cast<int32_t>(phase_step_rad_real * (POW_2_31));
|
||||||
|
|
||||||
// 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;
|
d_map_base[3] = phase_step_rad_int;
|
||||||
|
|
||||||
// repeat the calculation with the doppler step
|
// repeat the calculation with the doppler step
|
||||||
doppler = static_cast<int32_t>(d_doppler_step);
|
phase_step_rad_real = 2.0 * (doppler_step) / static_cast<float>(d_fs_in);
|
||||||
phase_step_rad = GPS_TWO_PI * (doppler) / 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
|
||||||
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
|
|
||||||
d_map_base[4] = phase_step_rad_int;
|
d_map_base[4] = phase_step_rad_int;
|
||||||
|
|
||||||
|
// write number of doppler sweeps
|
||||||
d_map_base[5] = num_sweeps;
|
d_map_base[5] = num_sweeps;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Fpga_Acquisition::configure_acquisition()
|
void Fpga_Acquisition::configure_acquisition()
|
||||||
{
|
{
|
||||||
Fpga_Acquisition::open_device();
|
//Fpga_Acquisition::open_device();
|
||||||
|
|
||||||
d_map_base[0] = d_select_queue;
|
d_map_base[0] = d_select_queue;
|
||||||
d_map_base[1] = d_vector_length;
|
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,
|
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)
|
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 = 0;
|
||||||
uint64_t readval_long_shifted = 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;
|
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
|
readval_long_shifted = readval_long << 32; // 2^32
|
||||||
|
|
||||||
initial_sample_tmp = initial_sample_tmp + readval_long_shifted; // 2^32
|
initial_sample_tmp = initial_sample_tmp + readval_long_shifted; // 2^32
|
||||||
*initial_sample = initial_sample_tmp;
|
*initial_sample = initial_sample_tmp;
|
||||||
|
|
||||||
readval = d_map_base[3];
|
readval = d_map_base[3]; // read first peak value
|
||||||
*firstpeak = static_cast<float>(readval);
|
*firstpeak = static_cast<float>(readval);
|
||||||
|
|
||||||
readval = d_map_base[4];
|
readval = d_map_base[4]; // read second peak value
|
||||||
*secondpeak = static_cast<float>(readval);
|
*secondpeak = static_cast<float>(readval);
|
||||||
|
|
||||||
readval = d_map_base[5];
|
readval = d_map_base[5]; // read max index position
|
||||||
*max_index = readval;
|
*max_index = readval;
|
||||||
|
|
||||||
*power_sum = 0;
|
*power_sum = 0; // power sum is not used
|
||||||
|
|
||||||
readval = d_map_base[8];
|
|
||||||
*total_blk_exp = readval;
|
|
||||||
|
|
||||||
readval = d_map_base[7]; // read doppler index -- this read releases the interrupt line
|
readval = d_map_base[7]; // read doppler index -- this read releases the interrupt line
|
||||||
*doppler_index = readval;
|
*doppler_index = readval;
|
||||||
|
|
||||||
readval = d_map_base[15]; // read dummy
|
readval = d_map_base[8]; // read FFT block exponent
|
||||||
|
*total_blk_exp = readval;
|
||||||
Fpga_Acquisition::close_device();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -380,9 +304,9 @@ void Fpga_Acquisition::close_device()
|
|||||||
|
|
||||||
void Fpga_Acquisition::reset_acquisition(void)
|
void Fpga_Acquisition::reset_acquisition(void)
|
||||||
{
|
{
|
||||||
Fpga_Acquisition::open_device();
|
d_map_base[8] = RESET_ACQUISITION; // writing a 2 to d_map_base[8] resets the acquisition. This causes a reset of all
|
||||||
d_map_base[8] = RESET_ACQUISITION; // writing a 2 to d_map_base[8] resets the multicorrelator
|
// the FPGA HW modules including the multicorrelators
|
||||||
Fpga_Acquisition::close_device();
|
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;
|
uint32_t readval = 0;
|
||||||
readval = d_map_base[8];
|
readval = d_map_base[8];
|
||||||
*total_scale_factor = readval;
|
*total_scale_factor = readval;
|
||||||
|
// only the total scale factor is used for the tests (fw scale factor to be removed)
|
||||||
//readval = d_map_base[8];
|
|
||||||
*fw_scale_factor = 0;
|
*fw_scale_factor = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,16 +53,14 @@ public:
|
|||||||
int64_t fs_in,
|
int64_t fs_in,
|
||||||
uint32_t sampled_ms,
|
uint32_t sampled_ms,
|
||||||
uint32_t select_queue,
|
uint32_t select_queue,
|
||||||
lv_16sc_t *all_fft_codes,
|
uint32_t *all_fft_codes,
|
||||||
uint32_t excludelimit);
|
uint32_t excludelimit);
|
||||||
|
|
||||||
~Fpga_Acquisition();
|
~Fpga_Acquisition();
|
||||||
bool init();
|
|
||||||
bool set_local_code(uint32_t PRN);
|
bool set_local_code(uint32_t PRN);
|
||||||
bool free();
|
void set_doppler_sweep(uint32_t num_sweeps, uint32_t doppler_step, int32_t doppler_min);
|
||||||
void set_doppler_sweep(uint32_t num_sweeps);
|
|
||||||
void run_acquisition(void);
|
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 read_acquisition_results(uint32_t *max_index, float *firstpeak, float *secondpeak, uint64_t *initial_sample, float *power_sum, uint32_t *doppler_index, uint32_t *total_blk_exp);
|
||||||
|
|
||||||
void block_samples();
|
void block_samples();
|
||||||
@ -110,7 +108,7 @@ private:
|
|||||||
// data related to the hardware module and the driver
|
// data related to the hardware module and the driver
|
||||||
int32_t d_fd; // driver descriptor
|
int32_t d_fd; // driver descriptor
|
||||||
volatile uint32_t *d_map_base; // driver memory map
|
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_vector_length; // number of samples incluing padding and number of ms
|
||||||
uint32_t d_excludelimit;
|
uint32_t d_excludelimit;
|
||||||
uint32_t d_nsamples_total; // number of samples including padding
|
uint32_t d_nsamples_total; // number of samples including padding
|
||||||
@ -122,7 +120,6 @@ private:
|
|||||||
uint32_t d_PRN; // PRN
|
uint32_t d_PRN; // PRN
|
||||||
// FPGA private functions
|
// FPGA private functions
|
||||||
void fpga_acquisition_test_register(void);
|
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);
|
void read_result_valid(uint32_t *result_valid);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -218,7 +218,6 @@ void Channel::set_signal(const Gnss_Signal& gnss_signal)
|
|||||||
acq_->set_local_code();
|
acq_->set_local_code();
|
||||||
if (flag_enable_fpga)
|
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_);
|
trk_->set_gnss_synchro(&gnss_synchro_);
|
||||||
}
|
}
|
||||||
nav_->set_satellite(gnss_signal_.get_satellite());
|
nav_->set_satellite(gnss_signal_.get_satellite());
|
||||||
|
@ -20,53 +20,6 @@ if(DEFINED __INCLUDED_VOLK_PYTHON_CMAKE)
|
|||||||
endif()
|
endif()
|
||||||
set(__INCLUDED_VOLK_PYTHON_CMAKE TRUE)
|
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:
|
# Check for the existence of a python module:
|
||||||
# - desc a string description of the check
|
# - desc a string description of the check
|
||||||
@ -102,6 +55,61 @@ except: pass
|
|||||||
"${have}")
|
"${have}")
|
||||||
endmacro()
|
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
|
# Sets the python installation directory VOLK_PYTHON_DIR
|
||||||
########################################################################
|
########################################################################
|
||||||
|
@ -114,7 +114,7 @@ hybrid_observables_gs::hybrid_observables_gs(uint32_t nchannels_in,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
T_rx_TOW_ms = 0U;
|
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;
|
T_rx_TOW_set = false;
|
||||||
|
|
||||||
// rework
|
// rework
|
||||||
@ -443,8 +443,8 @@ 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.
|
//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)
|
// the time step must match the observables timer block (connected to the las input channel)
|
||||||
std::vector<Gnss_Synchro>::const_iterator it;
|
std::vector<Gnss_Synchro>::const_iterator it;
|
||||||
// if (!T_rx_TOW_set)
|
if (!T_rx_TOW_set)
|
||||||
// {
|
{
|
||||||
//uint32_t TOW_ref = std::numeric_limits<uint32_t>::max();
|
//uint32_t TOW_ref = std::numeric_limits<uint32_t>::max();
|
||||||
uint32_t TOW_ref = 0U;
|
uint32_t TOW_ref = 0U;
|
||||||
for (it = data.cbegin(); it != data.cend(); it++)
|
for (it = data.cbegin(); it != data.cend(); it++)
|
||||||
@ -458,23 +458,24 @@ void hybrid_observables_gs::update_TOW(const std::vector<Gnss_Synchro> &data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
T_rx_TOW_ms = TOW_ref;
|
T_rx_TOW_ms = TOW_ref - (TOW_ref % 20);
|
||||||
//}
|
}
|
||||||
// else
|
else
|
||||||
// {
|
{
|
||||||
// T_rx_TOW_ms += T_rx_step_ms;
|
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
|
//todo: check what happens during the week rollover
|
||||||
// if (T_rx_TOW_ms >= 604800000)
|
if (T_rx_TOW_ms >= 604800000)
|
||||||
// {
|
{
|
||||||
// T_rx_TOW_ms = 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)
|
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;
|
std::vector<Gnss_Synchro>::iterator it;
|
||||||
for (it = data.begin(); it != data.end(); it++)
|
for (it = data.begin(); it != data.end(); it++)
|
||||||
{
|
{
|
||||||
@ -486,12 +487,20 @@ void hybrid_observables_gs::compute_pranges(std::vector<Gnss_Synchro> &data)
|
|||||||
it->Pseudorange_m = traveltime_s * SPEED_OF_LIGHT;
|
it->Pseudorange_m = traveltime_s * SPEED_OF_LIGHT;
|
||||||
it->Flag_valid_pseudorange = true;
|
it->Flag_valid_pseudorange = true;
|
||||||
// debug code
|
// 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 << "] 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 << "] Diff T_rx_TOW_ms - interp_TOW_ms: " << static_cast<double>(T_rx_TOW_ms) - it->interp_TOW_ms << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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 << "[" << it->Channel_ID << "] Pseudorange_m: " << it->Pseudorange_m << std::endl;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
// std::cout << std::endl;
|
||||||
// usleep(1000);
|
// 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++)
|
for (uint32_t n = 0; n < d_nchannels_out; n++)
|
||||||
{
|
{
|
||||||
Gnss_Synchro interpolated_gnss_synchro{};
|
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
|
// Produce an empty observation
|
||||||
interpolated_gnss_synchro = Gnss_Synchro();
|
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);
|
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)
|
if (n_valid > 0)
|
||||||
{
|
{
|
||||||
|
update_TOW(epoch_data);
|
||||||
compute_pranges(epoch_data);
|
compute_pranges(epoch_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ private:
|
|||||||
//rx time follow GPST
|
//rx time follow GPST
|
||||||
bool T_rx_TOW_set;
|
bool T_rx_TOW_set;
|
||||||
uint32_t T_rx_TOW_ms;
|
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;
|
||||||
bool d_dump_mat;
|
bool d_dump_mat;
|
||||||
uint32_t d_nchannels_in;
|
uint32_t d_nchannels_in;
|
||||||
|
@ -53,10 +53,10 @@ Ad9361FpgaSignalSource::Ad9361FpgaSignalSource(ConfigurationInterface* configura
|
|||||||
std::string default_item_type = "gr_complex";
|
std::string default_item_type = "gr_complex";
|
||||||
std::string default_dump_file = "./data/signal_source.dat";
|
std::string default_dump_file = "./data/signal_source.dat";
|
||||||
freq_ = configuration->property(role + ".freq", GPS_L1_FREQ_HZ);
|
freq_ = configuration->property(role + ".freq", GPS_L1_FREQ_HZ);
|
||||||
sample_rate_ = configuration->property(role + ".sampling_frequency", 2600000);
|
sample_rate_ = configuration->property(role + ".sampling_frequency", 12500000);
|
||||||
bandwidth_ = configuration->property(role + ".bandwidth", 2000000);
|
bandwidth_ = configuration->property(role + ".bandwidth", 12500000);
|
||||||
rx1_en_ = configuration->property(role + ".rx1_enable", true);
|
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);
|
buffer_size_ = configuration->property(role + ".buffer_size", 0xA0000);
|
||||||
quadrature_ = configuration->property(role + ".quadrature", true);
|
quadrature_ = configuration->property(role + ".quadrature", true);
|
||||||
rf_dc_ = configuration->property(role + ".rf_dc", true);
|
rf_dc_ = configuration->property(role + ".rf_dc", true);
|
||||||
|
@ -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))
|
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_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);
|
item_type_ = configuration->property(role + ".item_type", default_item_type);
|
||||||
dump_ = configuration->property(role + ".dump", false);
|
dump_ = configuration->property(role + ".dump", false);
|
||||||
dump_filename_ = configuration->property(role + ".dump_filename", default_dump_file);
|
dump_filename_ = configuration->property(role + ".dump_filename", default_dump_file);
|
||||||
|
|
||||||
int channel_selector = configuration->property(role + ".selected_channel", 1);
|
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);
|
filename_ = configuration->property(role + ".filename", default_filename);
|
||||||
|
|
||||||
if (item_type_ == "gr_complex")
|
if (item_type_ == "gr_complex")
|
||||||
{
|
{
|
||||||
item_size_ = sizeof(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) << "Item size " << item_size_;
|
||||||
DLOG(INFO) << "labsat23_source_(" << labsat23_source_->unique_id() << ")";
|
DLOG(INFO) << "labsat23_source_(" << labsat23_source_->unique_id() << ")";
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,6 @@ private:
|
|||||||
unsigned int out_stream_;
|
unsigned int out_stream_;
|
||||||
std::string item_type_;
|
std::string item_type_;
|
||||||
size_t item_size_;
|
size_t item_size_;
|
||||||
uint64_t samples_;
|
|
||||||
std::string filename_;
|
std::string filename_;
|
||||||
bool dump_;
|
bool dump_;
|
||||||
std::string dump_filename_;
|
std::string dump_filename_;
|
||||||
|
@ -64,6 +64,7 @@ target_link_libraries(signal_source_gr_blocks
|
|||||||
Gnuradio::runtime
|
Gnuradio::runtime
|
||||||
signal_source_libs
|
signal_source_libs
|
||||||
PRIVATE
|
PRIVATE
|
||||||
|
core_receiver
|
||||||
Gflags::gflags
|
Gflags::gflags
|
||||||
Glog::glog
|
Glog::glog
|
||||||
)
|
)
|
||||||
|
@ -30,30 +30,25 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "labsat23_source.h"
|
#include "labsat23_source.h"
|
||||||
|
#include "control_message_factory.h"
|
||||||
#include <gnuradio/io_signature.h>
|
#include <gnuradio/io_signature.h>
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#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));
|
return labsat23_source_sptr(new labsat23_source(signal_file_basename, channel_selector, queue));
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
labsat23_source::labsat23_source(const char *signal_file_basename,
|
labsat23_source::labsat23_source(const char *signal_file_basename,
|
||||||
int channel_selector) : gr::block("labsat23_source",
|
int channel_selector,
|
||||||
|
gr::msg_queue::sptr queue) : gr::block("labsat23_source",
|
||||||
gr::io_signature::make(0, 0, 0),
|
gr::io_signature::make(0, 0, 0),
|
||||||
gr::io_signature::make(1, 1, sizeof(gr_complex)))
|
gr::io_signature::make(1, 1, sizeof(gr_complex))),
|
||||||
|
d_queue(queue)
|
||||||
{
|
{
|
||||||
if (channel_selector < 1 or channel_selector > 2)
|
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)
|
int labsat23_source::getBit(uint8_t byte, int position)
|
||||||
{
|
{
|
||||||
return (byte >> position) & 0x01;
|
return (byte >> position) & 0x01;
|
||||||
@ -120,7 +134,7 @@ void labsat23_source::decode_samples_one_channel(int16_t input_short, gr_complex
|
|||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case 2:
|
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++)
|
for (int i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
out[i] = gr_complex(static_cast<float>(bs[15 - (2 * 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;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
//four bits per sample, 4 samples per int16
|
// bits per sample, 4 samples per int16
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
out[i] = gr_complex(0.0, 0.0);
|
out[i] = gr_complex(0.0, 0.0);
|
||||||
//In-Phase
|
// In-Phase
|
||||||
if (bs[15 - 4 * i])
|
if (bs[15 - 4 * i])
|
||||||
{
|
{
|
||||||
if (bs[13 - 4 * i]) //11
|
if (bs[13 - 4 * i]) // 11
|
||||||
{
|
{
|
||||||
out[i] += gr_complex(-1, 0);
|
out[i] += gr_complex(-1, 0);
|
||||||
}
|
}
|
||||||
else //10
|
else // 10
|
||||||
{
|
{
|
||||||
out[i] += gr_complex(-2, 0);
|
out[i] += gr_complex(-2, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (bs[13 - 4 * i]) //01
|
if (bs[13 - 4 * i]) // 01
|
||||||
{
|
{
|
||||||
out[i] += gr_complex(1, 0);
|
out[i] += gr_complex(1, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Quadrature
|
// Quadrature
|
||||||
if (bs[14 - 4 * i])
|
if (bs[14 - 4 * i])
|
||||||
{
|
{
|
||||||
if (bs[12 - 4 * i]) //11
|
if (bs[12 - 4 * i]) // 11
|
||||||
{
|
{
|
||||||
out[i] += gr_complex(0, -1);
|
out[i] += gr_complex(0, -1);
|
||||||
}
|
}
|
||||||
else //10
|
else // 10
|
||||||
{
|
{
|
||||||
out[i] += gr_complex(0, -2);
|
out[i] += gr_complex(0, -2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (bs[12 - 4 * i]) //01
|
if (bs[12 - 4 * i]) // 01
|
||||||
{
|
{
|
||||||
out[i] += gr_complex(0, 1);
|
out[i] += gr_complex(0, 1);
|
||||||
}
|
}
|
||||||
@ -192,8 +206,8 @@ int labsat23_source::general_work(int noutput_items,
|
|||||||
{
|
{
|
||||||
char memblock[1024];
|
char memblock[1024];
|
||||||
binary_input_file->read(memblock, 1024);
|
binary_input_file->read(memblock, 1024);
|
||||||
//parse Labsat header
|
// parse Labsat header
|
||||||
//check preamble
|
// check preamble
|
||||||
int byte_counter = 0;
|
int byte_counter = 0;
|
||||||
bool preamble_ok = true;
|
bool preamble_ok = true;
|
||||||
for (int i = 0; i < 8; i++)
|
for (int i = 0; i < 8; i++)
|
||||||
@ -388,7 +402,6 @@ int labsat23_source::general_work(int noutput_items,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ready to start reading samples
|
// ready to start reading samples
|
||||||
switch (d_bits_per_sample)
|
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
|
// trigger the read of the next file in the sequence
|
||||||
|
if (d_labsat_version == 3)
|
||||||
|
{
|
||||||
std::cout << "End of current file, reading the next Labsat file in sequence: " << generate_filename() << std::endl;
|
std::cout << "End of current file, reading the next Labsat file in sequence: " << generate_filename() << std::endl;
|
||||||
|
}
|
||||||
d_current_file_number++;
|
d_current_file_number++;
|
||||||
binary_input_file->close();
|
binary_input_file->close();
|
||||||
binary_input_file->open(generate_filename().c_str(), std::ios::in | std::ios::binary);
|
binary_input_file->open(generate_filename().c_str(), std::ios::in | std::ios::binary);
|
||||||
@ -429,8 +444,18 @@ int labsat23_source::general_work(int noutput_items,
|
|||||||
std::cout << "Labsat file source is reading samples from " << generate_filename() << std::endl;
|
std::cout << "Labsat file source is reading samples from " << generate_filename() << std::endl;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if (d_labsat_version == 3)
|
||||||
{
|
{
|
||||||
std::cout << "Last file reached, LabSat source stop" << std::endl;
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -468,8 +493,10 @@ int labsat23_source::general_work(int noutput_items,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// trigger the read of the next file in the sequence
|
// trigger the read of the next file in the sequence
|
||||||
|
if (d_labsat_version == 3)
|
||||||
|
{
|
||||||
std::cout << "End of current file, reading the next Labsat file in sequence: " << generate_filename() << std::endl;
|
std::cout << "End of current file, reading the next Labsat file in sequence: " << generate_filename() << std::endl;
|
||||||
|
}
|
||||||
d_current_file_number++;
|
d_current_file_number++;
|
||||||
binary_input_file->close();
|
binary_input_file->close();
|
||||||
binary_input_file->open(generate_filename().c_str(), std::ios::in | std::ios::binary);
|
binary_input_file->open(generate_filename().c_str(), std::ios::in | std::ios::binary);
|
||||||
@ -478,8 +505,18 @@ int labsat23_source::general_work(int noutput_items,
|
|||||||
std::cout << "Labsat file source is reading samples from " << generate_filename() << std::endl;
|
std::cout << "Labsat file source is reading samples from " << generate_filename() << std::endl;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
if (d_labsat_version == 3)
|
||||||
{
|
{
|
||||||
std::cout << "Last file reached, LabSat source stop" << std::endl;
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#define GNSS_SDR_LABSAT23_SOURCE_H
|
#define GNSS_SDR_LABSAT23_SOURCE_H
|
||||||
|
|
||||||
#include <gnuradio/block.h>
|
#include <gnuradio/block.h>
|
||||||
|
#include <gnuradio/msg_queue.h> // for msg_queue, msg_queue::sptr
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -41,7 +42,7 @@ class labsat23_source;
|
|||||||
|
|
||||||
using labsat23_source_sptr = boost::shared_ptr<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
|
* \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
|
class labsat23_source : public gr::block
|
||||||
{
|
{
|
||||||
private:
|
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();
|
std::string generate_filename();
|
||||||
void decode_samples_one_channel(int16_t input_short, gr_complex *out, int type);
|
void decode_samples_one_channel(int16_t input_short, gr_complex *out, int type);
|
||||||
int getBit(uint8_t byte, int position);
|
int getBit(uint8_t byte, int position);
|
||||||
@ -62,9 +64,9 @@ private:
|
|||||||
std::ifstream *binary_input_file;
|
std::ifstream *binary_input_file;
|
||||||
uint8_t d_ref_clock;
|
uint8_t d_ref_clock;
|
||||||
uint8_t d_bits_per_sample;
|
uint8_t d_bits_per_sample;
|
||||||
|
gr::msg_queue::sptr d_queue;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
labsat23_source(const char *signal_file_basename, int channel_selector);
|
|
||||||
~labsat23_source();
|
~labsat23_source();
|
||||||
int general_work(int noutput_items,
|
int general_work(int noutput_items,
|
||||||
gr_vector_int &ninput_items,
|
gr_vector_int &ninput_items,
|
||||||
|
@ -215,7 +215,7 @@ galileo_telemetry_decoder_gs::galileo_telemetry_decoder_gs(
|
|||||||
d_flag_preamble = false;
|
d_flag_preamble = false;
|
||||||
d_channel = 0;
|
d_channel = 0;
|
||||||
flag_TOW_set = false;
|
flag_TOW_set = false;
|
||||||
|
flag_PLL_180_deg_phase_locked = false;
|
||||||
d_symbol_history.set_capacity(d_required_symbols + 1);
|
d_symbol_history.set_capacity(d_required_symbols + 1);
|
||||||
|
|
||||||
// vars for Viterbi decoder
|
// 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)),
|
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)
|
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
|
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
|
const auto **in = reinterpret_cast<const Gnss_Synchro **>(&input_items[0]); // Get the input buffer pointer
|
||||||
|
|
||||||
@ -513,6 +510,14 @@ int galileo_telemetry_decoder_gs::general_work(int noutput_items __attribute__((
|
|||||||
d_sent_tlm_failed_msg = true;
|
d_sent_tlm_failed_msg = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ******* 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)
|
if (d_symbol_history.size() > d_required_symbols)
|
||||||
{
|
{
|
||||||
// ******* preamble correlation ********
|
// ******* preamble correlation ********
|
||||||
@ -528,12 +533,6 @@ int galileo_telemetry_decoder_gs::general_work(int noutput_items __attribute__((
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ******* frame sync ******************
|
|
||||||
switch (d_stat)
|
|
||||||
{
|
|
||||||
case 0: // no preamble information
|
|
||||||
{
|
|
||||||
if (abs(corr_value) >= d_samples_per_preamble)
|
if (abs(corr_value) >= d_samples_per_preamble)
|
||||||
{
|
{
|
||||||
d_preamble_index = d_sample_counter; // record the preamble sample stamp
|
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
|
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)
|
if (abs(corr_value) >= d_samples_per_preamble)
|
||||||
{
|
{
|
||||||
// check preamble separation
|
// 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;
|
DLOG(INFO) << "Starting page decoder for Galileo satellite " << this->d_satellite;
|
||||||
d_preamble_index = d_sample_counter; // record the preamble sample stamp
|
d_preamble_index = d_sample_counter; // record the preamble sample stamp
|
||||||
d_CRC_error_counter = 0;
|
d_CRC_error_counter = 0;
|
||||||
|
if (corr_value < 0) flag_PLL_180_deg_phase_locked = true;
|
||||||
d_stat = 2;
|
d_stat = 2;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -576,7 +594,7 @@ int galileo_telemetry_decoder_gs::general_work(int noutput_items __attribute__((
|
|||||||
case 1: // INAV
|
case 1: // INAV
|
||||||
// NEW Galileo page part is received
|
// NEW Galileo page part is received
|
||||||
// 0. fetch the symbols into an array
|
// 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++)
|
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
|
case 2: // FNAV
|
||||||
// NEW Galileo page part is received
|
// NEW Galileo page part is received
|
||||||
// 0. fetch the symbols into an array
|
// 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;
|
int k = 0;
|
||||||
for (uint32_t i = 0; i < d_frame_length_symbols; i++)
|
for (uint32_t i = 0; i < d_frame_length_symbols; i++)
|
||||||
|
@ -102,6 +102,7 @@ private:
|
|||||||
bool d_sent_tlm_failed_msg;
|
bool d_sent_tlm_failed_msg;
|
||||||
uint32_t d_stat;
|
uint32_t d_stat;
|
||||||
bool d_flag_frame_sync;
|
bool d_flag_frame_sync;
|
||||||
|
bool flag_PLL_180_deg_phase_locked;
|
||||||
|
|
||||||
bool d_flag_parity;
|
bool d_flag_parity;
|
||||||
bool d_flag_preamble;
|
bool d_flag_preamble;
|
||||||
|
@ -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"));
|
this->message_port_register_out(pmt::mp("telemetry_to_trk"));
|
||||||
d_last_valid_preamble = 0;
|
d_last_valid_preamble = 0;
|
||||||
d_sent_tlm_failed_msg = false;
|
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
|
// initialize internal vars
|
||||||
d_dump = dump;
|
d_dump = dump;
|
||||||
d_satellite = Gnss_Satellite(satellite.get_system(), satellite.get_PRN());
|
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
|
// 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
|
// 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;
|
int32_t n = 0;
|
||||||
for (uint16_t preambles_bit : preambles_bits)
|
for (int32_t i = 0; i < d_bits_per_preamble; i++)
|
||||||
|
{
|
||||||
|
if (GPS_CA_PREAMBLE.at(i) == '1')
|
||||||
{
|
{
|
||||||
for (uint32_t j = 0; j < GPS_CA_TELEMETRY_SYMBOLS_PER_BIT; j++)
|
for (uint32_t j = 0; j < GPS_CA_TELEMETRY_SYMBOLS_PER_BIT; j++)
|
||||||
{
|
{
|
||||||
if (preambles_bit == 1)
|
d_preamble_samples[n] = 1;
|
||||||
{
|
|
||||||
d_preambles_symbols[n] = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
d_preambles_symbols[n] = -1;
|
|
||||||
}
|
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
d_stat = 0U;
|
else
|
||||||
|
{
|
||||||
|
for (uint32_t j = 0; j < GPS_CA_TELEMETRY_SYMBOLS_PER_BIT; j++)
|
||||||
|
{
|
||||||
|
d_preamble_samples[n] = -1;
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
d_sample_counter = 0ULL;
|
||||||
|
d_stat = 0;
|
||||||
|
d_preamble_index = 0ULL;
|
||||||
|
|
||||||
d_flag_frame_sync = false;
|
d_flag_frame_sync = false;
|
||||||
d_prev_GPS_frame_4bytes = 0;
|
|
||||||
d_TOW_at_Preamble_ms = 0;
|
d_flag_parity = false;
|
||||||
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_TOW_at_current_symbol_ms = 0;
|
d_TOW_at_current_symbol_ms = 0;
|
||||||
d_symbol_history.set_capacity(GPS_CA_PREAMBLE_LENGTH_SYMBOLS);
|
d_TOW_at_Preamble_ms = 0;
|
||||||
d_crc_error_synchronization_counter = 0;
|
d_CRC_error_counter = 0;
|
||||||
d_current_subframe_symbol = 0;
|
d_flag_preamble = false;
|
||||||
d_sample_counter = 0;
|
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()
|
gps_l1_ca_telemetry_decoder_gs::~gps_l1_ca_telemetry_decoder_gs()
|
||||||
{
|
{
|
||||||
volk_gnsssdr_free(d_preambles_symbols);
|
volk_gnsssdr_free(d_preamble_samples);
|
||||||
d_symbol_history.clear();
|
volk_gnsssdr_free(d_page_part_symbols);
|
||||||
if (d_dump_file.is_open() == true)
|
if (d_dump_file.is_open() == true)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -209,11 +220,11 @@ bool gps_l1_ca_telemetry_decoder_gs::decode_subframe()
|
|||||||
bool subframe_synchro_confirmation = false;
|
bool subframe_synchro_confirmation = false;
|
||||||
bool CRC_ok = true;
|
bool CRC_ok = true;
|
||||||
|
|
||||||
for (float d_subframe_symbol : d_subframe_symbols)
|
for (float subframe_symbol : d_symbol_history)
|
||||||
{
|
{
|
||||||
// ******* SYMBOL TO BIT *******
|
// ******* SYMBOL TO BIT *******
|
||||||
// extended correlation to bit period is enabled in tracking!
|
// 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++;
|
symbol_accumulator_counter++;
|
||||||
if (symbol_accumulator_counter == 20)
|
if (symbol_accumulator_counter == 20)
|
||||||
{
|
{
|
||||||
@ -221,6 +232,11 @@ bool gps_l1_ca_telemetry_decoder_gs::decode_subframe()
|
|||||||
if (symbol_accumulator > 0)
|
if (symbol_accumulator > 0)
|
||||||
{
|
{
|
||||||
GPS_frame_4bytes += 1; // insert the telemetry bit in LSB
|
GPS_frame_4bytes += 1; // insert the telemetry bit in LSB
|
||||||
|
//std::cout << "1";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//std::cout << "0";
|
||||||
}
|
}
|
||||||
symbol_accumulator = 0;
|
symbol_accumulator = 0;
|
||||||
symbol_accumulator_counter = 0;
|
symbol_accumulator_counter = 0;
|
||||||
@ -276,7 +292,7 @@ bool gps_l1_ca_telemetry_decoder_gs::decode_subframe()
|
|||||||
// NEW GPS SUBFRAME HAS ARRIVED!
|
// NEW GPS SUBFRAME HAS ARRIVED!
|
||||||
if (CRC_ok)
|
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)
|
if (subframe_ID > 0 and subframe_ID < 6)
|
||||||
{
|
{
|
||||||
std::cout << "New GPS NAV message received in channel " << this->d_channel << ": "
|
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:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
d_flag_new_tow_available = true;
|
|
||||||
}
|
}
|
||||||
else
|
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)),
|
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)
|
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
|
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
|
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
|
// 1. Copy the current tracking output
|
||||||
current_symbol = in[0][0];
|
Gnss_Synchro current_symbol = in[0][0];
|
||||||
|
// add new symbol to the symbol queue
|
||||||
// record the oldest subframe symbol before inserting a new symbol into the circular buffer
|
d_symbol_history.push_back(current_symbol.Prompt_I);
|
||||||
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
|
|
||||||
d_sample_counter++; // count for the processed symbols
|
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)
|
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__
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ******* frame sync ******************
|
||||||
// ******* preamble correlation ********
|
switch (d_stat)
|
||||||
|
{
|
||||||
|
case 0: // no preamble information
|
||||||
|
{
|
||||||
|
//correlate with preamble
|
||||||
int32_t corr_value = 0;
|
int32_t corr_value = 0;
|
||||||
if ((d_symbol_history.size() == GPS_CA_PREAMBLE_LENGTH_SYMBOLS))
|
if (d_symbol_history.size() >= GPS_CA_PREAMBLE_LENGTH_SYMBOLS)
|
||||||
{
|
{
|
||||||
int i = 0;
|
// ******* preamble correlation ********
|
||||||
for (const auto &iter : d_symbol_history)
|
for (int32_t i = 0; i < GPS_CA_PREAMBLE_LENGTH_SYMBOLS; i++)
|
||||||
{
|
{
|
||||||
if (iter.Flag_valid_symbol_output == true)
|
if (d_symbol_history[i] < 0.0) // symbols clipping
|
||||||
{
|
{
|
||||||
if (iter.Prompt_I < 0.0) // symbols clipping
|
corr_value -= d_preamble_samples[i];
|
||||||
{
|
|
||||||
corr_value -= d_preambles_symbols[i];
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
corr_value += d_preambles_symbols[i];
|
corr_value += d_preamble_samples[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
}
|
if (abs(corr_value) >= d_samples_per_preamble)
|
||||||
|
|
||||||
// ******* frame sync ******************
|
|
||||||
if (std::abs(corr_value) == GPS_CA_PREAMBLE_LENGTH_SYMBOLS)
|
|
||||||
{
|
{
|
||||||
//TODO: Rewrite with state machine
|
d_preamble_index = d_sample_counter; // record the preamble sample stamp
|
||||||
if (d_stat == 0)
|
DLOG(INFO) << "Preamble detection for GPS L1 satellite " << this->d_satellite;
|
||||||
{
|
|
||||||
// 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
|
d_stat = 1; // enter into frame pre-detection status
|
||||||
}
|
}
|
||||||
else if (d_stat == 1) // check 6 seconds of preamble separation
|
break;
|
||||||
|
}
|
||||||
|
case 1: // possible preamble lock
|
||||||
{
|
{
|
||||||
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);
|
//correlate with preamble
|
||||||
if (std::abs(preamble_diff_ms - GPS_SUBFRAME_MS) % GPS_SUBFRAME_MS == 0)
|
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;
|
DLOG(INFO) << "Preamble confirmation for SAT " << this->d_satellite;
|
||||||
d_flag_preamble = true;
|
d_preamble_index = d_sample_counter; // record the preamble sample stamp
|
||||||
d_preamble_time_samples = d_symbol_history[0].Tracking_sample_counter; // record the PRN start sample index associated to the preamble
|
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)
|
||||||
|
|
||||||
|
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)
|
if (!d_flag_frame_sync)
|
||||||
{
|
{
|
||||||
d_flag_frame_sync = true;
|
d_flag_frame_sync = true;
|
||||||
if (corr_value < 0)
|
DLOG(INFO) << " Frame sync SAT " << this->d_satellite;
|
||||||
{
|
|
||||||
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]";
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
else
|
||||||
{
|
{
|
||||||
if (d_stat == 1)
|
d_CRC_error_counter++;
|
||||||
|
d_preamble_index = d_sample_counter; // record the preamble sample stamp
|
||||||
|
if (d_CRC_error_counter > 2)
|
||||||
{
|
{
|
||||||
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);
|
DLOG(INFO) << "Lost of frame sync SAT " << this->d_satellite;
|
||||||
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;
|
d_flag_frame_sync = false;
|
||||||
flag_TOW_set = false;
|
d_stat = 0;
|
||||||
d_current_subframe_symbol = 0;
|
|
||||||
d_crc_error_synchronization_counter = 0;
|
|
||||||
d_TOW_at_current_symbol_ms = 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
|
// 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);
|
d_TOW_at_Preamble_ms = static_cast<uint32_t>(d_nav.d_TOW * 1000.0);
|
||||||
flag_TOW_set = true;
|
flag_TOW_set = true;
|
||||||
d_flag_new_tow_available = false;
|
|
||||||
d_last_valid_preamble = d_sample_counter;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -73,46 +73,45 @@ private:
|
|||||||
gps_l1_ca_make_telemetry_decoder_gs(const Gnss_Satellite &satellite, bool dump);
|
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);
|
gps_l1_ca_telemetry_decoder_gs(const Gnss_Satellite &satellite, bool dump);
|
||||||
|
|
||||||
bool gps_word_parityCheck(uint32_t gpsword);
|
bool gps_word_parityCheck(uint32_t gpsword);
|
||||||
|
|
||||||
bool decode_subframe();
|
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;
|
uint64_t d_sample_counter;
|
||||||
bool d_sent_tlm_failed_msg;
|
uint64_t d_preamble_index;
|
||||||
uint64_t d_last_valid_preamble;
|
uint64_t d_last_valid_preamble;
|
||||||
uint32_t d_max_symbols_without_valid_frame;
|
uint32_t d_max_symbols_without_valid_frame;
|
||||||
|
|
||||||
int *d_preambles_symbols;
|
bool d_sent_tlm_failed_msg;
|
||||||
uint32_t d_stat;
|
uint32_t d_stat;
|
||||||
bool d_flag_frame_sync;
|
bool d_flag_frame_sync;
|
||||||
|
bool d_flag_parity;
|
||||||
// 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_preamble;
|
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;
|
Gnss_Satellite d_satellite;
|
||||||
int d_channel;
|
int32_t d_channel;
|
||||||
|
|
||||||
uint64_t d_preamble_time_samples;
|
|
||||||
|
|
||||||
uint32_t d_TOW_at_Preamble_ms;
|
uint32_t d_TOW_at_Preamble_ms;
|
||||||
uint32_t d_TOW_at_current_symbol_ms;
|
uint32_t d_TOW_at_current_symbol_ms;
|
||||||
|
|
||||||
bool flag_TOW_set;
|
bool flag_TOW_set;
|
||||||
bool flag_PLL_180_deg_phase_locked;
|
bool d_dump;
|
||||||
|
|
||||||
std::string d_dump_filename;
|
std::string d_dump_filename;
|
||||||
std::ofstream d_dump_file;
|
std::ofstream d_dump_file;
|
||||||
};
|
};
|
||||||
|
@ -48,6 +48,11 @@
|
|||||||
#include <cstring> // for memcpy
|
#include <cstring> // for memcpy
|
||||||
#include <iostream> // for operator<<,
|
#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(
|
GalileoE1DllPllVemlTrackingFpga::GalileoE1DllPllVemlTrackingFpga(
|
||||||
ConfigurationInterface* configuration, const std::string& role,
|
ConfigurationInterface* configuration, const std::string& role,
|
||||||
@ -56,8 +61,6 @@ GalileoE1DllPllVemlTrackingFpga::GalileoE1DllPllVemlTrackingFpga(
|
|||||||
Dll_Pll_Conf_Fpga trk_param_fpga = Dll_Pll_Conf_Fpga();
|
Dll_Pll_Conf_Fpga trk_param_fpga = Dll_Pll_Conf_Fpga();
|
||||||
DLOG(INFO) << "role " << role;
|
DLOG(INFO) << "role " << role;
|
||||||
//################# CONFIGURATION PARAMETERS ########################
|
//################# 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_deprecated = configuration->property("GNSS-SDR.internal_fs_hz", 2048000);
|
||||||
int32_t fs_in = configuration->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated);
|
int32_t fs_in = configuration->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated);
|
||||||
trk_param_fpga.fs_in = fs_in;
|
trk_param_fpga.fs_in = fs_in;
|
||||||
@ -68,16 +71,76 @@ GalileoE1DllPllVemlTrackingFpga::GalileoE1DllPllVemlTrackingFpga(
|
|||||||
trk_param_fpga.dump_filename = dump_filename;
|
trk_param_fpga.dump_filename = dump_filename;
|
||||||
bool dump_mat = configuration->property(role + ".dump_mat", true);
|
bool dump_mat = configuration->property(role + ".dump_mat", true);
|
||||||
trk_param_fpga.dump_mat = dump_mat;
|
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);
|
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;
|
trk_param_fpga.pll_bw_hz = pll_bw_hz;
|
||||||
float dll_bw_hz = configuration->property(role + ".dll_bw_hz", 0.5);
|
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;
|
trk_param_fpga.dll_bw_hz = dll_bw_hz;
|
||||||
float pll_bw_narrow_hz = configuration->property(role + ".pll_bw_narrow_hz", 2.0);
|
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;
|
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);
|
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;
|
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);
|
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);
|
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;
|
trk_param_fpga.early_late_space_chips = early_late_space_chips;
|
||||||
@ -111,16 +174,29 @@ GalileoE1DllPllVemlTrackingFpga::GalileoE1DllPllVemlTrackingFpga(
|
|||||||
char sig_[3] = "1B";
|
char sig_[3] = "1B";
|
||||||
std::memcpy(trk_param_fpga.signal, sig_, 3);
|
std::memcpy(trk_param_fpga.signal, sig_, 3);
|
||||||
int32_t cn0_samples = configuration->property(role + ".cn0_samples", 20);
|
int32_t cn0_samples = configuration->property(role + ".cn0_samples", 20);
|
||||||
if (FLAGS_cn0_samples != 20) cn0_samples = FLAGS_cn0_samples;
|
if (FLAGS_cn0_samples != 20)
|
||||||
|
{
|
||||||
|
cn0_samples = FLAGS_cn0_samples;
|
||||||
|
}
|
||||||
|
|
||||||
trk_param_fpga.cn0_samples = cn0_samples;
|
trk_param_fpga.cn0_samples = cn0_samples;
|
||||||
int32_t cn0_min = configuration->property(role + ".cn0_min", 25);
|
int32_t cn0_min = configuration->property(role + ".cn0_min", 25);
|
||||||
if (FLAGS_cn0_min != 25) cn0_min = FLAGS_cn0_min;
|
if (FLAGS_cn0_min != 25)
|
||||||
|
{
|
||||||
|
cn0_min = FLAGS_cn0_min;
|
||||||
|
}
|
||||||
trk_param_fpga.cn0_min = cn0_min;
|
trk_param_fpga.cn0_min = cn0_min;
|
||||||
int32_t max_lock_fail = configuration->property(role + ".max_lock_fail", 50);
|
int32_t max_lock_fail = configuration->property(role + ".max_lock_fail", 50);
|
||||||
if (FLAGS_max_lock_fail != 50) max_lock_fail = FLAGS_max_lock_fail;
|
if (FLAGS_max_lock_fail != 50)
|
||||||
|
{
|
||||||
|
max_lock_fail = FLAGS_max_lock_fail;
|
||||||
|
}
|
||||||
trk_param_fpga.max_lock_fail = max_lock_fail;
|
trk_param_fpga.max_lock_fail = max_lock_fail;
|
||||||
double carrier_lock_th = configuration->property(role + ".carrier_lock_th", 0.85);
|
double carrier_lock_th = configuration->property(role + ".carrier_lock_th", 0.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;
|
trk_param_fpga.carrier_lock_th = carrier_lock_th;
|
||||||
|
|
||||||
// FPGA configuration parameters
|
// 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(ca_codes_f, pilot_signal, PRN);
|
||||||
galileo_e1_code_gen_sinboc11_float(data_codes_f, data_signal, PRN);
|
galileo_e1_code_gen_sinboc11_float(data_codes_f, data_signal, PRN);
|
||||||
|
|
||||||
|
// 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++)
|
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]);
|
||||||
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]);
|
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
|
else
|
||||||
{
|
{
|
||||||
galileo_e1_code_gen_sinboc11_float(ca_codes_f, data_signal, PRN);
|
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++)
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,11 @@
|
|||||||
#include <cstring> // for memcpy
|
#include <cstring> // for memcpy
|
||||||
#include <iostream>
|
#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(
|
GalileoE5aDllPllTrackingFpga::GalileoE5aDllPllTrackingFpga(
|
||||||
ConfigurationInterface *configuration, const std::string &role,
|
ConfigurationInterface *configuration, const std::string &role,
|
||||||
@ -53,8 +58,6 @@ GalileoE5aDllPllTrackingFpga::GalileoE5aDllPllTrackingFpga(
|
|||||||
Dll_Pll_Conf_Fpga trk_param_fpga = Dll_Pll_Conf_Fpga();
|
Dll_Pll_Conf_Fpga trk_param_fpga = Dll_Pll_Conf_Fpga();
|
||||||
DLOG(INFO) << "role " << role;
|
DLOG(INFO) << "role " << role;
|
||||||
//################# CONFIGURATION PARAMETERS ########################
|
//################# 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_deprecated = configuration->property("GNSS-SDR.internal_fs_hz", 12000000);
|
||||||
int32_t fs_in = configuration->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated);
|
int32_t fs_in = configuration->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated);
|
||||||
trk_param_fpga.fs_in = fs_in;
|
trk_param_fpga.fs_in = fs_in;
|
||||||
@ -65,12 +68,71 @@ GalileoE5aDllPllTrackingFpga::GalileoE5aDllPllTrackingFpga(
|
|||||||
trk_param_fpga.dump_filename = dump_filename;
|
trk_param_fpga.dump_filename = dump_filename;
|
||||||
bool dump_mat = configuration->property(role + ".dump_mat", true);
|
bool dump_mat = configuration->property(role + ".dump_mat", true);
|
||||||
trk_param_fpga.dump_mat = dump_mat;
|
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);
|
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;
|
trk_param_fpga.pll_bw_hz = pll_bw_hz;
|
||||||
float dll_bw_hz = configuration->property(role + ".dll_bw_hz", 20.0);
|
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;
|
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);
|
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;
|
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);
|
float dll_bw_narrow_hz = configuration->property(role + ".dll_bw_narrow_hz", 2.0);
|
||||||
@ -106,17 +168,30 @@ GalileoE5aDllPllTrackingFpga::GalileoE5aDllPllTrackingFpga(
|
|||||||
char sig_[3] = "5X";
|
char sig_[3] = "5X";
|
||||||
std::memcpy(trk_param_fpga.signal, sig_, 3);
|
std::memcpy(trk_param_fpga.signal, sig_, 3);
|
||||||
int32_t cn0_samples = configuration->property(role + ".cn0_samples", 20);
|
int32_t cn0_samples = configuration->property(role + ".cn0_samples", 20);
|
||||||
if (FLAGS_cn0_samples != 20) cn0_samples = FLAGS_cn0_samples;
|
if (FLAGS_cn0_samples != 20)
|
||||||
|
{
|
||||||
|
cn0_samples = FLAGS_cn0_samples;
|
||||||
|
}
|
||||||
trk_param_fpga.cn0_samples = cn0_samples;
|
trk_param_fpga.cn0_samples = cn0_samples;
|
||||||
int32_t cn0_min = configuration->property(role + ".cn0_min", 25);
|
int32_t cn0_min = configuration->property(role + ".cn0_min", 25);
|
||||||
if (FLAGS_cn0_min != 25) cn0_min = FLAGS_cn0_min;
|
if (FLAGS_cn0_min != 25)
|
||||||
|
{
|
||||||
|
cn0_min = FLAGS_cn0_min;
|
||||||
|
}
|
||||||
trk_param_fpga.cn0_min = cn0_min;
|
trk_param_fpga.cn0_min = cn0_min;
|
||||||
int32_t max_lock_fail = configuration->property(role + ".max_lock_fail", 50);
|
int32_t max_lock_fail = configuration->property(role + ".max_lock_fail", 50);
|
||||||
if (FLAGS_max_lock_fail != 50) max_lock_fail = FLAGS_max_lock_fail;
|
if (FLAGS_max_lock_fail != 50)
|
||||||
|
{
|
||||||
|
max_lock_fail = FLAGS_max_lock_fail;
|
||||||
|
}
|
||||||
trk_param_fpga.max_lock_fail = max_lock_fail;
|
trk_param_fpga.max_lock_fail = max_lock_fail;
|
||||||
double carrier_lock_th = configuration->property(role + ".carrier_lock_th", 0.85);
|
double carrier_lock_th = configuration->property(role + ".carrier_lock_th", 0.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;
|
trk_param_fpga.carrier_lock_th = carrier_lock_th;
|
||||||
|
|
||||||
d_data_codes = nullptr;
|
d_data_codes = nullptr;
|
||||||
|
|
||||||
// FPGA configuration parameters
|
// FPGA configuration parameters
|
||||||
@ -143,19 +218,41 @@ GalileoE5aDllPllTrackingFpga::GalileoE5aDllPllTrackingFpga(
|
|||||||
for (uint32_t PRN = 1; PRN <= GALILEO_E5A_NUMBER_OF_CODES; PRN++)
|
for (uint32_t PRN = 1; PRN <= GALILEO_E5A_NUMBER_OF_CODES; PRN++)
|
||||||
{
|
{
|
||||||
galileo_e5_a_code_gen_complex_primary(aux_code, PRN, const_cast<char *>(sig_));
|
galileo_e5_a_code_gen_complex_primary(aux_code, PRN, const_cast<char *>(sig_));
|
||||||
|
|
||||||
if (trk_param_fpga.track_pilot)
|
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++)
|
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());
|
int32_t tmp_value = 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());
|
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
|
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++)
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,6 @@ private:
|
|||||||
std::string role_;
|
std::string role_;
|
||||||
uint32_t in_streams_;
|
uint32_t in_streams_;
|
||||||
uint32_t out_streams_;
|
uint32_t out_streams_;
|
||||||
|
|
||||||
int32_t* d_ca_codes;
|
int32_t* d_ca_codes;
|
||||||
int32_t* d_data_codes;
|
int32_t* d_data_codes;
|
||||||
bool d_track_pilot;
|
bool d_track_pilot;
|
||||||
|
@ -48,8 +48,11 @@
|
|||||||
#include <cstring> // for memcpy
|
#include <cstring> // for memcpy
|
||||||
#include <iostream>
|
#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(
|
GpsL1CaDllPllTrackingFpga::GpsL1CaDllPllTrackingFpga(
|
||||||
ConfigurationInterface* configuration, const std::string& role,
|
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_deprecated = configuration->property("GNSS-SDR.internal_fs_hz", 2048000);
|
||||||
int32_t fs_in = configuration->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated);
|
int32_t fs_in = configuration->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated);
|
||||||
trk_param_fpga.fs_in = fs_in;
|
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);
|
bool dump = configuration->property(role + ".dump", false);
|
||||||
trk_param_fpga.dump = dump;
|
trk_param_fpga.dump = dump;
|
||||||
std::string default_dump_filename = "./track_ch";
|
std::string default_dump_filename = "./track_ch";
|
||||||
@ -70,15 +84,64 @@ GpsL1CaDllPllTrackingFpga::GpsL1CaDllPllTrackingFpga(
|
|||||||
bool dump_mat = configuration->property(role + ".dump_mat", true);
|
bool dump_mat = configuration->property(role + ".dump_mat", true);
|
||||||
trk_param_fpga.dump_mat = dump_mat;
|
trk_param_fpga.dump_mat = dump_mat;
|
||||||
float pll_bw_hz = configuration->property(role + ".pll_bw_hz", 50.0);
|
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;
|
trk_param_fpga.pll_bw_hz = pll_bw_hz;
|
||||||
float pll_bw_narrow_hz = configuration->property(role + ".pll_bw_narrow_hz", 20.0);
|
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;
|
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);
|
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;
|
trk_param_fpga.dll_bw_narrow_hz = dll_bw_narrow_hz;
|
||||||
float dll_bw_hz = configuration->property(role + ".dll_bw_hz", 2.0);
|
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;
|
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);
|
float early_late_space_chips = configuration->property(role + ".early_late_space_chips", 0.5);
|
||||||
trk_param_fpga.early_late_space_chips = early_late_space_chips;
|
trk_param_fpga.early_late_space_chips = early_late_space_chips;
|
||||||
float early_late_space_narrow_chips = configuration->property(role + ".early_late_space_narrow_chips", 0.5);
|
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";
|
char sig_[3] = "1C";
|
||||||
std::memcpy(trk_param_fpga.signal, sig_, 3);
|
std::memcpy(trk_param_fpga.signal, sig_, 3);
|
||||||
int32_t cn0_samples = configuration->property(role + ".cn0_samples", 20);
|
int32_t cn0_samples = configuration->property(role + ".cn0_samples", 20);
|
||||||
if (FLAGS_cn0_samples != 20) cn0_samples = FLAGS_cn0_samples;
|
if (FLAGS_cn0_samples != 20)
|
||||||
|
{
|
||||||
|
cn0_samples = FLAGS_cn0_samples;
|
||||||
|
}
|
||||||
trk_param_fpga.cn0_samples = cn0_samples;
|
trk_param_fpga.cn0_samples = cn0_samples;
|
||||||
int32_t cn0_min = configuration->property(role + ".cn0_min", 25);
|
int32_t cn0_min = configuration->property(role + ".cn0_min", 30);
|
||||||
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;
|
trk_param_fpga.cn0_min = cn0_min;
|
||||||
int32_t max_lock_fail = configuration->property(role + ".max_lock_fail", 50);
|
int32_t max_lock_fail = configuration->property(role + ".max_lock_fail", 50);
|
||||||
if (FLAGS_max_lock_fail != 50) max_lock_fail = FLAGS_max_lock_fail;
|
if (FLAGS_max_lock_fail != 50)
|
||||||
|
{
|
||||||
|
max_lock_fail = FLAGS_max_lock_fail;
|
||||||
|
}
|
||||||
trk_param_fpga.max_lock_fail = max_lock_fail;
|
trk_param_fpga.max_lock_fail = max_lock_fail;
|
||||||
double carrier_lock_th = configuration->property(role + ".carrier_lock_th", 0.85);
|
double carrier_lock_th = configuration->property(role + ".carrier_lock_th", 0.80);
|
||||||
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;
|
trk_param_fpga.carrier_lock_th = carrier_lock_th;
|
||||||
|
|
||||||
// FPGA configuration parameters
|
// FPGA configuration parameters
|
||||||
@ -138,6 +213,18 @@ GpsL1CaDllPllTrackingFpga::GpsL1CaDllPllTrackingFpga(
|
|||||||
for (uint32_t PRN = 1; PRN <= NUM_PRNs; PRN++)
|
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);
|
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.ca_codes = d_ca_codes;
|
||||||
trk_param_fpga.code_length_chips = GPS_L1_CA_CODE_LENGTH_CHIPS;
|
trk_param_fpga.code_length_chips = GPS_L1_CA_CODE_LENGTH_CHIPS;
|
||||||
|
@ -50,7 +50,12 @@
|
|||||||
#include <cstring> // for memcpy
|
#include <cstring> // for memcpy
|
||||||
#include <iostream>
|
#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(
|
GpsL5DllPllTrackingFpga::GpsL5DllPllTrackingFpga(
|
||||||
@ -70,11 +75,27 @@ GpsL5DllPllTrackingFpga::GpsL5DllPllTrackingFpga(
|
|||||||
trk_param_fpga.dump_filename = dump_filename;
|
trk_param_fpga.dump_filename = dump_filename;
|
||||||
bool dump_mat = configuration->property(role + ".dump_mat", true);
|
bool dump_mat = configuration->property(role + ".dump_mat", true);
|
||||||
trk_param_fpga.dump_mat = dump_mat;
|
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);
|
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;
|
trk_param_fpga.pll_bw_hz = pll_bw_hz;
|
||||||
float dll_bw_hz = configuration->property(role + ".dll_bw_hz", 2.0);
|
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;
|
trk_param_fpga.dll_bw_hz = dll_bw_hz;
|
||||||
float pll_bw_narrow_hz = configuration->property(role + ".pll_bw_narrow_hz", 2.0);
|
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;
|
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;
|
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);
|
float early_late_space_chips = configuration->property(role + ".early_late_space_chips", 0.5);
|
||||||
trk_param_fpga.early_late_space_chips = early_late_space_chips;
|
trk_param_fpga.early_late_space_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)));
|
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;
|
trk_param_fpga.vector_length = vector_length;
|
||||||
int32_t extend_correlation_symbols = configuration->property(role + ".extend_correlation_symbols", 1);
|
int32_t extend_correlation_symbols = configuration->property(role + ".extend_correlation_symbols", 1);
|
||||||
@ -111,16 +175,28 @@ GpsL5DllPllTrackingFpga::GpsL5DllPllTrackingFpga(
|
|||||||
char sig_[3] = "L5";
|
char sig_[3] = "L5";
|
||||||
std::memcpy(trk_param_fpga.signal, sig_, 3);
|
std::memcpy(trk_param_fpga.signal, sig_, 3);
|
||||||
int32_t cn0_samples = configuration->property(role + ".cn0_samples", 20);
|
int32_t cn0_samples = configuration->property(role + ".cn0_samples", 20);
|
||||||
if (FLAGS_cn0_samples != 20) cn0_samples = FLAGS_cn0_samples;
|
if (FLAGS_cn0_samples != 20)
|
||||||
|
{
|
||||||
|
cn0_samples = FLAGS_cn0_samples;
|
||||||
|
}
|
||||||
trk_param_fpga.cn0_samples = cn0_samples;
|
trk_param_fpga.cn0_samples = cn0_samples;
|
||||||
int32_t cn0_min = configuration->property(role + ".cn0_min", 25);
|
int32_t cn0_min = configuration->property(role + ".cn0_min", 25);
|
||||||
if (FLAGS_cn0_min != 25) cn0_min = FLAGS_cn0_min;
|
if (FLAGS_cn0_min != 25)
|
||||||
|
{
|
||||||
|
cn0_min = FLAGS_cn0_min;
|
||||||
|
}
|
||||||
trk_param_fpga.cn0_min = cn0_min;
|
trk_param_fpga.cn0_min = cn0_min;
|
||||||
int32_t max_lock_fail = configuration->property(role + ".max_lock_fail", 50);
|
int32_t max_lock_fail = configuration->property(role + ".max_lock_fail", 50);
|
||||||
if (FLAGS_max_lock_fail != 50) max_lock_fail = FLAGS_max_lock_fail;
|
if (FLAGS_max_lock_fail != 50)
|
||||||
|
{
|
||||||
|
max_lock_fail = FLAGS_max_lock_fail;
|
||||||
|
}
|
||||||
trk_param_fpga.max_lock_fail = max_lock_fail;
|
trk_param_fpga.max_lock_fail = max_lock_fail;
|
||||||
double carrier_lock_th = configuration->property(role + ".carrier_lock_th", 0.75);
|
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;
|
trk_param_fpga.carrier_lock_th = carrier_lock_th;
|
||||||
|
|
||||||
// FPGA configuration parameters
|
// FPGA configuration parameters
|
||||||
@ -163,18 +239,40 @@ GpsL5DllPllTrackingFpga::GpsL5DllPllTrackingFpga(
|
|||||||
gps_l5q_code_gen_float(tracking_code, PRN);
|
gps_l5q_code_gen_float(tracking_code, PRN);
|
||||||
gps_l5i_code_gen_float(data_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++)
|
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]);
|
||||||
d_data_codes[static_cast<int32_t>(code_length_chips) * (PRN - 1) + s] = static_cast<int32_t>(data_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
|
else
|
||||||
{
|
{
|
||||||
gps_l5i_code_gen_float(tracking_code, PRN);
|
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++)
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -560,9 +560,6 @@ void dll_pll_veml_tracking::start_tracking()
|
|||||||
d_carrier_phase_rate_step_rad = 0.0;
|
d_carrier_phase_rate_step_rad = 0.0;
|
||||||
d_carr_ph_history.clear();
|
d_carr_ph_history.clear();
|
||||||
d_code_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")
|
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;
|
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_noise_bandwidth(trk_parameters.dll_bw_hz);
|
||||||
d_code_loop_filter.set_update_interval(d_code_period);
|
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
|
// 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;
|
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;
|
d_state = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int dll_pll_veml_tracking::general_work(int noutput_items __attribute__((unused)), gr_vector_int &ninput_items,
|
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)
|
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 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;
|
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_freq_chips = d_code_chip_rate;
|
||||||
d_code_phase_step_chips = d_code_freq_chips / trk_parameters.fs_in;
|
d_code_phase_step_chips = d_code_freq_chips / trk_parameters.fs_in;
|
||||||
d_code_phase_rate_step_chips = 0.0;
|
d_code_phase_rate_step_chips = 0.0;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -33,20 +33,20 @@
|
|||||||
#define GNSS_SDR_DLL_PLL_VEML_TRACKING_FPGA_H
|
#define GNSS_SDR_DLL_PLL_VEML_TRACKING_FPGA_H
|
||||||
|
|
||||||
#include "dll_pll_conf_fpga.h"
|
#include "dll_pll_conf_fpga.h"
|
||||||
#include "tracking_2nd_DLL_filter.h"
|
#include "tracking_FLL_PLL_filter.h" // for PLL/FLL filter
|
||||||
#include "tracking_2nd_PLL_filter.h"
|
#include "tracking_loop_filter.h" // for DLL filter
|
||||||
#include <boost/circular_buffer.hpp>
|
#include <boost/circular_buffer.hpp>
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp> // for boost::shared_ptr
|
||||||
#include <gnuradio/block.h>
|
#include <gnuradio/block.h> // for block
|
||||||
#include <gnuradio/gr_complex.h> // for gr_complex
|
#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 <pmt/pmt.h> // for pmt_t
|
||||||
#include <cstdint>
|
#include <cstdint> // for int32_t
|
||||||
#include <deque> // for deque
|
#include <deque> // for deque
|
||||||
#include <fstream> // for ofstream
|
#include <fstream> // for string, ofstream
|
||||||
#include <memory> // for shared_ptr
|
#include <memory> // for shared_ptr
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility> // for pair
|
||||||
|
|
||||||
class Fpga_Multicorrelator_8sc;
|
class Fpga_Multicorrelator_8sc;
|
||||||
class Gnss_Synchro;
|
class Gnss_Synchro;
|
||||||
@ -77,7 +77,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
friend dll_pll_veml_tracking_fpga_sptr dll_pll_veml_make_tracking_fpga(const Dll_Pll_Conf_Fpga &conf_);
|
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_);
|
dll_pll_veml_tracking_fpga(const Dll_Pll_Conf_Fpga &conf_);
|
||||||
void msg_handler_preamble_index(pmt::pmt_t msg);
|
void msg_handler_preamble_index(pmt::pmt_t msg);
|
||||||
|
|
||||||
@ -91,7 +91,7 @@ private:
|
|||||||
void log_data(bool integrating);
|
void log_data(bool integrating);
|
||||||
int32_t save_matfile();
|
int32_t save_matfile();
|
||||||
|
|
||||||
void run_state_2(Gnss_Synchro ¤t_synchro_data);
|
//void run_state_2(Gnss_Synchro ¤t_synchro_data);
|
||||||
|
|
||||||
// tracking configuration vars
|
// tracking configuration vars
|
||||||
Dll_Pll_Conf_Fpga trk_parameters;
|
Dll_Pll_Conf_Fpga trk_parameters;
|
||||||
@ -115,23 +115,20 @@ private:
|
|||||||
std::string *d_secondary_code_string;
|
std::string *d_secondary_code_string;
|
||||||
std::string signal_pretty_name;
|
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;
|
boost::circular_buffer<float> d_symbol_history;
|
||||||
|
|
||||||
//tracking state machine
|
// tracking state machine
|
||||||
int32_t d_state;
|
int32_t d_state;
|
||||||
//Integration period in samples
|
|
||||||
|
// Integration period in samples
|
||||||
int32_t d_correlation_length_ms;
|
int32_t d_correlation_length_ms;
|
||||||
int32_t d_n_correlator_taps;
|
int32_t d_n_correlator_taps;
|
||||||
|
|
||||||
float *d_local_code_shift_chips;
|
float *d_local_code_shift_chips;
|
||||||
float *d_prompt_data_shift;
|
float *d_prompt_data_shift;
|
||||||
std::shared_ptr<Fpga_Multicorrelator_8sc> multicorrelator_fpga;
|
std::shared_ptr<Fpga_Multicorrelator_8sc> multicorrelator_fpga;
|
||||||
/* TODO: currently the multicorrelator does not support adding extra correlator
|
|
||||||
with different local code, thus we need extra multicorrelator instance.
|
|
||||||
Implement this functionality inside multicorrelator class
|
|
||||||
as an enhancement to increase the performance
|
|
||||||
*/
|
|
||||||
gr_complex *d_correlator_outs;
|
gr_complex *d_correlator_outs;
|
||||||
gr_complex *d_Very_Early;
|
gr_complex *d_Very_Early;
|
||||||
gr_complex *d_Early;
|
gr_complex *d_Early;
|
||||||
@ -146,9 +143,9 @@ private:
|
|||||||
gr_complex d_VE_accu;
|
gr_complex d_VE_accu;
|
||||||
gr_complex d_E_accu;
|
gr_complex d_E_accu;
|
||||||
gr_complex d_P_accu;
|
gr_complex d_P_accu;
|
||||||
|
gr_complex d_P_accu_old;
|
||||||
gr_complex d_L_accu;
|
gr_complex d_L_accu;
|
||||||
gr_complex d_VL_accu;
|
gr_complex d_VL_accu;
|
||||||
gr_complex d_last_prompt;
|
|
||||||
|
|
||||||
gr_complex *d_Prompt_Data;
|
gr_complex *d_Prompt_Data;
|
||||||
|
|
||||||
@ -163,15 +160,18 @@ private:
|
|||||||
float d_rem_carr_phase_rad;
|
float d_rem_carr_phase_rad;
|
||||||
|
|
||||||
// PLL and DLL filter library
|
// PLL and DLL filter library
|
||||||
Tracking_2nd_DLL_filter d_code_loop_filter;
|
Tracking_loop_filter d_code_loop_filter;
|
||||||
Tracking_2nd_PLL_filter d_carrier_loop_filter;
|
Tracking_FLL_PLL_filter d_carrier_loop_filter;
|
||||||
|
|
||||||
// acquisition
|
// acquisition
|
||||||
double d_acq_code_phase_samples;
|
double d_acq_code_phase_samples;
|
||||||
double d_acq_carrier_doppler_hz;
|
double d_acq_carrier_doppler_hz;
|
||||||
|
|
||||||
// tracking vars
|
// 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_carr_error_filt_hz;
|
||||||
double d_code_error_chips;
|
double d_code_error_chips;
|
||||||
double d_code_error_filt_chips;
|
double d_code_error_filt_chips;
|
||||||
@ -194,11 +194,12 @@ private:
|
|||||||
// CN0 estimation and lock detector
|
// CN0 estimation and lock detector
|
||||||
int32_t d_cn0_estimation_counter;
|
int32_t d_cn0_estimation_counter;
|
||||||
int32_t d_carrier_lock_fail_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_carrier_lock_test;
|
||||||
double d_CN0_SNV_dB_Hz;
|
double d_CN0_SNV_dB_Hz;
|
||||||
double d_carrier_lock_threshold;
|
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;
|
gr_complex *d_Prompt_buffer;
|
||||||
|
|
||||||
// file dump
|
// file dump
|
||||||
|
@ -44,6 +44,15 @@ Dll_Pll_Conf_Fpga::Dll_Pll_Conf_Fpga()
|
|||||||
dump = false;
|
dump = false;
|
||||||
dump_mat = true;
|
dump_mat = true;
|
||||||
dump_filename = std::string("./dll_pll_dump.dat");
|
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;
|
pll_bw_hz = 35.0;
|
||||||
dll_bw_hz = 2.0;
|
dll_bw_hz = 2.0;
|
||||||
pll_bw_narrow_hz = 5.0;
|
pll_bw_narrow_hz = 5.0;
|
||||||
|
@ -42,11 +42,22 @@ class Dll_Pll_Conf_Fpga
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/* DLL/PLL tracking configuration */
|
/* 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;
|
double fs_in;
|
||||||
uint32_t vector_length;
|
uint32_t vector_length;
|
||||||
bool dump;
|
bool dump;
|
||||||
bool dump_mat;
|
bool dump_mat;
|
||||||
std::string dump_filename;
|
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 pll_bw_hz;
|
||||||
float dll_bw_hz;
|
float dll_bw_hz;
|
||||||
float pll_bw_narrow_hz;
|
float pll_bw_narrow_hz;
|
||||||
|
@ -51,14 +51,15 @@
|
|||||||
#define CODE_PHASE_STEP_CHIPS_NUM_NBITS CODE_RESAMPLER_NUM_BITS_PRECISION
|
#define CODE_PHASE_STEP_CHIPS_NUM_NBITS CODE_RESAMPLER_NUM_BITS_PRECISION
|
||||||
#define pwrtwo(x) (1 << (x))
|
#define pwrtwo(x) (1 << (x))
|
||||||
#define MAX_CODE_RESAMPLER_COUNTER pwrtwo(CODE_PHASE_STEP_CHIPS_NUM_NBITS) // 2^CODE_PHASE_STEP_CHIPS_NUM_NBITS
|
#define MAX_CODE_RESAMPLER_COUNTER pwrtwo(CODE_PHASE_STEP_CHIPS_NUM_NBITS) // 2^CODE_PHASE_STEP_CHIPS_NUM_NBITS
|
||||||
#define PHASE_CARR_NBITS 32
|
#define PHASE_CARR_MAX 2147483648 // 2^(31) The phase is represented as a 32-bit vector in 1.31 format
|
||||||
#define PHASE_CARR_NBITS_INT 1
|
#define PHASE_CARR_MAX_div_PI 683565275.5764316 // 2^(31)/pi
|
||||||
#define PHASE_CARR_NBITS_FRAC PHASE_CARR_NBITS - PHASE_CARR_NBITS_INT
|
#define TWO_PI 6.283185307179586
|
||||||
#define LOCAL_CODE_FPGA_CORRELATOR_SELECT_COUNT 0x20000000
|
#define LOCAL_CODE_FPGA_CORRELATOR_SELECT_COUNT 0x20000000
|
||||||
#define LOCAL_CODE_FPGA_CLEAR_ADDRESS_COUNTER 0x10000000
|
#define LOCAL_CODE_FPGA_CLEAR_ADDRESS_COUNTER 0x10000000
|
||||||
#define LOCAL_CODE_FPGA_ENABLE_WRITE_MEMORY 0x0C000000
|
#define LOCAL_CODE_FPGA_ENABLE_WRITE_MEMORY 0x0C000000
|
||||||
#define TEST_REGISTER_TRACK_WRITEVAL 0x55AA
|
#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
|
#ifndef TEMP_FAILURE_RETRY
|
||||||
#define TEMP_FAILURE_RETRY(exp) \
|
#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_data_codes = data_codes;
|
||||||
d_multicorr_type = multicorr_type;
|
d_multicorr_type = multicorr_type;
|
||||||
d_code_samples_per_chip = code_samples_per_chip;
|
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";
|
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_compute_code_shift_parameters();
|
||||||
Fpga_Multicorrelator_8sc::fpga_configure_code_parameters_in_fpga();
|
Fpga_Multicorrelator_8sc::fpga_configure_code_parameters_in_fpga();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Fpga_Multicorrelator_8sc::Carrier_wipeoff_multicorrelator_resampler(
|
void Fpga_Multicorrelator_8sc::Carrier_wipeoff_multicorrelator_resampler(
|
||||||
float rem_carrier_phase_in_rad,
|
float rem_carrier_phase_in_rad, // nco phase initial position
|
||||||
float phase_step_rad,
|
float phase_step_rad, // nco phase step
|
||||||
float carrier_phase_rate_step_rad __attribute__((unused)),
|
float carrier_phase_rate_step_rad __attribute__((unused)), // nco phase step rate change
|
||||||
float rem_code_phase_chips,
|
float rem_code_phase_chips, // code resampler initial position
|
||||||
float code_phase_step_chips __attribute__((unused)),
|
float code_phase_step_chips __attribute__((unused)), // code resampler step
|
||||||
float code_phase_rate_step_chips __attribute__((unused)),
|
float code_phase_rate_step_chips __attribute__((unused)), // code resampler step rate
|
||||||
int32_t signal_length_samples)
|
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; // nco phase initial position
|
||||||
d_rem_carrier_phase_in_rad = rem_carrier_phase_in_rad;
|
d_phase_step_rad = phase_step_rad; // nco phase step
|
||||||
d_code_phase_step_chips = code_phase_step_chips;
|
d_carrier_phase_rate_step_rad = carrier_phase_rate_step_rad; // nco phase step rate
|
||||||
d_phase_step_rad = phase_step_rad;
|
d_rem_code_phase_chips = rem_code_phase_chips; // code resampler initial position
|
||||||
d_correlator_length_samples = signal_length_samples;
|
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_compute_signal_parameters_in_fpga();
|
||||||
Fpga_Multicorrelator_8sc::fpga_configure_signal_parameters_in_fpga();
|
Fpga_Multicorrelator_8sc::fpga_configure_signal_parameters_in_fpga();
|
||||||
Fpga_Multicorrelator_8sc::fpga_launch_multicorrelator_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 !";
|
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)
|
void Fpga_Multicorrelator_8sc::fpga_configure_tracking_gps_local_code(int32_t PRN)
|
||||||
{
|
{
|
||||||
uint32_t k;
|
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;
|
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)
|
d_map_base[PROG_MEMS_ADDR] = d_ca_codes[(d_code_length_samples * (PRN - 1)) + k];
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
if (d_track_pilot)
|
if (d_track_pilot)
|
||||||
{
|
{
|
||||||
d_map_base[PROG_MEMS_ADDR] = LOCAL_CODE_FPGA_CLEAR_ADDRESS_COUNTER;
|
d_map_base[PROG_MEMS_ADDR] = LOCAL_CODE_FPGA_CLEAR_ADDRESS_COUNTER;
|
||||||
for (k = 0; k < d_code_length_chips * d_code_samples_per_chip; k++)
|
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)
|
d_map_base[PROG_MEMS_ADDR] = d_data_codes[(d_code_length_samples * (PRN - 1)) + k];
|
||||||
{
|
|
||||||
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[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)
|
void Fpga_Multicorrelator_8sc::fpga_compute_code_shift_parameters(void)
|
||||||
{
|
{
|
||||||
float temp_calculation;
|
float frac_part; // decimal part
|
||||||
int32_t i;
|
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));
|
d_initial_index[i] = dec_part;
|
||||||
temp_calculation = fmod(d_shifts_chips[i] - d_rem_code_phase_chips, 1.0);
|
|
||||||
if (temp_calculation < 0)
|
|
||||||
|
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)
|
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));
|
d_initial_index[d_n_correlators] = dec_part;
|
||||||
temp_calculation = fmod(d_prompt_data_shift[0] - d_rem_code_phase_chips, 1.0);
|
|
||||||
if (temp_calculation < 0)
|
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)
|
void Fpga_Multicorrelator_8sc::fpga_configure_code_parameters_in_fpga(void)
|
||||||
{
|
{
|
||||||
int32_t i;
|
for (uint32_t i = 0; i < d_n_correlators; i++)
|
||||||
for (i = 0; i < d_n_correlators; i++)
|
|
||||||
{
|
{
|
||||||
d_map_base[INITIAL_INDEX_REG_BASE_ADDR + i] = d_initial_index[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];
|
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_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[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;
|
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));
|
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)
|
d_code_phase_rate_step_chips_num = static_cast<uint32_t>(roundf(MAX_CODE_RESAMPLER_COUNTER * d_code_phase_rate_step_chips));
|
||||||
{
|
|
||||||
std::cout << "Warning : d_code_phase_step_chips = " << d_code_phase_step_chips << " cannot be bigger than one" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (d_rem_carrier_phase_in_rad > M_PI)
|
if (d_rem_carrier_phase_in_rad > M_PI)
|
||||||
{
|
{
|
||||||
d_rem_carrier_phase_in_rad_temp = -2 * M_PI + d_rem_carrier_phase_in_rad;
|
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)
|
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
|
else
|
||||||
{
|
{
|
||||||
d_rem_carrier_phase_in_rad_temp = d_rem_carrier_phase_in_rad;
|
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_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_phase_step_rad_int = -d_phase_step_rad_int;
|
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)
|
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)
|
void Fpga_Multicorrelator_8sc::fpga_launch_multicorrelator_fpga(void)
|
||||||
{
|
{
|
||||||
// enable interrupts
|
// // enable interrupts
|
||||||
int32_t reenable = 1;
|
// int32_t reenable = 1;
|
||||||
ssize_t nbytes = TEMP_FAILURE_RETRY(write(d_device_descriptor, reinterpret_cast<void *>(&reenable), sizeof(int32_t)));
|
// ssize_t nbytes = TEMP_FAILURE_RETRY(write(d_device_descriptor, reinterpret_cast<void *>(&reenable), sizeof(int32_t)));
|
||||||
if (nbytes != sizeof(int32_t))
|
// if (nbytes != sizeof(int32_t))
|
||||||
{
|
// {
|
||||||
std::cerr << "Error launching the FPGA multicorrelator" << std::endl;
|
// std::cerr << "Error launching the FPGA multicorrelator" << std::endl;
|
||||||
}
|
// }
|
||||||
// writing 1 to reg 14 launches the tracking
|
// writing 1 to reg 14 launches the tracking
|
||||||
d_map_base[START_FLAG_ADDR] = 1;
|
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_real;
|
||||||
int32_t readval_imag;
|
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_real = d_map_base[RESULT_REG_REAL_BASE_ADDR + k];
|
||||||
readval_imag = d_map_base[RESULT_REG_IMAG_BASE_ADDR + k];
|
readval_imag = d_map_base[RESULT_REG_IMAG_BASE_ADDR + k];
|
||||||
|
@ -54,7 +54,10 @@
|
|||||||
#define DROP_SAMPLES_REG_ADDR 18
|
#define DROP_SAMPLES_REG_ADDR 18
|
||||||
#define INITIAL_COUNTER_VALUE_REG_ADDR_LSW 19
|
#define INITIAL_COUNTER_VALUE_REG_ADDR_LSW 19
|
||||||
#define INITIAL_COUNTER_VALUE_REG_ADDR_MSW 20
|
#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 STOP_TRACKING_REG_ADDR 23
|
||||||
|
#define INT_ON_RST_REG_ADDR 24 // cause interrupt on reset to prevent deadlock
|
||||||
#define START_FLAG_ADDR 30
|
#define START_FLAG_ADDR 30
|
||||||
// read-write addresses
|
// read-write addresses
|
||||||
#define TEST_REG_ADDR 31
|
#define TEST_REG_ADDR 31
|
||||||
@ -77,7 +80,7 @@ public:
|
|||||||
void set_output_vectors(gr_complex *corr_out, gr_complex *Prompt_Data);
|
void set_output_vectors(gr_complex *corr_out, gr_complex *Prompt_Data);
|
||||||
void set_local_code_and_taps(
|
void set_local_code_and_taps(
|
||||||
float *shifts_chips, float *prompt_data_shift, int32_t PRN);
|
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(
|
void Carrier_wipeoff_multicorrelator_resampler(
|
||||||
float rem_carrier_phase_in_rad, float phase_step_rad,
|
float rem_carrier_phase_in_rad, float phase_step_rad,
|
||||||
float carrier_phase_rate_step_rad,
|
float carrier_phase_rate_step_rad,
|
||||||
@ -96,8 +99,9 @@ private:
|
|||||||
gr_complex *d_Prompt_Data;
|
gr_complex *d_Prompt_Data;
|
||||||
float *d_shifts_chips;
|
float *d_shifts_chips;
|
||||||
float *d_prompt_data_shift;
|
float *d_prompt_data_shift;
|
||||||
int32_t d_code_length_chips;
|
uint32_t d_code_length_chips;
|
||||||
int32_t d_n_correlators; // number of correlators
|
uint32_t d_code_length_samples;
|
||||||
|
uint32_t d_n_correlators; // number of correlators
|
||||||
|
|
||||||
// data related to the hardware module and the driver
|
// data related to the hardware module and the driver
|
||||||
int32_t d_device_descriptor; // driver descriptor
|
int32_t d_device_descriptor; // driver descriptor
|
||||||
@ -108,15 +112,19 @@ private:
|
|||||||
uint32_t d_correlator_length_samples;
|
uint32_t d_correlator_length_samples;
|
||||||
float d_rem_code_phase_chips;
|
float d_rem_code_phase_chips;
|
||||||
float d_code_phase_step_chips;
|
float d_code_phase_step_chips;
|
||||||
|
float d_code_phase_rate_step_chips;
|
||||||
float d_rem_carrier_phase_in_rad;
|
float d_rem_carrier_phase_in_rad;
|
||||||
float d_phase_step_rad;
|
float d_phase_step_rad;
|
||||||
|
float d_carrier_phase_rate_step_rad;
|
||||||
|
|
||||||
// configuration data computed in the format that the FPGA expects
|
// configuration data computed in the format that the FPGA expects
|
||||||
uint32_t *d_initial_index;
|
uint32_t *d_initial_index;
|
||||||
uint32_t *d_initial_interp_counter;
|
uint32_t *d_initial_interp_counter;
|
||||||
uint32_t d_code_phase_step_chips_num;
|
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_rem_carr_phase_rad_int;
|
||||||
int32_t d_phase_step_rad_int;
|
int32_t d_phase_step_rad_int;
|
||||||
|
int32_t d_carrier_phase_rate_step_rad_int;
|
||||||
uint64_t d_initial_sample_counter;
|
uint64_t d_initial_sample_counter;
|
||||||
|
|
||||||
// driver
|
// driver
|
||||||
|
@ -58,7 +58,7 @@ class AcquisitionInterface : public GNSSBlockInterface
|
|||||||
public:
|
public:
|
||||||
virtual void set_gnss_synchro(Gnss_Synchro* gnss_synchro) = 0;
|
virtual void set_gnss_synchro(Gnss_Synchro* gnss_synchro) = 0;
|
||||||
virtual void set_channel(unsigned int channel_id) = 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_threshold(float threshold) = 0;
|
||||||
virtual void set_doppler_max(unsigned int doppler_max) = 0;
|
virtual void set_doppler_max(unsigned int doppler_max) = 0;
|
||||||
virtual void set_doppler_step(unsigned int doppler_step) = 0;
|
virtual void set_doppler_step(unsigned int doppler_step) = 0;
|
||||||
|
@ -2,11 +2,12 @@
|
|||||||
* \file gnss_sdr_fpga_sample_counter.cc
|
* \file gnss_sdr_fpga_sample_counter.cc
|
||||||
* \brief Simple block to report the current receiver time based on the output
|
* \brief Simple block to report the current receiver time based on the output
|
||||||
* of the tracking or telemetry blocks
|
* of the tracking or telemetry blocks
|
||||||
|
* \author Marc Majoral 2019. mmajoral(at)cttc.es
|
||||||
* \author Javier Arribas 2018. jarribas(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
|
* GNSS-SDR is a software defined Global Navigation
|
||||||
* Satellite Systems receiver
|
* Satellite Systems receiver
|
||||||
@ -69,19 +70,17 @@ gnss_sdr_fpga_sample_counter::gnss_sdr_fpga_sample_counter(
|
|||||||
interval_ms = _interval_ms;
|
interval_ms = _interval_ms;
|
||||||
fs = _fs;
|
fs = _fs;
|
||||||
samples_per_output = std::round(fs * static_cast<double>(interval_ms) / 1e3);
|
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();
|
open_device();
|
||||||
is_open = true;
|
is_open = true;
|
||||||
sample_counter = 0ULL;
|
sample_counter = 0ULL;
|
||||||
|
last_sample_counter = 0ULL;
|
||||||
current_T_rx_ms = 0;
|
current_T_rx_ms = 0;
|
||||||
current_s = 0;
|
current_s = 0;
|
||||||
current_m = 0;
|
current_m = 0;
|
||||||
current_h = 0;
|
current_h = 0;
|
||||||
current_days = 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_enable_send_msg = false; // enable it for reporting time with asynchronous message
|
||||||
flag_m = false;
|
flag_m = false;
|
||||||
flag_h = 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()
|
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 the number of samples per output in the FPGA and enable the interrupts
|
||||||
configure_samples_per_output(samples_per_output);
|
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()
|
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();
|
close_device();
|
||||||
is_open = false;
|
is_open = false;
|
||||||
return true;
|
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)),
|
int gnss_sdr_fpga_sample_counter::general_work(int noutput_items __attribute__((unused)),
|
||||||
__attribute__((unused)) gr_vector_int &ninput_items,
|
__attribute__((unused)) gr_vector_int &ninput_items,
|
||||||
__attribute__((unused)) gr_vector_const_void_star &input_items,
|
__attribute__((unused)) gr_vector_const_void_star &input_items,
|
||||||
gr_vector_void_star &output_items)
|
gr_vector_void_star &output_items)
|
||||||
{
|
{
|
||||||
//todo: Call here a function that waits for an interrupt. Do not open a thread,
|
wait_for_interrupt();
|
||||||
//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.
|
|
||||||
|
|
||||||
uint32_t counter = wait_for_interrupt_and_read_counter();
|
uint64_t sample_counter_tmp, sample_counter_msw_tmp;
|
||||||
uint64_t samples_passed = 2 * static_cast<uint64_t>(samples_per_output) - static_cast<uint64_t>(counter); // ellapsed samples
|
sample_counter_tmp = map_base[0];
|
||||||
// Note: at this moment the sample counter is implemented as a sample counter that decreases to zero and then it is automatically
|
sample_counter_msw_tmp = map_base[1];
|
||||||
// reloaded again and keeps counter. It is done in this way to minimize the logic in the FPGA and maximize the FPGA clock performance
|
sample_counter_msw_tmp = sample_counter_msw_tmp << 32;
|
||||||
// (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
|
sample_counter_tmp = sample_counter_tmp + sample_counter_msw_tmp; // 2^32
|
||||||
// variable number).
|
sample_counter = sample_counter_tmp;
|
||||||
|
|
||||||
sample_counter = sample_counter + samples_passed; //samples_per_output;
|
|
||||||
auto *out = reinterpret_cast<Gnss_Synchro *>(output_items[0]);
|
auto *out = reinterpret_cast<Gnss_Synchro *>(output_items[0]);
|
||||||
out[0] = Gnss_Synchro();
|
out[0] = Gnss_Synchro();
|
||||||
out[0].Flag_valid_symbol_output = false;
|
out[0].Flag_valid_symbol_output = false;
|
||||||
out[0].Flag_valid_word = false;
|
out[0].Flag_valid_word = false;
|
||||||
out[0].Channel_ID = -1;
|
out[0].Channel_ID = -1;
|
||||||
out[0].fs = fs;
|
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++;
|
current_s++;
|
||||||
if ((current_s % 60) == 0)
|
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;
|
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;
|
current_T_rx_ms = interval_ms * (sample_counter) / samples_per_output;
|
||||||
return 1;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -55,11 +55,15 @@ private:
|
|||||||
void close_device(void);
|
void close_device(void);
|
||||||
void open_device(void);
|
void open_device(void);
|
||||||
bool start();
|
bool start();
|
||||||
|
|
||||||
bool stop();
|
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_output;
|
||||||
|
uint32_t samples_per_report;
|
||||||
double fs;
|
double fs;
|
||||||
uint64_t sample_counter;
|
uint64_t sample_counter;
|
||||||
|
uint64_t last_sample_counter;
|
||||||
|
|
||||||
uint32_t interval_ms;
|
uint32_t interval_ms;
|
||||||
uint64_t current_T_rx_ms; // Receiver time in ms since the beginning of the run
|
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
|
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
|
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
|
uint32_t current_days; // Receiver time in days since the beginning of the run
|
||||||
int32_t report_interval_ms;
|
int32_t report_interval_ms;
|
||||||
|
|
||||||
bool flag_enable_send_msg;
|
bool flag_enable_send_msg;
|
||||||
int32_t fd; // driver descriptor
|
int32_t fd; // driver descriptor
|
||||||
volatile uint32_t *map_base; // driver memory map
|
volatile uint32_t *map_base; // driver memory map
|
||||||
|
@ -246,8 +246,8 @@ void GNSSFlowgraph::connect()
|
|||||||
{
|
{
|
||||||
// Connect the multichannel signal source to multiple signal conditioners
|
// Connect the multichannel signal source to multiple signal conditioners
|
||||||
// GNURADIO max_streams=-1 means infinite ports!
|
// 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();
|
DLOG(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_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)
|
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
|
// create a FIR low pass filter
|
||||||
std::vector<float> taps;
|
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,
|
taps = gr::filter::firdes::low_pass(1.0,
|
||||||
fs,
|
fs,
|
||||||
acq_fs / 2.1,
|
acq_fs / 2.1,
|
||||||
acq_fs / 10,
|
acq_fs / 2,
|
||||||
gr::filter::firdes::win_type::WIN_HAMMING);
|
gr::filter::firdes::win_type::WIN_HAMMING);
|
||||||
|
|
||||||
gr::basic_block_sptr fir_filter_ccf_ = gr::filter::fir_filter_ccf::make(decimation, taps);
|
gr::basic_block_sptr fir_filter_ccf_ = gr::filter::fir_filter_ccf::make(decimation, taps);
|
||||||
|
@ -83,6 +83,7 @@ const int32_t GPS_L1_CA_HISTORY_DEEP = 100;
|
|||||||
{ \
|
{ \
|
||||||
1, 0, 0, 0, 1, 0, 1, 1 \
|
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_BITS = 8;
|
||||||
const int32_t GPS_CA_PREAMBLE_LENGTH_SYMBOLS = 160;
|
const int32_t GPS_CA_PREAMBLE_LENGTH_SYMBOLS = 160;
|
||||||
const double GPS_CA_PREAMBLE_DURATION_S = 0.160;
|
const double GPS_CA_PREAMBLE_DURATION_S = 0.160;
|
||||||
|
@ -63,7 +63,13 @@ for channelNr = channelList
|
|||||||
|
|
||||||
%% Plot all figures =======================================================
|
%% 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 ---------------------------------
|
%----- Discrete-Time Scatter Plot ---------------------------------
|
||||||
plot(handles(1, 1), trackResults(channelNr).data_I,...
|
plot(handles(1, 1), trackResults(channelNr).data_I,...
|
||||||
@ -77,29 +83,26 @@ for channelNr = channelList
|
|||||||
ylabel(handles(1, 1), 'Q prompt');
|
ylabel(handles(1, 1), 'Q prompt');
|
||||||
|
|
||||||
%----- Nav bits ---------------------------------------------------
|
%----- Nav bits ---------------------------------------------------
|
||||||
t = (1:length(trackResults(channelNr).data_I));
|
plot (handles(1, 2), timeAxis, ...
|
||||||
plot (handles(1, 2), t, ...
|
|
||||||
trackResults(channelNr).data_I);
|
trackResults(channelNr).data_I);
|
||||||
|
|
||||||
grid (handles(1, 2));
|
grid (handles(1, 2));
|
||||||
title (handles(1, 2), 'Bits of the navigation message');
|
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');
|
axis (handles(1, 2), 'tight');
|
||||||
|
|
||||||
%----- PLL discriminator unfiltered--------------------------------
|
%----- PLL discriminator unfiltered--------------------------------
|
||||||
t = (1:length(trackResults(channelNr).pllDiscr));
|
plot (handles(2, 1), timeAxis, ...
|
||||||
plot (handles(2, 1), t, ...
|
|
||||||
trackResults(channelNr).pllDiscr, 'r');
|
trackResults(channelNr).pllDiscr, 'r');
|
||||||
|
|
||||||
grid (handles(2, 1));
|
grid (handles(2, 1));
|
||||||
axis (handles(2, 1), 'tight');
|
axis (handles(2, 1), 'tight');
|
||||||
xlabel(handles(2, 1), 'Time (s)');
|
xlabel(handles(2, 1), time_label);
|
||||||
ylabel(handles(2, 1), 'Amplitude');
|
ylabel(handles(2, 1), 'Amplitude');
|
||||||
title (handles(2, 1), 'Raw PLL discriminator');
|
title (handles(2, 1), 'Raw PLL discriminator');
|
||||||
|
|
||||||
%----- Correlation ------------------------------------------------
|
%----- Correlation ------------------------------------------------
|
||||||
t = (1:length(trackResults(channelNr).I_VE));
|
plot(handles(2, 2), timeAxis, ...
|
||||||
plot(handles(2, 2), t, ...
|
|
||||||
[sqrt(trackResults(channelNr).I_VE.^2 + ...
|
[sqrt(trackResults(channelNr).I_VE.^2 + ...
|
||||||
trackResults(channelNr).Q_VE.^2)', ...
|
trackResults(channelNr).Q_VE.^2)', ...
|
||||||
sqrt(trackResults(channelNr).I_E.^2 + ...
|
sqrt(trackResults(channelNr).I_E.^2 + ...
|
||||||
@ -114,7 +117,7 @@ for channelNr = channelList
|
|||||||
|
|
||||||
grid (handles(2, 2));
|
grid (handles(2, 2));
|
||||||
title (handles(2, 2), 'Correlation results');
|
title (handles(2, 2), 'Correlation results');
|
||||||
xlabel(handles(2, 2), 'Time (s)');
|
xlabel(handles(2, 2), time_label);
|
||||||
axis (handles(2, 2), 'tight');
|
axis (handles(2, 2), 'tight');
|
||||||
|
|
||||||
hLegend = legend(handles(2, 2), '$\sqrt{I_{VE}^2 + Q_{VE}^2}$', ...
|
hLegend = legend(handles(2, 2), '$\sqrt{I_{VE}^2 + Q_{VE}^2}$', ...
|
||||||
@ -127,35 +130,32 @@ for channelNr = channelList
|
|||||||
set(hLegend, 'Interpreter', 'Latex');
|
set(hLegend, 'Interpreter', 'Latex');
|
||||||
|
|
||||||
%----- PLL discriminator filtered----------------------------------
|
%----- PLL discriminator filtered----------------------------------
|
||||||
t = (1:length(trackResults(channelNr).pllDiscrFilt));
|
plot (handles(3, 1), timeAxis, ...
|
||||||
plot (handles(3, 1), t, ...
|
|
||||||
trackResults(channelNr).pllDiscrFilt, 'b');
|
trackResults(channelNr).pllDiscrFilt, 'b');
|
||||||
|
|
||||||
grid (handles(3, 1));
|
grid (handles(3, 1));
|
||||||
axis (handles(3, 1), 'tight');
|
axis (handles(3, 1), 'tight');
|
||||||
xlabel(handles(3, 1), 'Time (s)');
|
xlabel(handles(3, 1), time_label);
|
||||||
ylabel(handles(3, 1), 'Amplitude');
|
ylabel(handles(3, 1), 'Amplitude');
|
||||||
title (handles(3, 1), 'Filtered PLL discriminator');
|
title (handles(3, 1), 'Filtered PLL discriminator');
|
||||||
|
|
||||||
%----- DLL discriminator unfiltered--------------------------------
|
%----- DLL discriminator unfiltered--------------------------------
|
||||||
t = (1:length(trackResults(channelNr).dllDiscr));
|
plot (handles(3, 2), timeAxis, ...
|
||||||
plot (handles(3, 2), t, ...
|
|
||||||
trackResults(channelNr).dllDiscr, 'r');
|
trackResults(channelNr).dllDiscr, 'r');
|
||||||
|
|
||||||
grid (handles(3, 2));
|
grid (handles(3, 2));
|
||||||
axis (handles(3, 2), 'tight');
|
axis (handles(3, 2), 'tight');
|
||||||
xlabel(handles(3, 2), 'Time (s)');
|
xlabel(handles(3, 2), time_label);
|
||||||
ylabel(handles(3, 2), 'Amplitude');
|
ylabel(handles(3, 2), 'Amplitude');
|
||||||
title (handles(3, 2), 'Raw DLL discriminator');
|
title (handles(3, 2), 'Raw DLL discriminator');
|
||||||
|
|
||||||
%----- DLL discriminator filtered----------------------------------
|
%----- DLL discriminator filtered----------------------------------
|
||||||
t = (1:length(trackResults(channelNr).dllDiscrFilt));
|
plot (handles(3, 3), timeAxis, ...
|
||||||
plot (handles(3, 3), t, ...
|
|
||||||
trackResults(channelNr).dllDiscrFilt, 'b');
|
trackResults(channelNr).dllDiscrFilt, 'b');
|
||||||
|
|
||||||
grid (handles(3, 3));
|
grid (handles(3, 3));
|
||||||
axis (handles(3, 3), 'tight');
|
axis (handles(3, 3), 'tight');
|
||||||
xlabel(handles(3, 3), 'Time (s)');
|
xlabel(handles(3, 3), time_label);
|
||||||
ylabel(handles(3, 3), 'Amplitude');
|
ylabel(handles(3, 3), 'Amplitude');
|
||||||
title (handles(3, 3), 'Filtered DLL discriminator');
|
title (handles(3, 3), 'Filtered DLL discriminator');
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user