title: CRC-16 calculation C#
body: <p>I have a terminal that communicates through RS232 COM with the computer. The protocol that I was given says that I have to send a certain combination of bytes and the CRC 16 IBM calculation of the data sent at the end</p>
  
  <p>I was also given a C written application that I can test with, that application writes a log with send data and received data. In that log I see if I send the terminal this string <code>hexString = "02 00 04 a0 00 01 01 03"</code>. I must also send this CRC16 IBM result of data 06 35.</p>
  
  <p>I have managed to somehow translate the C method that was given as an example, into C#. But my result is far away from what I know I must receive.</p>
  
  <p>I have tested sending the data from the log and everything is fine. I must have my calculation done wrong. Am I doing anything wrong here?</p>
  
  <p>Here is my code:</p>
  
  <p>CRC class:</p>
  
  <pre><code>public enum Crc16Mode : ushort
      {
          ARINC_NORMAL = 0XA02B, ARINC_REVERSED = 0xD405, ARINC_REVERSED_RECIPROCAL = 0XD015,
          CCITT_NORMAL = 0X1021, CCITT_REVERSED = 0X8408, CCITT_REVERSED_RECIPROCAL = 0X8810,
          CDMA2000_NORMAL = 0XC867, CDMA2000_REVERSED = 0XE613, CDMA2000_REVERSED_RECIPROCAL = 0XE433,
          DECT_NORMAL = 0X0589, DECT_REVERSED = 0X91A0, DECT_REVERSED_RECIPROCAL = 0X82C4,
          T10_DIF_NORMAL = 0X8BB7, T10_DIF_REVERSED = 0XEDD1, T10_DIF_REVERSED_RECIPROCAL = 0XC5DB,
          DNP_NORMAL = 0X3D65, DNP_REVERSED = 0XA6BC, DNP_REVERSED_RECIPROCAL = 0X9EB2,
          IBM_NORMAL = 0X8005, IBM_REVERSED = 0XA001, IBM_REVERSED_RECIPROCAL = 0XC002,
          OPENSAFETY_A_NORMAL = 0X5935, OPENSAFETY_A_REVERSED = 0XAC9A, OPENSAFETY_A_REVERSED_RECIPROCAL = 0XAC9A,
          OPENSAFETY_B_NORMAL = 0X755B, OPENSAFETY_B_REVERSED = 0XDDAE, OPENSAFETY_B_REVERSED_RECIPROCAL = 0XBAAD,
          PROFIBUS_NORMAL = 0X1DCF, PROFIBUS_REVERSED = 0XF3B8, PROFIBUS_REVERSED_RECIPROCAL = 0X8EE7
  
      }
  
  public class Crc16
  {
      readonly ushort[] table = new ushort[256];
  
      public ushort ComputeChecksum(params byte[] bytes)
      {
          ushort crc = 0;
          for (int i = 0; i &lt; bytes.Length; ++i)
          {
              byte index = (byte)(crc ^ bytes[i]);
              crc = (ushort)((crc &gt;&gt; 8) ^ table[index]);
          }
          return crc;
      }
  
      public byte[] ComputeChecksumBytes(params byte[] bytes)
      {
          ushort crc = ComputeChecksum(bytes);
          return BitConverter.GetBytes(crc);
      }
  
      public Crc16(Crc16Mode mode)
      {
          ushort polynomial = (ushort)mode;
          ushort value;
          ushort temp;
          for (ushort i = 0; i &lt; table.Length; ++i)
          {
              value = 0;
              temp = i;
              for (byte j = 0; j &lt; 8; ++j)
              {
                  if (((value ^ temp) &amp; 0x0001) != 0)
                  {
                      value = (ushort)((value &gt;&gt; 1) ^ polynomial);
                  }
                  else
                  {
                      value &gt;&gt;= 1;
                  }
                  temp &gt;&gt;= 1;
              }
              table[i] = value;
          }
      }
  }
  </code></pre>
  
  <p>Method to process the bytes received:</p>
  
  <pre><code>public ushort CalculateCRC(byte[] data)
      {
          Crc16 crcCalc = new Crc16(Crc16Mode.IBM_NORMAL);
          ushort crc = crcCalc.ComputeChecksum(data);
          return crc;
      }
  </code></pre>
  
  <p>In this method you can select polynomial from the Enum.</p>
  
  <p>Main in Program Class:</p>
  
  <p>static void Main(string[] args)
          {
              try
              {
                  Metode m = new Metode();</p>
  
  <pre><code>            string hexString = "02 00 04 a0 00 01 01 03";
              byte[] bytes = m.HexStringToByteArray(hexString);
  
  
              ushort crc = m.CalculateCRC(bytes);
  
              string hexResult;
              int myInt = crc;
              hexResult = myInt.ToString("X");
  
  
              //Console.WriteLine(crc.ToString());
              Console.WriteLine(hexResult);
              Console.ReadLine();
          }
          catch (Exception ex)
          {
              Metode m = new Metode();
              m.writeError(ex.Message);
          }
      }
  </code></pre>
  
  <p>Convert from hexstring to byte array:</p>
  
  <pre><code>public byte[] HexStringToByteArray(string hexString)
      {
          hexString = hexString.Replace(" ", "");
  
          return Enumerable.Range(0, hexString.Length)
                   .Where(x =&gt; x % 2 == 0)
                   .Select(x =&gt; Convert.ToByte(hexString.Substring(x, 2), 16))
                   .ToArray();
      }
  </code></pre>
  
  <p>Convert from byte array to hex string:</p>
  
  <pre><code>public string ByteArrayToHexString(byte[] byteArray)
      {
          return BitConverter.ToString(byteArray);
      }
  </code></pre>
  
  <p>What am I doing wrong here?</p>
  
  <p>UPDATE:</p>
  
  <p>Thanks to @MarkAdler I have managed to translate the calculation. What I didn't notice until late was the fact that the CRC calculation should have been for online the DATA sent to the terminal, NOT the entire message!</p>
  
  <p>So the hexString should have been in fact "a0 00 01 01", the data without the STX/length/ETX.</p>
  
  <p>Here is the code for this particular CRC16 Calculus in C#:</p>
  
  <pre><code>public ushort CalculateCRC(byte[] data, int len)
          {
              int crc = 0, i = 0;
              while (len-- != 0)
              {
                  crc ^= data[i++] &lt;&lt; 8;
                  for (int k = 0; k &lt; 8; k++)
                      crc = ((crc &amp; 0x8000) != 0) ? (crc &lt;&lt; 1) ^ 0x8005 : (crc &lt;&lt; 1);
              }
              return (ushort)(crc &amp; 0xffff);
          }
  </code></pre>