using System; using System.Collections.Generic; using System.Text; namespace myCRC { public enum CRCMethod { CRC16, CRC16Kermit, CRC16DNP, CRC16CCITT, CRC32 }; public enum DataType { TEXT, HEX }; class MyCRC { private uint[] crctab = new uint[256]; public Encoding Encoding = Encoding.Default; public string CalcCRC(string data, DataType datatype, CRCMethod methodCRC, string Polynomial, string crcinit, bool revert) { ushort CRC16 = 0; uint CRC32 = 0; byte Q; ushort HI_, LO_; CrTabl(methodCRC, Convert.ToUInt32(Polynomial, 16)); if (methodCRC == CRCMethod.CRC32) CRC32 = Convert.ToUInt32(crcinit, 16); else CRC16 = Convert.ToUInt16(crcinit, 16); if (data.Length > 0) { if (datatype == DataType.TEXT) { foreach (byte b in this.Encoding.GetBytes(data)) { switch (methodCRC) { case CRCMethod.CRC16: case CRCMethod.CRC16Kermit: case CRCMethod.CRC16DNP: CRC16 = (ushort)(HI(CRC16) ^ Lo(crctab[b ^ LO(CRC16)])); break; case CRCMethod.CRC16CCITT: CRC16 = (ushort)((CRC16 << 8) ^ Lo(crctab[b ^ (CRC16 >> 8)])); break; case CRCMethod.CRC32: CRC32 = (uint)((CRC32 >> 8) ^ crctab[b ^ (CRC32 & 0x000000FF)]); break; } } } else { for (int i = 0; i < data.Length; i += 2) { Q = Hex2Byte(data.Substring(i, 2)); switch (methodCRC) { case CRCMethod.CRC16: case CRCMethod.CRC16Kermit: case CRCMethod.CRC16DNP: CRC16 = (ushort)(HI(CRC16) ^ Lo(crctab[Q ^ LO(CRC16)])); break; case CRCMethod.CRC16CCITT: CRC16 = (ushort)((CRC16 << 8) ^ Lo(crctab[Q ^ (CRC16 >> 8)])); break; case CRCMethod.CRC32: CRC32 = (uint)((CRC32 >> 8) ^ crctab[Q ^ (CRC32 & 0x000000FF)]); break; } } } } switch (methodCRC) { case CRCMethod.CRC16: case CRCMethod.CRC16CCITT: break; case CRCMethod.CRC16Kermit: LO_ = (ushort)((CRC16 & 0xff00) >> 8); HI_ = (ushort)((CRC16 & 0x00ff) << 8); CRC16 = (ushort)(LO_ | HI_); break; case CRCMethod.CRC16DNP: CRC16 = (ushort)(CRC16 ^ 0xFFFF); LO_ = (ushort)((CRC16 & 0xff00) >> 8); HI_ = (ushort)((CRC16 & 0x00ff) << 8); CRC16 = (ushort)(LO_ | HI_); break; case CRCMethod.CRC32: CRC32 = (uint)(CRC32 ^ 0xFFFFFFFF); break; } if (methodCRC == CRCMethod.CRC32) return CRC32.ToString("X8"); else { if (revert) { LO_ = (ushort)((CRC16 & 0xff00) >> 8); HI_ = (ushort)((CRC16 & 0x00ff) << 8); CRC16 = (ushort)(LO_ | HI_); } return CRC16.ToString("X4"); } } private byte Hex2Byte(string p) { int hi = Uri.FromHex(p[0]); int lo = Uri.FromHex(p[1]); return (byte)(lo | (hi << 4)); } private ushort Lo(uint p) { return BitConverter.ToUInt16(BitConverter.GetBytes(p & 0xFFFF), 0); } private byte HI(ushort p) { return (byte)(p >> 8); } private byte LO(ushort p) { return (byte)(p & 0xFF); } private void CrTabl(CRCMethod methodCRC, uint POLY) { uint crc; uint L = 0; for (uint i = 0; i <= 255; i++) { crc = 0; switch (methodCRC) { case CRCMethod.CRC16: case CRCMethod.CRC16Kermit: case CRCMethod.CRC16DNP: L = i; break; case CRCMethod.CRC16CCITT: L = i << 8; break; case CRCMethod.CRC32: crc = i; break; } for (int j = 0; j <= 7; j++) { switch (methodCRC) { case CRCMethod.CRC16: case CRCMethod.CRC16Kermit: case CRCMethod.CRC16DNP: if (((crc ^ L) & 0x00000001) != 0) crc = (crc >> 1) ^ POLY; else crc = crc >> 1; break; case CRCMethod.CRC16CCITT: if (((crc ^ L) & 0x00008000) != 0) crc = (crc << 1) ^ POLY; else crc = crc << 1; break; case CRCMethod.CRC32: if ((crc & 0x00000001) != 0) crc = (crc >> 1) ^ POLY; else crc = crc >> 1; break; } switch (methodCRC) { case CRCMethod.CRC16: case CRCMethod.CRC16Kermit: case CRCMethod.CRC16DNP: L = L >> 1; break; case CRCMethod.CRC16CCITT: L = L << 1; break; case CRCMethod.CRC32: crctab[i] = crc; break; } } if (methodCRC != CRCMethod.CRC32) crctab[i] = crc; } } } }