From 61d4447657e65127dde69bbd29059eddf16e9152 Mon Sep 17 00:00:00 2001 From: Marc Majoral Date: Fri, 25 Sep 2026 21:26:20 +0200 Subject: [PATCH] Enable FPGA acceleration for Galileo E6 --- .../adapters/pcps_acquisition_adapter_fpga.cc | 10 +++- .../adapters/dll_pll_tracking_adapter_fpga.cc | 59 ++++++++++++++++++- .../dll_pll_veml_tracking_fpga.cc | 39 +++++++++++- src/core/receiver/gnss_block_factory.cc | 8 +++ 4 files changed, 110 insertions(+), 6 deletions(-) diff --git a/src/algorithms/acquisition/adapters/pcps_acquisition_adapter_fpga.cc b/src/algorithms/acquisition/adapters/pcps_acquisition_adapter_fpga.cc index 1532409bc..1bca5c1ef 100644 --- a/src/algorithms/acquisition/adapters/pcps_acquisition_adapter_fpga.cc +++ b/src/algorithms/acquisition/adapters/pcps_acquisition_adapter_fpga.cc @@ -7,7 +7,7 @@ * GNSS-SDR is a Global Navigation Satellite System software-defined receiver. * This file is part of GNSS-SDR. * - * Copyright (C) 2010-2025 (see AUTHORS file for a list of contributors) + * Copyright (C) 2010-2026 (see AUTHORS file for a list of contributors) * SPDX-License-Identifier: GPL-3.0-or-later * * ----------------------------------------------------------------------------- @@ -21,9 +21,11 @@ #include "Galileo_E1.h" #include "Galileo_E5a.h" #include "Galileo_E5b.h" +#include "Galileo_E6.h" #include "configuration_interface.h" #include "galileo_e1_signal_replica.h" #include "galileo_e5_signal_replica.h" +#include "galileo_e6_signal_replica.h" #include "gnss_sdr_fft.h" #include "gnss_sdr_flags.h" #include "gps_l2c_signal_replica.h" @@ -82,6 +84,8 @@ fpga_signal_info get_fpga_signal_info(signal_flag sig_flag) return {GALILEO_E5A_CODE_CHIP_RATE_CPS, GALILEO_E5A_CODE_LENGTH_CHIPS, 0, 13, ACQ_BUFF_1, GALILEO_E5A_NUMBER_OF_CODES}; case GAL_E5b: return {GALILEO_E5B_CODE_CHIP_RATE_CPS, GALILEO_E5B_CODE_LENGTH_CHIPS, 0, 13, ACQ_BUFF_1, GALILEO_E5B_NUMBER_OF_CODES}; + case GAL_E6: + return {GALILEO_E6_B_CODE_CHIP_RATE_CPS, GALILEO_E6_B_CODE_LENGTH_CHIPS, 0, 13, ACQ_BUFF_1, GALILEO_E6_NUMBER_OF_CODES}; default: break; } @@ -172,6 +176,10 @@ void generate_code(signal_flag sig_flag, } galileo_e5_b_code_gen_complex_sampled(code, prn, signal, acq_parameters.fs_in, 0); } + case GAL_E6: + { + galileo_e6_b_code_gen_complex_sampled(code, prn, acq_parameters.fs_in, 0); + } break; default: break; diff --git a/src/algorithms/tracking/adapters/dll_pll_tracking_adapter_fpga.cc b/src/algorithms/tracking/adapters/dll_pll_tracking_adapter_fpga.cc index f93c1b9dd..8c1415779 100644 --- a/src/algorithms/tracking/adapters/dll_pll_tracking_adapter_fpga.cc +++ b/src/algorithms/tracking/adapters/dll_pll_tracking_adapter_fpga.cc @@ -7,7 +7,7 @@ * GNSS-SDR is a Global Navigation Satellite System software-defined receiver. * This file is part of GNSS-SDR. * - * Copyright (C) 2010-2025 (see AUTHORS file for a list of contributors) + * Copyright (C) 2010-2026 (see AUTHORS file for a list of contributors) * SPDX-License-Identifier: GPL-3.0-or-later * * ----------------------------------------------------------------------------- @@ -20,10 +20,12 @@ #include "GPS_L5.h" #include "Galileo_E1.h" #include "Galileo_E5a.h" +#include "Galileo_E6.h" #include "configuration_interface.h" #include "display.h" #include "galileo_e1_signal_replica.h" #include "galileo_e5_signal_replica.h" +#include "galileo_e6_signal_replica.h" #include "gps_l2c_signal_replica.h" #include "gps_l5_signal_replica.h" #include "gps_sdr_signal_replica.h" @@ -84,10 +86,11 @@ tracking_fpga_signal_info get_tracking_fpga_signal_info(signal_flag sig_flag) return {'E', {'1', 'B', '\0'}, "1B", GALILEO_E1_CODE_CHIP_RATE_CPS, GALILEO_E1_B_CODE_LENGTH_CHIPS, GALILEO_E1_NUMBER_OF_CODES, 2}; case GAL_E5a: return {'E', {'5', 'X', '\0'}, "5X", GALILEO_E5A_CODE_CHIP_RATE_CPS, GALILEO_E5A_CODE_LENGTH_CHIPS, GALILEO_E5A_NUMBER_OF_CODES, 1}; + case GAL_E6: + return {'E', {'E', '6', '\0'}, "E6", GALILEO_E6_B_CODE_CHIP_RATE_CPS, GALILEO_E6_B_CODE_LENGTH_CHIPS, GALILEO_E6_NUMBER_OF_CODES, 1}; default: break; } - return {}; } @@ -112,6 +115,7 @@ const std::map DllPllTrackingAdapterFpga::signal_to_de {"L5", "multicorrelator_resampler_3_1_AXI"}, {"1B", "multicorrelator_resampler_5_1_AXI"}, {"5X", "multicorrelator_resampler_3_1_AXI"}, + {"E6", "multicorrelator_resampler_3_1_AXI"}, }; const std::map DllPllTrackingAdapterFpga::signal_to_alternative_device_ = { @@ -265,6 +269,24 @@ void DllPllTrackingAdapterFpga::configure_signal_parameters(const ConfigurationI } warn_narrow_bw("Galileo E5a", trk_params_); break; + case GAL_E6: + if (trk_params_.extend_correlation_symbols < 1) + { + trk_params_.extend_correlation_symbols = 1; + std::cout << TEXT_RED + << "WARNING: Galileo E6. extend_correlation_symbols must be >= 1. " + << "Set to 1 symbol (1 ms)." << TEXT_RESET << '\n'; + } + else if (!trk_params_.track_pilot && trk_params_.extend_correlation_symbols > 1) + { + trk_params_.extend_correlation_symbols = 1; + std::cout << TEXT_RED + << "WARNING: Galileo E6. Extended coherent integration is only supported " + << "when tracking the pilot component. Set to 1 ms (1 symbol)." + << TEXT_RESET << '\n'; + } + warn_narrow_bw("Galileo E6", trk_params_); + break; default: break; } @@ -321,7 +343,7 @@ void DllPllTrackingAdapterFpga::generate_prn_codes() volk_gnsssdr_malloc(code_samples * sig_info.num_prns * sizeof(int32_t), volk_gnsssdr_get_alignment())); - if (trk_params_.track_pilot && (sig_flag_ == GAL_1B || sig_flag_ == GAL_E5a || sig_flag_ == GPS_L5)) + if (trk_params_.track_pilot && (sig_flag_ == GAL_1B || sig_flag_ == GAL_E5a || sig_flag_ == GPS_L5 || sig_flag_ == GAL_E6)) { data_codes_ptr_ = static_cast( volk_gnsssdr_malloc(code_samples * sig_info.num_prns * sizeof(int32_t), @@ -455,6 +477,37 @@ void DllPllTrackingAdapterFpga::generate_prn_codes() } } break; + case GAL_E6: + { + volk_gnsssdr::vector ca_codes_f(code_length_chips, 0.0F); + volk_gnsssdr::vector data_codes_f(code_length_chips, 0.0F); + for (uint32_t prn = 1; prn <= sig_info.num_prns; prn++) + { + if (trk_params_.track_pilot) + { + galileo_e6_c_code_gen_float_primary(ca_codes_f, prn); + galileo_e6_b_code_gen_float_primary(data_codes_f, prn); + } + else + { + galileo_e6_b_code_gen_float_primary(ca_codes_f, prn); + } + for (uint32_t s = 0; s < code_length_chips; s++) + { + int32_t pilot = (ca_codes_f[s] < 0) ? 0 : 1; + pilot |= LOCAL_CODE_FPGA_ENABLE_WRITE_MEMORY; + prn_codes_ptr_[code_length_chips * (prn - 1) + s] = pilot; + + if (trk_params_.track_pilot) + { + int32_t data = (data_codes_f[s] < 0) ? 0 : 1; + data |= LOCAL_CODE_FPGA_ENABLE_WRITE_MEMORY | + LOCAL_CODE_FPGA_CORRELATOR_SELECT_COUNT; + data_codes_ptr_[code_length_chips * (prn - 1) + s] = data; + } + } + } + } default: break; } diff --git a/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking_fpga.cc b/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking_fpga.cc index f5a3013eb..383525f4f 100644 --- a/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking_fpga.cc +++ b/src/algorithms/tracking/gnuradio_blocks/dll_pll_veml_tracking_fpga.cc @@ -1,7 +1,7 @@ /*! * \file dll_pll_veml_tracking_fpga.cc * \brief Implementation of a code DLL + carrier PLL tracking block using an FPGA - * \author Marc Majoral, 2019. marc.majoral(at)cttc.es + * \author Marc Majoral, 2019-2026. marc.majoral(at)cttc.es * \author Javier Arribas, 2019. jarribas(at)cttc.es * * Code DLL + carrier PLL according to the algorithms described in: @@ -14,7 +14,7 @@ * GNSS-SDR is a Global Navigation Satellite System software-defined receiver. * This file is part of GNSS-SDR. * - * Copyright (C) 2010-2020 (see AUTHORS file for a list of contributors) + * Copyright (C) 2010-2026 (see AUTHORS file for a list of contributors) * SPDX-License-Identifier: GPL-3.0-or-later * * ----------------------------------------------------------------------------- @@ -26,8 +26,10 @@ #include "GPS_L5.h" #include "Galileo_E1.h" #include "Galileo_E5a.h" +#include "Galileo_E6.h" #include "MATH_CONSTANTS.h" #include "fpga_multicorrelator.h" +#include "galileo_e6_signal_replica.h" #include "gnss_satellite.h" #include "gnss_sdr_create_directory.h" #include "gnss_sdr_filesystem.h" @@ -169,6 +171,7 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(const Dll_Pll_Conf_Fpga & map_signal_pretty_name["2G"] = "L2 C/A"; map_signal_pretty_name["5X"] = "E5a"; map_signal_pretty_name["L5"] = "L5"; + map_signal_pretty_name["E6"] = "E6"; d_signal_pretty_name = map_signal_pretty_name[d_signal_type]; @@ -325,6 +328,29 @@ dll_pll_veml_tracking_fpga::dll_pll_veml_tracking_fpga(const Dll_Pll_Conf_Fpga & d_signal_pretty_name = d_signal_pretty_name + "I"; } } + else if (d_signal_type == "E6") + { + d_signal_carrier_freq = GALILEO_E6_FREQ_HZ; + d_code_period = GALILEO_E6_CODE_PERIOD_S; + d_code_chip_rate = GALILEO_E6_B_CODE_CHIP_RATE_CPS; + // Galileo E6 has 1 trk symbol (4 ms) per tlm bit, no symbol integration required + d_symbols_per_bit = 1; + d_correlation_length_ms = GALILEO_E6_CODE_PERIOD_MS; + d_trk_parameters.spc = d_trk_parameters.early_late_space_chips; + d_trk_parameters.slope = 1.0; + d_trk_parameters.y_intercept = 1.0; + if (d_trk_parameters.track_pilot) + { + d_secondary = true; + d_secondary_code_length = static_cast(GALILEO_E6_C_SECONDARY_CODE_LENGTH_CHIPS); + d_signal_pretty_name = d_signal_pretty_name + "C"; + } + else + { + d_secondary = false; + d_signal_pretty_name = d_signal_pretty_name + "B"; + } + } else { LOG(WARNING) << "Invalid Signal argument when instantiating tracking blocks"; @@ -1399,6 +1425,15 @@ void dll_pll_veml_tracking_fpga::set_gnss_synchro(Gnss_Synchro *p_gnss_synchro) } } } + else if (d_systemName == "Galileo" && d_signal_type == "E6") + { + if (d_trk_parameters.track_pilot) + { + d_Prompt_Data[0] = gr_complex(0.0, 0.0); + + d_secondary_code_string = galileo_e6_c_secondary_code(d_acquisition_gnss_synchro->PRN); + } + } std::fill_n(d_correlator_outs.begin(), d_n_correlator_taps, gr_complex(0.0, 0.0)); diff --git a/src/core/receiver/gnss_block_factory.cc b/src/core/receiver/gnss_block_factory.cc index 0a1b3a052..75e6ed43f 100644 --- a/src/core/receiver/gnss_block_factory.cc +++ b/src/core/receiver/gnss_block_factory.cc @@ -560,6 +560,10 @@ std::unique_ptr get_acq_block( { return std::make_unique(configuration, role, implementation, in_streams, out_streams, GAL_E5b); } + else if (implementation == "Galileo_E6_PCPS_Acquisition_FPGA") + { + return std::make_unique(configuration, role, implementation, in_streams, out_streams, GAL_E6); + } #endif return nullptr; @@ -680,6 +684,10 @@ std::unique_ptr get_trk_block( { return std::make_unique(configuration, role, implementation, in_streams, out_streams, GAL_E5a); } + else if (implementation == "Galileo_E6_DLL_PLL_Tracking_FPGA") + { + return std::make_unique(configuration, role, implementation, in_streams, out_streams, GAL_E6); + } #endif return nullptr;