using System; namespace Xylem.Common.Utils.Crc16Ccitt { /// /// Class for CRC16 CCITT calculation /// public static class Crc16Ccitt { /// /// Initial CRC value /// private const UInt16 CrcSeedFfff = 0xFFFF; /// /// Initial CRC value /// private const UInt16 CrcSeed3791 = 0x3791; /// /// Generator polynomial MagFlux - Modbus RTU /// private const UInt16 CrcGpA001 = 0xA001; /// /// Generator polynomial GENESIS /// private const UInt16 CrcGp1021 = 0x1021; /// /// Generator polynomial RFID /// private const UInt16 CrcGp0408 = 0x0408; /// /// Generator polynomial for reversed IrDA /// private const UInt16 CrcGp8408 = 0x8408; /// /// Calculates the CRC (LSB first, reversed, CRC CCITT 0x8408) from a data array of bytes. /// /// data to be processed /// Calculated CRC public static UInt16 CalculateReversedLsb8408(Byte[] data) { var crc = CrcSeedFfff; foreach (var t in data) { //copy data byte to lower word because of LSB will be XORed var dataWord = (UInt16)(t & 0x00FF); for (var i = 0; i < 8; i++) { //test if CRC lowest bit is XORed set to one if (0x0001 == ((crc ^ dataWord) & 0x0001)) { crc >>= 1; //apply generator polynomial crc ^= CrcGp8408; } else { crc >>= 1; } dataWord >>= 1; } } return ((UInt16)~crc); } /// /// Calculates the bitwise inverted CRC (MSB first, CRCCCITT 0x1021) /// from a data array of bytes. /// /// data to be processed /// Calculated CRC public static UInt16 CalculateInvertedMsb1021(Byte[] data) { return (UInt16)~CalculateMsb1021(data); } /// /// Calculates the Modbus RTU CRC (LSB first, CRCCCITT 0xA001) /// from a data array of bytes. /// /// data to be processed /// Calculated CRC public static UInt16 ModbusRtuLsbA001(Byte[] data) { var crc = CrcSeedFfff; for (var t = 0; t < data.Length; t++) { crc ^= data[t]; // XOR byte into least sig. byte of crc for (var i = 8; i != 0; i--) { if ((crc & 0x0001) != 0) { crc >>= 1; crc ^= CrcGpA001; } else { crc >>= 1; } } } return crc; } /// /// Calculates the CRC (MSB first, CRCCCITT 0x1021) from a data array of bytes. /// /// data to be processed /// Calculated CRC public static UInt16 CalculateMsb1021(Byte[] data) { var crc = CrcSeedFfff; foreach (var t in data) { //copy data byte to higher word because of MSB will be XORed var dataWord = (UInt16)((t << 8) & 0xFF00); for (var i = 0; i < 8; i++) { //test if CRC highest bit or data input highest bit is XORed set to one if (0x8000 == ((crc ^ dataWord) & 0x8000)) //shifted in MSB first { //shift CRC high bit out crc <<= 1; //apply generator polynomial crc ^= CrcGp1021; } else //CRC highest bit and data input highest bit is equal { crc <<= 1; } dataWord <<= 1; //MSB first shifted out } } return crc; } /// /// Calculates the CRC (LSB first, CRCCCITT 0x0408) from a data array of bytes. /// /// data to be processed /// Calculated CRC public static UInt16 CalculateLsb0408(Byte[] data) { var crc = CrcSeed3791; foreach (var t in data) { var dataByte = t; for (var i = 0; i < 8; i++) { //test if CRC lowest bit is set to one if (1 == (crc & 1)) { //shift CRC low bit out crc >>= 1; //test lowest bit of data word if (1 == (dataByte & 1)) crc |= 0x8000; //invert CRC MSB crc ^= 0x8000; } else //CRC lowest bit not set { //shift CRC low bit out crc >>= 1; //test lowest bit of data word if (1 == (dataByte & 1)) crc |= 0x8000; } if (0x8000 == (crc & 0x8000)) //apply generator polynomial crc ^= CrcGp0408; dataByte >>= 1; //LSB first shifted out } } return crc; } } }