mirror of
https://github.com/gnss-sdr/gnss-sdr
synced 2026-06-01 10:12:13 +00:00
Add code generation, acquisition and tracking adapters for QZSS L1 C/A and L5
This commit is contained in:
@@ -36,8 +36,8 @@ uint32_t flags_from_config(const ConfigurationInterface* configuration)
|
||||
{GLO_2G, "Channels_2G.count"},
|
||||
{BDS_B1, "Channels_B1.count"},
|
||||
{BDS_B3, "Channels_B3.count"},
|
||||
{QZS_L1, "Channels_Q1.count"},
|
||||
{QZS_L5, "Channels_Q5.count"}
|
||||
{QZS_J1, "Channels_J1.count"},
|
||||
{QZS_J5, "Channels_J5.count"}
|
||||
};
|
||||
|
||||
for (const auto& pair_aux : signal_flag_to_prop)
|
||||
@@ -67,9 +67,11 @@ Signal_Enabled_Flags::Signal_Enabled_Flags(uint32_t flags_) : flags(flags_),
|
||||
has_galileo(check_any_enabled(GAL_1B, GAL_E5a, GAL_E5b, GAL_E6)),
|
||||
has_glonass(check_any_enabled(GLO_1G, GLO_2G)),
|
||||
has_beidou(check_any_enabled(BDS_B1, BDS_B3)),
|
||||
only_gps(has_gps && !(has_galileo || has_glonass || has_beidou)),
|
||||
only_galileo(has_galileo && !(has_gps || has_glonass || has_beidou)),
|
||||
only_glonass(has_glonass && !(has_gps || has_galileo || has_beidou)),
|
||||
only_beidou(has_beidou && !(has_gps || has_galileo || has_glonass))
|
||||
has_qzss(check_any_enabled(QZS_J1, QZS_J5)),
|
||||
only_gps(has_gps && !(has_galileo || has_glonass || has_beidou || has_qzss)),
|
||||
only_galileo(has_galileo && !(has_gps || has_glonass || has_beidou || has_qzss)),
|
||||
only_glonass(has_glonass && !(has_gps || has_galileo || has_beidou || has_qzss)),
|
||||
only_beidou(has_beidou && !(has_gps || has_galileo || has_glonass || has_qzss)),
|
||||
only_qzss(has_qzss && !(has_gps || has_galileo || has_glonass || has_beidou))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -34,8 +34,8 @@ enum signal_flag : uint32_t
|
||||
GLO_2G = 0x1 << 8,
|
||||
BDS_B1 = 0x1 << 9,
|
||||
BDS_B3 = 0x1 << 10,
|
||||
QZS_L1 = 0x1 << 11,
|
||||
QZS_L5 = 0x1 << 12
|
||||
QZS_J1 = 0x1 << 11,
|
||||
QZS_J5 = 0x1 << 12
|
||||
};
|
||||
|
||||
class Signal_Enabled_Flags
|
||||
@@ -74,11 +74,13 @@ public:
|
||||
const bool has_galileo;
|
||||
const bool has_glonass;
|
||||
const bool has_beidou;
|
||||
const bool has_qzss;
|
||||
|
||||
const bool only_gps;
|
||||
const bool only_galileo;
|
||||
const bool only_glonass;
|
||||
const bool only_beidou;
|
||||
const bool only_qzss;
|
||||
};
|
||||
|
||||
#endif // GNSS_SDR_SIGNAL_ENABLED_FLAGS_H
|
||||
|
||||
@@ -28,6 +28,8 @@ set(ACQ_ADAPTER_SOURCES
|
||||
glonass_l2_ca_pcps_acquisition.cc
|
||||
beidou_b1i_pcps_acquisition.cc
|
||||
beidou_b3i_pcps_acquisition.cc
|
||||
qzss_l1_pcps_acquisition.cc
|
||||
qzss_l5i_pcps_acquisition.cc
|
||||
)
|
||||
|
||||
set(ACQ_ADAPTER_HEADERS
|
||||
@@ -53,6 +55,8 @@ set(ACQ_ADAPTER_HEADERS
|
||||
glonass_l2_ca_pcps_acquisition.h
|
||||
beidou_b1i_pcps_acquisition.h
|
||||
beidou_b3i_pcps_acquisition.h
|
||||
qzss_l1_pcps_acquisition.h
|
||||
qzss_l5i_pcps_acquisition.h
|
||||
)
|
||||
|
||||
if(ENABLE_FPGA)
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/*!
|
||||
* \file qzss_l1_pcps_acquisition.cc
|
||||
* \brief Adapts a PCPS acquisition block to an AcquisitionInterface for
|
||||
* QZSS L1 signals
|
||||
* \authors <ul>
|
||||
* <li> Carles Fernandez, 2026. cfernandez(at)cttc.es
|
||||
* </ul>
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*
|
||||
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* Copyright (C) 2010-2026 (see AUTHORS file for a list of contributors)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#include "qzss_l1_pcps_acquisition.h"
|
||||
#include "qzss.h"
|
||||
#include "qzss_signal_replica.h"
|
||||
|
||||
|
||||
QzssL1PcpsAcquisition::QzssL1PcpsAcquisition(
|
||||
const ConfigurationInterface* configuration,
|
||||
const std::string& role,
|
||||
unsigned int in_streams,
|
||||
unsigned int out_streams)
|
||||
: BasePcpsAcquisition(configuration,
|
||||
role,
|
||||
in_streams,
|
||||
out_streams,
|
||||
QZSS_L1_CHIP_RATE,
|
||||
QZSS_L1_OPT_ACQ_FS_SPS,
|
||||
QZSS_L1_CODE_LENGTH,
|
||||
QZSS_L1_PERIOD_MS)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void QzssL1PcpsAcquisition::code_gen_complex_sampled(own::span<std::complex<float>> dest, uint32_t prn, int32_t sampling_freq)
|
||||
{
|
||||
qzss_l1_code_gen_complex_sampled(dest, prn, sampling_freq);
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*!
|
||||
* \file qzss_l1_pcps_acquisition.h
|
||||
* \brief Adapts a PCPS acquisition block to an AcquisitionInterface for
|
||||
* QZSS L1 signals
|
||||
* \authors <ul>
|
||||
* <li> Carles Fernandez, 2026. cfernandez(at)cttc.es
|
||||
* </ul>
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*
|
||||
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* Copyright (C) 2010-2026 (see AUTHORS file for a list of contributors)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef GNSS_SDR_QZSS_L1_PCPS_ACQUISITION_H
|
||||
#define GNSS_SDR_QZSS_L1_PCPS_ACQUISITION_H
|
||||
|
||||
#include "base_pcps_acquisition.h"
|
||||
|
||||
/** \addtogroup Acquisition
|
||||
* \{ */
|
||||
/** \addtogroup Acq_adapters
|
||||
* \{ */
|
||||
|
||||
/*!
|
||||
* \brief This class adapts a PCPS acquisition block to an AcquisitionInterface
|
||||
* for QZSS L1 signals
|
||||
*/
|
||||
class QzssL1PcpsAcquisition : public BasePcpsAcquisition
|
||||
{
|
||||
public:
|
||||
QzssL1PcpsAcquisition(
|
||||
const ConfigurationInterface* configuration,
|
||||
const std::string& role,
|
||||
unsigned int in_streams,
|
||||
unsigned int out_streams);
|
||||
|
||||
~QzssL1PcpsAcquisition() = default;
|
||||
|
||||
/*!
|
||||
* \brief Returns "QZSS_L1_PCPS_Acquisition"
|
||||
*/
|
||||
inline std::string implementation() override
|
||||
{
|
||||
return "QZSS_L1_PCPS_Acquisition";
|
||||
}
|
||||
|
||||
private:
|
||||
void code_gen_complex_sampled(own::span<std::complex<float>> dest, uint32_t prn, int32_t sampling_freq) override;
|
||||
};
|
||||
|
||||
|
||||
/** \} */
|
||||
/** \} */
|
||||
|
||||
|
||||
#endif // GNSS_SDR_QZSS_L1_PCPS_ACQUISITION_H
|
||||
@@ -0,0 +1,46 @@
|
||||
/*!
|
||||
* \file qzss_l5i_pcps_acquisition.cc
|
||||
* \brief Adapts a PCPS acquisition block to an AcquisitionInterface for
|
||||
* QZSS L5I signals
|
||||
* \authors <ul>
|
||||
* <li> Carles Fernandez, 2026. cfernandez(at)cttc.es
|
||||
* </ul>
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*
|
||||
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* Copyright (C) 2010-2026 (see AUTHORS file for a list of contributors)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#include "qzss_l5i_pcps_acquisition.h"
|
||||
#include "qzss.h"
|
||||
#include "qzss_signal_replica.h"
|
||||
|
||||
|
||||
QzssL5iPcpsAcquisition::QzssL5iPcpsAcquisition(
|
||||
const ConfigurationInterface* configuration,
|
||||
const std::string& role,
|
||||
unsigned int in_streams,
|
||||
unsigned int out_streams)
|
||||
: BasePcpsAcquisition(configuration,
|
||||
role,
|
||||
in_streams,
|
||||
out_streams,
|
||||
QZSS_L5_CHIP_RATE,
|
||||
QZSS_L5_OPT_ACQ_FS_SPS,
|
||||
QZSS_L5_CODE_LENGTH,
|
||||
QZSS_L5I_PERIOD_MS)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void QzssL5iPcpsAcquisition::code_gen_complex_sampled(own::span<std::complex<float>> dest, uint32_t prn, int32_t sampling_freq)
|
||||
{
|
||||
qzss_l5i_code_gen_complex_sampled(dest, prn, sampling_freq);
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*!
|
||||
* \file qzss_l5i_pcps_acquisition.h
|
||||
* \brief Adapts a PCPS acquisition block to an AcquisitionInterface for
|
||||
* QZSS L5I signals
|
||||
* \authors <ul>
|
||||
* <li> Carles Fernandez, 2026. cfernandez(at)cttc.es
|
||||
* </ul>
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*
|
||||
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* Copyright (C) 2010-2026 (see AUTHORS file for a list of contributors)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef GNSS_SDR_QZSS_L5I_PCPS_ACQUISITION_H
|
||||
#define GNSS_SDR_QZSS_L5I_PCPS_ACQUISITION_H
|
||||
|
||||
#include "base_pcps_acquisition.h"
|
||||
|
||||
/** \addtogroup Acquisition
|
||||
* \{ */
|
||||
/** \addtogroup Acq_adapters
|
||||
* \{ */
|
||||
|
||||
/*!
|
||||
* \brief This class adapts a PCPS acquisition block to an AcquisitionInterface
|
||||
* for QZSS L5I signals
|
||||
*/
|
||||
class QzssL5iPcpsAcquisition : public BasePcpsAcquisition
|
||||
{
|
||||
public:
|
||||
QzssL5iPcpsAcquisition(
|
||||
const ConfigurationInterface* configuration,
|
||||
const std::string& role,
|
||||
unsigned int in_streams,
|
||||
unsigned int out_streams);
|
||||
|
||||
~QzssL5iPcpsAcquisition() = default;
|
||||
|
||||
/*!
|
||||
* \brief Returns "QZSS_L5I_PCPS_Acquisition"
|
||||
*/
|
||||
inline std::string implementation() override
|
||||
{
|
||||
return "QZSS_L5I_PCPS_Acquisition";
|
||||
}
|
||||
|
||||
private:
|
||||
void code_gen_complex_sampled(own::span<std::complex<float>> dest, uint32_t prn, int32_t sampling_freq) override;
|
||||
};
|
||||
|
||||
|
||||
/** \} */
|
||||
/** \} */
|
||||
|
||||
|
||||
#endif // GNSS_SDR_QZSS_L5I_PCPS_ACQUISITION_H
|
||||
@@ -32,6 +32,7 @@ set(GNSS_SPLIBS_SOURCES
|
||||
pass_through.cc
|
||||
short_x2_to_cshort.cc
|
||||
gnss_sdr_string_literals.cc
|
||||
qzss_signal_replica.cc
|
||||
)
|
||||
|
||||
set(GNSS_SPLIBS_HEADERS
|
||||
@@ -66,6 +67,7 @@ set(GNSS_SPLIBS_HEADERS
|
||||
gnss_sdr_string_literals.h
|
||||
gnss_time.h
|
||||
matlab_writter_helper.h
|
||||
qzss_signal_replica.h
|
||||
)
|
||||
|
||||
set(GNSS_SPLIBS_HEADERS ${GNSS_SPLIBS_HEADERS}
|
||||
|
||||
@@ -0,0 +1,352 @@
|
||||
/*!
|
||||
* \file qzss_signal_replica.cc
|
||||
* \brief This file implements signal generators for QZSS signals
|
||||
* \author Carles Fernández-Prades, 2026. cfernandez (at) cttc.es
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*
|
||||
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* Copyright (C) 2010-2026 (see AUTHORS file for a list of contributors)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "qzss_signal_replica.h"
|
||||
#include "qzss.h"
|
||||
#include <array>
|
||||
#if USE_GLOG_AND_GFLAGS
|
||||
#include <glog/logging.h>
|
||||
#else
|
||||
#include <absl/log/log.h>
|
||||
#endif
|
||||
|
||||
// -----------------------------
|
||||
// QZSS L1 C/A utils
|
||||
// -----------------------------
|
||||
|
||||
struct QzssL1Entry
|
||||
{
|
||||
uint16_t g2_delay_chips; // Provided by ICD, but not applied if using init_g2_octal
|
||||
uint16_t init_g2_octal; // 10-bit value expressed in octal digits in ICD
|
||||
};
|
||||
|
||||
|
||||
// IS-QZSS-PNT-006 Table 3.2.2-1 (PRN 193..206)
|
||||
static QzssL1Entry qzss_l1_table(uint32_t prn)
|
||||
{
|
||||
switch (prn)
|
||||
{
|
||||
case 193:
|
||||
return {339, 01050};
|
||||
case 194:
|
||||
return {208, 01607};
|
||||
case 195:
|
||||
return {711, 01747};
|
||||
case 196:
|
||||
return {189, 01305};
|
||||
case 197:
|
||||
return {263, 00540};
|
||||
case 198:
|
||||
return {537, 01363}; // non-standard
|
||||
case 199:
|
||||
return {663, 00727};
|
||||
case 200:
|
||||
return {942, 00147};
|
||||
case 201:
|
||||
return {173, 01206};
|
||||
case 202:
|
||||
return {900, 01045}; // non-standard
|
||||
case 203:
|
||||
return {30, 00476}; // L1C/B
|
||||
case 204:
|
||||
return {500, 00604}; // L1C/B
|
||||
case 205:
|
||||
return {935, 01757}; // L1C/B
|
||||
case 206:
|
||||
return {556, 01330}; // L1C/B
|
||||
default:
|
||||
LOG(WARNING) << "Unsupported QZSS L1 PRN";
|
||||
return {0, 0};
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------
|
||||
// QZSS L5 utils
|
||||
// -----------------------------
|
||||
|
||||
struct QzssL5Entry
|
||||
{
|
||||
uint16_t init_i5;
|
||||
uint16_t init_q5;
|
||||
int advance_i5;
|
||||
int advance_q5;
|
||||
};
|
||||
|
||||
|
||||
// IS-QZSS-PNT-006 Table 3.2.5-1
|
||||
static QzssL5Entry qzss_l5_table(uint32_t prn)
|
||||
{
|
||||
switch (prn)
|
||||
{
|
||||
case 193:
|
||||
return {0b0110000101110, 0b1001110000111, 5836, 4757};
|
||||
case 194:
|
||||
return {0b0110010011111, 0b0110100111010, 926, 427};
|
||||
case 195:
|
||||
return {0b1000111001100, 0b0110001100110, 6086, 5452};
|
||||
case 196:
|
||||
return {0b111101110001, 0b0000100001100, 950, 5182};
|
||||
case 197:
|
||||
return {0b0011111100001, 0b0101000101101, 5905, 6606};
|
||||
case 198:
|
||||
return {0b0000001110001, 0b1000001010111, 3240, 6531};
|
||||
case 199:
|
||||
return {0b1010110100100, 0b0011001110001, 6675, 4268};
|
||||
case 200:
|
||||
return {0b0100001110110, 0b0100011100110, 3197, 3115};
|
||||
case 201:
|
||||
return {0b0111110100011, 0b0100101100101, 1555, 6835};
|
||||
case 202:
|
||||
return {0b0001111001011, 0b1110001010111, 3589, 862};
|
||||
default:
|
||||
LOG(WARNING) << "Unsupported QZSS L5 PRN";
|
||||
return {0, 0, 0, 0};
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------
|
||||
// QZSS L1 C/A code generation
|
||||
// -----------------------------------
|
||||
|
||||
// Generates real QZSS L1 C/A code (1023 chips, +/-1)
|
||||
void qzss_l1_code_gen_float(own::span<float> dest, uint32_t prn)
|
||||
{
|
||||
if (dest.size() != QZSS_L1_CODE_LENGTH)
|
||||
{
|
||||
LOG(WARNING) << "QZSS L1 code must be 1023 chips";
|
||||
return;
|
||||
}
|
||||
|
||||
const auto entry = qzss_l1_table(prn);
|
||||
|
||||
std::array<uint8_t, 10> g1{};
|
||||
std::array<uint8_t, 10> g2{};
|
||||
|
||||
g1.fill(1);
|
||||
const uint16_t init = entry.init_g2_octal;
|
||||
for (int s = 0; s < 10; ++s)
|
||||
{
|
||||
g2[s] = static_cast<uint8_t>((init >> s) & 0x1);
|
||||
}
|
||||
|
||||
// Generate 1023 chips
|
||||
for (int i = 0; i < QZSS_L1_CODE_LENGTH; ++i)
|
||||
{
|
||||
const uint8_t g1_out = g1[9];
|
||||
const uint8_t g2_out = g2[9];
|
||||
const uint8_t prn_bit = static_cast<uint8_t>(g1_out ^ g2_out);
|
||||
|
||||
// Map 0 -> -1, 1 -> +1
|
||||
dest[i] = prn_bit ? 1.0F : -1.0F;
|
||||
|
||||
// Step G1
|
||||
const uint8_t g1_fb = static_cast<uint8_t>(g1[2] ^ g1[9]);
|
||||
for (int k = 9; k > 0; --k)
|
||||
{
|
||||
g1[k] = g1[k - 1];
|
||||
}
|
||||
g1[0] = g1_fb;
|
||||
|
||||
// Step G2
|
||||
const uint8_t g2_fb = static_cast<uint8_t>(
|
||||
g2[1] ^ g2[2] ^ g2[5] ^ g2[7] ^ g2[8] ^ g2[9]);
|
||||
for (int k = 9; k > 0; --k)
|
||||
{
|
||||
g2[k] = g2[k - 1];
|
||||
}
|
||||
g2[0] = g2_fb;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void qzss_l1_code_gen_complex_sampled(
|
||||
own::span<std::complex<float>> dest,
|
||||
uint32_t prn,
|
||||
int32_t sampling_freq)
|
||||
{
|
||||
if (sampling_freq <= 0)
|
||||
{
|
||||
LOG(WARNING) << "Invalid sampling frequency";
|
||||
return;
|
||||
}
|
||||
|
||||
std::array<float, QZSS_L1_CODE_LENGTH> code{};
|
||||
qzss_l1_code_gen_float(own::span<float>(code.data(), code.size()), prn);
|
||||
|
||||
const double phase_step = QZSS_L1_CHIP_RATE / static_cast<double>(sampling_freq);
|
||||
double code_phase = 0.0;
|
||||
|
||||
for (size_t i = 0; i < dest.size(); ++i)
|
||||
{
|
||||
int chip = static_cast<int>(code_phase);
|
||||
chip %= QZSS_L1_CODE_LENGTH;
|
||||
dest[i] = {code[static_cast<size_t>(chip)], 0.0F};
|
||||
|
||||
code_phase += phase_step;
|
||||
if (code_phase >= QZSS_L1_CODE_LENGTH)
|
||||
{
|
||||
code_phase -= QZSS_L1_CODE_LENGTH;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------
|
||||
// QZSS L5 (I&Q) code generation
|
||||
// -----------------------------------
|
||||
|
||||
static uint8_t xa_step(uint16_t& state)
|
||||
{
|
||||
const uint8_t out = static_cast<uint8_t>(state & 0x1);
|
||||
const uint8_t fb = static_cast<uint8_t>(
|
||||
((state >> 4) ^ (state >> 3) ^ (state >> 1) ^ (state >> 0)) & 0x1);
|
||||
|
||||
uint16_t next = static_cast<uint16_t>((state >> 1) | (static_cast<uint16_t>(fb) << 12));
|
||||
|
||||
if (state == XA_SHORT_DECODE)
|
||||
{
|
||||
next = XA_ALL_ONES;
|
||||
}
|
||||
|
||||
state = next;
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
static uint8_t xb_step(uint16_t& state)
|
||||
{
|
||||
const uint8_t out = static_cast<uint8_t>(state & 0x1);
|
||||
const uint8_t fb = static_cast<uint8_t>(
|
||||
((state >> 12) ^ (state >> 10) ^ (state >> 9) ^ (state >> 7) ^
|
||||
(state >> 6) ^ (state >> 5) ^ (state >> 1) ^ (state >> 0)) &
|
||||
0x1);
|
||||
|
||||
state = static_cast<uint16_t>((state >> 1) | (static_cast<uint16_t>(fb) << 12));
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
void qzss_l5i_code_gen_float(own::span<float> dest, uint32_t prn)
|
||||
{
|
||||
if (dest.size() != QZSS_L5_CODE_LENGTH)
|
||||
{
|
||||
LOG(WARNING) << "L5I code must be 10230 chips";
|
||||
return;
|
||||
}
|
||||
|
||||
const auto entry = qzss_l5_table(prn);
|
||||
uint16_t xa_state = XA_ALL_ONES;
|
||||
uint16_t xb_state = entry.init_i5;
|
||||
|
||||
for (int i = 0; i < QZSS_L5_CODE_LENGTH; ++i)
|
||||
{
|
||||
const uint8_t xa = xa_step(xa_state);
|
||||
const uint8_t xb = xb_step(xb_state);
|
||||
const uint8_t bit = static_cast<uint8_t>(xa ^ xb);
|
||||
|
||||
dest[i] = bit ? 1.0F : -1.0F;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void qzss_l5q_code_gen_float(own::span<float> dest, uint32_t prn)
|
||||
{
|
||||
if (dest.size() != QZSS_L5_CODE_LENGTH)
|
||||
{
|
||||
LOG(WARNING) << "L5Q code must be 10230 chips";
|
||||
return;
|
||||
}
|
||||
|
||||
const auto entry = qzss_l5_table(prn);
|
||||
uint16_t xa_state = XA_ALL_ONES;
|
||||
uint16_t xb_state = entry.init_q5;
|
||||
|
||||
for (int i = 0; i < QZSS_L5_CODE_LENGTH; ++i)
|
||||
{
|
||||
const uint8_t xa = xa_step(xa_state);
|
||||
const uint8_t xb = xb_step(xb_state);
|
||||
const uint8_t bit = static_cast<uint8_t>(xa ^ xb);
|
||||
|
||||
dest[i] = bit ? 1.0F : -1.0F;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void qzss_l5i_code_gen_complex_sampled(
|
||||
own::span<std::complex<float>> dest,
|
||||
uint32_t prn,
|
||||
int32_t sampling_freq)
|
||||
{
|
||||
if (sampling_freq <= 0)
|
||||
{
|
||||
LOG(WARNING) << "Invalid sampling frequency";
|
||||
return;
|
||||
}
|
||||
|
||||
std::array<float, QZSS_L5_CODE_LENGTH> code{};
|
||||
qzss_l5i_code_gen_float(own::span<float>(code.data(), code.size()), prn);
|
||||
|
||||
const double phase_step = QZSS_L5_CHIP_RATE / static_cast<double>(sampling_freq);
|
||||
double code_phase = 0.0;
|
||||
|
||||
for (size_t i = 0; i < dest.size(); ++i)
|
||||
{
|
||||
int chip = static_cast<int>(code_phase);
|
||||
chip %= QZSS_L5_CODE_LENGTH;
|
||||
|
||||
dest[i] = {code[static_cast<size_t>(chip)], 0.0F};
|
||||
|
||||
code_phase += phase_step;
|
||||
if (code_phase >= QZSS_L5_CODE_LENGTH)
|
||||
{
|
||||
code_phase -= QZSS_L5_CODE_LENGTH;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void qzss_l5q_code_gen_complex_sampled(
|
||||
own::span<std::complex<float>> dest,
|
||||
uint32_t prn,
|
||||
int32_t sampling_freq)
|
||||
{
|
||||
if (sampling_freq <= 0)
|
||||
{
|
||||
LOG(WARNING) << "Invalid sampling frequency";
|
||||
return;
|
||||
}
|
||||
|
||||
std::array<float, QZSS_L5_CODE_LENGTH> code{};
|
||||
qzss_l5q_code_gen_float(own::span<float>(code.data(), code.size()), prn);
|
||||
|
||||
const double phase_step = QZSS_L5_CHIP_RATE / static_cast<double>(sampling_freq);
|
||||
double code_phase = 0.0;
|
||||
|
||||
for (size_t i = 0; i < dest.size(); ++i)
|
||||
{
|
||||
int chip = static_cast<int>(code_phase);
|
||||
chip %= QZSS_L5_CODE_LENGTH;
|
||||
|
||||
dest[i] = {0.0F, code[static_cast<size_t>(chip)]};
|
||||
|
||||
code_phase += phase_step;
|
||||
if (code_phase >= QZSS_L5_CODE_LENGTH)
|
||||
{
|
||||
code_phase -= QZSS_L5_CODE_LENGTH;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*!
|
||||
* \file qzss_signal_replica.h
|
||||
* \brief This file implements signal generators for QZSS signals
|
||||
* \author Carles Fernández-Prades, 2026. cfernandez (at) cttc.es
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*
|
||||
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* Copyright (C) 2010-2026 (see AUTHORS file for a list of contributors)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef GNSS_SDR_QZSS_SIGNAL_REPLICA_H
|
||||
#define GNSS_SDR_QZSS_SIGNAL_REPLICA_H
|
||||
|
||||
#include <complex>
|
||||
#include <cstdint>
|
||||
#if HAS_STD_SPAN
|
||||
#include <span>
|
||||
namespace own = std;
|
||||
#else
|
||||
#include <gsl-lite/gsl-lite.hpp>
|
||||
namespace own = gsl_lite;
|
||||
#endif
|
||||
|
||||
/** \addtogroup Algorithms_Library
|
||||
* \{ */
|
||||
/** \addtogroup Algorithm_libs algorithms_libs
|
||||
* \{ */
|
||||
|
||||
//! Generates complex QZSS L1 C/A code for the desired SV ID, and sampled to specific sampling frequency
|
||||
void qzss_l1_code_gen_complex_sampled(own::span<std::complex<float>> dest, uint32_t prn, int32_t sampling_freq);
|
||||
|
||||
//! Generates real QZSS L1 C/A code for the desired SV ID
|
||||
void qzss_l1_code_gen_float(own::span<float> dest, uint32_t prn);
|
||||
|
||||
//! Generates complex QZSS L5I code for the desired SV ID, and sampled to specific sampling frequency
|
||||
void qzss_l5i_code_gen_complex_sampled(own::span<std::complex<float>> dest, uint32_t prn, int32_t sampling_freq);
|
||||
|
||||
//! Generates real QZSS L5I code for the desired SV ID
|
||||
void qzss_l5i_code_gen_float(own::span<float> dest, uint32_t prn);
|
||||
|
||||
//! Generates complex QZSS L5Q code for the desired SV ID, and sampled to specific sampling frequency
|
||||
void qzss_l5q_code_gen_complex_sampled(own::span<std::complex<float>> dest, uint32_t prn, int32_t sampling_freq);
|
||||
|
||||
//! Generates real QZSS L5I code for the desired SV ID
|
||||
void qzss_l5q_code_gen_float(own::span<float> dest, uint32_t prn);
|
||||
|
||||
/** \} */
|
||||
/** \} */
|
||||
#endif // GNSS_SDR_QZSS_SIGNAL_REPLICA_H
|
||||
@@ -53,6 +53,8 @@ set(TRACKING_ADAPTER_SOURCES
|
||||
gps_l1_ca_tcp_connector_tracking.cc
|
||||
gps_l1_ca_gaussian_tracking.cc
|
||||
gps_l1_ca_kf_tracking.cc
|
||||
qzss_l1_dll_pll_tracking.cc
|
||||
qzss_l5_dll_pll_tracking.cc
|
||||
${OPT_TRACKING_ADAPTERS_SOURCES}
|
||||
)
|
||||
|
||||
@@ -73,6 +75,8 @@ set(TRACKING_ADAPTER_HEADERS
|
||||
gps_l1_ca_tcp_connector_tracking.h
|
||||
gps_l1_ca_gaussian_tracking.h
|
||||
gps_l1_ca_kf_tracking.h
|
||||
qzss_l1_dll_pll_tracking.h
|
||||
qzss_l5_dll_pll_tracking.h
|
||||
${OPT_TRACKING_ADAPTERS_HEADERS}
|
||||
)
|
||||
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
/*!
|
||||
* \file qzss_l1_dll_pll_tracking.cc
|
||||
* \brief Interface of an adapter of a DLL+PLL tracking loop block
|
||||
* for QZSS L1 signals to a TrackingInterface
|
||||
* \author Carles Fernandez, 2026. cfernandez(at)cttc.es
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*
|
||||
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* Copyright (C) 2010-2026 (see AUTHORS file for a list of contributors)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "qzss_l1_dll_pll_tracking.h"
|
||||
#include "configuration_interface.h"
|
||||
#include "display.h"
|
||||
#include "qzss.h"
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
|
||||
#if USE_GLOG_AND_GFLAGS
|
||||
#include <glog/logging.h>
|
||||
#else
|
||||
#include <absl/log/log.h>
|
||||
#endif
|
||||
|
||||
QzssL1DllPllTracking::QzssL1DllPllTracking(
|
||||
const ConfigurationInterface* configuration,
|
||||
const std::string& role,
|
||||
unsigned int in_streams,
|
||||
unsigned int out_streams)
|
||||
: BaseDllPllTracking(configuration, role, in_streams, out_streams)
|
||||
{
|
||||
configure_tracking_parameters(configuration);
|
||||
create_tracking_block();
|
||||
}
|
||||
|
||||
|
||||
void QzssL1DllPllTracking::configure_tracking_parameters(
|
||||
const ConfigurationInterface* configuration __attribute__((unused)))
|
||||
{
|
||||
// Set basic signal identifiers
|
||||
config_params().system = 'Q';
|
||||
const std::array<char, 3> sig{'J', '1', '\0'};
|
||||
std::copy_n(sig.data(), 3, config_params().signal);
|
||||
|
||||
const auto vector_length = static_cast<int>(std::round(config_params().fs_in / (QZSS_L1_CHIP_RATE / QZSS_L1_CODE_LENGTH)));
|
||||
config_params().vector_length = vector_length;
|
||||
|
||||
// Sanity checks and warnings
|
||||
if (config_params().extend_correlation_symbols < 1)
|
||||
{
|
||||
config_params().extend_correlation_symbols = 1;
|
||||
std::cout << TEXT_RED
|
||||
<< "WARNING: QZSS L1 C/A: extend_correlation_symbols must be > 0. "
|
||||
<< "Coherent integration set to 1 ms."
|
||||
<< TEXT_RESET << std::endl;
|
||||
}
|
||||
else if (config_params().extend_correlation_symbols > 20)
|
||||
{
|
||||
config_params().extend_correlation_symbols = 20;
|
||||
std::cout << TEXT_RED
|
||||
<< "WARNING: QZSS L1 C/A: extend_correlation_symbols limited to 20 (20 ms)."
|
||||
<< TEXT_RESET << std::endl;
|
||||
}
|
||||
|
||||
// QZSS 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: QZSS L1 C/A 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: QZSS L1 C/A: Narrow tracking bandwidth is higher than wide bandwidth."
|
||||
<< TEXT_RESET << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void QzssL1DllPllTracking::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
|
||||
{
|
||||
set_item_size(0);
|
||||
tracking_sptr_ = nullptr;
|
||||
LOG(WARNING) << config_params().item_type << " unknown tracking item type.";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*!
|
||||
* \file qzss_l1_dll_pll_tracking.h
|
||||
* \brief Interface of an adapter of a DLL+PLL tracking loop block
|
||||
* for QZSS L1 signals to a TrackingInterface
|
||||
* \author Carles Fernandez, 2026. cfernandez(at)cttc.es
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*
|
||||
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* Copyright (C) 2010-2026 (see AUTHORS file for a list of contributors)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef GNSS_SDR_QZSS_L1_DLL_PLL_TRACKING_H
|
||||
#define GNSS_SDR_QZSS_L1_DLL_PLL_TRACKING_H
|
||||
|
||||
#include "base_dll_pll_tracking.h"
|
||||
|
||||
/** \addtogroup Tracking
|
||||
* Classes for GNSS signal tracking.
|
||||
* \{ */
|
||||
/** \addtogroup Tracking_adapters tracking_adapters
|
||||
* Wrap GNU Radio blocks for GNSS signal tracking with a TrackingInterface
|
||||
* \{ */
|
||||
|
||||
|
||||
/*!
|
||||
* \brief This class implements a code DLL + carrier PLL tracking loop
|
||||
* block adapter for QZSS L1 signals
|
||||
*/
|
||||
class QzssL1DllPllTracking : public BaseDllPllTracking
|
||||
{
|
||||
public:
|
||||
//! Constructor
|
||||
QzssL1DllPllTracking(const ConfigurationInterface* configuration,
|
||||
const std::string& role,
|
||||
unsigned int in_streams,
|
||||
unsigned int out_streams);
|
||||
|
||||
//! Returns "QZSS_L1_CA_DLL_PLL_Tracking"
|
||||
inline std::string implementation() override
|
||||
{
|
||||
return "QZSS_L1_CA_DLL_PLL_Tracking";
|
||||
}
|
||||
|
||||
private:
|
||||
void configure_tracking_parameters(const ConfigurationInterface* configuration) override;
|
||||
void create_tracking_block() override;
|
||||
};
|
||||
|
||||
/** \} */
|
||||
/** \} */
|
||||
#endif // GNSS_SDR_QZSS_L1_CA_DLL_PLL_TRACKING_H
|
||||
@@ -0,0 +1,87 @@
|
||||
/*!
|
||||
* \file qzss_l5_dll_pll_tracking.cc
|
||||
* \brief Interface of an adapter of a DLL+PLL tracking loop block
|
||||
* for QZSS L5 signals to a TrackingInterface
|
||||
* \author Carles Fernandez, 2026. cfernandez(at)cttc.es
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*
|
||||
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* Copyright (C) 2010-2026 (see AUTHORS file for a list of contributors)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "qzss_l5_dll_pll_tracking.h"
|
||||
#include "qzss.h"
|
||||
#include "configuration_interface.h"
|
||||
#include "display.h"
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
|
||||
#if USE_GLOG_AND_GFLAGS
|
||||
#include <glog/logging.h>
|
||||
#else
|
||||
#include <absl/log/log.h>
|
||||
#endif
|
||||
|
||||
QzssL5DllPllTracking::QzssL5DllPllTracking(
|
||||
const ConfigurationInterface* configuration,
|
||||
const std::string& role,
|
||||
unsigned int in_streams,
|
||||
unsigned int out_streams)
|
||||
: BaseDllPllTracking(configuration, role, in_streams, out_streams)
|
||||
{
|
||||
configure_tracking_parameters(configuration);
|
||||
create_tracking_block();
|
||||
}
|
||||
|
||||
|
||||
void QzssL5DllPllTracking::configure_tracking_parameters(
|
||||
const ConfigurationInterface* configuration __attribute__((unused)))
|
||||
{
|
||||
const auto vector_length = static_cast<int>(std::round(static_cast<double>(config_params().fs_in) / (static_cast<double>(QZSS_L5_CHIP_RATE) / static_cast<double>(QZSS_L5_CODE_LENGTH))));
|
||||
config_params().vector_length = vector_length;
|
||||
if (config_params().extend_correlation_symbols < 1)
|
||||
{
|
||||
config_params().extend_correlation_symbols = 1;
|
||||
std::cout << TEXT_RED << "WARNING: QZSS L5. extend_correlation_symbols must be bigger than 0. Coherent integration has been set to 1 symbol (1 ms)" << TEXT_RESET << '\n';
|
||||
}
|
||||
else if (!config_params().track_pilot and config_params().extend_correlation_symbols > QZSS_L5I_NH_CODE_LENGTH)
|
||||
{
|
||||
config_params().extend_correlation_symbols = QZSS_L5I_NH_CODE_LENGTH;
|
||||
std::cout << TEXT_RED << "WARNING: QZSS L5. extend_correlation_symbols must be lower than 11 when tracking the data component. Coherent integration has been set to 10 symbols (10 ms)" << TEXT_RESET << '\n';
|
||||
}
|
||||
if ((config_params().extend_correlation_symbols > 1) and (config_params().pll_bw_narrow_hz > config_params().pll_bw_hz or config_params().dll_bw_narrow_hz > config_params().dll_bw_hz))
|
||||
{
|
||||
std::cout << TEXT_RED << "WARNING: QZSS L5. PLL or DLL narrow tracking bandwidth is higher than wide tracking one" << TEXT_RESET << '\n';
|
||||
}
|
||||
config_params().system = 'Q';
|
||||
const std::array<char, 3> sig{'J', '5', '\0'};
|
||||
std::copy_n(sig.data(), 3, config_params().signal);
|
||||
}
|
||||
|
||||
|
||||
void QzssL5DllPllTracking::create_tracking_block()
|
||||
{
|
||||
// ################# Make a GNU Radio Tracking block object ################
|
||||
if (config_params().item_type == "gr_complex")
|
||||
{
|
||||
tracking_sptr_ = dll_pll_veml_make_tracking(config_params());
|
||||
DLOG(INFO) << "tracking(" << tracking_sptr_->unique_id() << ")";
|
||||
}
|
||||
else
|
||||
{
|
||||
set_item_size(0);
|
||||
tracking_sptr_ = nullptr;
|
||||
LOG(WARNING) << config_params().item_type << " unknown tracking item type.";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*!
|
||||
* \file qzss_l5_dll_pll_tracking.h
|
||||
* \brief Interface of an adapter of a DLL+PLL tracking loop block
|
||||
* for QZSS L5 signals to a TrackingInterface
|
||||
* \author Carles Fernandez, 2026. cfernandez(at)cttc.es
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*
|
||||
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* Copyright (C) 2010-2026 (see AUTHORS file for a list of contributors)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef GNSS_SDR_QZSS_L5_DLL_PLL_TRACKING_H
|
||||
#define GNSS_SDR_QZSS_L5_DLL_PLL_TRACKING_H
|
||||
|
||||
#include "base_dll_pll_tracking.h"
|
||||
|
||||
/** \addtogroup Tracking
|
||||
* Classes for GNSS signal tracking.
|
||||
* \{ */
|
||||
/** \addtogroup Tracking_adapters tracking_adapters
|
||||
* Wrap GNU Radio blocks for GNSS signal tracking with a TrackingInterface
|
||||
* \{ */
|
||||
|
||||
|
||||
/*!
|
||||
* \brief This class implements a code DLL + carrier PLL tracking loop
|
||||
* block adapter for QZSS L5 signals
|
||||
*/
|
||||
class QzssL5DllPllTracking : public BaseDllPllTracking
|
||||
{
|
||||
public:
|
||||
//! Constructor
|
||||
QzssL5DllPllTracking(const ConfigurationInterface* configuration,
|
||||
const std::string& role,
|
||||
unsigned int in_streams,
|
||||
unsigned int out_streams);
|
||||
|
||||
//! Returns "QZSS_L5_DLL_PLL_Tracking"
|
||||
inline std::string implementation() override
|
||||
{
|
||||
return "QZSS_L5_DLL_PLL_Tracking";
|
||||
}
|
||||
|
||||
private:
|
||||
void configure_tracking_parameters(const ConfigurationInterface* configuration) override;
|
||||
void create_tracking_block() override;
|
||||
};
|
||||
|
||||
/** \} */
|
||||
/** \} */
|
||||
#endif // GNSS_SDR_QZSS_L5_DLL_PLL_TRACKING_H
|
||||
@@ -49,6 +49,8 @@
|
||||
#include "gps_sdr_signal_replica.h"
|
||||
#include "lock_detectors.h"
|
||||
#include "matlab_writter_helper.h"
|
||||
#include "qzss.h"
|
||||
#include "qzss_signal_replica.h"
|
||||
#include "tracking_discriminators.h"
|
||||
#include <gnuradio/io_signature.h> // for io_signature
|
||||
#include <gnuradio/thread/thread.h> // for scoped_lock
|
||||
@@ -179,6 +181,8 @@ dll_pll_veml_tracking::dll_pll_veml_tracking(const Dll_Pll_Conf &conf_)
|
||||
map_signal_pretty_name["B1"] = "B1I";
|
||||
map_signal_pretty_name["B3"] = "B3I";
|
||||
map_signal_pretty_name["E6"] = "E6";
|
||||
map_signal_pretty_name["J1"] = "L1 C/A";
|
||||
map_signal_pretty_name["J5"] = "L5";
|
||||
|
||||
d_signal_pretty_name = map_signal_pretty_name[d_signal_type];
|
||||
|
||||
@@ -509,6 +513,77 @@ dll_pll_veml_tracking::dll_pll_veml_tracking(const Dll_Pll_Conf &conf_)
|
||||
d_symbols_per_bit = 0;
|
||||
}
|
||||
}
|
||||
else if (d_trk_parameters.system == 'Q')
|
||||
{
|
||||
d_systemName = "QZSS";
|
||||
if (d_signal_type == "J1")
|
||||
{
|
||||
d_signal_carrier_freq = QZSS_L1_FREQ_HZ;
|
||||
d_code_period = QZSS_L1_CA_CODE_PERIOD_S;
|
||||
d_code_chip_rate = QZSS_L1_CHIP_RATE;
|
||||
d_correlation_length_ms = 1;
|
||||
d_code_samples_per_chip = 1;
|
||||
d_code_length_chips = static_cast<int32_t>(QZSS_L1_CODE_LENGTH);
|
||||
// QZSS L1 C/A does not have pilot component nor secondary code
|
||||
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;
|
||||
// symbol integration: 20 trk symbols (20 ms) = 1 tlm bit
|
||||
// set the bit transition pattern in secondary code to obtain bit synchronization
|
||||
d_secondary_code_length = static_cast<uint32_t>(QZSS_CA_PREAMBLE_LENGTH_SYMBOLS);
|
||||
d_secondary_code_string = QZSS_CA_PREAMBLE_SYMBOLS_STR;
|
||||
d_symbols_per_bit = QZSS_CA_TELEMETRY_SYMBOLS_PER_BIT;
|
||||
}
|
||||
else if (d_signal_type == "J5")
|
||||
{
|
||||
d_signal_carrier_freq = QZSS_L5_FREQ_HZ;
|
||||
d_code_period = QZSS_L5I_CODE_PERIOD_S;
|
||||
d_code_chip_rate = QZSS_L5_CHIP_RATE;
|
||||
// symbol integration: 10 trk symbols (10 ms) = 1 tlm bit
|
||||
d_symbols_per_bit = QZSS_L5_SAMPLES_PER_SYMBOL;
|
||||
d_correlation_length_ms = 1;
|
||||
d_code_samples_per_chip = 1;
|
||||
d_code_length_chips = static_cast<int32_t>(QZSS_L5_CODE_LENGTH);
|
||||
d_secondary = true;
|
||||
d_trk_parameters.slope = 1.0;
|
||||
d_trk_parameters.spc = d_trk_parameters.early_late_space_chips;
|
||||
d_trk_parameters.y_intercept = 1.0;
|
||||
if (d_trk_parameters.track_pilot)
|
||||
{
|
||||
// synchronize pilot secondary code
|
||||
d_secondary_code_length = static_cast<uint32_t>(QZSS_L5Q_NH_CODE_LENGTH);
|
||||
d_secondary_code_string = QZSS_L5Q_NH_CODE_STR;
|
||||
// remove data secondary code
|
||||
// remove Neuman-Hofman Code
|
||||
d_data_secondary_code_length = static_cast<uint32_t>(QZSS_L5I_NH_CODE_LENGTH);
|
||||
d_data_secondary_code_string = QZSS_L5I_NH_CODE_STR;
|
||||
d_signal_pretty_name = d_signal_pretty_name + "Q";
|
||||
}
|
||||
else
|
||||
{
|
||||
// synchronize and remove data secondary code
|
||||
// remove Neuman-Hofman Code
|
||||
d_secondary_code_length = static_cast<uint32_t>(QZSS_L5I_NH_CODE_LENGTH);
|
||||
d_secondary_code_string = QZSS_L5I_NH_CODE_STR;
|
||||
d_signal_pretty_name = d_signal_pretty_name + "I";
|
||||
d_interchange_iq = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(WARNING) << "Invalid Signal argument when instantiating tracking blocks";
|
||||
std::cerr << "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";
|
||||
@@ -933,6 +1008,25 @@ void dll_pll_veml_tracking::start_tracking()
|
||||
d_extend_correlation_symbols = GLONASS_GNAV_TELEMETRY_SYMBOLS_PER_BIT;
|
||||
}
|
||||
}
|
||||
else if (d_systemName == "QZSS" && d_signal_type == "J1")
|
||||
{
|
||||
qzss_l1_code_gen_float(d_tracking_code, d_acquisition_gnss_synchro->PRN);
|
||||
}
|
||||
else if (d_systemName == "QZSS" && d_signal_type == "J5")
|
||||
{
|
||||
if (d_trk_parameters.track_pilot)
|
||||
{
|
||||
qzss_l5q_code_gen_float(d_tracking_code, d_acquisition_gnss_synchro->PRN);
|
||||
qzss_l5i_code_gen_float(d_data_code, d_acquisition_gnss_synchro->PRN);
|
||||
d_Prompt_Data[0] = gr_complex(0.0, 0.0);
|
||||
d_correlator_data_cpu.set_local_code_and_taps(d_code_length_chips, d_data_code.data(), d_prompt_data_shift);
|
||||
}
|
||||
else
|
||||
{
|
||||
qzss_l5i_code_gen_float(d_tracking_code, d_acquisition_gnss_synchro->PRN);
|
||||
}
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
|
||||
@@ -97,6 +97,7 @@ set(SYSTEM_PARAMETERS_HEADERS
|
||||
osnma_data.h
|
||||
osnma_dsm_reader.h
|
||||
tow_to_trk.h
|
||||
qzss.h
|
||||
)
|
||||
|
||||
list(SORT SYSTEM_PARAMETERS_HEADERS)
|
||||
|
||||
@@ -57,6 +57,8 @@ const std::unordered_map<std::string, double> SIGNAL_FREQ_MAP = {
|
||||
{"B1", FREQ1_BDS},
|
||||
{"B2", FREQ2_BDS},
|
||||
{"B3", FREQ3_BDS},
|
||||
{"J1", FREQ1},
|
||||
{"J5", FREQ5},
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/*!
|
||||
* \file qzss.h
|
||||
* \brief Defines system parameters for QZSS signals
|
||||
* \author Carles Fernández-Prades, 2026. cfernandez (at) cttc.es
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*
|
||||
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* Copyright (C) 2010-2026 (see AUTHORS file for a list of contributors)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#ifndef GNSS_SDR_QZSS_H
|
||||
#define GNSS_SDR_QZSS_H
|
||||
|
||||
#include "gnss_frequencies.h"
|
||||
#include <cstdint>
|
||||
|
||||
/** \addtogroup Core
|
||||
* \{ */
|
||||
/** \addtogroup System_Parameters
|
||||
* \{ */
|
||||
|
||||
static constexpr double QZSS_L1_FREQ_HZ = FREQ1;
|
||||
static constexpr double QZSS_L5_FREQ_HZ = FREQ5;
|
||||
static constexpr double QZSS_L1_CHIP_RATE = 1.023e6;
|
||||
static constexpr double QZSS_L5_CHIP_RATE = 10.23e6;
|
||||
static constexpr double QZSS_L1_CA_CODE_PERIOD_S = 0.001;
|
||||
static constexpr double QZSS_L5I_CODE_PERIOD_S = 0.001;
|
||||
|
||||
static constexpr int QZSS_L1_CODE_LENGTH = 1023;
|
||||
static constexpr int QZSS_L5_CODE_LENGTH = 10230;
|
||||
static constexpr int QZSS_L1_PERIOD_MS = 1;
|
||||
static constexpr int QZSS_L5I_PERIOD_MS = 1;
|
||||
static constexpr int32_t QZSS_CA_PREAMBLE_LENGTH_SYMBOLS = 160;
|
||||
static constexpr int32_t QZSS_CA_TELEMETRY_SYMBOLS_PER_BIT = 20;
|
||||
static constexpr int32_t QZSS_L5_SAMPLES_PER_SYMBOL = 10;
|
||||
static constexpr int32_t QZSS_L5Q_NH_CODE_LENGTH = 20;
|
||||
static constexpr int32_t QZSS_L5I_NH_CODE_LENGTH = 10;
|
||||
static constexpr uint32_t QZSS_L1_OPT_ACQ_FS_SPS = 2000000;
|
||||
static constexpr uint32_t QZSS_L5_OPT_ACQ_FS_SPS = 10000000;
|
||||
|
||||
static constexpr uint16_t XA_ALL_ONES = 0x1FFF; // 13 bits all ones
|
||||
static constexpr uint16_t XA_SHORT_DECODE = 0x1FFD; // 1111111111101 (ICD)
|
||||
|
||||
constexpr const char QZSS_CA_PREAMBLE_SYMBOLS_STR[161] = "1111111111111111111100000000000000000000000000000000000000000000000000000000000011111111111111111111000000000000000000001111111111111111111111111111111111111111";
|
||||
constexpr const char QZSS_L5Q_NH_CODE_STR[21] = "00000100110101001110";
|
||||
constexpr const char QZSS_L5I_NH_CODE_STR[11] = "0000110101";
|
||||
|
||||
/** \} */
|
||||
/** \} */
|
||||
|
||||
#endif // GNSS_SDR_QZSS_H
|
||||
@@ -137,6 +137,7 @@ private:
|
||||
#include "unit-tests/system-parameters/glonass_gnav_ephemeris_test.cc"
|
||||
#include "unit-tests/system-parameters/glonass_gnav_nav_message_test.cc"
|
||||
#include "unit-tests/system-parameters/has_decoding_test.cc"
|
||||
#include "unit-tests/system-parameters/qzss_code_generation_test.cc"
|
||||
|
||||
#ifndef EXCLUDE_TESTS_REQUIRING_BINARIES
|
||||
#include "unit-tests/control-plane/control_thread_test.cc"
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
/*!
|
||||
* \file qzss_code_generation_test.cc
|
||||
* \brief This file implements unit tests for the QZSS code generation
|
||||
* \author Carles Fernández-Prades, 2026. cfernandez (at)) cttc.es
|
||||
*
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*
|
||||
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
||||
* This file is part of GNSS-SDR.
|
||||
*
|
||||
* Copyright (C) 2010-2026 (see AUTHORS file for a list of contributors)
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "qzss_signal_replica.h"
|
||||
#include <gtest/gtest.h>
|
||||
#include <vector>
|
||||
|
||||
|
||||
TEST(QzssL1Code, Periodicity)
|
||||
{
|
||||
constexpr uint32_t prn = 193;
|
||||
std::vector<float> code1(1023);
|
||||
std::vector<float> code2(1023);
|
||||
|
||||
qzss_l1_code_gen_float(code1, prn);
|
||||
qzss_l1_code_gen_float(code2, prn);
|
||||
|
||||
EXPECT_EQ(code1, code2);
|
||||
}
|
||||
|
||||
|
||||
TEST(QzssL1Code, GoldenFirst32Chips)
|
||||
{
|
||||
constexpr uint32_t prn = 193;
|
||||
std::vector<float> code(1023);
|
||||
qzss_l1_code_gen_float(code, prn);
|
||||
|
||||
const float golden[32] = {
|
||||
-1, 1, 1, 1, -1, 1, -1, 1,
|
||||
1, 1, -1, -1, -1, -1, 1, 1,
|
||||
-1, -1, -1, -1, -1, -1, 1, -1,
|
||||
1, -1, -1, -1, -1, -1, -1, 1};
|
||||
|
||||
for (int i = 0; i < 32; ++i)
|
||||
{
|
||||
EXPECT_FLOAT_EQ(code[i], golden[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST(QzssL5Code, L5IGoldenFirst32Chips)
|
||||
{
|
||||
std::vector<float> code(10230);
|
||||
qzss_l5i_code_gen_float(code, 193);
|
||||
|
||||
const float golden[32] = {
|
||||
1, -1, -1, -1, 1, -1, 1, 1,
|
||||
1, 1, -1, -1, 1, 1, 1, -1,
|
||||
1, -1, -1, 1, -1, -1, 1, -1,
|
||||
-1, 1, 1, 1, -1, -1, -1, 1};
|
||||
|
||||
for (int i = 0; i < 32; ++i)
|
||||
{
|
||||
EXPECT_FLOAT_EQ(code[i], golden[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST(QzssL5Code, L5QGoldenFirst32Chips)
|
||||
{
|
||||
std::vector<float> code(10230);
|
||||
qzss_l5q_code_gen_float(code, 193);
|
||||
|
||||
const float golden[32] = {
|
||||
-1, -1, -1, 1, 1, 1, 1, -1,
|
||||
-1, -1, 1, 1, -1, 1, 1, -1,
|
||||
-1, 1, 1, -1, -1, -1, -1, -1,
|
||||
1, 1, -1, -1, -1, -1, -1, 1};
|
||||
|
||||
for (int i = 0; i < 32; ++i)
|
||||
{
|
||||
EXPECT_FLOAT_EQ(code[i], golden[i]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user