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

sys/checksum: Adding three new crc16 variations #18516

Merged
merged 1 commit into from
Aug 31, 2022
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
69 changes: 64 additions & 5 deletions sys/checksum/crc16_ccitt.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,42 @@

#include "checksum/crc16_ccitt.h"

static const uint16_t _crc16_lookuptable[256] = {
static const uint16_t crc_ccitt_lookuptable[256] = {
0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
};

static const uint16_t _crc16_ccitt_false_lookuptable[256] = {
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
Expand Down Expand Up @@ -58,16 +93,40 @@ static const uint16_t _crc16_lookuptable[256] = {
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
};

uint16_t crc16_ccitt_update(uint16_t crc, const unsigned char *buf, size_t len)
uint16_t crc16_ccitt_kermit_update(uint16_t crc, const unsigned char *buf, size_t len)
{
while (len--) {
crc = (crc >> 8) ^ crc_ccitt_lookuptable[(crc ^ (*buf++)) & 0xff];
}

return crc;
}

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

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_false_update(uint16_t crc, const unsigned char *buf, size_t len)
{
while (len--) {
crc = ((crc << 8) ^ _crc16_lookuptable[((crc >> 8) ^ ((*buf++) & 0x00FF))]);
crc = ((crc << 8) ^ _crc16_ccitt_false_lookuptable[((crc >> 8) ^ ((*buf++) & 0x00FF))]);
}

return crc;
}

uint16_t crc16_ccitt_calc(const unsigned char *buf, size_t len)
uint16_t crc16_ccitt_aug_calc(const unsigned char *buf, size_t len)
{
return crc16_ccitt_false_update(0x1D0F, buf, len);
}

uint16_t crc16_ccitt_false_calc(const unsigned char *buf, size_t len)
{
return crc16_ccitt_update(0x1D0F, buf, len);
return crc16_ccitt_false_update(0xFFFF, buf, len);
}
174 changes: 162 additions & 12 deletions sys/include/checksum/crc16_ccitt.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,18 @@
* @defgroup sys_checksum_crc16_ccitt CRC16-CCITT
* @ingroup sys_checksum
*
* @brief CRC16-CCITT checksum algorithm
* @details This implementation of CRC16 is based on the CCITT
* specification using 0x1D0F as a start value.
* Using a different start value is possible by calling
* crc16_ccitt_update() with the desired start value
* instead of crc16_ccitt_calc().
*
* @brief Variations of CRC16-CCITT checksum algorithms
* @details This provides implementations for multiple variations
* of CRC16 checks.
* There is a more generalized version in @ref sys_checksum_ucrc16,
* that does not utilize a look-up table as this implementation
* does (and is thus also for more memory efficient). Its caveat
* however is that it is slower by about factor 8 than this version.
* that does not utilize a look-up table as these implementation
* do (and is thus also far more memory efficient). Its caveat
* however is that it is slower by about factor 8 than these versions.
*
* @{
* @file
* @author Ludwig Knüpfer <[email protected]>
* @author Bennet Blischke <[email protected]>
*/

#ifndef CHECKSUM_CRC16_CCITT_H
Expand All @@ -37,8 +34,153 @@
extern "C" {
#endif

/**
* @brief Update CRC16-CCITT-KERMIT
*
* @param[in] crc A start value for the CRC calculation, usually the
* return value of a previous call to
* crc16_ccitt_kermit_calc() or crc16_ccitt_kermit_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_kermit_update(uint16_t crc, const unsigned char *buf, size_t len);

/**
* @brief Calculate CRC16-CCITT-KERMIT
*
* Parameter | Value
* --------: | :----
* Polynom | `0x1021`
* Init | `0x0000`
* Refin | `true`
* Refout | `true`
* Xorout | `0x0000`
* Check | `0x2189`
*
* @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_kermit_calc(const unsigned char *buf, size_t len);

/**
* @brief Update CRC16-CCITT-MCRF4XX
*
* @param[in] crc A start value for the CRC calculation, usually the
* return value of a previous call to
* crc16_ccitt_mcrf4xx_calc() or crc16_ccitt_mcrf4xx_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
*/
static inline uint16_t crc16_ccitt_mcrf4xx_update(uint16_t crc, const unsigned char *buf,
size_t len)
{
/* Since CCITT-KERMIT and CCITT-MCRF4XX only differ in the starting
* seed, we wrap around crc16_ccitt_kermit_update() for updating */
return crc16_ccitt_kermit_update(crc, buf, len);
}

/**
* @brief Calculate CRC16-CCITT-MCRF4XX
*
* Parameter | Value
* --------: | :----
* Polynom | `0x1021`
* Init | `0xffff`
* Refin | `true`
* Refout | `true`
* Xorout | `0x0000`
* Check | `0x6f91`
*
* @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_mcrf4xx_calc(const unsigned char *buf, size_t len);

/**
* @brief Update CRC16-CCITT-FALSE
*
* @param[in] crc A start value for the CRC calculation, usually the
* return value of a previous call to
* crc16_ccitt_false_calc() or crc16_ccitt_false_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_false_update(uint16_t crc, const unsigned char *buf, size_t len);

/**
* @brief Calculate CRC16-CCITT-FALSE
*
* Parameter | Value
* --------: | :----
* Polynom | `0x1021`
* Init | `0xffff`
* Refin | `false`
* Refout | `false`
* Xorout | `0x0000`
* Check | `0x29b1`
*
* @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_false_calc(const unsigned char *buf, size_t len);

/**
* @brief Update CRC16-CCITT-AUG
*
* @param[in] crc A start value for the CRC calculation, usually the
* return value of a previous call to
* crc16_ccitt_aug_calc() or crc16_ccitt_aug_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
*/
static inline uint16_t crc16_ccitt_aug_update(uint16_t crc, const unsigned char *buf, size_t len)
{
/* Since CCITT-AUG and CCITT-FALSE only differ in the starting
* seed, we wrap around crc16_ccitt_false_update() for updating */
return crc16_ccitt_false_update(crc, buf, len);
}

/**
* @brief Calculate CRC16-CCITT-AUG
*
* Parameter | Value
* --------: | :----
* Polynom | `0x1021`
* Init | `0x1d0f`
* Refin | `false`
* Refout | `false`
* Xorout | `0x0000`
* Check | `0xe5cc`
*
* @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_aug_calc(const unsigned char *buf, size_t len);

/**
* @brief Update CRC16-CCITT
* @deprecated Use @ref crc16_ccitt_aug_update instead.
* Will be removed after 2023.01 release.
*
* @param[in] crc A start value for the CRC calculation, usually the
* return value of a previous call to
Expand All @@ -49,17 +191,25 @@ extern "C" {
* @return Checksum of the specified memory area based on the
* given start value
*/
uint16_t crc16_ccitt_update(uint16_t crc, const unsigned char *buf, size_t len);
static inline uint16_t crc16_ccitt_update(uint16_t crc, const unsigned char *buf, size_t len)
{
return crc16_ccitt_false_update(crc, buf, len);
}

/**
* @brief Calculate CRC16-CCITT
* @deprecated Use @ref crc16_ccitt_aug_calc instead.
* Will be removed after 2023.01 release.
*
* @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_calc(const unsigned char *buf, size_t len);
static inline uint16_t crc16_ccitt_calc(const unsigned char *buf, size_t len)
{
return crc16_ccitt_aug_calc(buf, len);
}

#ifdef __cplusplus
}
Expand Down
Loading