using System;
using System.Collections.Generic;
using System.Text;


namespace EnsembleAnalyzer
{
/// <summary>
/// Tool to calculate and add CRC codes to a string
///
/// ***************************************************************************
/// Copyright (c) 2003 Thoraxcentrum, Erasmus MC, The Netherlands.
///
/// Written by Marcel de Wijs with help from a lot of others,
/// especially Stefan Nelwan
///
/// This code is for free. I ported it from several different sources to C#.
///
/// For comments: Marcel_de_Wijs@hotmail.com
/// ***************************************************************************
/// </summary>
public class CRCTool
{
// 'order' [1..32] is the CRC polynom order, counted without the leading '1' bit
// 'polynom' is the CRC polynom without leading '1' bit
// 'direct' [0,1] specifies the kind of algorithm: 1=direct, no augmented zero bits
// 'crcinit' is the initial CRC value belonging to that algorithm
// 'crcxor' is the final XOR value
// 'refin' [0,1] specifies if a data byte is reflected before processing (UART) or not
// 'refout' [0,1] specifies if the CRC will be reflected before XOR
// Data character string
// For CRC-CCITT : order = 16, direct=1, poly=0x1021, CRCinit = 0xFFFF, crcxor=0; refin =0, refout=0
// For CRC-DAB-XPAD : order = 16, direct=1, poly=0x1021, CRCinit = 0xFFFF, crcxor=0xFFFF; refin =0, refout=0
// For CRC16:      order = 16, direct=1, poly=0x8005, CRCinit = 0x0, crcxor=0x0; refin =1, refout=1
// For CRC32:      order = 32, direct=1, poly=0x4c11db7, CRCinit = 0xFFFFFFFF, crcxor=0xFFFFFFFF; refin =1, refout=1
// Default : CRC-CCITT


private int order = 16;
private ulong polynom = 0x1021;
private int direct = 1;
private ulong crcinit = 0xFFFF;
private ulong crcxor = 0x0;
private int refin = 0;
private int refout = 0;


private ulong crcmask;
private ulong crchighbit;
private ulong crcinit_direct;
private ulong crcinit_nondirect;
private ulong[] crctab = new ulong[256];


// Enumeration used in the init function to specify which CRC algorithm to use
public enum CRCCode { CRC_CCITT, CRC16, CRC32, CRC_DAB };


public CRCTool()
{
//
// TODO: Add constructor logic here
//
}


public void Init(CRCCode CodingType)
{
switch (CodingType)
{
case CRCCode.CRC_CCITT:
order = 16; direct = 1; polynom = 0x1021; crcinit = 0xFFFF; crcxor = 0; refin = 0; refout = 0;
break;
case CRCCode.CRC16:
order = 16; direct = 1; polynom = 0x8005; crcinit = 0x0; crcxor = 0x0; refin = 1; refout = 1;
break;
case CRCCode.CRC32:
order = 32; direct = 1; polynom = 0x4c11db7; crcinit = 0xFFFFFFFF; crcxor = 0xFFFFFFFF; refin = 1; refout = 1;
break;
case CRCCode.CRC_DAB:
order = 16; direct = 1; polynom = 0x1021; crcinit = 0xFFFF; crcxor = 0xFFFF; refin = 0; refout = 0;
break;
}


// Initialize all variables for seeding and builing based upon the given coding type
// at first, compute constant bit masks for whole CRC and CRC high bit


crcmask = ((((ulong)1 << (order - 1)) - 1) << 1) | 1;
crchighbit = (ulong)1 << (order - 1);


// generate lookup table
generate_crc_table();


ulong bit, crc;
int i;
if (direct == 0)
{
crcinit_nondirect = crcinit;
crc = crcinit;
for (i = 0; i < order; i++)
{
bit = crc & crchighbit;
crc <<= 1;
if (bit != 0)
{
crc ^= polynom;
}
}
crc &= crcmask;
crcinit_direct = crc;
}
else
{
crcinit_direct = crcinit;
crc = crcinit;
for (i = 0; i < order; i++)
{
bit = crc & 1;
if (bit != 0)
{
crc ^= polynom;
}
crc >>= 1;
if (bit != 0)
{
crc |= crchighbit;
}
}
crcinit_nondirect = crc;
}
}



/// <summary>
/// 4 ways to calculate the crc checksum. If you have to do a lot of encoding
/// you should use the table functions. Since they use precalculated values, which
/// saves some calculating.
/// </summary>.
public ulong crctablefast(byte[] p)
{
return crctablefast(p, 0, p.Length);
}


/// <summary>
/// 4 ways to calculate the crc checksum. If you have to do a lot of encoding
/// you should use the table functions. Since they use precalculated values, which
/// saves some calculating.
/// </summary>.
public ulong crctablefast(byte[] p, int start, int count)
{
// fast lookup table algorithm without augmented zero bytes, e.g. used in pkzip.
// only usable with polynom orders of 8, 16, 24 or 32.
ulong crc = crcinit_direct;
if (refin != 0)
{
crc = reflect(crc, order);
}
if (refin == 0)
{
for (int i = start; i < start + count; i++)
{
crc = (crc << 8) ^ crctab[((crc >> (order - 8)) & 0xff) ^ p];
}
}
else
{
for (int i = start; i < start + count; i++)
{
crc = (crc >> 8) ^ crctab[(crc & 0xff) ^ p];
}
}
if ((refout ^ refin) != 0)
{
crc = reflect(crc, order);
}
crc ^= crcxor;
crc &= crcmask;
return (crc);
}


public ulong crctable(byte[] p)
{
// normal lookup table algorithm with augmented zero bytes.
// only usable with polynom orders of 8, 16, 24 or 32.
ulong crc = crcinit_nondirect;
if (refin != 0)
{
crc = reflect(crc, order);
}
if (refin == 0)
{
for (int i = 0; i < p.Length; i++)
{
crc = ((crc << 8) | p) ^ crctab[(crc >> (order - 8)) & 0xff];
}
}
else
{
for (int i = 0; i < p.Length; i++)
{
crc = (ulong)(((int)(crc >> 8) | (p << (order - 8))) ^ (int)crctab[crc & 0xff]);
}
}
if (refin == 0)
{
for (int i = 0; i < order / 8; i++)
{
crc = (crc << 8) ^ crctab[(crc >> (order - 8)) & 0xff];
}
}
else
{
for (int i = 0; i < order / 8; i++)
{
crc = (crc >> 8) ^ crctab[crc & 0xff];
}
}


if ((refout ^ refin) != 0)
{
crc = reflect(crc, order);
}
crc ^= crcxor;
crc &= crcmask;


return (crc);
}


public ulong crcbitbybit(byte[] p)
{
// bit by bit algorithm with augmented zero bytes.
// does not use lookup table, suited for polynom orders between 1...32.
int i;
ulong j, c, bit;
ulong crc = crcinit_nondirect;


for (i = 0; i < p.Length; i++)
{
c = (ulong)p;
if (refin != 0)
{
c = reflect(c, 8);
}


for (j = 0x80; j != 0; j >>= 1)
{
bit = crc & crchighbit;
crc <<= 1;
if ((c & j) != 0)
{
crc |= 1;
}
if (bit != 0)
{
crc ^= polynom;
}
}
}


for (i = 0; (int)i < order; i++)
{


bit = crc & crchighbit;
crc <<= 1;
if (bit != 0) crc ^= polynom;
}


if (refout != 0)
{
crc = reflect(crc, order);
}
crc ^= crcxor;
crc &= crcmask;


return (crc);
}


public ulong crcbitbybitfast(byte[] p)
{
// fast bit by bit algorithm without augmented zero bytes.
// does not use lookup table, suited for polynom orders between 1...32.
int i;
ulong j, c, bit;
ulong crc = crcinit_direct;


for (i = 0; i < p.Length; i++)
{
c = (ulong)p;
if (refin != 0)
{
c = reflect(c, 8);
}


for (j = 0x80; j > 0; j >>= 1)
{
bit = crc & crchighbit;
crc <<= 1;
if ((c & j) > 0) bit ^= crchighbit;
if (bit > 0) crc ^= polynom;
}
}


if (refout > 0)
{
crc = reflect(crc, order);
}
crc ^= crcxor;
crc &= crcmask;


return (crc);
}



/// <summary>
/// CalcCRCITT is an algorithm found on the web for calculating the CRCITT checksum
/// It is included to demonstrate that although it looks different it is the same
/// routine as the crcbitbybit* functions. But it is optimized and preconfigured for CRCITT.
/// </summary>
public ushort CalcCRCITT(byte[] p)
{
uint uiCRCITTSum = 0xFFFF;
uint uiByteValue;


for (int iBufferIndex = 0; iBufferIndex < p.Length; iBufferIndex++)
{
uiByteValue = ((uint)p[iBufferIndex] << 8);
for (int iBitIndex = 0; iBitIndex < 8; iBitIndex++)
{
if (((uiCRCITTSum ^ uiByteValue) & 0x8000) != 0)
{
uiCRCITTSum = (uiCRCITTSum << 1) ^ 0x1021;
}
else
{
uiCRCITTSum <<= 1;
}
uiByteValue <<= 1;
}
}
return (ushort)uiCRCITTSum;
}



#region subroutines
private ulong reflect(ulong crc, int bitnum)
{


// reflects the lower 'bitnum' bits of 'crc'


ulong i, j = 1, crcout = 0;


for (i = (ulong)1 << (bitnum - 1); i != 0; i >>= 1)
{
if ((crc & i) != 0)
{
crcout |= j;
}
j <<= 1;
}
return (crcout);
}


private void generate_crc_table()
{


// make CRC lookup table used by table algorithms


int i, j;
ulong bit, crc;


for (i = 0; i < 256; i++)
{
crc = (ulong)i;
if (refin != 0)
{
crc = reflect(crc, 8);
}
crc <<= order - 8;


for (j = 0; j < 8; j++)
{
bit = crc & crchighbit;
crc <<= 1;
if (bit != 0) crc ^= polynom;
}


if (refin != 0)
{
crc = reflect(crc, order);
}
crc &= crcmask;
crctab = crc;
}
}
#endregion
}
}

selected crc is 16.

Edited 3 Years Ago by happygeek: fixed formatting

if you mean how to test the crc check is right, download some other crc checkers thats supposed to use the same methodology, and see if you get the same answer

This article has been dead for over six months. Start a new discussion instead.