184 lines
6.2 KiB
C#
184 lines
6.2 KiB
C#
using System;
|
|
|
|
namespace Xylem.Common.Utils.Crc16Ccitt
|
|
{
|
|
/// <summary>
|
|
/// Class for CRC16 CCITT calculation
|
|
/// </summary>
|
|
public static class Crc16Ccitt
|
|
{
|
|
/// <summary>
|
|
/// Initial CRC value
|
|
/// </summary>
|
|
private const UInt16 CrcSeedFfff = 0xFFFF;
|
|
/// <summary>
|
|
/// Initial CRC value
|
|
/// </summary>
|
|
private const UInt16 CrcSeed3791 = 0x3791;
|
|
|
|
/// <summary>
|
|
/// Generator polynomial MagFlux - Modbus RTU
|
|
/// </summary>
|
|
private const UInt16 CrcGpA001 = 0xA001;
|
|
/// <summary>
|
|
/// Generator polynomial GENESIS
|
|
/// </summary>
|
|
private const UInt16 CrcGp1021 = 0x1021;
|
|
|
|
/// <summary>
|
|
/// Generator polynomial RFID
|
|
/// </summary>
|
|
private const UInt16 CrcGp0408 = 0x0408;
|
|
|
|
/// <summary>
|
|
/// Generator polynomial for reversed IrDA
|
|
/// </summary>
|
|
private const UInt16 CrcGp8408 = 0x8408;
|
|
|
|
/// <summary>
|
|
/// Calculates the CRC (LSB first, reversed, CRC CCITT 0x8408) from a data array of bytes.
|
|
/// </summary>
|
|
/// <param name="data">data to be processed</param>
|
|
/// <returns>Calculated CRC</returns>
|
|
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);
|
|
}
|
|
/// <summary>
|
|
/// Calculates the bitwise inverted CRC (MSB first, CRCCCITT 0x1021)
|
|
/// from a data array of bytes.
|
|
/// </summary>
|
|
/// <param name="data">data to be processed</param>
|
|
/// <returns>Calculated CRC</returns>
|
|
public static UInt16 CalculateInvertedMsb1021(Byte[] data)
|
|
{
|
|
return (UInt16)~CalculateMsb1021(data);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Calculates the Modbus RTU CRC (LSB first, CRCCCITT 0xA001)
|
|
/// from a data array of bytes.
|
|
/// </summary>
|
|
/// <param name="data">data to be processed</param>
|
|
/// <returns>Calculated CRC</returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Calculates the CRC (MSB first, CRCCCITT 0x1021) from a data array of bytes.
|
|
/// </summary>
|
|
/// <param name="data">data to be processed</param>
|
|
/// <returns>Calculated CRC</returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Calculates the CRC (LSB first, CRCCCITT 0x0408) from a data array of bytes.
|
|
/// </summary>
|
|
/// <param name="data">data to be processed</param>
|
|
/// <returns>Calculated CRC</returns>
|
|
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;
|
|
}
|
|
}
|
|
} |