title: CRC-CCITT Kermit 16 in C#
body: <p>Attempting to reverse engineer a serial port protocol. I am unable to recreate the crc-16 bytes.</p>
  
  <p><strong>According to the documentation, this is the format of the packet</strong></p>
  
  <pre><code>48 45 4c 4f // HELO
  01 00 00 01 // ARG 1
  00 00 00 00 // ARG 2
  00 00 00 00 // ARG 3
  00 00 00 00 // ARG 4
  00 00 00 00 // REQUEST BODY
  5c b1 00 00 // CRC-16
  b7 ba b3 b0  // Bit-wise inversion of HELO command
  </code></pre>
  
  <p><strong>This is the write command that was sniffed from serial monitoring</strong></p>
  
  <pre><code>48 45 4c 4f 01 00 00 01 00 00 00 00 00 00 00 00
  00 00 00 00 00 00 00 00 5c b1 00 00 b7 ba b3 b0   
  </code></pre>
  
  <p>I am able to recreate the packet fine, except for the 2 bytes "5c b1". According to the documentation, the 5c b1 bytes is a crc-ccit16 over the packet, with zeros in the crc-16 slot. The CRC16 function does return the 5C byte but not b1.</p>
  
  <p>I am using the code below to calculate the crc:</p>
  
  <pre><code>  public class Crc16
  {
      static 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;
          }
      }
  }
  
         public byte[] getPreCRC16Bytes()
      {
              byte[] x = new byte[28];
              byte[] cmdBytes = Encoding.ASCII.GetBytes(this.cmd.ToString());
              byte[] arg1Bytes = (byte[])this.arg1;
              byte[] arg2Bytes = (byte[])this.arg2;
              byte[] arg3Bytes = (byte[])this.arg3;
              byte[] arg4Bytes = (byte[])this.arg4;
              byte[] bodyLen = { 0x00, 0x00, 0x00, 0x00 };
              byte[] emptyCRC = { 0x00, 0x00, 0x00, 0x00 };
              byte[] checksum = Encoding.ASCII.GetBytes(this.checksum);
              var list = new List&lt;byte&gt;();
              list.AddRange(cmdBytes);
              list.AddRange(arg1Bytes);
              list.AddRange(arg2Bytes);
              list.AddRange(arg3Bytes);
              list.AddRange(arg4Bytes);
              list.AddRange(bodyLen);
              list.AddRange(emptyCRC);
              list.AddRange(checksum);
              var xx = list.ToArray();
  
          string hex = BitConverter.ToString(cmdBytes).Replace("-", "");
  
          return list.ToArray();
  
      }
  </code></pre>