1
0
mirror of https://github.com/gnss-sdr/gnss-sdr synced 2025-12-14 04:18:08 +00:00

Adapting glonass_l1_ca_dll_pll_tracking to the common dll pll tracking block

This commit is contained in:
Javier Arribas
2025-12-11 17:29:43 +01:00
parent ecaf3bad9f
commit 06d191f39c
7 changed files with 202 additions and 177 deletions

View File

@@ -75,6 +75,60 @@ void glonass_l1_ca_code_gen_complex(own::span<std::complex<float>> dest, uint32_
}
}
void glonass_l1_ca_code_gen_float(own::span<float> dest, uint32_t chip_shift)
{
const uint32_t code_length = 511;
std::bitset<code_length> G1{};
auto G1_register = std::bitset<9>{}.set(); // All true
uint32_t lcv;
uint32_t lcv2;
bool feedback1;
bool aux;
/* Generate G1 Register */
for (lcv = 0; lcv < code_length; lcv++)
{
G1[lcv] = G1_register[2];
feedback1 = G1_register[4] ^ G1_register[0];
for (lcv2 = 0; lcv2 < 8; lcv2++)
{
G1_register[lcv2] = G1_register[lcv2 + 1];
}
G1_register[8] = feedback1;
}
/* Generate PRN from G1 Register */
for (lcv = 0; lcv < code_length; lcv++)
{
aux = G1[lcv];
if (aux == true)
{
dest[lcv] = 1;
}
else
{
dest[lcv] = -1;
}
}
/* Generate PRN from G1 and G2 Registers */
for (lcv = 0; lcv < code_length; lcv++)
{
aux = G1[(lcv + chip_shift) % code_length];
if (aux == true)
{
dest[lcv] = 1;
}
else
{
dest[lcv] = -1;
}
}
}
/*
* Generates complex GLONASS L1 C/A code for the desired SV ID and sampled to specific sampling frequency

View File

@@ -38,6 +38,9 @@ namespace own = gsl_lite;
//! Generates complex GLONASS L1 C/A code for the desired SV ID and code shift
void glonass_l1_ca_code_gen_complex(own::span<std::complex<float>> dest, uint32_t chip_shift);
//! Generates float GLONASS L1 C/A code for the desired SV ID and code shift
void glonass_l1_ca_code_gen_float(own::span<float> dest, uint32_t chip_shift);
//! Generates complex GLONASS L1 C/A code for the desired SV ID and code shift, and sampled to specific sampling frequency
void glonass_l1_ca_code_gen_complex_sampled(own::span<std::complex<float>> dest, int32_t sampling_freq, uint32_t chip_shift);

View File

@@ -22,11 +22,16 @@
* -----------------------------------------------------------------------------
*/
#include "glonass_l1_ca_dll_pll_tracking.h"
#include "GLONASS_L1_L2_CA.h"
#include "configuration_interface.h"
#include "gnss_sdr_flags.h"
#include <utility>
#include "display.h"
#include <algorithm>
#include <array>
#include <cmath>
#include <iostream>
#if USE_GLOG_AND_GFLAGS
#include <glog/logging.h>
@@ -34,138 +39,81 @@
#include <absl/log/log.h>
#endif
GlonassL1CaDllPllTracking::GlonassL1CaDllPllTracking(
const ConfigurationInterface* configuration,
const std::string& role,
unsigned int in_streams,
unsigned int out_streams)
: role_(role),
item_size_(sizeof(gr_complex)),
channel_(0),
in_streams_(in_streams),
out_streams_(out_streams)
: BaseDllPllTracking(configuration, role, in_streams, out_streams)
{
// ################# CONFIGURATION PARAMETERS ########################
const std::string default_item_type("gr_complex");
std::string item_type = configuration->property(role_ + ".item_type", default_item_type);
int fs_in_deprecated = configuration->property("GNSS-SDR.internal_fs_hz", 2048000);
int fs_in = configuration->property("GNSS-SDR.internal_fs_sps", fs_in_deprecated);
bool dump = configuration->property(role_ + ".dump", false);
float pll_bw_hz = configuration->property(role_ + ".pll_bw_hz", static_cast<float>(50.0));
configure_tracking_parameters(configuration);
create_tracking_block();
}
#if USE_GLOG_AND_GFLAGS
if (FLAGS_pll_bw_hz != 0.0)
{
pll_bw_hz = static_cast<float>(FLAGS_pll_bw_hz);
}
#else
if (absl::GetFlag(FLAGS_pll_bw_hz) != 0.0)
{
pll_bw_hz = static_cast<float>(absl::GetFlag(FLAGS_pll_bw_hz));
}
#endif
float dll_bw_hz = configuration->property(role_ + ".dll_bw_hz", static_cast<float>(2.0));
#if USE_GLOG_AND_GFLAGS
if (FLAGS_dll_bw_hz != 0.0)
{
dll_bw_hz = static_cast<float>(FLAGS_dll_bw_hz);
}
#else
if (absl::GetFlag(FLAGS_dll_bw_hz) != 0.0)
{
dll_bw_hz = static_cast<float>(absl::GetFlag(FLAGS_dll_bw_hz));
}
#endif
float early_late_space_chips = configuration->property(role_ + ".early_late_space_chips", static_cast<float>(0.5));
const std::string default_dump_filename("./track_ch");
std::string dump_filename = configuration->property(role_ + ".dump_filename", default_dump_filename);
const auto vector_length = static_cast<int>(std::round(fs_in / (GLONASS_L1_CA_CODE_RATE_CPS / GLONASS_L1_CA_CODE_LENGTH_CHIPS)));
// ################# MAKE TRACKING GNURadio object ###################
DLOG(INFO) << "role " << role_;
if (item_type == "gr_complex")
void GlonassL1CaDllPllTracking::configure_tracking_parameters(
const ConfigurationInterface* configuration __attribute__((unused)))
{
// Set basic signal identifiers
config_params().system = 'R';
const std::array<char, 3> sig{'1', 'G', '\0'};
std::copy_n(sig.data(), 3, config_params().signal);
const auto vector_length = static_cast<int>(std::round(config_params().fs_in / (GLONASS_L1_CA_CODE_RATE_CPS / GLONASS_L1_CA_CODE_LENGTH_CHIPS)));
config_params().vector_length = vector_length;
// Sanity checks and warnings
if (config_params().extend_correlation_symbols < 1)
{
tracking_sptr_ = glonass_l1_ca_dll_pll_make_tracking_cc(
fs_in,
vector_length,
dump,
dump_filename,
pll_bw_hz,
dll_bw_hz,
early_late_space_chips);
DLOG(INFO) << "tracking(" << tracking_sptr_->unique_id() << ")";
config_params().extend_correlation_symbols = 1;
std::cout << TEXT_RED
<< "WARNING: Glonass L1: extend_correlation_symbols must be > 0. "
<< "Coherent integration set to 1 ms."
<< TEXT_RESET << std::endl;
}
else if (config_params().extend_correlation_symbols > 10)
{
config_params().extend_correlation_symbols = 10;
std::cout << TEXT_RED
<< "WARNING: Glonass L1: extend_correlation_symbols limited to 10 (10 ms)."
<< TEXT_RESET << std::endl;
}
// GPS L1 C/A does not have a pilot component
config_params().track_pilot = configuration->property(this->role() + ".track_pilot", false);
if (config_params().track_pilot)
{
config_params().track_pilot = false;
std::cout << TEXT_RED
<< "WARNING: Glonass L1 does not have pilot signal. "
<< "Data tracking enabled instead."
<< TEXT_RESET << std::endl;
}
// Ensure bandwidth sanity when narrow-band is enabled
if ((config_params().extend_correlation_symbols > 1) &&
(config_params().pll_bw_narrow_hz > config_params().pll_bw_hz ||
config_params().dll_bw_narrow_hz > config_params().dll_bw_hz))
{
std::cout << TEXT_RED
<< "WARNING: Glonass L1: Narrow tracking bandwidth is higher than wide bandwidth."
<< TEXT_RESET << std::endl;
}
}
void GlonassL1CaDllPllTracking::create_tracking_block()
{
// Create GNU Radio block
if (config_params().item_type == "gr_complex")
{
tracking_sptr_ = dll_pll_veml_make_tracking(config_params());
DLOG(INFO) << "Tracking block (" << tracking_sptr_->unique_id() << ")";
}
else
{
item_size_ = 0;
set_item_size(0);
tracking_sptr_ = nullptr;
LOG(WARNING) << item_type << " unknown tracking item type.";
}
if (in_streams_ > 1)
{
LOG(ERROR) << "This implementation only supports one input stream";
}
if (out_streams_ > 1)
{
LOG(ERROR) << "This implementation only supports one output stream";
LOG(WARNING) << config_params().item_type << " unknown tracking item type.";
}
}
void GlonassL1CaDllPllTracking::stop_tracking()
{
}
void GlonassL1CaDllPllTracking::start_tracking()
{
tracking_sptr_->start_tracking();
}
/*
* Set tracking channel unique ID
*/
void GlonassL1CaDllPllTracking::set_channel(unsigned int channel)
{
channel_ = channel;
tracking_sptr_->set_channel(channel);
}
void GlonassL1CaDllPllTracking::set_gnss_synchro(Gnss_Synchro* p_gnss_synchro)
{
tracking_sptr_->set_gnss_synchro(p_gnss_synchro);
}
void GlonassL1CaDllPllTracking::connect(gr::top_block_sptr top_block)
{
if (top_block)
{ /* top_block is not null */
};
// nothing to connect, now the tracking uses gr_sync_decimator
}
void GlonassL1CaDllPllTracking::disconnect(gr::top_block_sptr top_block)
{
if (top_block)
{ /* top_block is not null */
};
// nothing to disconnect, now the tracking uses gr_sync_decimator
}
gr::basic_block_sptr GlonassL1CaDllPllTracking::get_left_block()
{
return tracking_sptr_;
}
gr::basic_block_sptr GlonassL1CaDllPllTracking::get_right_block()
{
return tracking_sptr_;
}

View File

@@ -25,81 +25,40 @@
#ifndef GNSS_SDR_GLONASS_L1_CA_DLL_PLL_TRACKING_H
#define GNSS_SDR_GLONASS_L1_CA_DLL_PLL_TRACKING_H
#include "glonass_ca_dll_pll_tracking_cc.h"
#include "tracking_interface.h"
#include <string>
#include "base_dll_pll_tracking.h"
/** \addtogroup Tracking
* Classes for GNSS signal tracking.
* \{ */
/** \addtogroup Tracking_adapters
/** \addtogroup Tracking_adapters tracking_adapters
* Wrap GNU Radio blocks for GNSS signal tracking with a TrackingInterface
* \{ */
class ConfigurationInterface;
/*!
* \brief This class implements a code DLL + carrier PLL tracking loop
* block adapter for GLONASS L1 signals
*/
class GlonassL1CaDllPllTracking : public TrackingInterface
class GlonassL1CaDllPllTracking : public BaseDllPllTracking
{
public:
GlonassL1CaDllPllTracking(
const ConfigurationInterface* configuration,
//! Constructor
GlonassL1CaDllPllTracking(const ConfigurationInterface* configuration,
const std::string& role,
unsigned int in_streams,
unsigned int out_streams);
~GlonassL1CaDllPllTracking() = default;
inline std::string role() override
{
return role_;
}
//! Returns "GLONASS_L1_CA_DLL_PLL_Tracking"
inline std::string implementation() override
{
return "GLONASS_L1_CA_DLL_PLL_Tracking";
}
inline size_t item_size() override
{
return item_size_;
}
void connect(gr::top_block_sptr top_block) override;
void disconnect(gr::top_block_sptr top_block) override;
gr::basic_block_sptr get_left_block() override;
gr::basic_block_sptr get_right_block() override;
/*!
* \brief Set tracking channel unique ID
*/
void set_channel(unsigned int channel) override;
/*!
* \brief Set acquisition/tracking common Gnss_Synchro object pointer
* to efficiently exchange synchronization data between acquisition and tracking blocks
*/
void set_gnss_synchro(Gnss_Synchro* p_gnss_synchro) override;
void start_tracking() override;
/*!
* \brief Stop running tracking
*/
void stop_tracking() override;
private:
glonass_l1_ca_dll_pll_tracking_cc_sptr tracking_sptr_;
std::string role_;
size_t item_size_;
unsigned int channel_;
unsigned int in_streams_;
unsigned int out_streams_;
void configure_tracking_parameters(const ConfigurationInterface* configuration) override;
void create_tracking_block() override;
};
/** \} */
/** \} */
#endif // GNSS_SDR_GLONASS_L1_CA_DLL_PLL_TRACKING_H
#endif // GNSS_SDR_GLONASS_L1_DLL_PLL_TRACKING_H

View File

@@ -30,12 +30,14 @@
#include "Galileo_E5a.h"
#include "Galileo_E5b.h"
#include "Galileo_E6.h"
#include "GLONASS_L1_L2_CA.h"
#include "MATH_CONSTANTS.h"
#include "beidou_b1i_signal_replica.h"
#include "beidou_b3i_signal_replica.h"
#include "galileo_e1_signal_replica.h"
#include "galileo_e5_signal_replica.h"
#include "galileo_e6_signal_replica.h"
#include "glonass_l1_signal_replica.h"
#include "gnss_satellite.h"
#include "gnss_sdr_create_directory.h"
#include "gnss_sdr_filesystem.h"
@@ -94,6 +96,7 @@ dll_pll_veml_tracking::dll_pll_veml_tracking(const Dll_Pll_Conf &conf_)
d_acq_code_phase_samples(0.0),
d_acq_carrier_doppler_hz(0.0),
d_current_correlation_time_s(0.0),
d_cfo_frequency_hz(0.0),
d_carrier_doppler_hz(0.0),
d_acc_carrier_phase_rad(0.0),
d_rem_code_phase_chips(0.0),
@@ -450,6 +453,41 @@ dll_pll_veml_tracking::dll_pll_veml_tracking(const Dll_Pll_Conf &conf_)
d_symbols_per_bit = 0;
}
}
else if (d_trk_parameters.system == 'R')
{
d_systemName = "Glonass";
if (d_signal_type == "1G")
{
d_signal_carrier_freq = GLONASS_L1_CA_FREQ_HZ;
d_code_period = GLONASS_L1_CA_CODE_PERIOD_S;
d_code_chip_rate = GLONASS_L1_CA_CODE_RATE_CPS;
d_code_length_chips = static_cast<int32_t>(GLONASS_L1_CA_CODE_LENGTH_CHIPS);
d_signal_carrier_freq = BEIDOU_B1I_FREQ_HZ;
d_symbols_per_bit = GLONASS_GNAV_TELEMETRY_SYMBOLS_PER_BIT;
d_correlation_length_ms = 1;
d_code_samples_per_chip = 1;
d_secondary = false;
d_trk_parameters.track_pilot = false;
d_trk_parameters.slope = 1.0;
d_trk_parameters.spc = d_trk_parameters.early_late_space_chips;
d_trk_parameters.y_intercept = 1.0;
d_secondary_code_length = static_cast<uint32_t>(GLONASS_GNAV_PREAMBLE_LENGTH_SYMBOLS);
d_secondary_code_string = GLONASS_GNAV_PREAMBLE_STR;
d_symbols_per_bit = GLONASS_GNAV_TELEMETRY_SYMBOLS_PER_BIT;
}
else {
LOG(WARNING) << "Invalid Signal argument when instantiating tracking blocks";
std::cout << "Invalid Signal argument when instantiating tracking blocks\n";
d_correlation_length_ms = 1;
d_secondary = false;
d_signal_carrier_freq = 0.0;
d_code_period = 0.0;
d_code_length_chips = 0;
d_code_samples_per_chip = 0U;
d_symbols_per_bit = 0;
}
}
else
{
LOG(WARNING) << "Invalid System argument when instantiating tracking blocks";
@@ -846,7 +884,27 @@ void dll_pll_veml_tracking::start_tracking()
d_Prompt_circular_buffer.set_capacity(d_secondary_code_length);
}
}
else if (d_systemName == "Glonass" and d_signal_type == "1G")
{
glonass_l1_ca_code_gen_float(d_tracking_code, 0);
d_cfo_frequency_hz = (DFRQ1_GLO * GLONASS_PRN.at(d_acquisition_gnss_synchro->PRN));
d_carrier_phase_step_rad = TWO_PI * (d_cfo_frequency_hz+d_carrier_doppler_hz) / static_cast<double>(d_trk_parameters.fs_in);
d_symbols_per_bit = GLONASS_GNAV_TELEMETRY_SYMBOLS_PER_BIT; // todo: enable after fixing beidou symbol synchronization
d_correlation_length_ms = 1;
d_code_samples_per_chip = 1;
d_secondary = false;
d_trk_parameters.track_pilot = false;
// set the preamble in the secondary code acquisition
d_secondary_code_length = static_cast<uint32_t>(GLONASS_GNAV_PREAMBLE_LENGTH_SYMBOLS);
d_secondary_code_string = GLONASS_GNAV_PREAMBLE_STR;
d_data_secondary_code_length = 0;
d_Prompt_circular_buffer.set_capacity(d_secondary_code_length);
if (d_extend_correlation_symbols > GLONASS_GNAV_TELEMETRY_SYMBOLS_PER_BIT)
{
d_extend_correlation_symbols = GLONASS_GNAV_TELEMETRY_SYMBOLS_PER_BIT;
}
}
d_multicorrelator_cpu.set_local_code_and_taps(d_code_samples_per_chip * d_code_length_chips, d_tracking_code.data(), d_local_code_shift_chips.data());
std::fill_n(d_correlator_outs.begin(), d_n_correlator_taps, gr_complex(0.0, 0.0));
@@ -1216,7 +1274,7 @@ void dll_pll_veml_tracking::update_tracking_vars()
// ################### PLL COMMANDS #################################################
// carrier phase step (NCO phase increment per sample) [rads/sample]
d_carrier_phase_step_rad = TWO_PI * d_carrier_doppler_hz / d_trk_parameters.fs_in;
d_carrier_phase_step_rad = TWO_PI * (d_carrier_doppler_hz+d_cfo_frequency_hz) / d_trk_parameters.fs_in;
// carrier phase rate step (NCO phase increment rate per sample) [rads/sample^2]
if (d_trk_parameters.high_dyn)
{
@@ -1974,7 +2032,7 @@ int dll_pll_veml_tracking::general_work(int noutput_items __attribute__((unused)
run_dll_pll();
update_tracking_vars();
check_carrier_phase_coherent_initialization();
if (d_current_data_symbol == 0)
if ((d_current_data_symbol == 0) || (d_signal_type == "1G")) // Glonass telemetry decoder require symbols instead of bits
{
// enable write dump file this cycle (valid DLL/PLL cycle)
log_data();
@@ -2013,7 +2071,7 @@ int dll_pll_veml_tracking::general_work(int noutput_items __attribute__((unused)
}
}
}
current_synchro_data.TOW_at_current_symbol_ms = d_tow_from_telemetry_ms;
// time tags
std::vector<gr::tag_t> tags_vec;

View File

@@ -128,6 +128,7 @@ private:
double d_code_error_chips;
double d_code_error_filt_chips;
double d_code_freq_chips;
double d_cfo_frequency_hz;
double d_carrier_doppler_hz;
double d_acc_carrier_phase_rad;
double d_rem_code_phase_chips;

View File

@@ -92,6 +92,8 @@ constexpr int32_t GLONASS_L1_CA_HISTORY_DEEP = 100;
#define GLONASS_GNAV_PREAMBLE \
{ \
1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 0}
constexpr char GLONASS_GNAV_PREAMBLE_STR[301] = "111111111111111111111111111111111111111111111111110000000000000000000000000000001111111111111111111100000000001111111111111111111111111111110000000000111111111100000000001111111111000000000000000000000000000000000000000011111111110000000000000000000011111111110000000000111111111111111111110000000000";
constexpr double GLONASS_GNAV_PREAMBLE_DURATION_S = 0.300;
constexpr int32_t GLONASS_GNAV_PREAMBLE_LENGTH_BITS = 30;
constexpr int32_t GLONASS_GNAV_PREAMBLE_LENGTH_SYMBOLS = 300;