1
0
mirror of https://github.com/gnss-sdr/gnss-sdr synced 2024-10-31 23:26:22 +00:00

- Added Hamming code correction method

- Added google tests for this method
This commit is contained in:
Alexander V. Joura 2022-09-09 15:43:59 +03:00
parent 45e1fa3ade
commit 7333f0ce73
No known key found for this signature in database
GPG Key ID: 0A54C128A9C89772
4 changed files with 168 additions and 3 deletions

View File

@ -239,6 +239,9 @@ const std::vector<int32_t> GLONASS_GNAV_CRC_N_INDEX{35, 36, 37, 38, 39, 40, 41,
const std::vector<int32_t> GLONASS_GNAV_CRC_P_INDEX{66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85};
const std::vector<int32_t> GLONASS_GNAV_CRC_Q_INDEX{9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85};
const std::vector<std::vector<int32_t>> GLONASS_GNAV_HAMMING_INDEX{GLONASS_GNAV_CRC_I_INDEX, GLONASS_GNAV_CRC_J_INDEX, GLONASS_GNAV_CRC_K_INDEX, GLONASS_GNAV_CRC_L_INDEX,
GLONASS_GNAV_CRC_M_INDEX, GLONASS_GNAV_CRC_N_INDEX, GLONASS_GNAV_CRC_P_INDEX, GLONASS_GNAV_CRC_Q_INDEX};
// GLONASS GNAV NAVIGATION MESSAGE STRUCTURE
// NAVIGATION MESSAGE FIELDS POSITIONS

View File

@ -133,6 +133,95 @@ bool Glonass_Gnav_Navigation_Message::CRC_test(const std::bitset<GLONASS_GNAV_ST
}
bool Glonass_Gnav_Navigation_Message::hamming_correct(std::bitset<GLONASS_GNAV_STRING_BITS>& bits_io) const
{
std::vector<int> bits(GLONASS_GNAV_STRING_BITS);
// Populate data and Hamming code vectors
for (size_t i = 0; i < bits.size(); i++)
{
bits[i] = static_cast<int>(bits_io[i]);
}
std::vector<int> C(GLONASS_GNAV_HAMMING_CODE_BITS, 0);
int sum_bits;
for (size_t m = 0; m < GLONASS_GNAV_HAMMING_CODE_BITS; ++m)
{
sum_bits = 0;
for (int i : GLONASS_GNAV_HAMMING_INDEX[m])
sum_bits += bits[i - 1];
C[m] = bits[m] ^ (sum_bits % 2);
}
int sum_hamming = 0;
for (int i = 0; i < GLONASS_GNAV_HAMMING_CODE_BITS; ++i)
{
sum_hamming += bits[i];
}
C[GLONASS_GNAV_HAMMING_CODE_BITS - 1] = (sum_hamming % 2) ^ (sum_bits % 2);
int shortSumC = 0;
for (size_t m = 0; m < GLONASS_GNAV_HAMMING_CODE_BITS - 1; ++m)
{
shortSumC += C[m];
}
if (C[GLONASS_GNAV_HAMMING_CODE_BITS - 1] == 0)
{
if (shortSumC == 0)
{
// (A1) All checksums (C1, ..., C7 and C_Sigma) are equal to zero (all information
// bits and check bits are valid)
return true;
}
}
else
{
int highestNonZeroIdx = -1;
for (int i = 0; i < GLONASS_GNAV_HAMMING_CODE_BITS - 1; ++i) // C_Sigma should not be taken into account
{
if (C[i] != 0)
highestNonZeroIdx = i + 1; // 1-based indices
}
if (shortSumC == 1)
{
// (A2) Only one of the checksums (C1, ..., C7) is equal to 1 and C_Sigma = 1 (all
// information bits are valid and there is an error in one (!) of the check bits.
bits_io[highestNonZeroIdx - 1] = 1 - bits_io[highestNonZeroIdx - 1];
return true;
}
if (highestNonZeroIdx == -1)
{
// Error only in parity bit (C_Sigma = 1)
bits_io[GLONASS_GNAV_HAMMING_CODE_BITS - 1] = 1 - bits_io[GLONASS_GNAV_HAMMING_CODE_BITS - 1];
return true;
}
int idx = C[GLONASS_GNAV_HAMMING_CODE_BITS - 2];
for (int i = GLONASS_GNAV_HAMMING_CODE_BITS - 3; i >= 0; --i)
{
idx <<= 1;
idx += C[i];
}
int position = idx + GLONASS_GNAV_HAMMING_CODE_BITS - highestNonZeroIdx - 1;
if (position < GLONASS_GNAV_STRING_BITS)
{
// (B) Error only in a single information bit
bits_io[position] = 1 - bits_io[position];
return true;
}
}
// Irrecoverable error in information bits
return false;
}
bool Glonass_Gnav_Navigation_Message::read_navigation_bool(const std::bitset<GLONASS_GNAV_STRING_BITS>& bits, const std::vector<std::pair<int32_t, int32_t>>& parameter) const
{
bool value;
@ -238,10 +327,10 @@ int32_t Glonass_Gnav_Navigation_Message::string_decoder(const std::string& frame
uint64_t P_1_tmp = 0;
// Unpack bytes to bits
const std::bitset<GLONASS_GNAV_STRING_BITS> string_bits(frame_string);
std::bitset<GLONASS_GNAV_STRING_BITS> string_bits(frame_string);
// Perform data verification and exit code if error in bit sequence
flag_CRC_test = CRC_test(string_bits);
// Perform data correction and exit code if error in bit sequence is irrecoverable
flag_CRC_test = hamming_correct(string_bits);
if (flag_CRC_test == false)
{
return 0;

View File

@ -57,6 +57,12 @@ public:
*/
bool CRC_test(const std::bitset<GLONASS_GNAV_STRING_BITS>& bits) const;
/*!
* \brief Check and (if needed and possible) correct information bits for GLONASS GNAV strings
* \param[in,out] bits_io Bits of the string message (information and Hamming codes)
*/
bool hamming_correct(std::bitset<GLONASS_GNAV_STRING_BITS>& bits_io) const;
/*!
* \brief Computes the frame number being decoded given the satellite slot number
* \param satellite_slot_number [in] Satellite slot number identifier

View File

@ -20,6 +20,9 @@
#include "glonass_gnav_navigation_message.h"
#include "gnss_signal_replica.h"
// A valid GLONASS GNAV message string
std::string valid_msg("0001110000000001001101001110100011111011010011001101001101110110010011110011100100011");
/*!
* \brief Testing CRC computation for GLONASS GNAV data bits of a string
* \test The provided string was generated with a version of MATLAB GNSS-SDR that
@ -60,6 +63,70 @@ TEST(GlonassGnavNavigationMessageTest, CRCTestFailure)
ASSERT_FALSE(test_result);
}
/*!
* \brief Testing Hamming code correction method for GLONASS GNAV data.
* \test A single-bit error is introduced into each bit of a valid string
* and the result of error correction is compared to the original string
*/
TEST(GlonassGnavNavigationMessageTest, hamming_correct_1bit)
{
bool test_result;
std::bitset<GLONASS_GNAV_STRING_BITS> bits(valid_msg);
const std::bitset<GLONASS_GNAV_STRING_BITS> bits_original = bits;
auto gnav_nav_message = Glonass_Gnav_Navigation_Message();
test_result = gnav_nav_message.hamming_correct(bits);
// check correct return value for a valid string
ASSERT_TRUE(test_result);
// check that a valid string is not being changed
ASSERT_EQ(bits, bits_original);
for (int i = 0; i < GLONASS_GNAV_STRING_BITS; ++i)
{
bits[i] = 1 - bits[i];
test_result = gnav_nav_message.hamming_correct(bits);
// check correct return value for a string with a single bit error
ASSERT_TRUE(test_result);
// check that a string is restored correctly
ASSERT_EQ(bits, bits_original);
}
}
/*!
* \brief Testing Hamming code correction method for GLONASS GNAV data.
* \test A two-bit error is introduced into each possible pair of bits of
* a valid string in order to check that the error correction method
* returns correction result as 'false'.
*/
TEST(GlonassGnavNavigationMessageTest, hamming_correct_2bits)
{
std::bitset<GLONASS_GNAV_STRING_BITS> bits(valid_msg);
auto gnav_nav_message = Glonass_Gnav_Navigation_Message();
for (int i = 0; i < GLONASS_GNAV_STRING_BITS - 1; ++i)
{
bits[i] = 1 - bits[i];
for (int j = i + 1; j < GLONASS_GNAV_STRING_BITS; ++j)
{
bits[j] = 1 - bits[j];
std::bitset<GLONASS_GNAV_STRING_BITS> bits_with_errors = bits;
bool test_result = gnav_nav_message.hamming_correct(bits);
// check correct return value for a string with 2 wrong bits
ASSERT_FALSE(test_result);
// check that a string with 2 wrong bits is not being changed
ASSERT_EQ(bits, bits_with_errors);
bits[j] = 1 - bits[j];
}
bits[i] = 1 - bits[i];
}
}
/*!
* \brief Testing string decoding for GLONASS GNAV messages