mirror of
https://github.com/gnss-sdr/gnss-sdr
synced 2025-01-07 07:50:32 +00:00
Minor fixes
This commit is contained in:
parent
b3764f6ed1
commit
539e24f0ac
@ -1,7 +1,7 @@
|
|||||||
/*!
|
/*!
|
||||||
* \file dll_pll_veml_tracking.cc
|
* \file dll_pll_veml_tracking.cc
|
||||||
* \brief Implementation of a code DLL + carrier PLL tracking block.
|
* \brief Implementation of a code DLL + carrier PLL tracking block.
|
||||||
* \author Antonio Ramos, 2018 antonioramosdet(at)gmail.com
|
* \author Antonio Ramos, 2018 antonio.ramosdet(at)gmail.com
|
||||||
*
|
*
|
||||||
* Code DLL + carrier PLL according to the algorithms described in:
|
* Code DLL + carrier PLL according to the algorithms described in:
|
||||||
* [1] K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen,
|
* [1] K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen,
|
||||||
@ -112,7 +112,8 @@ dll_pll_veml_tracking::dll_pll_veml_tracking(
|
|||||||
float pll_bw_narrow_hz, float dll_bw_narrow_hz,
|
float pll_bw_narrow_hz, float dll_bw_narrow_hz,
|
||||||
float early_late_space_chips, float very_early_late_space_chips,
|
float early_late_space_chips, float very_early_late_space_chips,
|
||||||
float early_late_space_narrow_chips, float very_early_late_space_narrow_chips,
|
float early_late_space_narrow_chips, float very_early_late_space_narrow_chips,
|
||||||
int extend_correlation_symbols, bool track_pilot, char system, char signal[3]) : gr::block("dll_pll_veml_tracking", gr::io_signature::make(1, 1, sizeof(gr_complex)),
|
int extend_correlation_symbols, bool track_pilot, char system,
|
||||||
|
char signal[3]) : gr::block("dll_pll_veml_tracking", gr::io_signature::make(1, 1, sizeof(gr_complex)),
|
||||||
gr::io_signature::make(1, 1, sizeof(Gnss_Synchro)))
|
gr::io_signature::make(1, 1, sizeof(Gnss_Synchro)))
|
||||||
{
|
{
|
||||||
// Telemetry bit synchronization message port input
|
// Telemetry bit synchronization message port input
|
||||||
@ -145,7 +146,7 @@ dll_pll_veml_tracking::dll_pll_veml_tracking(
|
|||||||
d_correlation_length_ms = 1;
|
d_correlation_length_ms = 1;
|
||||||
d_code_samples_per_chip = 1;
|
d_code_samples_per_chip = 1;
|
||||||
d_code_length_chips = static_cast<unsigned int>(GPS_L1_CA_CODE_LENGTH_CHIPS);
|
d_code_length_chips = static_cast<unsigned int>(GPS_L1_CA_CODE_LENGTH_CHIPS);
|
||||||
//GPS L1 C/A does not have pilot component nor secondary code
|
// GPS L1 C/A does not have pilot component nor secondary code
|
||||||
d_secondary = false;
|
d_secondary = false;
|
||||||
d_track_pilot = false;
|
d_track_pilot = false;
|
||||||
interchange_iq = false;
|
interchange_iq = false;
|
||||||
@ -159,7 +160,7 @@ dll_pll_veml_tracking::dll_pll_veml_tracking(
|
|||||||
d_symbols_per_bit = GPS_L2_SAMPLES_PER_SYMBOL;
|
d_symbols_per_bit = GPS_L2_SAMPLES_PER_SYMBOL;
|
||||||
d_correlation_length_ms = 20;
|
d_correlation_length_ms = 20;
|
||||||
d_code_samples_per_chip = 1;
|
d_code_samples_per_chip = 1;
|
||||||
//GPS L2 does not have pilot component nor secondary code
|
// GPS L2 does not have pilot component nor secondary code
|
||||||
d_secondary = false;
|
d_secondary = false;
|
||||||
d_track_pilot = false;
|
d_track_pilot = false;
|
||||||
interchange_iq = false;
|
interchange_iq = false;
|
||||||
@ -173,7 +174,7 @@ dll_pll_veml_tracking::dll_pll_veml_tracking(
|
|||||||
d_correlation_length_ms = 1;
|
d_correlation_length_ms = 1;
|
||||||
d_code_samples_per_chip = 1;
|
d_code_samples_per_chip = 1;
|
||||||
d_code_length_chips = static_cast<unsigned int>(GPS_L5i_CODE_LENGTH_CHIPS);
|
d_code_length_chips = static_cast<unsigned int>(GPS_L5i_CODE_LENGTH_CHIPS);
|
||||||
//GPS L5 does not have pilot secondary code
|
// GPS L5 does not have pilot secondary code
|
||||||
d_secondary = true;
|
d_secondary = true;
|
||||||
if (d_track_pilot)
|
if (d_track_pilot)
|
||||||
{
|
{
|
||||||
@ -191,7 +192,7 @@ dll_pll_veml_tracking::dll_pll_veml_tracking(
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOG(WARNING) << "Invalid Signal argument when instantiating tracking blocks";
|
LOG(WARNING) << "Invalid Signal argument when instantiating tracking blocks";
|
||||||
std::cout << "Invalid Signal argument when instantiating tracking blocks" << std::endl;
|
std::cerr << "Invalid Signal argument when instantiating tracking blocks" << std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (system == 'E')
|
else if (system == 'E')
|
||||||
@ -250,7 +251,7 @@ dll_pll_veml_tracking::dll_pll_veml_tracking(
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOG(WARNING) << "Invalid System argument when instantiating tracking blocks";
|
LOG(WARNING) << "Invalid System argument when instantiating tracking blocks";
|
||||||
std::cout << "Invalid System argument when instantiating tracking blocks" << std::endl;
|
std::cerr << "Invalid System argument when instantiating tracking blocks" << std::endl;
|
||||||
d_correlation_length_ms = 1;
|
d_correlation_length_ms = 1;
|
||||||
d_secondary = false;
|
d_secondary = false;
|
||||||
interchange_iq = false;
|
interchange_iq = false;
|
||||||
@ -411,12 +412,11 @@ void dll_pll_veml_tracking::start_tracking()
|
|||||||
d_acq_carrier_doppler_hz = d_acquisition_gnss_synchro->Acq_doppler_hz;
|
d_acq_carrier_doppler_hz = d_acquisition_gnss_synchro->Acq_doppler_hz;
|
||||||
d_acq_sample_stamp = d_acquisition_gnss_synchro->Acq_samplestamp_samples;
|
d_acq_sample_stamp = d_acquisition_gnss_synchro->Acq_samplestamp_samples;
|
||||||
|
|
||||||
long int acq_trk_diff_samples = static_cast<long int>(d_sample_counter) - static_cast<long int>(d_acq_sample_stamp); //-d_vector_length;
|
long int acq_trk_diff_samples = static_cast<long int>(d_sample_counter) - static_cast<long int>(d_acq_sample_stamp);
|
||||||
double acq_trk_diff_seconds = static_cast<double>(acq_trk_diff_samples) / d_fs_in;
|
double acq_trk_diff_seconds = static_cast<double>(acq_trk_diff_samples) / d_fs_in;
|
||||||
DLOG(INFO) << "Number of samples between Acquisition and Tracking = " << acq_trk_diff_samples;
|
DLOG(INFO) << "Number of samples between Acquisition and Tracking = " << acq_trk_diff_samples;
|
||||||
DLOG(INFO) << "Number of seconds between Acquisition and Tracking = " << acq_trk_diff_seconds;
|
DLOG(INFO) << "Number of seconds between Acquisition and Tracking = " << acq_trk_diff_seconds;
|
||||||
// Doppler effect
|
// Doppler effect Fd = (C / (C + Vr)) * F
|
||||||
// Fd=(C/(C+Vr))*F
|
|
||||||
double radial_velocity = (d_signal_carrier_freq + d_acq_carrier_doppler_hz) / d_signal_carrier_freq;
|
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
|
// new chip and prn sequence periods based on acq Doppler
|
||||||
d_code_freq_chips = radial_velocity * d_code_chip_rate;
|
d_code_freq_chips = radial_velocity * d_code_chip_rate;
|
||||||
@ -604,7 +604,7 @@ dll_pll_veml_tracking::~dll_pll_veml_tracking()
|
|||||||
|
|
||||||
bool dll_pll_veml_tracking::acquire_secondary()
|
bool dll_pll_veml_tracking::acquire_secondary()
|
||||||
{
|
{
|
||||||
//******* preamble correlation ********
|
// ******* preamble correlation ********
|
||||||
int corr_value = 0;
|
int corr_value = 0;
|
||||||
for (unsigned int i = 0; i < d_secondary_code_length; i++)
|
for (unsigned int i = 0; i < d_secondary_code_length; i++)
|
||||||
{
|
{
|
||||||
@ -766,6 +766,7 @@ void dll_pll_veml_tracking::clear_tracking_vars()
|
|||||||
d_last_prompt = gr_complex(0.0, 0.0);
|
d_last_prompt = gr_complex(0.0, 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void dll_pll_veml_tracking::update_tracking_vars()
|
void dll_pll_veml_tracking::update_tracking_vars()
|
||||||
{
|
{
|
||||||
T_chip_seconds = 1.0 / d_code_freq_chips;
|
T_chip_seconds = 1.0 / d_code_freq_chips;
|
||||||
@ -796,6 +797,7 @@ void dll_pll_veml_tracking::update_tracking_vars()
|
|||||||
d_rem_code_phase_chips = d_code_freq_chips * d_rem_code_phase_samples / d_fs_in;
|
d_rem_code_phase_chips = d_code_freq_chips * d_rem_code_phase_samples / d_fs_in;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void dll_pll_veml_tracking::save_correlation_results()
|
void dll_pll_veml_tracking::save_correlation_results()
|
||||||
{
|
{
|
||||||
if (d_secondary)
|
if (d_secondary)
|
||||||
@ -960,301 +962,6 @@ void dll_pll_veml_tracking::log_data(bool integrating)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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::thread::scoped_lock l(d_setlock);
|
|
||||||
const gr_complex *in = reinterpret_cast<const gr_complex *>(input_items[0]);
|
|
||||||
Gnss_Synchro **out = reinterpret_cast<Gnss_Synchro **>(&output_items[0]);
|
|
||||||
Gnss_Synchro current_synchro_data = Gnss_Synchro();
|
|
||||||
|
|
||||||
switch (d_state)
|
|
||||||
{
|
|
||||||
case 0: // Standby - Pass Through. Full throttle
|
|
||||||
{
|
|
||||||
d_sample_counter += ninput_items[0];
|
|
||||||
consume_each(ninput_items[0]);
|
|
||||||
return 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 1: // Pull-in
|
|
||||||
{
|
|
||||||
// Signal alignment (skip samples until the incoming signal is aligned with local replica)
|
|
||||||
// Fill the acquisition data
|
|
||||||
unsigned long int acq_to_trk_delay_samples = d_sample_counter - d_acq_sample_stamp;
|
|
||||||
double acq_trk_shif_correction_samples = static_cast<double>(d_current_prn_length_samples) - std::fmod(static_cast<double>(acq_to_trk_delay_samples), static_cast<double>(d_current_prn_length_samples));
|
|
||||||
int samples_offset = std::round(d_acq_code_phase_samples + acq_trk_shif_correction_samples);
|
|
||||||
if (samples_offset < 0)
|
|
||||||
{
|
|
||||||
samples_offset = 0;
|
|
||||||
}
|
|
||||||
d_acc_carrier_phase_rad -= d_carrier_phase_step_rad * d_acq_code_phase_samples;
|
|
||||||
d_state = 2;
|
|
||||||
d_sample_counter += samples_offset; // count for the processed samples
|
|
||||||
consume_each(samples_offset); // shift input to perform alignment with local replica
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
case 2: // Wide tracking and symbol synchronization
|
|
||||||
{
|
|
||||||
do_correlation_step(in);
|
|
||||||
// Save single correlation step variables
|
|
||||||
if (d_veml)
|
|
||||||
{
|
|
||||||
d_VE_accu = *d_Very_Early;
|
|
||||||
d_VL_accu = *d_Very_Late;
|
|
||||||
}
|
|
||||||
d_E_accu = *d_Early;
|
|
||||||
d_P_accu = *d_Prompt;
|
|
||||||
d_L_accu = *d_Late;
|
|
||||||
|
|
||||||
// Check lock status
|
|
||||||
if (!cn0_and_tracking_lock_status())
|
|
||||||
{
|
|
||||||
clear_tracking_vars();
|
|
||||||
d_state = 0; // loss-of-lock detected
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
bool next_state = false;
|
|
||||||
// Perform DLL/PLL tracking loop computations. Costas Loop enabled
|
|
||||||
run_dll_pll();
|
|
||||||
update_tracking_vars();
|
|
||||||
|
|
||||||
// enable write dump file this cycle (valid DLL/PLL cycle)
|
|
||||||
log_data(false);
|
|
||||||
if (d_secondary)
|
|
||||||
{
|
|
||||||
// ####### SECONDARY CODE LOCK #####
|
|
||||||
d_Prompt_buffer_deque.push_back(*d_Prompt);
|
|
||||||
if (d_Prompt_buffer_deque.size() == d_secondary_code_length)
|
|
||||||
{
|
|
||||||
next_state = acquire_secondary();
|
|
||||||
if (next_state)
|
|
||||||
{
|
|
||||||
std::cout << "Secondary code locked for CH " << d_channel
|
|
||||||
<< " : Satellite " << Gnss_Satellite(systemName, d_acquisition_gnss_synchro->PRN) << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
d_Prompt_buffer_deque.pop_front();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else //Signal does not have secondary code. Search a bit transition by sign change
|
|
||||||
{
|
|
||||||
if (d_synchonizing)
|
|
||||||
{
|
|
||||||
if (d_Prompt->real() * d_last_prompt.real() > 0.0)
|
|
||||||
{
|
|
||||||
d_current_symbol++;
|
|
||||||
}
|
|
||||||
else if (d_current_symbol > d_symbols_per_bit)
|
|
||||||
{
|
|
||||||
d_synchonizing = false;
|
|
||||||
d_current_symbol = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
d_current_symbol = 1;
|
|
||||||
d_last_prompt = *d_Prompt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (d_last_prompt.real() != 0.0)
|
|
||||||
{
|
|
||||||
d_current_symbol++;
|
|
||||||
if (d_current_symbol == d_symbols_per_bit) next_state = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
d_last_prompt = *d_Prompt;
|
|
||||||
d_synchonizing = true;
|
|
||||||
d_current_symbol = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (next_state)
|
|
||||||
{ // reset extended correlator
|
|
||||||
d_VE_accu = gr_complex(0.0, 0.0);
|
|
||||||
d_E_accu = gr_complex(0.0, 0.0);
|
|
||||||
d_P_accu = gr_complex(0.0, 0.0);
|
|
||||||
d_L_accu = gr_complex(0.0, 0.0);
|
|
||||||
d_VL_accu = gr_complex(0.0, 0.0);
|
|
||||||
d_last_prompt = gr_complex(0.0, 0.0);
|
|
||||||
d_Prompt_buffer_deque.clear();
|
|
||||||
d_current_symbol = 0;
|
|
||||||
d_synchonizing = false;
|
|
||||||
// Set narrow taps delay values [chips]
|
|
||||||
d_code_loop_filter.set_DLL_BW(d_dll_bw_narrow_hz);
|
|
||||||
d_carrier_loop_filter.set_PLL_BW(d_pll_bw_narrow_hz);
|
|
||||||
if (d_veml)
|
|
||||||
{
|
|
||||||
d_local_code_shift_chips[0] = -d_very_early_late_spc_narrow_chips * static_cast<float>(d_code_samples_per_chip);
|
|
||||||
d_local_code_shift_chips[1] = -d_early_late_spc_narrow_chips * static_cast<float>(d_code_samples_per_chip);
|
|
||||||
d_local_code_shift_chips[3] = d_early_late_spc_narrow_chips * static_cast<float>(d_code_samples_per_chip);
|
|
||||||
d_local_code_shift_chips[4] = d_very_early_late_spc_narrow_chips * static_cast<float>(d_code_samples_per_chip);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
d_local_code_shift_chips[0] = -d_early_late_spc_narrow_chips * static_cast<float>(d_code_samples_per_chip);
|
|
||||||
d_local_code_shift_chips[2] = d_early_late_spc_narrow_chips * static_cast<float>(d_code_samples_per_chip);
|
|
||||||
}
|
|
||||||
|
|
||||||
// UPDATE INTEGRATION TIME
|
|
||||||
if (d_enable_extended_integration)
|
|
||||||
{
|
|
||||||
d_extend_correlation_symbols_count = 0;
|
|
||||||
float new_correlation_time_s = static_cast<float>(d_extend_correlation_symbols) * static_cast<float>(d_code_period);
|
|
||||||
d_carrier_loop_filter.set_pdi(new_correlation_time_s);
|
|
||||||
d_code_loop_filter.set_pdi(new_correlation_time_s);
|
|
||||||
d_state = 3; // next state is the extended correlator integrator
|
|
||||||
LOG(INFO) << "Enabled " << d_extend_correlation_symbols << " [symbols] extended correlator for CH "
|
|
||||||
<< d_channel
|
|
||||||
<< " : Satellite " << Gnss_Satellite(systemName, d_acquisition_gnss_synchro->PRN);
|
|
||||||
std::cout << "Enabled " << d_extend_correlation_symbols << " [symbols] extended correlator for CH "
|
|
||||||
<< d_channel
|
|
||||||
<< " : Satellite " << Gnss_Satellite(systemName, d_acquisition_gnss_synchro->PRN) << std::endl;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
d_state = 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 3: // coherent integration (correlation time extension)
|
|
||||||
{
|
|
||||||
// Fill the acquisition data
|
|
||||||
current_synchro_data = *d_acquisition_gnss_synchro;
|
|
||||||
// perform a correlation step
|
|
||||||
do_correlation_step(in);
|
|
||||||
update_tracking_vars();
|
|
||||||
save_correlation_results();
|
|
||||||
|
|
||||||
// ########### Output the tracking results to Telemetry block ##########
|
|
||||||
if (interchange_iq)
|
|
||||||
{
|
|
||||||
if (d_track_pilot)
|
|
||||||
{
|
|
||||||
//Note that data and pilot components are in quadrature. I and Q are interchanged
|
|
||||||
current_synchro_data.Prompt_I = static_cast<double>((*d_Prompt_Data).imag());
|
|
||||||
current_synchro_data.Prompt_Q = static_cast<double>((*d_Prompt_Data).real());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
current_synchro_data.Prompt_I = static_cast<double>((*d_Prompt).imag());
|
|
||||||
current_synchro_data.Prompt_Q = static_cast<double>((*d_Prompt).real());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (d_track_pilot)
|
|
||||||
{
|
|
||||||
//Note that data and pilot components are in quadrature. I and Q are interchanged
|
|
||||||
current_synchro_data.Prompt_I = static_cast<double>((*d_Prompt_Data).real());
|
|
||||||
current_synchro_data.Prompt_Q = static_cast<double>((*d_Prompt_Data).imag());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
current_synchro_data.Prompt_I = static_cast<double>((*d_Prompt).real());
|
|
||||||
current_synchro_data.Prompt_Q = static_cast<double>((*d_Prompt).imag());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
current_synchro_data.Code_phase_samples = d_rem_code_phase_samples;
|
|
||||||
current_synchro_data.Carrier_phase_rads = d_acc_carrier_phase_rad;
|
|
||||||
current_synchro_data.Carrier_Doppler_hz = d_carrier_doppler_hz;
|
|
||||||
current_synchro_data.CN0_dB_hz = d_CN0_SNV_dB_Hz;
|
|
||||||
current_synchro_data.Flag_valid_symbol_output = true;
|
|
||||||
current_synchro_data.correlation_length_ms = d_correlation_length_ms;
|
|
||||||
d_extend_correlation_symbols_count++;
|
|
||||||
if (d_extend_correlation_symbols_count == (d_extend_correlation_symbols - 1))
|
|
||||||
{
|
|
||||||
d_extend_correlation_symbols_count = 0;
|
|
||||||
d_state = 4;
|
|
||||||
}
|
|
||||||
log_data(true);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 4: // narrow tracking
|
|
||||||
{
|
|
||||||
// Fill the acquisition data
|
|
||||||
current_synchro_data = *d_acquisition_gnss_synchro;
|
|
||||||
|
|
||||||
// perform a correlation step
|
|
||||||
do_correlation_step(in);
|
|
||||||
save_correlation_results();
|
|
||||||
|
|
||||||
// check lock status
|
|
||||||
if (!cn0_and_tracking_lock_status())
|
|
||||||
{
|
|
||||||
clear_tracking_vars();
|
|
||||||
d_state = 0; // loss-of-lock detected
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
run_dll_pll();
|
|
||||||
update_tracking_vars();
|
|
||||||
|
|
||||||
// ########### Output the tracking results to Telemetry block ##########
|
|
||||||
if (interchange_iq)
|
|
||||||
{
|
|
||||||
if (d_track_pilot)
|
|
||||||
{
|
|
||||||
//Note that data and pilot components are in quadrature. I and Q are interchanged
|
|
||||||
current_synchro_data.Prompt_I = static_cast<double>((*d_Prompt_Data).imag());
|
|
||||||
current_synchro_data.Prompt_Q = static_cast<double>((*d_Prompt_Data).real());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
current_synchro_data.Prompt_I = static_cast<double>((*d_Prompt).imag());
|
|
||||||
current_synchro_data.Prompt_Q = static_cast<double>((*d_Prompt).real());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (d_track_pilot)
|
|
||||||
{
|
|
||||||
//Note that data and pilot components are in quadrature. I and Q are interchanged
|
|
||||||
current_synchro_data.Prompt_I = static_cast<double>((*d_Prompt_Data).real());
|
|
||||||
current_synchro_data.Prompt_Q = static_cast<double>((*d_Prompt_Data).imag());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
current_synchro_data.Prompt_I = static_cast<double>((*d_Prompt).real());
|
|
||||||
current_synchro_data.Prompt_Q = static_cast<double>((*d_Prompt).imag());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
current_synchro_data.Code_phase_samples = d_rem_code_phase_samples;
|
|
||||||
current_synchro_data.Carrier_phase_rads = d_acc_carrier_phase_rad;
|
|
||||||
current_synchro_data.Carrier_Doppler_hz = d_carrier_doppler_hz;
|
|
||||||
current_synchro_data.CN0_dB_hz = d_CN0_SNV_dB_Hz;
|
|
||||||
current_synchro_data.Flag_valid_symbol_output = true;
|
|
||||||
current_synchro_data.correlation_length_ms = d_correlation_length_ms;
|
|
||||||
// enable write dump file this cycle (valid DLL/PLL cycle)
|
|
||||||
log_data(false);
|
|
||||||
// reset extended correlator
|
|
||||||
d_VE_accu = gr_complex(0.0, 0.0);
|
|
||||||
d_E_accu = gr_complex(0.0, 0.0);
|
|
||||||
d_P_accu = gr_complex(0.0, 0.0);
|
|
||||||
d_L_accu = gr_complex(0.0, 0.0);
|
|
||||||
d_VL_accu = gr_complex(0.0, 0.0);
|
|
||||||
if (d_enable_extended_integration)
|
|
||||||
{
|
|
||||||
d_state = 3; //new coherent integration (correlation time extension) cycle
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
consume_each(d_current_prn_length_samples);
|
|
||||||
d_sample_counter += d_current_prn_length_samples;
|
|
||||||
if (current_synchro_data.Flag_valid_symbol_output)
|
|
||||||
{
|
|
||||||
current_synchro_data.fs = static_cast<long int>(d_fs_in);
|
|
||||||
current_synchro_data.Tracking_sample_counter = d_sample_counter;
|
|
||||||
*out[0] = current_synchro_data;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int dll_pll_veml_tracking::save_matfile()
|
int dll_pll_veml_tracking::save_matfile()
|
||||||
{
|
{
|
||||||
// READ DUMP FILE
|
// READ DUMP FILE
|
||||||
@ -1510,3 +1217,297 @@ void dll_pll_veml_tracking::set_gnss_synchro(Gnss_Synchro *p_gnss_synchro)
|
|||||||
gr::thread::scoped_lock l(d_setlock);
|
gr::thread::scoped_lock l(d_setlock);
|
||||||
d_acquisition_gnss_synchro = p_gnss_synchro;
|
d_acquisition_gnss_synchro = p_gnss_synchro;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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::thread::scoped_lock l(d_setlock);
|
||||||
|
const gr_complex *in = reinterpret_cast<const gr_complex *>(input_items[0]);
|
||||||
|
Gnss_Synchro **out = reinterpret_cast<Gnss_Synchro **>(&output_items[0]);
|
||||||
|
Gnss_Synchro current_synchro_data = Gnss_Synchro();
|
||||||
|
|
||||||
|
switch (d_state)
|
||||||
|
{
|
||||||
|
case 0: // Standby - Consume samples at full throttle, do nothing
|
||||||
|
{
|
||||||
|
d_sample_counter += ninput_items[0];
|
||||||
|
consume_each(ninput_items[0]);
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1: // Pull-in
|
||||||
|
{
|
||||||
|
// Signal alignment (skip samples until the incoming signal is aligned with local replica)
|
||||||
|
unsigned long int acq_to_trk_delay_samples = d_sample_counter - d_acq_sample_stamp;
|
||||||
|
double acq_trk_shif_correction_samples = static_cast<double>(d_current_prn_length_samples) - std::fmod(static_cast<double>(acq_to_trk_delay_samples), static_cast<double>(d_current_prn_length_samples));
|
||||||
|
int samples_offset = std::round(d_acq_code_phase_samples + acq_trk_shif_correction_samples);
|
||||||
|
if (samples_offset < 0)
|
||||||
|
{
|
||||||
|
samples_offset = 0;
|
||||||
|
}
|
||||||
|
d_acc_carrier_phase_rad -= d_carrier_phase_step_rad * d_acq_code_phase_samples;
|
||||||
|
d_state = 2;
|
||||||
|
d_sample_counter += samples_offset; // count for the processed samples
|
||||||
|
consume_each(samples_offset); // shift input to perform alignment with local replica
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
case 2: // Wide tracking and symbol synchronization
|
||||||
|
{
|
||||||
|
do_correlation_step(in);
|
||||||
|
// Save single correlation step variables
|
||||||
|
if (d_veml)
|
||||||
|
{
|
||||||
|
d_VE_accu = *d_Very_Early;
|
||||||
|
d_VL_accu = *d_Very_Late;
|
||||||
|
}
|
||||||
|
d_E_accu = *d_Early;
|
||||||
|
d_P_accu = *d_Prompt;
|
||||||
|
d_L_accu = *d_Late;
|
||||||
|
|
||||||
|
// Check lock status
|
||||||
|
if (!cn0_and_tracking_lock_status())
|
||||||
|
{
|
||||||
|
clear_tracking_vars();
|
||||||
|
d_state = 0; // loss-of-lock detected
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bool next_state = false;
|
||||||
|
// Perform DLL/PLL tracking loop computations. Costas Loop enabled
|
||||||
|
run_dll_pll();
|
||||||
|
update_tracking_vars();
|
||||||
|
|
||||||
|
// enable write dump file this cycle (valid DLL/PLL cycle)
|
||||||
|
log_data(false);
|
||||||
|
if (d_secondary)
|
||||||
|
{
|
||||||
|
// ####### SECONDARY CODE LOCK #####
|
||||||
|
d_Prompt_buffer_deque.push_back(*d_Prompt);
|
||||||
|
if (d_Prompt_buffer_deque.size() == d_secondary_code_length)
|
||||||
|
{
|
||||||
|
next_state = acquire_secondary();
|
||||||
|
if (next_state)
|
||||||
|
{
|
||||||
|
std::cout << "Secondary code locked for CH " << d_channel
|
||||||
|
<< " : Satellite " << Gnss_Satellite(systemName, d_acquisition_gnss_synchro->PRN) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
d_Prompt_buffer_deque.pop_front();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // Signal does not have secondary code. Search a bit transition by sign change
|
||||||
|
{
|
||||||
|
if (d_synchonizing)
|
||||||
|
{
|
||||||
|
if (d_Prompt->real() * d_last_prompt.real() > 0.0)
|
||||||
|
{
|
||||||
|
d_current_symbol++;
|
||||||
|
}
|
||||||
|
else if (d_current_symbol > d_symbols_per_bit)
|
||||||
|
{
|
||||||
|
d_synchonizing = false;
|
||||||
|
d_current_symbol = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
d_current_symbol = 1;
|
||||||
|
d_last_prompt = *d_Prompt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (d_last_prompt.real() != 0.0)
|
||||||
|
{
|
||||||
|
d_current_symbol++;
|
||||||
|
if (d_current_symbol == d_symbols_per_bit) next_state = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
d_last_prompt = *d_Prompt;
|
||||||
|
d_synchonizing = true;
|
||||||
|
d_current_symbol = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (next_state)
|
||||||
|
{ // reset extended correlator
|
||||||
|
d_VE_accu = gr_complex(0.0, 0.0);
|
||||||
|
d_E_accu = gr_complex(0.0, 0.0);
|
||||||
|
d_P_accu = gr_complex(0.0, 0.0);
|
||||||
|
d_L_accu = gr_complex(0.0, 0.0);
|
||||||
|
d_VL_accu = gr_complex(0.0, 0.0);
|
||||||
|
d_last_prompt = gr_complex(0.0, 0.0);
|
||||||
|
d_Prompt_buffer_deque.clear();
|
||||||
|
d_current_symbol = 0;
|
||||||
|
d_synchonizing = false;
|
||||||
|
// Set narrow taps delay values [chips]
|
||||||
|
d_code_loop_filter.set_DLL_BW(d_dll_bw_narrow_hz);
|
||||||
|
d_carrier_loop_filter.set_PLL_BW(d_pll_bw_narrow_hz);
|
||||||
|
if (d_veml)
|
||||||
|
{
|
||||||
|
d_local_code_shift_chips[0] = -d_very_early_late_spc_narrow_chips * static_cast<float>(d_code_samples_per_chip);
|
||||||
|
d_local_code_shift_chips[1] = -d_early_late_spc_narrow_chips * static_cast<float>(d_code_samples_per_chip);
|
||||||
|
d_local_code_shift_chips[3] = d_early_late_spc_narrow_chips * static_cast<float>(d_code_samples_per_chip);
|
||||||
|
d_local_code_shift_chips[4] = d_very_early_late_spc_narrow_chips * static_cast<float>(d_code_samples_per_chip);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
d_local_code_shift_chips[0] = -d_early_late_spc_narrow_chips * static_cast<float>(d_code_samples_per_chip);
|
||||||
|
d_local_code_shift_chips[2] = d_early_late_spc_narrow_chips * static_cast<float>(d_code_samples_per_chip);
|
||||||
|
}
|
||||||
|
|
||||||
|
// UPDATE INTEGRATION TIME
|
||||||
|
if (d_enable_extended_integration)
|
||||||
|
{
|
||||||
|
d_extend_correlation_symbols_count = 0;
|
||||||
|
float new_correlation_time_s = static_cast<float>(d_extend_correlation_symbols) * static_cast<float>(d_code_period);
|
||||||
|
d_carrier_loop_filter.set_pdi(new_correlation_time_s);
|
||||||
|
d_code_loop_filter.set_pdi(new_correlation_time_s);
|
||||||
|
d_state = 3; // next state is the extended correlator integrator
|
||||||
|
LOG(INFO) << "Enabled " << d_extend_correlation_symbols << " [symbols] extended correlator for CH "
|
||||||
|
<< d_channel
|
||||||
|
<< " : Satellite " << Gnss_Satellite(systemName, d_acquisition_gnss_synchro->PRN);
|
||||||
|
std::cout << "Enabled " << d_extend_correlation_symbols << " [symbols] extended correlator for CH "
|
||||||
|
<< d_channel
|
||||||
|
<< " : Satellite " << Gnss_Satellite(systemName, d_acquisition_gnss_synchro->PRN) << std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
d_state = 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 3: // coherent integration (correlation time extension)
|
||||||
|
{
|
||||||
|
// Fill the acquisition data
|
||||||
|
current_synchro_data = *d_acquisition_gnss_synchro;
|
||||||
|
// perform a correlation step
|
||||||
|
do_correlation_step(in);
|
||||||
|
update_tracking_vars();
|
||||||
|
save_correlation_results();
|
||||||
|
|
||||||
|
// ########### Output the tracking results to Telemetry block ##########
|
||||||
|
if (interchange_iq)
|
||||||
|
{
|
||||||
|
if (d_track_pilot)
|
||||||
|
{
|
||||||
|
// Note that data and pilot components are in quadrature. I and Q are interchanged
|
||||||
|
current_synchro_data.Prompt_I = static_cast<double>((*d_Prompt_Data).imag());
|
||||||
|
current_synchro_data.Prompt_Q = static_cast<double>((*d_Prompt_Data).real());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
current_synchro_data.Prompt_I = static_cast<double>((*d_Prompt).imag());
|
||||||
|
current_synchro_data.Prompt_Q = static_cast<double>((*d_Prompt).real());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (d_track_pilot)
|
||||||
|
{
|
||||||
|
// Note that data and pilot components are in quadrature. I and Q are interchanged
|
||||||
|
current_synchro_data.Prompt_I = static_cast<double>((*d_Prompt_Data).real());
|
||||||
|
current_synchro_data.Prompt_Q = static_cast<double>((*d_Prompt_Data).imag());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
current_synchro_data.Prompt_I = static_cast<double>((*d_Prompt).real());
|
||||||
|
current_synchro_data.Prompt_Q = static_cast<double>((*d_Prompt).imag());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
current_synchro_data.Code_phase_samples = d_rem_code_phase_samples;
|
||||||
|
current_synchro_data.Carrier_phase_rads = d_acc_carrier_phase_rad;
|
||||||
|
current_synchro_data.Carrier_Doppler_hz = d_carrier_doppler_hz;
|
||||||
|
current_synchro_data.CN0_dB_hz = d_CN0_SNV_dB_Hz;
|
||||||
|
current_synchro_data.Flag_valid_symbol_output = true;
|
||||||
|
current_synchro_data.correlation_length_ms = d_correlation_length_ms;
|
||||||
|
d_extend_correlation_symbols_count++;
|
||||||
|
if (d_extend_correlation_symbols_count == (d_extend_correlation_symbols - 1))
|
||||||
|
{
|
||||||
|
d_extend_correlation_symbols_count = 0;
|
||||||
|
d_state = 4;
|
||||||
|
}
|
||||||
|
log_data(true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 4: // narrow tracking
|
||||||
|
{
|
||||||
|
// Fill the acquisition data
|
||||||
|
current_synchro_data = *d_acquisition_gnss_synchro;
|
||||||
|
|
||||||
|
// perform a correlation step
|
||||||
|
do_correlation_step(in);
|
||||||
|
save_correlation_results();
|
||||||
|
|
||||||
|
// check lock status
|
||||||
|
if (!cn0_and_tracking_lock_status())
|
||||||
|
{
|
||||||
|
clear_tracking_vars();
|
||||||
|
d_state = 0; // loss-of-lock detected
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
run_dll_pll();
|
||||||
|
update_tracking_vars();
|
||||||
|
|
||||||
|
// ########### Output the tracking results to Telemetry block ##########
|
||||||
|
if (interchange_iq)
|
||||||
|
{
|
||||||
|
if (d_track_pilot)
|
||||||
|
{
|
||||||
|
// Note that data and pilot components are in quadrature. I and Q are interchanged
|
||||||
|
current_synchro_data.Prompt_I = static_cast<double>((*d_Prompt_Data).imag());
|
||||||
|
current_synchro_data.Prompt_Q = static_cast<double>((*d_Prompt_Data).real());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
current_synchro_data.Prompt_I = static_cast<double>((*d_Prompt).imag());
|
||||||
|
current_synchro_data.Prompt_Q = static_cast<double>((*d_Prompt).real());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (d_track_pilot)
|
||||||
|
{
|
||||||
|
// Note that data and pilot components are in quadrature. I and Q are interchanged
|
||||||
|
current_synchro_data.Prompt_I = static_cast<double>((*d_Prompt_Data).real());
|
||||||
|
current_synchro_data.Prompt_Q = static_cast<double>((*d_Prompt_Data).imag());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
current_synchro_data.Prompt_I = static_cast<double>((*d_Prompt).real());
|
||||||
|
current_synchro_data.Prompt_Q = static_cast<double>((*d_Prompt).imag());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
current_synchro_data.Code_phase_samples = d_rem_code_phase_samples;
|
||||||
|
current_synchro_data.Carrier_phase_rads = d_acc_carrier_phase_rad;
|
||||||
|
current_synchro_data.Carrier_Doppler_hz = d_carrier_doppler_hz;
|
||||||
|
current_synchro_data.CN0_dB_hz = d_CN0_SNV_dB_Hz;
|
||||||
|
current_synchro_data.Flag_valid_symbol_output = true;
|
||||||
|
current_synchro_data.correlation_length_ms = d_correlation_length_ms;
|
||||||
|
// enable write dump file this cycle (valid DLL/PLL cycle)
|
||||||
|
log_data(false);
|
||||||
|
// reset extended correlator
|
||||||
|
d_VE_accu = gr_complex(0.0, 0.0);
|
||||||
|
d_E_accu = gr_complex(0.0, 0.0);
|
||||||
|
d_P_accu = gr_complex(0.0, 0.0);
|
||||||
|
d_L_accu = gr_complex(0.0, 0.0);
|
||||||
|
d_VL_accu = gr_complex(0.0, 0.0);
|
||||||
|
if (d_enable_extended_integration)
|
||||||
|
{
|
||||||
|
d_state = 3; // new coherent integration (correlation time extension) cycle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
consume_each(d_current_prn_length_samples);
|
||||||
|
d_sample_counter += d_current_prn_length_samples;
|
||||||
|
if (current_synchro_data.Flag_valid_symbol_output)
|
||||||
|
{
|
||||||
|
current_synchro_data.fs = static_cast<long int>(d_fs_in);
|
||||||
|
current_synchro_data.Tracking_sample_counter = d_sample_counter;
|
||||||
|
*out[0] = current_synchro_data;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/*!
|
/*!
|
||||||
* \file dll_pll_veml_tracking.h
|
* \file dll_pll_veml_tracking.h
|
||||||
* \brief Implementation of a code DLL + carrier PLL tracking block.
|
* \brief Implementation of a code DLL + carrier PLL tracking block.
|
||||||
* \author Antonio Ramos, 2018 antonioramosdet(at)gmail.com
|
* \author Antonio Ramos, 2018 antonio.ramosdet(at)gmail.com
|
||||||
*
|
*
|
||||||
* -------------------------------------------------------------------------
|
* -------------------------------------------------------------------------
|
||||||
*
|
*
|
||||||
@ -55,8 +55,7 @@ dll_pll_veml_tracking_sptr dll_pll_veml_make_tracking(double fs_in, unsigned int
|
|||||||
char system, char signal[3]);
|
char system, char signal[3]);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief This class implements a code DLL + carrier PLL VEML (Very Early
|
* \brief This class implements a code DLL + carrier PLL tracking block.
|
||||||
* Minus Late) tracking block for Galileo E1 signals
|
|
||||||
*/
|
*/
|
||||||
class dll_pll_veml_tracking : public gr::block
|
class dll_pll_veml_tracking : public gr::block
|
||||||
{
|
{
|
||||||
@ -67,12 +66,6 @@ public:
|
|||||||
void set_gnss_synchro(Gnss_Synchro *p_gnss_synchro);
|
void set_gnss_synchro(Gnss_Synchro *p_gnss_synchro);
|
||||||
void start_tracking();
|
void start_tracking();
|
||||||
|
|
||||||
/*!
|
|
||||||
* \brief Code DLL + carrier PLL according to the algorithms described in:
|
|
||||||
* K.Borre, D.M.Akos, N.Bertelsen, P.Rinder, and S.H.Jensen,
|
|
||||||
* A Software-Defined GPS and Galileo Receiver. A Single-Frequency Approach,
|
|
||||||
* Birkhauser, 2007
|
|
||||||
*/
|
|
||||||
int general_work(int noutput_items, gr_vector_int &ninput_items,
|
int general_work(int noutput_items, 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);
|
||||||
|
|
||||||
@ -214,9 +207,9 @@ private:
|
|||||||
double T_prn_seconds;
|
double T_prn_seconds;
|
||||||
double T_prn_samples;
|
double T_prn_samples;
|
||||||
double K_blk_samples;
|
double K_blk_samples;
|
||||||
//PRN period in samples
|
// PRN period in samples
|
||||||
int d_current_prn_length_samples;
|
int d_current_prn_length_samples;
|
||||||
//processing samples counters
|
// processing samples counters
|
||||||
unsigned long int d_sample_counter;
|
unsigned long int d_sample_counter;
|
||||||
unsigned long int d_acq_sample_stamp;
|
unsigned long int d_acq_sample_stamp;
|
||||||
|
|
||||||
@ -234,4 +227,4 @@ private:
|
|||||||
std::ofstream d_dump_file;
|
std::ofstream d_dump_file;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //GNSS_SDR_DLL_PLL_VEML_TRACKING_H
|
#endif // GNSS_SDR_DLL_PLL_VEML_TRACKING_H
|
||||||
|
Loading…
Reference in New Issue
Block a user