2020-11-07 20:33:26 +00:00
|
|
|
/*!
|
2020-11-07 21:43:19 +00:00
|
|
|
* \file galileo_e6_signal_replica.cc
|
|
|
|
* \brief This library implements various functions for Galileo E6 signal
|
|
|
|
* replica generation
|
2020-11-07 20:33:26 +00:00
|
|
|
* \author Carles Fernandez-Prades, 2020. cfernandez(at)cttc.es
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* -----------------------------------------------------------------------------
|
|
|
|
*
|
2020-12-30 12:35:06 +00:00
|
|
|
* GNSS-SDR is a Global Navigation Satellite System software-defined receiver.
|
2020-11-07 20:33:26 +00:00
|
|
|
* This file is part of GNSS-SDR.
|
|
|
|
*
|
2020-12-30 12:35:06 +00:00
|
|
|
* Copyright (C) 2010-2020 (see AUTHORS file for a list of contributors)
|
2020-11-07 20:33:26 +00:00
|
|
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
*
|
|
|
|
* -----------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
2020-11-07 21:43:19 +00:00
|
|
|
#include "galileo_e6_signal_replica.h"
|
2020-11-07 20:33:26 +00:00
|
|
|
#include "Galileo_E6.h"
|
2020-11-07 21:43:19 +00:00
|
|
|
#include "gnss_signal_replica.h"
|
2021-10-08 09:15:01 +00:00
|
|
|
#include <utility>
|
2020-11-07 20:33:26 +00:00
|
|
|
#include <vector>
|
|
|
|
|
2020-12-29 13:47:28 +00:00
|
|
|
void galileo_e6_b_code_gen_complex_primary(own::span<std::complex<float>> dest,
|
|
|
|
int32_t prn)
|
2020-11-07 20:33:26 +00:00
|
|
|
{
|
2020-12-29 13:47:28 +00:00
|
|
|
const uint32_t prn_ = prn - 1;
|
2020-11-07 20:33:26 +00:00
|
|
|
uint32_t index = 0;
|
|
|
|
std::array<int32_t, 4> a{};
|
2020-12-29 13:47:28 +00:00
|
|
|
if ((prn < 1) || (prn > 50))
|
2020-11-07 20:33:26 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (size_t i = 0; i < GALILEO_E6_B_PRIMARY_CODE_STR_LENGTH - 1; i++)
|
|
|
|
{
|
2020-12-29 13:47:28 +00:00
|
|
|
hex_to_binary_converter(a, GALILEO_E6_B_PRIMARY_CODE[prn_][i]);
|
|
|
|
dest[index] = std::complex<float>(static_cast<float>(a[0]), 0.0);
|
|
|
|
dest[index + 1] = std::complex<float>(static_cast<float>(a[1]), 0.0);
|
|
|
|
dest[index + 2] = std::complex<float>(static_cast<float>(a[2]), 0.0);
|
|
|
|
dest[index + 3] = std::complex<float>(static_cast<float>(a[3]), 0.0);
|
2020-11-07 20:33:26 +00:00
|
|
|
index = index + 4;
|
|
|
|
}
|
|
|
|
// last bit is filled up with a zero
|
2020-12-29 13:47:28 +00:00
|
|
|
hex_to_binary_converter(a, GALILEO_E6_B_PRIMARY_CODE[prn_][GALILEO_E6_B_PRIMARY_CODE_STR_LENGTH - 1]);
|
|
|
|
dest[index] = std::complex<float>(static_cast<float>(a[0]), 0.0);
|
|
|
|
dest[index + 1] = std::complex<float>(static_cast<float>(a[1]), 0.0);
|
|
|
|
dest[index + 2] = std::complex<float>(static_cast<float>(a[2]), 0.0);
|
2020-11-07 20:33:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-12-29 13:47:28 +00:00
|
|
|
void galileo_e6_b_code_gen_float_primary(own::span<float> dest, int32_t prn)
|
2020-11-07 20:33:26 +00:00
|
|
|
{
|
2020-12-29 13:47:28 +00:00
|
|
|
const uint32_t prn_ = prn - 1;
|
2020-11-07 20:33:26 +00:00
|
|
|
uint32_t index = 0;
|
|
|
|
std::array<int32_t, 4> a{};
|
2020-12-29 13:47:28 +00:00
|
|
|
if ((prn < 1) || (prn > 50))
|
2020-11-07 20:33:26 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (size_t i = 0; i < GALILEO_E6_B_PRIMARY_CODE_STR_LENGTH - 1; i++)
|
|
|
|
{
|
2020-12-29 13:47:28 +00:00
|
|
|
hex_to_binary_converter(a, GALILEO_E6_B_PRIMARY_CODE[prn_][i]);
|
|
|
|
dest[index] = static_cast<float>(a[0]);
|
|
|
|
dest[index + 1] = static_cast<float>(a[1]);
|
|
|
|
dest[index + 2] = static_cast<float>(a[2]);
|
|
|
|
dest[index + 3] = static_cast<float>(a[3]);
|
2020-11-07 20:33:26 +00:00
|
|
|
index = index + 4;
|
|
|
|
}
|
|
|
|
// last bit is filled up with a zero
|
2020-12-29 13:47:28 +00:00
|
|
|
hex_to_binary_converter(a, GALILEO_E6_B_PRIMARY_CODE[prn_][GALILEO_E6_B_PRIMARY_CODE_STR_LENGTH - 1]);
|
|
|
|
dest[index] = static_cast<float>(a[0]);
|
|
|
|
dest[index + 1] = static_cast<float>(a[1]);
|
|
|
|
dest[index + 2] = static_cast<float>(a[2]);
|
2020-11-07 20:33:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-12-29 13:47:28 +00:00
|
|
|
void galileo_e6_b_code_gen_complex_sampled(own::span<std::complex<float>> dest,
|
|
|
|
uint32_t prn,
|
|
|
|
int32_t sampling_freq,
|
|
|
|
uint32_t chip_shift)
|
2020-11-07 20:33:26 +00:00
|
|
|
{
|
2020-12-29 13:47:28 +00:00
|
|
|
constexpr uint32_t codeLength = GALILEO_E6_B_CODE_LENGTH_CHIPS;
|
|
|
|
constexpr int32_t codeFreqBasis = GALILEO_E6_B_CODE_CHIP_RATE_CPS;
|
2020-11-07 20:33:26 +00:00
|
|
|
|
2020-12-29 13:47:28 +00:00
|
|
|
const auto samplesPerCode = static_cast<uint32_t>(static_cast<double>(sampling_freq) / (static_cast<double>(codeFreqBasis) / static_cast<double>(codeLength)));
|
|
|
|
const uint32_t delay = ((codeLength - chip_shift) % codeLength) * samplesPerCode / codeLength;
|
2020-11-07 20:33:26 +00:00
|
|
|
|
2020-12-29 13:47:28 +00:00
|
|
|
std::vector<std::complex<float>> code_aux(codeLength);
|
|
|
|
galileo_e6_b_code_gen_complex_primary(code_aux, prn);
|
2020-11-07 20:33:26 +00:00
|
|
|
|
2020-12-29 13:47:28 +00:00
|
|
|
if (sampling_freq != codeFreqBasis)
|
2020-11-07 20:33:26 +00:00
|
|
|
{
|
2020-12-29 13:47:28 +00:00
|
|
|
std::vector<std::complex<float>> resampled_signal_aux(samplesPerCode);
|
|
|
|
resampler(code_aux, resampled_signal_aux, codeFreqBasis, sampling_freq); // resamples code to sampling_freq
|
|
|
|
code_aux = std::move(resampled_signal_aux);
|
2020-11-07 20:33:26 +00:00
|
|
|
}
|
|
|
|
|
2020-12-29 13:47:28 +00:00
|
|
|
for (uint32_t i = 0; i < samplesPerCode; i++)
|
2020-11-07 20:33:26 +00:00
|
|
|
{
|
2020-12-29 13:47:28 +00:00
|
|
|
dest[(i + delay) % samplesPerCode] = code_aux[i];
|
2020-11-07 20:33:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-12-29 13:47:28 +00:00
|
|
|
void galileo_e6_c_code_gen_complex_primary(own::span<std::complex<float>> dest,
|
|
|
|
int32_t prn)
|
2020-11-07 20:33:26 +00:00
|
|
|
{
|
2020-12-29 13:47:28 +00:00
|
|
|
const uint32_t prn_ = prn - 1;
|
2020-11-07 20:33:26 +00:00
|
|
|
uint32_t index = 0;
|
|
|
|
std::array<int32_t, 4> a{};
|
2020-12-29 13:47:28 +00:00
|
|
|
if ((prn < 1) || (prn > 50))
|
2020-11-07 20:33:26 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (size_t i = 0; i < GALILEO_E6_C_PRIMARY_CODE_STR_LENGTH - 1; i++)
|
|
|
|
{
|
2020-12-29 13:47:28 +00:00
|
|
|
hex_to_binary_converter(a, GALILEO_E6_C_PRIMARY_CODE[prn_][i]);
|
|
|
|
dest[index] = std::complex<float>(static_cast<float>(a[0]), 0.0);
|
|
|
|
dest[index + 1] = std::complex<float>(static_cast<float>(a[1]), 0.0);
|
|
|
|
dest[index + 2] = std::complex<float>(static_cast<float>(a[2]), 0.0);
|
|
|
|
dest[index + 3] = std::complex<float>(static_cast<float>(a[3]), 0.0);
|
2020-11-07 20:33:26 +00:00
|
|
|
index = index + 4;
|
|
|
|
}
|
|
|
|
// last bit is filled up with a zero
|
2020-12-29 13:47:28 +00:00
|
|
|
hex_to_binary_converter(a, GALILEO_E6_C_PRIMARY_CODE[prn_][GALILEO_E6_C_PRIMARY_CODE_STR_LENGTH - 1]);
|
|
|
|
dest[index] = std::complex<float>(static_cast<float>(a[0]), 0.0);
|
|
|
|
dest[index + 1] = std::complex<float>(static_cast<float>(a[1]), 0.0);
|
|
|
|
dest[index + 2] = std::complex<float>(static_cast<float>(a[2]), 0.0);
|
2020-11-07 20:33:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-12-29 13:47:28 +00:00
|
|
|
void galileo_e6_c_code_gen_float_primary(own::span<float> dest, int32_t prn)
|
2020-11-07 20:33:26 +00:00
|
|
|
{
|
2020-12-29 13:47:28 +00:00
|
|
|
const uint32_t prn_ = prn - 1;
|
2020-11-07 20:33:26 +00:00
|
|
|
uint32_t index = 0;
|
|
|
|
std::array<int32_t, 4> a{};
|
2020-12-29 13:47:28 +00:00
|
|
|
if ((prn < 1) || (prn > 50))
|
2020-11-07 20:33:26 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (size_t i = 0; i < GALILEO_E6_C_PRIMARY_CODE_STR_LENGTH - 1; i++)
|
|
|
|
{
|
2020-12-29 13:47:28 +00:00
|
|
|
hex_to_binary_converter(a, GALILEO_E6_C_PRIMARY_CODE[prn_][i]);
|
|
|
|
dest[index] = static_cast<float>(a[0]);
|
|
|
|
dest[index + 1] = static_cast<float>(a[1]);
|
|
|
|
dest[index + 2] = static_cast<float>(a[2]);
|
|
|
|
dest[index + 3] = static_cast<float>(a[3]);
|
2020-11-07 20:33:26 +00:00
|
|
|
index = index + 4;
|
|
|
|
}
|
|
|
|
// last bit is filled up with a zero
|
2020-12-29 13:47:28 +00:00
|
|
|
hex_to_binary_converter(a, GALILEO_E6_C_PRIMARY_CODE[prn_][GALILEO_E6_C_PRIMARY_CODE_STR_LENGTH - 1]);
|
|
|
|
dest[index] = static_cast<float>(a[0]);
|
|
|
|
dest[index + 1] = static_cast<float>(a[1]);
|
|
|
|
dest[index + 2] = static_cast<float>(a[2]);
|
2020-11-07 20:33:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-12-29 13:47:28 +00:00
|
|
|
void galileo_e6_c_code_gen_complex_sampled(own::span<std::complex<float>> dest,
|
|
|
|
uint32_t prn,
|
|
|
|
int32_t sampling_freq,
|
|
|
|
uint32_t chip_shift)
|
2020-11-07 20:33:26 +00:00
|
|
|
{
|
2020-12-29 13:47:28 +00:00
|
|
|
constexpr uint32_t codeLength = GALILEO_E6_C_CODE_LENGTH_CHIPS;
|
|
|
|
constexpr int32_t codeFreqBasis = GALILEO_E6_C_CODE_CHIP_RATE_CPS;
|
2020-11-07 20:33:26 +00:00
|
|
|
|
2020-12-29 13:47:28 +00:00
|
|
|
const auto samplesPerCode = static_cast<uint32_t>(static_cast<double>(sampling_freq) / (static_cast<double>(codeFreqBasis) / static_cast<double>(codeLength)));
|
|
|
|
const uint32_t delay = ((codeLength - chip_shift) % codeLength) * samplesPerCode / codeLength;
|
2020-11-07 20:33:26 +00:00
|
|
|
|
2020-12-29 13:47:28 +00:00
|
|
|
std::vector<std::complex<float>> code_aux(codeLength);
|
|
|
|
galileo_e6_c_code_gen_complex_primary(code_aux, prn);
|
2020-11-07 20:33:26 +00:00
|
|
|
|
2020-12-29 13:47:28 +00:00
|
|
|
if (sampling_freq != codeFreqBasis)
|
2020-11-07 20:33:26 +00:00
|
|
|
{
|
2020-12-29 13:47:28 +00:00
|
|
|
std::vector<std::complex<float>> resampled_signal_aux(samplesPerCode);
|
|
|
|
resampler(code_aux, resampled_signal_aux, codeFreqBasis, sampling_freq); // resamples code to sampling_freq
|
|
|
|
code_aux = std::move(resampled_signal_aux);
|
2020-11-07 20:33:26 +00:00
|
|
|
}
|
|
|
|
|
2020-12-29 13:47:28 +00:00
|
|
|
for (uint32_t i = 0; i < samplesPerCode; i++)
|
2020-11-07 20:33:26 +00:00
|
|
|
{
|
2020-12-29 13:47:28 +00:00
|
|
|
dest[(i + delay) % samplesPerCode] = code_aux[i];
|
2020-11-07 20:33:26 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-12-29 13:47:28 +00:00
|
|
|
void galileo_e6_c_secondary_code_gen_complex(own::span<std::complex<float>> dest,
|
|
|
|
int32_t prn)
|
2020-11-07 20:33:26 +00:00
|
|
|
{
|
2020-12-29 13:47:28 +00:00
|
|
|
const uint32_t prn_ = prn - 1;
|
2020-11-07 20:33:26 +00:00
|
|
|
uint32_t index = 0;
|
|
|
|
std::array<int32_t, 4> a{};
|
2020-12-29 13:47:28 +00:00
|
|
|
if ((prn < 1) || (prn > 50))
|
2020-11-07 20:33:26 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (size_t i = 0; i < GALILEO_E6_C_SECONDARY_CODE_STR_LENGTH; i++)
|
|
|
|
{
|
2020-12-29 13:47:28 +00:00
|
|
|
hex_to_binary_converter(a, GALILEO_E6_C_SECONDARY_CODE[prn_][i]);
|
|
|
|
dest[index] = std::complex<float>(static_cast<float>(a[0]), 0.0);
|
|
|
|
dest[index + 1] = std::complex<float>(static_cast<float>(a[1]), 0.0);
|
|
|
|
dest[index + 2] = std::complex<float>(static_cast<float>(a[2]), 0.0);
|
|
|
|
dest[index + 3] = std::complex<float>(static_cast<float>(a[3]), 0.0);
|
2020-11-07 20:33:26 +00:00
|
|
|
index = index + 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-12-29 13:47:28 +00:00
|
|
|
void galileo_e6_c_secondary_code_gen_float(own::span<float> dest,
|
|
|
|
int32_t prn)
|
2020-11-07 20:33:26 +00:00
|
|
|
{
|
2020-12-29 13:47:28 +00:00
|
|
|
const uint32_t prn_ = prn - 1;
|
2020-11-07 20:33:26 +00:00
|
|
|
uint32_t index = 0;
|
|
|
|
std::array<int32_t, 4> a{};
|
2020-12-29 13:47:28 +00:00
|
|
|
if ((prn < 1) || (prn > 50))
|
2020-11-07 20:33:26 +00:00
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
for (size_t i = 0; i < GALILEO_E6_C_SECONDARY_CODE_STR_LENGTH; i++)
|
|
|
|
{
|
2020-12-29 13:47:28 +00:00
|
|
|
hex_to_binary_converter(a, GALILEO_E6_C_SECONDARY_CODE[prn_][i]);
|
|
|
|
dest[index] = static_cast<float>(a[0]);
|
|
|
|
dest[index + 1] = static_cast<float>(a[1]);
|
|
|
|
dest[index + 2] = static_cast<float>(a[2]);
|
|
|
|
dest[index + 3] = static_cast<float>(a[3]);
|
2020-11-07 20:33:26 +00:00
|
|
|
index = index + 4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2020-12-29 13:47:28 +00:00
|
|
|
std::string galileo_e6_c_secondary_code(int32_t prn)
|
2020-11-07 20:33:26 +00:00
|
|
|
{
|
|
|
|
std::string dest(static_cast<size_t>(GALILEO_E6_C_SECONDARY_CODE_LENGTH_CHIPS), '0');
|
2020-12-29 13:47:28 +00:00
|
|
|
const uint32_t prn_ = prn - 1;
|
2021-06-17 09:09:41 +00:00
|
|
|
if ((prn < 1) || (prn > 50))
|
|
|
|
{
|
|
|
|
return dest;
|
|
|
|
}
|
2020-11-07 20:33:26 +00:00
|
|
|
uint32_t index = 0;
|
|
|
|
for (size_t i = 0; i < GALILEO_E6_C_SECONDARY_CODE_STR_LENGTH; i++)
|
|
|
|
{
|
2020-12-29 13:47:28 +00:00
|
|
|
std::string aux = hex_to_binary_string(GALILEO_E6_C_SECONDARY_CODE[prn_][i]);
|
2020-11-07 20:33:26 +00:00
|
|
|
dest[index] = aux[0];
|
|
|
|
dest[index + 1] = aux[1];
|
|
|
|
dest[index + 2] = aux[2];
|
|
|
|
dest[index + 3] = aux[3];
|
|
|
|
index = index + 4;
|
|
|
|
}
|
|
|
|
|
|
|
|
return dest;
|
|
|
|
}
|