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:
parent
45e1fa3ade
commit
7333f0ce73
@ -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_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<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
|
// GLONASS GNAV NAVIGATION MESSAGE STRUCTURE
|
||||||
// NAVIGATION MESSAGE FIELDS POSITIONS
|
// NAVIGATION MESSAGE FIELDS POSITIONS
|
||||||
|
|
||||||
|
@ -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 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;
|
bool value;
|
||||||
@ -238,10 +327,10 @@ int32_t Glonass_Gnav_Navigation_Message::string_decoder(const std::string& frame
|
|||||||
uint64_t P_1_tmp = 0;
|
uint64_t P_1_tmp = 0;
|
||||||
|
|
||||||
// Unpack bytes to bits
|
// 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
|
// Perform data correction and exit code if error in bit sequence is irrecoverable
|
||||||
flag_CRC_test = CRC_test(string_bits);
|
flag_CRC_test = hamming_correct(string_bits);
|
||||||
if (flag_CRC_test == false)
|
if (flag_CRC_test == false)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -57,6 +57,12 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool CRC_test(const std::bitset<GLONASS_GNAV_STRING_BITS>& bits) const;
|
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
|
* \brief Computes the frame number being decoded given the satellite slot number
|
||||||
* \param satellite_slot_number [in] Satellite slot number identifier
|
* \param satellite_slot_number [in] Satellite slot number identifier
|
||||||
|
@ -20,6 +20,9 @@
|
|||||||
#include "glonass_gnav_navigation_message.h"
|
#include "glonass_gnav_navigation_message.h"
|
||||||
#include "gnss_signal_replica.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
|
* \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
|
* \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);
|
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
|
* \brief Testing string decoding for GLONASS GNAV messages
|
||||||
|
Loading…
Reference in New Issue
Block a user