diff --git a/sys/ecc/repetition.c b/sys/ecc/repetition.c new file mode 100644 index 0000000000000000000000000000000000000000..6ce90056dcaca8a85d07c0d94e2abee32e2757bd --- /dev/null +++ b/sys/ecc/repetition.c @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2007 - 2015 Joseph Gaeddert + * Copyright (c) 2018 HAW Hamburg + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/** + * @ingroup sys_ecc + * @{ + * + * @file + * @brief Repetition code + * + * Code referring to Liquid-DSP + * https://github.com/jgaeddert/liquid-dsp/blob/master/src/fec/src/repetition.c + * + * @author Joseph Gaeddert + * @author Peter Kietzmann <peter.kietzmann@haw.hamburg.de> + * + * @} + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "ecc/repetition.h" + +void repetition_encode(unsigned int _dec_msg_len, + unsigned char *_msg_dec, + unsigned char *_msg_enc) +{ + unsigned int i; + + for (i = 0; i < ECC_REPETITION_COUNT; i++) { + memcpy(&_msg_enc[i * _dec_msg_len], _msg_dec, _dec_msg_len); + } +} + +void repetition_decode(unsigned int _dec_msg_len, + unsigned char *_msg_enc, + unsigned char *_msg_dec) +{ + unsigned char s[ECC_REPETITION_COUNT]; + unsigned char bitcnt = 0; + + for (unsigned i = 0; i < _dec_msg_len; i++) { + /* get all repetitions of a symbol */ + for (int k = 0; k < ECC_REPETITION_COUNT; k++) { + s[k] = _msg_enc[i + k * _dec_msg_len]; + } + + /* sum all ones for each bit position in a byte */ + for (int j = 0; j < 8; j++) { + for (int k = 0; k < ECC_REPETITION_COUNT; k++) { + bitcnt += ((s[k] >> j) & 0x01); + } + /* decide for a one if majority says one */ + if (bitcnt > DECODER_MAJORITY) { + _msg_dec[i] |= (1 << (j)); + } + else { + _msg_dec[i] &= ~(1 << (j)); + } + bitcnt = 0; + } + } +} diff --git a/sys/include/ecc/repetition.h b/sys/include/ecc/repetition.h new file mode 100644 index 0000000000000000000000000000000000000000..389cb47955e98f30cebbe008115050a28e708ea2 --- /dev/null +++ b/sys/include/ecc/repetition.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2007 - 2015 Joseph Gaeddert + * Copyright (c) 2018 HAW Hamburg + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/** + * @ingroup sys_ecc + * @{ + * + * @file + * @brief ECC repetition code + * + * @author Joseph Gaeddert + * @author Peter Kietzmann <peter.kietzmann@haw.hamburg.de> + * + * @} + */ + +#ifndef ECC_REPETITION_H +#define ECC_REPETITION_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** Number of repetitions of a byte */ +#ifndef ECC_REPETITION_COUNT +#define ECC_REPETITION_COUNT (3) +#endif + +/** Calculates the majority according to the number of repetitions */ +#define DECODER_MAJORITY ((ECC_REPETITION_COUNT - 1) / 2) + +/** + * @brief encode block of data with @ref ECC_REPETITION_COUNT number of repetitions + * + * @param[in] _dec_msg_len decoded message length (number of bytes) + * @param[in] _msg_dec decoded message [size: 1 x _dec_msg_len] + * @param[out] _msg_enc encoded message [size: 1 x ECC_REPETITION_COUNT*_dec_msg_len] + */ +void repetition_encode(unsigned int _dec_msg_len, + unsigned char *_msg_dec, + unsigned char *_msg_enc); + +/** + * @brief decode block of data with @ref ECC_REPETITION_COUNT repetitions + * + * @param[in] _dec_msg_len decoded message length (number of bytes) + * @param[in] _msg_enc encoded message [size: 1 x ECC_REPETITION_COUNT*_dec_msg_len] + * @param[out] _msg_dec decoded message [size: 1 x _dec_msg_len] + */ +void repetition_decode(unsigned int _dec_msg_len, + unsigned char *_msg_enc, + unsigned char *_msg_dec); + +#ifdef __cplusplus +} +#endif + +#endif /* ECC_REPETITION_H */ +/** @} */ diff --git a/tests/unittests/tests-ecc/Makefile.include b/tests/unittests/tests-ecc/Makefile.include index ed7dbc9eeb8d1989ea7baa51b5eebbac87b63488..889c743b7a74f7b94fb44ba693006ab64b6796fc 100644 --- a/tests/unittests/tests-ecc/Makefile.include +++ b/tests/unittests/tests-ecc/Makefile.include @@ -1,2 +1,3 @@ USEMODULE += ecc_golay2412 USEMODULE += ecc_hamming256 +USEMODULE += ecc_repetition diff --git a/tests/unittests/tests-ecc/tests-ecc.c b/tests/unittests/tests-ecc/tests-ecc.c index 98f5d95b449a5e70dc4e74e8a169ad9aadfe7324..8523d9dae9f86458145967363443493c2035d181 100644 --- a/tests/unittests/tests-ecc/tests-ecc.c +++ b/tests/unittests/tests-ecc/tests-ecc.c @@ -21,17 +21,29 @@ #include "ecc/hamming256.h" #include "ecc/golay2412.h" +#include "ecc/repetition.h" + /* source for random bytes: https://www.random.org/bytes */ -unsigned char data_in[] = { 201, 240, 154, 5, 227, 60, 116, 192, 214 }; -/* encoded sequence */ -unsigned char msg_enc[] = { 220, 124, 159, 19, 64, 154, 135, 208, 94, - 227, 35, 60, 248, 39, 76, 187, 16, 214 }; +unsigned char data_in[] = { 201, 240, 154, 5, 227, 60, 116, 192, 214 }; +/* golay encoded sequence */ +unsigned char msg_enc_golay[] = { 220, 124, 159, 19, 64, 154, 135, 208, 94, + 227, 35, 60, 248, 39, 76, 187, 16, 214 }; /* Added errors. golay(24, 12) can correct up to 3 errors in one 24-bit * symbol (= 3 bytes). Positions for bitflips generated at * https://www.random.org/bytes */ -unsigned char msg_enc_3_err_per_symbol[] = { 252, 60, 191, 18, 64, 190, 135, 209, 22, - 227, 43, 188, 252, 33, 76, 57, 16, 212 }; +unsigned char msg_enc_golay_3_err_per_symbol[] = { 252, 60, 191, 18, 64, 190, 135, 209, 22, + 227, 43, 188, 252, 33, 76, 57, 16, 212 }; +/* repetition encoded sequence */ +unsigned char msg_enc_rep[] = { 201, 240, 154, 5, 227, 60, 116, 192, 214, + 201, 240, 154, 5, 227, 60, 116, 192, 214, + 201, 240, 154, 5, 227, 60, 116, 192, 214 }; +/* Added errors. repetition(3,1) can correct up to (ECC_REPETITION_COUNT-1)/2 errors + * per symbol (one encoded has 3 bytes here). Positions for bitflips generated at + * https://www.random.org/bytes */ +unsigned char msg_enc_rep_1_err_per_symbol[] = { 193, 240, 158, 5, 226, 60, 116, 193, 214, + 201, 242, 154, 5, 227, 28, 116, 192, 210, + 201, 240, 154, 21, 227, 60, 112, 192, 214 }; static void test_hamming256_single(void) { @@ -93,7 +105,7 @@ static void test_golay2412_message_encode(void) golay2412_encode(sizeof(data_in), &data_in[0], &encoded[0]); - TEST_ASSERT_EQUAL_INT(0, memcmp(&msg_enc, &encoded, sizeof(encoded))); + TEST_ASSERT_EQUAL_INT(0, memcmp(&msg_enc_golay, &encoded, sizeof(encoded))); } static void test_golay2412_message_noerr(void) @@ -110,7 +122,7 @@ static void test_golay2412_message_decode_success(void) { unsigned char result[sizeof(data_in)]; - golay2412_decode(sizeof(result), &msg_enc_3_err_per_symbol[0], &result[0]); + golay2412_decode(sizeof(result), &msg_enc_golay_3_err_per_symbol[0], &result[0]); TEST_ASSERT_EQUAL_INT(0, memcmp(&data_in, &result, sizeof(data_in))); } @@ -120,10 +132,51 @@ static void test_golay2412_message_decode_fail(void) unsigned char result[sizeof(data_in)]; /* adding a 4th error to the first symbol leads to an - uncorrectable sequence */ - msg_enc_3_err_per_symbol[0] ^= (1L << 6); + * uncorrectable sequence */ + msg_enc_golay_3_err_per_symbol[0] ^= (1L << 6); + + golay2412_decode(sizeof(result), &msg_enc_golay_3_err_per_symbol[0], &result[0]); + + TEST_ASSERT(memcmp(&data_in, &result, sizeof(data_in))); +} +static void test_repetition_message_encode(void) +{ + unsigned char encoded[ECC_REPETITION_COUNT * sizeof(data_in)]; + + repetition_encode(sizeof(data_in), &data_in[0], &encoded[0]); + + TEST_ASSERT_EQUAL_INT(0, memcmp(encoded, msg_enc_rep, sizeof(encoded))); +} + +static void test_repetition_message_noerr(void) +{ + unsigned char result[sizeof(data_in)]; + unsigned char encoded[ECC_REPETITION_COUNT * sizeof(data_in)]; + + repetition_encode(sizeof(data_in), &data_in[0], &encoded[0]); + repetition_decode(sizeof(result), &encoded[0], &result[0]); + + TEST_ASSERT_EQUAL_INT(0, memcmp(&data_in, &result, sizeof(data_in))); +} + +static void test_repetition_message_decode_success(void) +{ + unsigned char result[sizeof(data_in)]; + + repetition_decode(sizeof(result), &msg_enc_rep_1_err_per_symbol[0], &result[0]); + + TEST_ASSERT_EQUAL_INT(0, memcmp(&data_in, &result, sizeof(data_in))); +} + +static void test_repetition_message_decode_fail(void) +{ + unsigned char result[sizeof(data_in)]; + + /* adding a second error to the first symbol leads to an + * uncorrectable sequence */ + msg_enc_rep_1_err_per_symbol[0] ^= (1L << 6); - golay2412_decode(sizeof(result), &msg_enc_3_err_per_symbol[0], &result[0]); + golay2412_decode(sizeof(result), &msg_enc_rep_1_err_per_symbol[0], &result[0]); TEST_ASSERT(memcmp(&data_in, &result, sizeof(data_in))); } @@ -137,6 +190,10 @@ TestRef test_all(void) new_TestFixture(test_golay2412_message_noerr), new_TestFixture(test_golay2412_message_decode_success), new_TestFixture(test_golay2412_message_decode_fail), + new_TestFixture(test_repetition_message_encode), + new_TestFixture(test_repetition_message_noerr), + new_TestFixture(test_repetition_message_decode_success), + new_TestFixture(test_repetition_message_decode_fail), }; EMB_UNIT_TESTCALLER(EccTest, NULL, NULL, fixtures);