namespace ZB.MOM.WW.OtOpcUa.Driver.Modbus;
///
/// CRC-16/MODBUS helper: reflected polynomial 0xA001, initial value 0xFFFF.
/// On the wire the CRC is appended low byte first, high byte second —
/// does that; just returns the 16-bit value. Byte-stream-agnostic:
/// no socket or framing knowledge lives here.
///
public static class ModbusCrc
{
/// Computes the CRC-16/MODBUS checksum over .
/// The bytes to checksum (e.g. the RTU frame minus the trailing CRC).
/// The 16-bit CRC value.
public static ushort Compute(ReadOnlySpan data)
{
ushort crc = 0xFFFF;
foreach (var b in data)
{
crc ^= b;
for (var i = 0; i < 8; i++)
{
var carry = (crc & 0x0001) != 0;
crc >>= 1;
if (carry)
{
crc ^= 0xA001;
}
}
}
return crc;
}
///
/// Returns with its CRC-16/MODBUS appended, low byte first.
///
/// The frame body to checksum.
/// A new array: followed by [crc & 0xFF, crc >> 8].
public static byte[] Append(ReadOnlySpan body)
{
var crc = Compute(body);
var result = new byte[body.Length + 2];
body.CopyTo(result);
result[^2] = (byte)(crc & 0xFF);
result[^1] = (byte)(crc >> 8);
return result;
}
}