Skip to content

Commit

Permalink
lib: crc: Add CRC4
Browse files Browse the repository at this point in the history
Add two new functions: crc4 for generic calculations
of CRC4, and crc4_ti which use look-up table for
faster calculations of CRC4 algortihms that base
on 0x03 polynomial.

Signed-off-by: Michal Morsisko <[email protected]>
  • Loading branch information
morsisko authored and carlescufi committed Sep 26, 2023
1 parent d118ef5 commit 39aa2ad
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 0 deletions.
41 changes: 41 additions & 0 deletions include/zephyr/sys/crc.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ extern "C" {
* These values should be used with the @ref crc dispatch function.
*/
enum crc_type {
CRC4, /**< Use @ref crc4 */
CRC4_TI, /**< Use @ref crc4_ti */
CRC7_BE, /**< Use @ref crc7_be */
CRC8, /**< Use @ref crc8 */
CRC8_CCITT, /**< Use @ref crc8_ccitt */
Expand Down Expand Up @@ -278,6 +280,41 @@ uint8_t crc8_ccitt(uint8_t initial_value, const void *buf, size_t len);
*/
uint8_t crc7_be(uint8_t seed, const uint8_t *src, size_t len);

/**
* @brief Compute the CRC-4 checksum of a buffer.
*
* Used by the TMAG5170 sensor. Uses 0x03 as the
* polynomial with no reflection. 4 most significant
* bits of the CRC result will be set to zero.
*
* @param seed Value to seed the CRC with
* @param src Input bytes for the computation
* @param len Length of the input in bytes
*
* @return The computed CRC4 value
*/
uint8_t crc4_ti(uint8_t seed, const uint8_t *src, size_t len);

/**
* @brief Generic function for computing CRC 4
*
* Compute CRC 4 by passing in the address of the input, the input length
* and polynomial used in addition to the initial value. The input buffer
* must be aligned to a whole byte. It is guaranteed that 4 most significant
* bits of the result will be set to zero.
*
* @param src Input bytes for the computation
* @param len Length of the input in bytes
* @param polynomial The polynomial to use omitting the leading x^4
* coefficient
* @param initial_value Initial value for the CRC computation
* @param reversed Should we use reflected/reversed values or not
*
* @return The computed CRC4 value
*/
uint8_t crc4(const uint8_t *src, size_t len, uint8_t polynomial, uint8_t initial_value,
bool reversed);

/**
* @brief Compute a CRC checksum, in a generic way.
*
Expand Down Expand Up @@ -305,6 +342,10 @@ static inline uint32_t crc_by_type(enum crc_type type, const uint8_t *src, size_
bool last)
{
switch (type) {
case CRC4:
return crc4(src, len, poly, seed, reflect);
case CRC4_TI:
return crc4_ti(seed, src, len);
case CRC7_BE:
return crc7_be(seed, src, len);
case CRC8:
Expand Down
1 change: 1 addition & 0 deletions lib/crc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,6 @@ zephyr_sources_ifdef(CONFIG_CRC
crc16_sw.c
crc8_sw.c
crc7_sw.c
crc4_sw.c
)
zephyr_sources_ifdef(CONFIG_CRC_SHELL crc_shell.c)
53 changes: 53 additions & 0 deletions lib/crc/crc4_sw.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright (c) 2023 Michal Morsisko
*
* SPDX-License-Identifier: Apache-2.0
*/

#include <zephyr/sys/crc.h>

uint8_t crc4(const uint8_t *src, size_t len, uint8_t polynomial, uint8_t initial_value,
bool reversed)
{
uint8_t crc = initial_value;
size_t i, j, k;

for (i = 0; i < len; i++) {
for (j = 0; j < 2; j++) {
crc ^= ((src[i] >> (4 * (1 - j))) & 0xf);

for (k = 0; k < 4; k++) {
if (reversed) {
if (crc & 0x01) {
crc = (crc >> 1) ^ polynomial;
} else {
crc >>= 1;
}
} else {
if (crc & 0x8) {
crc = (crc << 1) ^ polynomial;
} else {
crc <<= 1;
}
}
}
}
}

return crc & 0xF;
}

uint8_t crc4_ti(uint8_t seed, const uint8_t *src, size_t len)
{
static const uint8_t lookup[8] = { 0x03, 0x65, 0xcf, 0xa9, 0xb8, 0xde, 0x74, 0x12 };
uint8_t index;

for (size_t i = 0; i < len; i++) {
for (size_t j = 0U; j < 2U; j++) {
index = seed ^ ((src[i] >> (4*(1-j))) & 0xf);
seed = (lookup[index >> 1] >> (1 - (index & 1)) * 4) & 0xf;
}
}

return seed;
}

0 comments on commit 39aa2ad

Please sign in to comment.