/*
 * ul_crc.h
 *
 *  Created on: Sep 11, 2011
 *      Author: qwer1
 */

#ifndef UL_CRC_H_
#define UL_CRC_H_

#include "ul_other.h"

// CRC-----------------------------------------------------------------------------------------------------------

// CRC8 Dallas (021cb801000000a2=0x00)
#define CRC8_DS_INIT 0x00
#define inc_crc8_ds_upd(data, crc_prev) { \
    data ^= crc_prev; \
    crc_prev = 0; \
    if(data & 0x01) crc_prev = 0x5e; \
    if(data & 0x02) crc_prev ^= 0xbc; \
    if(data & 0x04) crc_prev ^= 0x61; \
    if(data & 0x08) crc_prev ^= 0xc2; \
    if(data & 0x10) crc_prev ^= 0x9d; \
    if(data & 0x20) crc_prev ^= 0x23; \
    if(data & 0x40) crc_prev ^= 0x46; \
    if(data & 0x80) crc_prev ^= 0x8c; \
}
U8  crc8_ds_upd(U8 data, U8 crc_prev);
U16 crc8_ds_buf(U8 *buf, U16 buf_size, U8 crc_prev);

// CRC16 Dallas (data=0x75, crc_in=0x90f1, crc_out=0x6390)
#define CRC16_DS_INIT 0x0000
#define CRC16_DS_POLY 0x4002
#define inc_crc16_ds_upd(data, crc_prev) { \
    for (U8 cnt_bits = 8; cnt_bits; cnt_bits--) { \
        U8 flag_xor = (data ^ (U8) crc_prev) & 1; \
        if (flag_xor) { \
            crc_prev ^= CRC16_DS_POLY; \
            crc_prev >>= 1; \
            crc_prev |= 0x8000; \
        } else crc_prev >>= 1; \
        data >>= 1; \
    } \
}
U16 crc16_ds_upd(U8 data, U16 crc_prev);
U16 crc16_ds_buf(U8 *buf, U16 buf_size, U16 crc_prev);


// CRC16 Modbus (0401000a000d=0x98dd; 0401020a11=0x50b3; 0402000a000d=0x9899;)
#define CRC16_MODBUS_INIT 0xffff
#define CRC16_MODBUS_POLY 0xa001
#define inc_crc16_modbus_upd(data, crc_prev) { \
    crc_prev ^= data; \
    for (U8 cnt_bits = 8; cnt_bits; cnt_bits--) { \
        U8 flag_xor = crc_prev & 1; \
        crc_prev >>= 1; \
        if (flag_xor) crc_prev ^= CRC16_MODBUS_POLY; \
    } \
}
U16 crc16_modbus_upd(U8 data, U16 crc_prev);
U16 crc16_modbus_buf(U8 *buf, U16 buf_size, U16 crc_prev);


// CRC16 CCIT (''=0x1D0F; 'A'=0x9479; '123456789'=0xE5CC;)
#define CRC16_CCIT_INIT 0xffff
#define CRC16_CCIT_POLY 0x1021
#define inc_crc16_ccit_upd(data, crc_prev) { \
    for (U8 cnt_bits = 8; cnt_bits; cnt_bits--) { \
        U8 flag_xor = (crc_prev >> 8) & 0x80; \
        crc_prev <<= 1; \
        if (data & 0x80) crc_prev |= 1; \
        if (flag_xor) crc_prev ^= CRC16_CCIT_POLY; \
        data <<= 1; \
    } \
}
U16 crc16_ccit_upd(U8 data, U16 crc_prev);
#define inc_crc16_ccit_augment(crc_prev) { \
    for (U8 cnt_bits = 16; cnt_bits; cnt_bits--) { \
        U8 flag_xor = (crc_prev >> 8) & 0x80; \
        crc_prev <<= 1; \
        if (flag_xor) crc_prev ^= CRC16_CCIT_POLY; \
    } \
}
U16 crc16_ccit_augment(U16 crc_prev);
U16 crc16_ccit_buf(U8 *buf, U16 buf_size, U16 crc_prev);


// CRC7 MMC (4000000000=4a)
#define CRC7_MMC_INIT  0
#define CRC7_MMC_POLY  0x09
#define inc_crc7_mmc_upd(data, crc_prev) { \
    for (U8 cnt_bits = 8; cnt_bits; cnt_bits--) { \
        crc_prev <<= 1; \
        if (((crc_prev & 0x80)) ^ ((data & 0x80))) crc_prev ^= CRC7_MMC_POLY; \
        data <<= 1; \
    } \
}
U8 crc7_mmc_upd(U8 data, U8 crc_prev);
U16 crc7_mmc_buf(U8 *buf, U16 buf_size, U8 crc_prev);


// CRC16 MMC (sort of CRC16 CCIT) ('123456789'=31c3, 'A'=58e5)
#define CRC16_MMC_INIT 0
#define CRC16_MMC_POLY 0x1021
#define inc_crc16_mmc_upd(data, crc_prev) { \
    for (U8 cnt_bits = 8; cnt_bits; cnt_bits--) { \
        U8 flag_xor = ((crc_prev >> 8) & 0x80) ^ (data & 0x80); \
        data <<= 1; \
        crc_prev <<= 1; \
        if (flag_xor) crc_prev ^= CRC16_MMC_POLY; \
    } \
 }
U16 crc16_mmc_upd(U8 data, U16 crc_prev);
U16 crc16_mmc_buf(U8 *buf, U16 buf_size, U16 crc_prev);

#endif /* UL_CRC_H_ */
