Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hamming code correction method (Glonass) #667

Open
wants to merge 1 commit into
base: next
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/core/system_parameters/GLONASS_L1_L2_CA.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
95 changes: 92 additions & 3 deletions src/core/system_parameters/glonass_gnav_navigation_message.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
6 changes: 6 additions & 0 deletions src/core/system_parameters/glonass_gnav_navigation_message.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ class Glonass_Gnav_Navigation_Message
*/
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down