Skip to content
Merged
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
15 changes: 15 additions & 0 deletions sys/checksum/crc16_ccitt.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,21 @@ uint16_t crc16_ccitt_mcrf4xx_calc(const unsigned char *buf, size_t len)
return crc16_ccitt_kermit_update(0xFFFF, buf, len);
}

uint16_t crc16_ccitt_fcs_start(const unsigned char *buf, size_t len)
{
return crc16_ccitt_kermit_update(0xFFFF, buf, len);
}

uint16_t crc16_ccitt_fcs_finish(uint16_t crc, const unsigned char *buf, size_t len)
{
return crc16_ccitt_kermit_update(crc, buf, len) ^ 0xFFFFU;
}

uint16_t crc16_ccitt_fcs_calc(const unsigned char *buf, size_t len)
{
return crc16_ccitt_fcs_start(buf, len) ^ 0xFFFFU;
}

uint16_t crc16_ccitt_false_update(uint16_t crc, const unsigned char *buf, size_t len)
{
while (len--) {
Expand Down
65 changes: 65 additions & 0 deletions sys/include/checksum/crc16_ccitt.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,71 @@ uint16_t crc16_ccitt_kermit_update(uint16_t crc, const unsigned char *buf, size_
*/
uint16_t crc16_ccitt_kermit_calc(const unsigned char *buf, size_t len);

/**
* @brief Start a CRC16-CCITT-FCS / IBM-SDLC calculation
*
* @param[in] buf Start of the memory area to checksum
* @param[in] len Number of bytes to checksum
*
* @return Partial checksum of the specified memory area. To be finalised
* with crc16_ccitt_fcs_finish()
*/
uint16_t crc16_ccitt_fcs_start(const unsigned char *buf, size_t len);

/**
* @brief Update CRC16-CCITT-FCS / IBM-SDLC
*
* @param[in] crc A start value for the CRC calculation, usually the
* return value of a previous call to
* crc16_ccitt_fcs_start() or crc16_ccitt_fcs_update()
* @param[in] buf Start of the memory area to checksum
* @param[in] len Number of bytes to checksum
*
* @return Partial checksum of the specified memory area based on the
* given start value. To be finalised with crc16_ccitt_fcs_finish()
*/
static inline uint16_t crc16_ccitt_fcs_update(uint16_t crc, const unsigned char *buf,
size_t len)
{
/* Since CCITT-KERMIT and CCITT-FCS only differ in the starting
* seed, we wrap around crc16_ccitt_kermit_update() for updating */
return crc16_ccitt_kermit_update(crc, buf, len);
}

/**
* @brief Finalise CRC16-CCITT-FCS / IBM-SDLC
*
* @param[in] crc A start value for the CRC calculation, usually the
* return value of a previous call to
* crc16_ccitt_fcs_start() or crc16_ccitt_fcs_update()
* @param[in] buf Start of the memory area to checksum
* @param[in] len Number of bytes to checksum
*
* @return Checksum of the specified memory area based on the
* given start value.
*/
uint16_t crc16_ccitt_fcs_finish(uint16_t crc, const unsigned char *buf, size_t len);

/**
* @brief Calculate CRC16-CCITT-FCS / IBM-SDLC in one pass.
*
* Parameter | Value
* --------: | :----
* Polynom | `0x1021`
* Init | `0xffff`
* Refin | `true`
* Refout | `true`
* Xorout | `0xffff`
* Check | `0x906e`
* Residue | `0xf0b8`
*
* @param[in] buf Start of the memory area to checksum
* @param[in] len Number of bytes to checksum
*
* @return Checksum of the specified memory area
*/
uint16_t crc16_ccitt_fcs_calc(const unsigned char *buf, size_t len);

/**
* @brief Update CRC16-CCITT-MCRF4XX
*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2022 Bennet Blischke <[email protected]>
* Copyright 2022 Bennet Hattesen <[email protected]>
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
Expand Down
126 changes: 126 additions & 0 deletions tests/unittests/tests-checksum/tests-checksum-crc16-ccitt-fcs.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/*
* Copyright 2025 Bennet Hattesen <[email protected]>
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
#include <stdio.h>
#include <stdint.h>

#include "embUnit/embUnit.h"

#include "checksum/crc16_ccitt.h"

#include "tests-checksum.h"

static int calc_and_compare_crc16_ccitt_fcs_with_update(const unsigned char *buf,
size_t len, size_t split,
uint16_t expected)
{
uint16_t result = crc16_ccitt_fcs_start(buf, split);

result = crc16_ccitt_fcs_finish(result, buf + split, len - split);
return result == expected;
}

static int calc_and_compare_crc16_ccitt_fcs(const unsigned char *buf, size_t len,
uint16_t expected)
{
uint16_t result = crc16_ccitt_fcs_calc(buf, len);

return result == expected;
}

static void test_checksum_crc16_ccitt_fcs_sequence_empty(void)
{
unsigned char buf[] = "";
uint16_t expect = 0x0000;

TEST_ASSERT(calc_and_compare_crc16_ccitt_fcs(buf, sizeof(buf) - 1, expect));
TEST_ASSERT(calc_and_compare_crc16_ccitt_fcs_with_update(buf, sizeof(buf) - 1,
(sizeof(buf) - 1) / 2, expect));
}

static void test_checksum_crc16_ccitt_fcs_sequence_1a(void)
{
unsigned char buf[] = "A";
uint16_t expect = 0xA3F5;

TEST_ASSERT(calc_and_compare_crc16_ccitt_fcs(buf, sizeof(buf) - 1, expect));
TEST_ASSERT(calc_and_compare_crc16_ccitt_fcs_with_update(buf, sizeof(buf) - 1,
(sizeof(buf) - 1) / 2, expect));
}

static void test_checksum_crc16_ccitt_fcs_sequence_256a(void)
{
unsigned char buf[] = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
"AAAA";
uint16_t expect = 0x0F9F;

TEST_ASSERT(calc_and_compare_crc16_ccitt_fcs(buf, sizeof(buf) - 1, expect));
TEST_ASSERT(calc_and_compare_crc16_ccitt_fcs_with_update(buf, sizeof(buf) - 1,
(sizeof(buf) - 1) / 2, expect));
}

static void test_checksum_crc16_ccitt_fcs_sequence_1to9(void)
{
unsigned char buf[] = "123456789";
uint16_t expect = 0x906E;

TEST_ASSERT(calc_and_compare_crc16_ccitt_fcs(buf, sizeof(buf) - 1, expect));
TEST_ASSERT(calc_and_compare_crc16_ccitt_fcs_with_update(buf, sizeof(buf)
- 1, (sizeof(buf) - 1) / 2,
expect));
}

static void test_checksum_crc16_ccitt_fcs_sequence_4bytes(void)
{
unsigned char buf[] = { 0x12, 0x34, 0x56, 0x78 };
uint16_t expect = 0x9B2E;

TEST_ASSERT(calc_and_compare_crc16_ccitt_fcs(buf, sizeof(buf), expect));
TEST_ASSERT(calc_and_compare_crc16_ccitt_fcs_with_update(buf, sizeof(buf),
sizeof(buf) / 2, expect));
}

static void test_checksum_crc16_ccitt_fcs_sequence_6bytes(void)
{
unsigned char buf[] = { 0x00, 0x01, 0x02, 0x03 };
uint16_t expect = 0xA729;

TEST_ASSERT(calc_and_compare_crc16_ccitt_fcs(buf, sizeof(buf), expect));
TEST_ASSERT(calc_and_compare_crc16_ccitt_fcs_with_update(buf, sizeof(buf),
sizeof(buf) / 2, expect));

unsigned char buf2[] = { 0x00, 0x01, 0x02, 0x03, 0x29, 0xA7 };
uint16_t expect2 = 0x0F47;

// Residue test
TEST_ASSERT(crc16_ccitt_fcs_start(buf2, sizeof(buf2)) == 0xF0B8);

TEST_ASSERT(calc_and_compare_crc16_ccitt_fcs(buf2, sizeof(buf2), expect2));
TEST_ASSERT(calc_and_compare_crc16_ccitt_fcs_with_update(buf2, sizeof(buf2),
sizeof(buf2) / 2, expect2));
}

Test *tests_checksum_crc16_ccitt_fcs_tests(void)
{
EMB_UNIT_TESTFIXTURES(fixtures) {
new_TestFixture(test_checksum_crc16_ccitt_fcs_sequence_empty),
new_TestFixture(test_checksum_crc16_ccitt_fcs_sequence_1a),
new_TestFixture(test_checksum_crc16_ccitt_fcs_sequence_256a),
new_TestFixture(test_checksum_crc16_ccitt_fcs_sequence_1to9),
new_TestFixture(test_checksum_crc16_ccitt_fcs_sequence_4bytes),
new_TestFixture(test_checksum_crc16_ccitt_fcs_sequence_6bytes),
};

EMB_UNIT_TESTCALLER(checksum_crc16_ccitt_fcs_tests, NULL, NULL, fixtures);

return (Test *)&checksum_crc16_ccitt_fcs_tests;
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2022 Bennet Blischke <[email protected]>
* Copyright 2022 Bennet Hattesen <[email protected]>
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2022 Bennet Blischke <[email protected]>
* Copyright 2022 Bennet Hattesen <[email protected]>
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
Expand Down
1 change: 1 addition & 0 deletions tests/unittests/tests-checksum/tests-checksum.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ void tests_checksum(void)
TESTS_RUN(tests_checksum_crc8_tests());
TESTS_RUN(tests_checksum_crc8_lsb_tests());
TESTS_RUN(tests_checksum_crc16_ccitt_kermit_tests());
TESTS_RUN(tests_checksum_crc16_ccitt_fcs_tests());
TESTS_RUN(tests_checksum_crc16_ccitt_mcrf4xx_tests());
TESTS_RUN(tests_checksum_crc16_ccitt_aug_tests());
TESTS_RUN(tests_checksum_crc16_ccitt_false_tests());
Expand Down
7 changes: 7 additions & 0 deletions tests/unittests/tests-checksum/tests-checksum.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,13 @@ Test *tests_checksum_crc8_lsb_tests(void);
*/
Test *tests_checksum_crc16_ccitt_kermit_tests(void);

/**
* @brief Generates tests for crc16-ccitt-fcs from checksum/crc16_ccitt.h
*
* @return embUnit tests if successful, NULL if not.
*/
Test *tests_checksum_crc16_ccitt_fcs_tests(void);

/**
* @brief Generates tests for crc16-ccitt-mcrf4xx from checksum/crc16_ccitt.h
*
Expand Down