/** *! * \file algo_crc.c * \version v0.0.1 * \date 2020/05/13 * \author Bean(notrynohigh@outlook.com) ******************************************************************************* * @attention * * Copyright (c) 2020 Bean * * 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. ******************************************************************************* */ /*Includes ----------------------------------------------*/ #include "inc/algo_crc.h" #if (defined(_ALGO_CRC_ENABLE) && (_ALGO_CRC_ENABLE == 1)) /** * \addtogroup ALGORITHM * \{ */ /** * \addtogroup CRC * \{ */ /** * \defgroup CRC_Private_TypesDefinitions * \{ */ /** * \} */ /** * \defgroup CRC_Private_Defines * \{ */ /** * \} */ /** * \defgroup CRC_Private_Macros * \{ */ /** * \} */ /** * \defgroup CRC_Private_Variables * \{ */ /** * \} */ /** * \defgroup CRC_Private_Functions * \{ */ #if (defined(_ALGO_CRC8_ENABLE) && (_ALGO_CRC8_ENABLE == 1)) /* * Name: CRC-8 x8+x2+x+1 * Initial value 0x00 */ uint8_t crc8_d(uint8_t crc_8, uint8_t *data, uint32_t length, uint8_t flag) { uint8_t i; uint8_t crc = crc_8; // Initial value (void)flag; while (length--) { crc ^= *data++; // crc ^= *data; data++; for (i = 0; i < 8; i++) { if (crc & 0x80) crc = (crc << 1) ^ 0x07; else crc <<= 1; } } return crc; } #endif #if (defined(_ALGO_CRC8_ITU_ENABLE) && (_ALGO_CRC8_ITU_ENABLE == 1)) /****************************************************************************** * Name: CRC-8/ITU x8+x2+x+1 * Initial value 0x00 *****************************************************************************/ uint8_t crc8_itu(uint8_t crc_8, uint8_t *data, uint32_t length, uint8_t flag) { uint8_t i; uint8_t crc = crc_8; // Initial value if (flag) { crc = crc ^ 0x55; } while (length--) { crc ^= *data++; // crc ^= *data; data++; for (i = 0; i < 8; i++) { if (crc & 0x80) crc = (crc << 1) ^ 0x07; else crc <<= 1; } } return crc ^ 0x55; } #endif #if (defined(_ALGO_CRC8_ROHC_ENABLE) && (_ALGO_CRC8_ROHC_ENABLE == 1)) /* * Name: CRC-8/ROHC x8+x2+x+1 * Initial value 0xff */ uint8_t crc8_rohc(uint8_t crc_8, uint8_t *data, uint32_t length, uint8_t flag) { uint8_t i; uint8_t crc = crc_8; // Initial value (void)flag; while (length--) { crc ^= *data++; // crc ^= *data; data++; for (i = 0; i < 8; ++i) { if (crc & 1) crc = (crc >> 1) ^ 0xE0; // 0xE0 = reverse 0x07 else crc = (crc >> 1); } } return crc; } #endif #if (defined(_ALGO_CRC8_MAXIM_ENABLE) && (_ALGO_CRC8_MAXIM_ENABLE == 1)) /****************************************************************************** * Name: CRC-8/MAXIM x8+x5+x4+1 * Initial value 0x00 *****************************************************************************/ uint8_t crc8_maxim(uint8_t crc_8, uint8_t *data, uint32_t length, uint8_t flag) { uint8_t i; uint8_t crc = crc_8; // Initial value (void)flag; while (length--) { crc ^= *data++; // crc ^= *data; data++; for (i = 0; i < 8; i++) { if (crc & 1) crc = (crc >> 1) ^ 0x8C; // 0x8C = reverse 0x31 else crc >>= 1; } } return crc; } #endif #if (defined(_ALGO_CRC16_IBM_ENABLE) && (_ALGO_CRC16_IBM_ENABLE == 1)) /****************************************************************************** * Name: CRC-16/IBM x16+x15+x2+1 * Initial value 0x00 ****************************************************************************/ uint16_t crc16_ibm(uint16_t crc_16, uint8_t *data, uint32_t length, uint8_t flag) { uint8_t i; uint16_t crc = crc_16; // Initial value (void)flag; while (length--) { crc ^= *data++; // crc ^= *data; data++; for (i = 0; i < 8; ++i) { if (crc & 1) crc = (crc >> 1) ^ 0xA001; // 0xA001 = reverse 0x8005 else crc = (crc >> 1); } } return crc; } #endif #if (defined(_ALGO_CRC16_MAXIM_ENABLE) && (_ALGO_CRC16_MAXIM_ENABLE == 1)) /****************************************************************************** * Name: CRC-16/MAXIM x16+x15+x2+1 * Initial value 0x00 *****************************************************************************/ uint16_t crc16_maxim(uint16_t crc_16, uint8_t *data, uint32_t length, uint8_t flag) { uint8_t i; uint16_t crc = crc_16; // Initial value if (flag) { crc = ~crc; } while (length--) { crc ^= *data++; // crc ^= *data; data++; for (i = 0; i < 8; ++i) { if (crc & 1) crc = (crc >> 1) ^ 0xA001; // 0xA001 = reverse 0x8005 else crc = (crc >> 1); } } return ~crc; // crc^0xffff } #endif #if (defined(_ALGO_CRC16_USB_ENABLE) && (_ALGO_CRC16_USB_ENABLE == 1)) /****************************************************************************** * Name: CRC-16/USB x16+x15+x2+1 * Initial value 0xffff *****************************************************************************/ uint16_t crc16_usb(uint16_t crc_16, uint8_t *data, uint32_t length, uint8_t flag) { uint8_t i; uint16_t crc = crc_16; // Initial value if (flag) { crc = ~crc; } while (length--) { crc ^= *data++; // crc ^= *data; data++; for (i = 0; i < 8; ++i) { if (crc & 1) crc = (crc >> 1) ^ 0xA001; // 0xA001 = reverse 0x8005 else crc = (crc >> 1); } } return ~crc; // crc^0xffff } #endif #if (defined(_ALGO_CRC16_MODBUS_ENABLE) && (_ALGO_CRC16_MODBUS_ENABLE == 1)) /****************************************************************************** * Name: CRC-16/MODBUS x16+x15+x2+1 * Initial value 0xffff *****************************************************************************/ uint16_t crc16_modbus(uint16_t crc_16, uint8_t *data, uint32_t length, uint8_t flag) { uint8_t i; uint16_t crc = crc_16; // Initial value (void)flag; while (length--) { crc ^= *data++; // crc ^= *data; data++; for (i = 0; i < 8; ++i) { if (crc & 1) crc = (crc >> 1) ^ 0xA001; // 0xA001 = reverse 0x8005 else crc = (crc >> 1); } } return crc; } #endif #if (defined(_ALGO_CRC16_CCITT_ENABLE) && (_ALGO_CRC16_CCITT_ENABLE == 1)) /****************************************************************************** * Name: CRC-16/CCITT x16+x12+x5+1 * Initial value 0x00 *****************************************************************************/ uint16_t crc16_ccitt(uint16_t crc_16, uint8_t *data, uint32_t length, uint8_t flag) { uint8_t i; uint16_t crc = crc_16; // Initial value (void)flag; while (length--) { crc ^= *data++; // crc ^= *data; data++; for (i = 0; i < 8; ++i) { if (crc & 1) crc = (crc >> 1) ^ 0x8408; // 0x8408 = reverse 0x1021 else crc = (crc >> 1); } } return crc; } #endif #if (defined(_ALGO_CRC16_CCITT_FALSE_ENABLE) && (_ALGO_CRC16_CCITT_FALSE_ENABLE == 1)) /****************************************************************************** * Name: CRC-16/CCITT-FALSE x16+x12+x5+1 * Initial value 0xffff *****************************************************************************/ uint16_t crc16_ccitt_false(uint16_t crc_16, uint8_t *data, uint32_t length, uint8_t flag) { uint8_t i; uint16_t crc = crc_16; // Initial value (void)flag; while (length--) { crc ^= (uint16_t)(*data++) << 8; // crc ^= (uint6_t)(*data)<<8; data++; for (i = 0; i < 8; ++i) { if (crc & 0x8000) crc = (crc << 1) ^ 0x1021; else crc <<= 1; } } return crc; } #endif #if (defined(_ALGO_CRC16_X25_ENABLE) && (_ALGO_CRC16_X25_ENABLE == 1)) /****************************************************************************** * Name: CRC-16/X25 x16+x12+x5+1 * Initial value 0xffff *****************************************************************************/ uint16_t crc16_x25(uint16_t crc_16, uint8_t *data, uint32_t length, uint8_t flag) { uint8_t i; uint16_t crc = crc_16; // Initial value if (flag) { crc = ~crc; } while (length--) { crc ^= *data++; // crc ^= *data; data++; for (i = 0; i < 8; ++i) { if (crc & 1) crc = (crc >> 1) ^ 0x8408; // 0x8408 = reverse 0x1021 else crc = (crc >> 1); } } return ~crc; // crc^Xorout } #endif #if (defined(_ALGO_CRC16_XMODEM_ENABLE) && (_ALGO_CRC16_XMODEM_ENABLE == 1)) /****************************************************************************** * Name: CRC-16/XMODEM x16+x12+x5+1 * Initial value 0x00 *****************************************************************************/ uint16_t crc16_xmodem(uint16_t crc_16, uint8_t *data, uint32_t length, uint8_t flag) { uint8_t i; uint16_t crc = crc_16; // Initial value (void)flag; while (length--) { crc ^= (uint16_t)(*data++) << 8; // crc ^= (uint16_t)(*data)<<8; data++; for (i = 0; i < 8; ++i) { if (crc & 0x8000) crc = (crc << 1) ^ 0x1021; else crc <<= 1; } } return crc; } #endif #if (defined(_ALGO_CRC16_DNP_ENABLE) && (_ALGO_CRC16_DNP_ENABLE == 1)) /****************************************************************************** * Name: CRC-16/DNP x16+x13+x12+x11+x10+x8+x6+x5+x2+1 * Initial value 0x00 *****************************************************************************/ uint16_t crc16_dnp(uint16_t crc_16, uint8_t *data, uint32_t length, uint8_t flag) { uint8_t i; uint16_t crc = crc_16; // Initial value if (flag) { crc = ~crc; } while (length--) { crc ^= *data++; // crc ^= *data; data++; for (i = 0; i < 8; ++i) { if (crc & 1) crc = (crc >> 1) ^ 0xA6BC; // 0xA6BC = reverse 0x3D65 else crc = (crc >> 1); } } return ~crc; // crc^Xorout } #endif #if (defined(_ALGO_CRC32_ENABLE) && (_ALGO_CRC32_ENABLE == 1)) /****************************************************************************** * Name: CRC-32 x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1 * Initial value 0xffffffff *****************************************************************************/ uint32_t crc32_d(uint32_t crc_32, uint8_t *data, uint32_t length, uint8_t flag) { uint8_t i; uint32_t crc = crc_32; // Initial value if (flag) { crc = ~crc; } while (length--) { crc ^= *data++; // crc ^= *data; data++; for (i = 0; i < 8; ++i) { if (crc & 1) crc = (crc >> 1) ^ 0xEDB88320; // 0xEDB88320= reverse 0x04C11DB7 else crc = (crc >> 1); } } return ~crc; } #endif #if (defined(_ALGO_CRC32_MPEG2_ENABLE) && (_ALGO_CRC32_MPEG2_ENABLE == 1)) /****************************************************************************** * Name: CRC-32/MPEG-2 x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1 * Initial value 0xffffffff *****************************************************************************/ uint32_t crc32_mpeg_2(uint32_t crc_32, uint8_t *data, uint32_t length, uint8_t flag) { uint8_t i; uint32_t crc = crc_32; // Initial value (void)flag; while (length--) { crc ^= (uint32_t)(*data++) << 24; // crc ^=(uint32_t)(*data)<<24; data++; for (i = 0; i < 8; ++i) { if (crc & 0x80000000) crc = (crc << 1) ^ 0x04C11DB7; else crc <<= 1; } } return crc; } #endif /** * \} */ /** * \addtogroup CRC_Exported_Functions * \{ */ /** #define ALGO_CRC8 (0) // Initial value 0x00 #define ALGO_CRC8_ITU (1) // Initial value 0x00 #define ALGO_CRC8_ROHC (2) // Initial value 0xff #define ALGO_CRC8_MAXIM (3) // Initial value 0x00 #define ALGO_CRC16_IBM (4) // Initial value 0x00 #define ALGO_CRC16_MAXIM (5) // Initial value 0x00 #define ALGO_CRC16_USB (6) // Initial value 0xffff #define ALGO_CRC16_MODBUS (7) // Initial value 0xffff #define ALGO_CRC16_CCITT (8) // Initial value 0x00 #define ALGO_CRC16_CCITT_FALSE (9) // Initial value 0xffff #define ALGO_CRC16_X25 (10) // Initial value 0xffff #define ALGO_CRC16_XMODEM (11) // Initial value 0x00 #define ALGO_CRC16_DNP (12) // Initial value 0x00 #define ALGO_CRC32 (13) // Initial value 0xffffffff #define ALGO_CRC32_MPEG2 (14) // Initial value 0xffffffff */ uint32_t crc_calculate(uint8_t type, uint8_t *pbuf, uint32_t len) { uint32_t retval = 0; uint32_t crc_val = 0; if (pbuf == NULL || len == 0) { return 0; } if (CRC_INITIAL_VALUE_IS_FF(type)) { crc_val = 0xffffffff; } switch (type) { #if (defined(_ALGO_CRC8_ENABLE) && (_ALGO_CRC8_ENABLE == 1)) case ALGO_CRC8: { retval = crc8_d(crc_val & 0xff, pbuf, len, 0); } break; #endif #if (defined(_ALGO_CRC8_ITU_ENABLE) && (_ALGO_CRC8_ITU_ENABLE == 1)) case ALGO_CRC8_ITU: { retval = crc8_itu(crc_val & 0xff, pbuf, len, 0); } break; #endif #if (defined(_ALGO_CRC8_ROHC_ENABLE) && (_ALGO_CRC8_ROHC_ENABLE == 1)) case ALGO_CRC8_ROHC: { retval = crc8_rohc(crc_val & 0xff, pbuf, len, 0); } break; #endif #if (defined(_ALGO_CRC8_MAXIM_ENABLE) && (_ALGO_CRC8_MAXIM_ENABLE == 1)) case ALGO_CRC8_MAXIM: { retval = crc8_maxim(crc_val & 0xff, pbuf, len, 0); } break; #endif #if (defined(_ALGO_CRC16_IBM_ENABLE) && (_ALGO_CRC16_IBM_ENABLE == 1)) case ALGO_CRC16_IBM: { retval = crc16_ibm(crc_val & 0xffff, pbuf, len, 0); } break; #endif #if (defined(_ALGO_CRC16_MAXIM_ENABLE) && (_ALGO_CRC16_MAXIM_ENABLE == 1)) case ALGO_CRC16_MAXIM: { retval = crc16_maxim(crc_val & 0xffff, pbuf, len, 0); } break; #endif #if (defined(_ALGO_CRC16_USB_ENABLE) && (_ALGO_CRC16_USB_ENABLE == 1)) case ALGO_CRC16_USB: { retval = crc16_usb(crc_val & 0xffff, pbuf, len, 0); } break; #endif #if (defined(_ALGO_CRC16_MODBUS_ENABLE) && (_ALGO_CRC16_MODBUS_ENABLE == 1)) case ALGO_CRC16_MODBUS: { retval = crc16_modbus(crc_val & 0xffff, pbuf, len, 0); } break; #endif #if (defined(_ALGO_CRC16_CCITT_ENABLE) && (_ALGO_CRC16_CCITT_ENABLE == 1)) case ALGO_CRC16_CCITT: { retval = crc16_ccitt(crc_val & 0xffff, pbuf, len, 0); } break; #endif #if (defined(_ALGO_CRC16_CCITT_FALSE_ENABLE) && (_ALGO_CRC16_CCITT_FALSE_ENABLE == 1)) case ALGO_CRC16_CCITT_FALSE: { retval = crc16_ccitt_false(crc_val & 0xffff, pbuf, len, 0); } break; #endif #if (defined(_ALGO_CRC16_X25_ENABLE) && (_ALGO_CRC16_X25_ENABLE == 1)) case ALGO_CRC16_X25: { retval = crc16_x25(crc_val & 0xffff, pbuf, len, 0); } break; #endif #if (defined(_ALGO_CRC16_XMODEM_ENABLE) && (_ALGO_CRC16_XMODEM_ENABLE == 1)) case ALGO_CRC16_XMODEM: { retval = crc16_xmodem(crc_val & 0xffff, pbuf, len, 0); } break; #endif #if (defined(_ALGO_CRC16_DNP_ENABLE) && (_ALGO_CRC16_DNP_ENABLE == 1)) case ALGO_CRC16_DNP: { retval = crc16_dnp(crc_val & 0xffff, pbuf, len, 0); } break; #endif #if (defined(_ALGO_CRC32_ENABLE) && (_ALGO_CRC32_ENABLE == 1)) case ALGO_CRC32: { retval = crc32_d(crc_val, pbuf, len, 0); } break; #endif #if (defined(_ALGO_CRC32_MPEG2_ENABLE) && (_ALGO_CRC32_MPEG2_ENABLE == 1)) case ALGO_CRC32_MPEG2: { retval = crc32_mpeg_2(crc_val, pbuf, len, 0); } break; #endif default: break; } return retval; } void crc_calculate_sbs(algo_crc_sbs_t *phandle, uint8_t *pbuf, uint32_t len) { uint32_t crc_val = 0, retval = 0; uint8_t flag = 0; if (phandle == NULL || pbuf == NULL || len == 0) { return; } flag = (phandle->flag != 0); if (flag) { crc_val = phandle->crc; } else { if (CRC_INITIAL_VALUE_IS_FF(phandle->type)) { crc_val = 0xffffffff; } phandle->flag = 1; } switch (phandle->type) { #if (defined(_ALGO_CRC8_ENABLE) && (_ALGO_CRC8_ENABLE == 1)) case ALGO_CRC8: { retval = crc8_d(crc_val & 0xff, pbuf, len, flag); } break; #endif #if (defined(_ALGO_CRC8_ITU_ENABLE) && (_ALGO_CRC8_ITU_ENABLE == 1)) case ALGO_CRC8_ITU: { retval = crc8_itu(crc_val & 0xff, pbuf, len, flag); } break; #endif #if (defined(_ALGO_CRC8_ROHC_ENABLE) && (_ALGO_CRC8_ROHC_ENABLE == 1)) case ALGO_CRC8_ROHC: { retval = crc8_rohc(crc_val & 0xff, pbuf, len, flag); } break; #endif #if (defined(_ALGO_CRC8_MAXIM_ENABLE) && (_ALGO_CRC8_MAXIM_ENABLE == 1)) case ALGO_CRC8_MAXIM: { retval = crc8_maxim(crc_val & 0xff, pbuf, len, flag); } break; #endif #if (defined(_ALGO_CRC16_IBM_ENABLE) && (_ALGO_CRC16_IBM_ENABLE == 1)) case ALGO_CRC16_IBM: { retval = crc16_ibm(crc_val & 0xffff, pbuf, len, flag); } break; #endif #if (defined(_ALGO_CRC16_MAXIM_ENABLE) && (_ALGO_CRC16_MAXIM_ENABLE == 1)) case ALGO_CRC16_MAXIM: { retval = crc16_maxim(crc_val & 0xffff, pbuf, len, flag); } break; #endif #if (defined(_ALGO_CRC16_USB_ENABLE) && (_ALGO_CRC16_USB_ENABLE == 1)) case ALGO_CRC16_USB: { retval = crc16_usb(crc_val & 0xffff, pbuf, len, flag); } break; #endif #if (defined(_ALGO_CRC16_MODBUS_ENABLE) && (_ALGO_CRC16_MODBUS_ENABLE == 1)) case ALGO_CRC16_MODBUS: { retval = crc16_modbus(crc_val & 0xffff, pbuf, len, flag); } break; #endif #if (defined(_ALGO_CRC16_CCITT_ENABLE) && (_ALGO_CRC16_CCITT_ENABLE == 1)) case ALGO_CRC16_CCITT: { retval = crc16_ccitt(crc_val & 0xffff, pbuf, len, flag); } break; #endif #if (defined(_ALGO_CRC16_CCITT_FALSE_ENABLE) && (_ALGO_CRC16_CCITT_FALSE_ENABLE == 1)) case ALGO_CRC16_CCITT_FALSE: { retval = crc16_ccitt_false(crc_val & 0xffff, pbuf, len, flag); } break; #endif #if (defined(_ALGO_CRC16_X25_ENABLE) && (_ALGO_CRC16_X25_ENABLE == 1)) case ALGO_CRC16_X25: { retval = crc16_x25(crc_val & 0xffff, pbuf, len, flag); } break; #endif #if (defined(_ALGO_CRC16_XMODEM_ENABLE) && (_ALGO_CRC16_XMODEM_ENABLE == 1)) case ALGO_CRC16_XMODEM: { retval = crc16_xmodem(crc_val & 0xffff, pbuf, len, flag); } break; #endif #if (defined(_ALGO_CRC16_DNP_ENABLE) && (_ALGO_CRC16_DNP_ENABLE == 1)) case ALGO_CRC16_DNP: { retval = crc16_dnp(crc_val & 0xffff, pbuf, len, flag); } break; #endif #if (defined(_ALGO_CRC32_ENABLE) && (_ALGO_CRC32_ENABLE == 1)) case ALGO_CRC32: { retval = crc32_d(crc_val, pbuf, len, flag); } break; #endif #if (defined(_ALGO_CRC32_MPEG2_ENABLE) && (_ALGO_CRC32_MPEG2_ENABLE == 1)) case ALGO_CRC32_MPEG2: { retval = crc32_mpeg_2(crc_val, pbuf, len, flag); } break; #endif default: { retval = crc_val; } break; } phandle->crc = retval; } /** * \} */ /** * \} */ /** * \} */ #endif /************************ Copyright (c) 2020 Bean *****END OF FILE****/