Added error correction to the metadata of LDU1 and LDU2.

Refactored implementation of p25p1_ldu1.c and p25p1_ldu2.c. There are less duplicities now and hopefully is easier to read and maintain.
Added a unit test for the Hamming algorithm.
This commit is contained in:
EdFuentetaja
2014-03-31 23:37:08 +08:00
parent 7299b78c3b
commit 01a2b6959a
17 changed files with 1594 additions and 612 deletions

View File

@@ -3,12 +3,13 @@ project(dsdtest)
add_subdirectory(gtest)
add_subdirectory(gmock)
FILE(GLOB SRCS *.cpp)
FILE(GLOB SRCS *.cpp ${dsdtest_SOURCE_DIR}/../Hamming.cpp)
include_directories(
${PROJECT_SOURCE_DIR}/gtest/include
${PROJECT_SOURCE_DIR}/gmock/include
${dsd_SOURCE_DIR}
${dsdtest_SOURCE_DIR}
${dsdtest_SOURCE_DIR}/..
)
add_custom_target(test

View File

@@ -1,5 +1,10 @@
/**
* Unit tests for the Golay24 implementation.
*/
#include "gtest/gtest.h"
#include "gmock/gmock.h"
#include "Golay24.hpp"
class Golay24Test : public testing::Test

251
test/hamming-test.cpp Normal file
View File

@@ -0,0 +1,251 @@
#include "gtest/gtest.h"
#include "gmock/gmock.h"
#include <iostream>
#include <bitset>
#include "Hamming.hpp"
class HammingTest : public testing::Test
{
protected:
static void print_debug(int value, int fixed, int error_count)
{
std::cout << std::bitset<10>(value) << ": ";
switch (error_count) {
case 0:
std::cout << "OK";
break;
case 1:
std::cout << "one error detected, hopefully fixed: " << std::bitset<6>(fixed);
break;
case 2:
std::cout << "irrecoverable :(";
break;
default:
break;
}
std::cout << std::endl;
}
static void check_hamming(int v, int expected_v, int expected_errors)
{
Hamming_10_6_3 hamming;
Hamming_10_6_3_TableImpl hamming_table;
int output_1;
int output_2;
int error_count_1 = hamming.decode(v, &output_1);
int error_count_2 = hamming_table.decode(v, &output_2);
//print_debug(v, output_1, error_count_1);
if (expected_errors != -1) {
EXPECT_THAT(expected_errors, error_count_1);
}
EXPECT_THAT(error_count_1, error_count_2);
if (expected_v != -1) {
EXPECT_THAT(expected_v, output_1);
}
EXPECT_THAT(output_1, output_2);
}
static void check_hamming(Hamming_Inteface* hamming, char* hex, char* parity, int expected_errors, char* expected)
{
int value = Hamming_10_6_3_TableImpl::convert_hex_parity_to_int(hex, parity);
int error_count = hamming->decode(hex, parity);
int fixed = Hamming_10_6_3_TableImpl::convert_hex_to_int(hex);
//print_debug(value, fixed, error_count);
EXPECT_THAT(expected_errors, error_count);
for (unsigned int i=0; i<6; i++) {
EXPECT_THAT(expected[i], hex[i]);
}
}
};
TEST_F(HammingTest, Test1)
{
// OK
std::bitset<10> value(std::string("1010100110"));
std::bitset< 6> expected(std::string("101010"));
check_hamming((int)value.to_ulong(), (int)expected.to_ulong(), 0);
}
TEST_F(HammingTest, Test2)
{
// Error on parity bit 0 (9 is the left-most and 0 is the right-most)
std::bitset<10> value(std::string("1010100111"));
std::bitset< 6> expected(std::string("101010"));
check_hamming((int)value.to_ulong(), (int)expected.to_ulong(), 1);
}
TEST_F(HammingTest, Test3)
{
// Error on parity bit 1 (9 is the left-most and 0 is the right-most)
std::bitset<10> value(std::string("1010100100"));
std::bitset< 6> expected(std::string("101010"));
check_hamming((int)value.to_ulong(), (int)expected.to_ulong(), 1);
}
TEST_F(HammingTest, Test4)
{
// Error on parity bit 2 (9 is the left-most and 0 is the right-most)
std::bitset<10> value(std::string("1010100010"));
std::bitset< 6> expected(std::string("101010"));
check_hamming((int)value.to_ulong(), (int)expected.to_ulong(), 1);
}
TEST_F(HammingTest, Test5)
{
// Error on parity bit 3 (9 is the left-most and 0 is the right-most)
std::bitset<10> value(std::string("1010101110"));
std::bitset< 6> expected(std::string("101010"));
check_hamming((int)value.to_ulong(), (int)expected.to_ulong(), 1);
}
TEST_F(HammingTest, Test6)
{
// Error on bit 4 (9 is the left-most and 0 is the right-most)
std::bitset<10> value(std::string("1010110110"));
std::bitset< 6> expected(std::string("101010"));
check_hamming((int)value.to_ulong(), (int)expected.to_ulong(), 1);
}
TEST_F(HammingTest, Test7)
{
// Error on bit 5 (9 is the left-most and 0 is the right-most)
std::bitset<10> value(std::string("1010000110"));
std::bitset< 6> expected(std::string("101010"));
check_hamming((int)value.to_ulong(), (int)expected.to_ulong(), 1);
}
TEST_F(HammingTest, Test8)
{
// Error on bit 6 (9 is the left-most and 0 is the right-most)
std::bitset<10> value(std::string("1011100110"));
std::bitset< 6> expected(std::string("101010"));
check_hamming((int)value.to_ulong(), (int)expected.to_ulong(), 1);
}
TEST_F(HammingTest, Test9)
{
// Error on bit 7 (9 is the left-most and 0 is the right-most)
std::bitset<10> value(std::string("1000100110"));
std::bitset< 6> expected(std::string("101010"));
check_hamming((int)value.to_ulong(), (int)expected.to_ulong(), 1);
}
TEST_F(HammingTest, Test10)
{
// Error on bit 8 (9 is the left-most and 0 is the right-most)
std::bitset<10> value(std::string("1110100110"));
std::bitset< 6> expected(std::string("101010"));
check_hamming((int)value.to_ulong(), (int)expected.to_ulong(), 1);
}
TEST_F(HammingTest, Test11)
{
// Error on bit 9 (9 is the left-most and 0 is the right-most)
std::bitset<10> value(std::string("0010100110"));
std::bitset< 6> expected(std::string("101010"));
check_hamming((int)value.to_ulong(), (int)expected.to_ulong(), 1);
}
TEST_F(HammingTest, Test12)
{
// Two errors
std::bitset<10> value(std::string("0010100111"));
std::bitset< 6> expected(std::string("001010"));
check_hamming((int)value.to_ulong(), (int)expected.to_ulong(), 2);
}
TEST_F(HammingTest, Test13)
{
// Two errors, in this case they go undetected, thinks it's a parity error
std::bitset<10> value(std::string("1011000110"));
std::bitset< 6> expected(std::string("101100"));
check_hamming((int)value.to_ulong(), (int)expected.to_ulong(), 1);
}
TEST_F(HammingTest, Test14)
{
// OK
std::bitset<10> value(std::string("0001000111"));
std::bitset< 6> expected(std::string("000100"));
check_hamming((int)value.to_ulong(), (int)expected.to_ulong(), 0);
}
TEST_F(HammingTest, TestEveryValue)
{
// Test every posible value
for (int v=0; v<1023; v++) {
check_hamming(v, -1, -1);
}
}
TEST_F(HammingTest, Test_hex_parity_interface_no_errors)
{
char hex [6] = {1,1,1,0,1,0};
char fixed [6] = {1,1,1,0,1,0};
char parity[4] = {1,0,1,1};
Hamming_10_6_3 hamming;
check_hamming(&hamming, hex, parity, 0, fixed);
Hamming_10_6_3_TableImpl hamming_table;
check_hamming(&hamming_table, hex, parity, 0, fixed);
}
TEST_F(HammingTest, Test_hex_parity_interface_one_error_1)
{
char hex_1 [6] = {1,1,1,1,1,0};
char hex_2 [6] = {1,1,1,1,1,0};
char fixed [6] = {1,1,1,0,1,0};
char parity[4] = {1,0,1,1};
Hamming_10_6_3 hamming;
check_hamming(&hamming, hex_1, parity, 1, fixed);
// hex is modified in place
Hamming_10_6_3_TableImpl hamming_table;
check_hamming(&hamming_table, hex_2, parity, 1, fixed);
// hex is modified in place
}
TEST_F(HammingTest, Test_hex_parity_interface_one_error_2)
{
char hex_1 [6] = {1,1,1,1,1,0};
char hex_2 [6] = {1,1,1,1,1,0};
char fixed [6] = {1,1,1,1,1,1};
char parity[4] = {0,0,0,0};
Hamming_10_6_3 hamming;
check_hamming(&hamming, hex_1, parity, 1, fixed);
// hex is modified in place
Hamming_10_6_3_TableImpl hamming_table;
check_hamming(&hamming_table, hex_2, parity, 1, fixed);
// hex is modified in place
}
TEST_F(HammingTest, Test_hex_parity_interface_one_error_3)
{
char hex_1 [6] = {1,0,0,0,0,0};
char hex_2 [6] = {1,0,0,0,0,0};
char fixed [6] = {0,0,0,0,0,0};
char parity[4] = {0,0,0,0};
Hamming_10_6_3 hamming;
check_hamming(&hamming, hex_1, parity, 1, fixed);
// hex is modified in place
Hamming_10_6_3_TableImpl hamming_table;
check_hamming(&hamming_table, hex_2, parity, 1, fixed);
// hex is modified in place
}

View File

@@ -1,7 +1,22 @@
/**
* Unit tests for the Reed-Solomon implementation.
*/
#include "gtest/gtest.h"
#include "gmock/gmock.h"
#include "ReedSolomon.hpp"
static void byte_to_binary(char* b, int x)
{
int z, i;
for (z = 32, i=0; z > 0; z >>= 1, i++) {
b[i] = ((x & z) != 0) ? 'X' : ' ';
}
b[6] = 0;
}
TEST(ReedSolomonTest, Test1)
{
ReedSolomon_63_47_17 rs;
@@ -10,25 +25,29 @@ TEST(ReedSolomonTest, Test1)
int output[63];
// send this message
recd[16+0] = 1;
recd[16+6] = 8;
recd[ 0] = 8+4;
recd[ 1] = 3;
recd[ 2] = 8+2;
recd[ 3] = 16+1;
recd[ 4] = 16+2;
recd[ 5] = 32+8+3;
recd[ 5] = 32+8+3; // error
recd[ 6] = 4;
recd[ 7] = 32+2;
recd[ 8] = 32+2;
recd[ 8] = 32+2; // error
recd[ 9] = 32+16+8+1;
recd[10] = 32+16+1;
recd[11] = 32+16+3;
recd[12] = 16+8;
recd[13] = 32+2;
recd[12] = 16+8; // error
recd[13] = 32+2; // error
recd[14] = 16+4;
recd[15] = 16+4+3;
recd[16+0] = 1;
recd[16+1] = 0;
recd[16+2] = 0;
recd[16+3] = 0;
recd[16+4] = 0;
recd[16+5] = 0;
recd[16+6] = 8;
// expect this message
expected[ 0] = 8+4;
@@ -47,11 +66,27 @@ TEST(ReedSolomonTest, Test1)
expected[13] = 32+8+2;
expected[14] = 16+4;
expected[15] = 16+4+3;
expected[16] = 1;
expected[22] = 8;
expected[16+0] = 1;
expected[16+1] = 0;
expected[16+2] = 0;
expected[16+3] = 0;
expected[16+4] = 0;
expected[16+5] = 0;
expected[16+6] = 8;
rs.decode(recd, output); /* recd[] is returned in polynomial form */
/*
printf("Results for Reed-Solomon code (n=%3d, k=%3d, t= %3d)\n\n", nn, kk, tt);
printf(" i recd[i](decoded)\n");
for (int i = 0; i < nn; i++) {
char b[9];
byte_to_binary(b, output[i]);
printf("%3d [%s]\n", i, b);
}
printf("\n");
*/
EXPECT_THAT(expected, testing::ElementsAreArray(output, 63));
}