Attribute VB_Name = "basCRC16" Option Explicit Option Base 0 ' basCRC16: Calculates CRC-16 checksum for a given message string ' Version 1. Published 6 May 2001. ' Updated 23 October 2006 - changed i from Integer to Long. ' Updated 17 June 2020 - changed license on this code to MIT. ' ******************************* LICENSE *********************************** ' * Copyright (C) 2001-20 David Ireland, DI Management Services Pty Limited. ' * All rights reserved. <www.di-mgt.com.au> <www.cryptosys.net> ' * The code in this module is licensed under the terms of the MIT license. ' * For a copy, see <http://opensource.org/licenses/MIT> ' *************************************************************************** ' Please forward comments or bug reports to https://di-mgt.com.au/contact Private aCRC16Table(255) As Integer Public Function crc16(sMessage As String) As Integer ' Given table is already setup. ' Set iCRC = 0 ' For each byte in message ' calculate iCRC = (iCRC >> 8) ^ Table[(iCRC & 0xFF) ^ byte] ' Return iCRC Dim iCRC As Integer Dim i As Long Dim bytT As Byte Dim bytC As Byte Dim ia As Integer iCRC = 0 For i = 1 To Len(sMessage) bytC = Asc(Mid(sMessage, i, 1)) bytT = (iCRC And &HFF) Xor bytC ia = uiShiftRightBy8(iCRC) iCRC = ia Xor aCRC16Table(bytT) Next crc16 = iCRC End Function Public Function uiShiftRightBy8(x As Integer) As Integer ' Shift 16-bit integer value to right by 8 bits ' Avoiding problem with sign bit Dim iNew As Integer iNew = (x And &H7FFF) \ 256 If (x And &H8000) <> 0 Then iNew = iNew Or &H80 End If uiShiftRightBy8 = iNew End Function Public Function CRC16Setup() Dim vntA As Variant Dim i As Integer ' Use variant array kludge to set up table vntA = Array( _ &H0, &HC0C1, &HC181, &H140, &HC301, &H3C0, &H280, &HC241, _ &HC601, &H6C0, &H780, &HC741, &H500, &HC5C1, &HC481, &H440, _ &HCC01, &HCC0, &HD80, &HCD41, &HF00, &HCFC1, &HCE81, &HE40, _ &HA00, &HCAC1, &HCB81, &HB40, &HC901, &H9C0, &H880, &HC841, _ &HD801, &H18C0, &H1980, &HD941, &H1B00, &HDBC1, &HDA81, &H1A40, _ &H1E00, &HDEC1, &HDF81, &H1F40, &HDD01, &H1DC0, &H1C80, &HDC41, _ &H1400, &HD4C1, &HD581, &H1540, &HD701, &H17C0, &H1680, &HD641, _ &HD201, &H12C0, &H1380, &HD341, &H1100, &HD1C1, &HD081, &H1040) For i = 0 To 63 aCRC16Table(i) = vntA(i - 0) Next vntA = Array( _ &HF001, &H30C0, &H3180, &HF141, &H3300, &HF3C1, &HF281, &H3240, _ &H3600, &HF6C1, &HF781, &H3740, &HF501, &H35C0, &H3480, &HF441, _ &H3C00, &HFCC1, &HFD81, &H3D40, &HFF01, &H3FC0, &H3E80, &HFE41, _ &HFA01, &H3AC0, &H3B80, &HFB41, &H3900, &HF9C1, &HF881, &H3840, _ &H2800, &HE8C1, &HE981, &H2940, &HEB01, &H2BC0, &H2A80, &HEA41, _ &HEE01, &H2EC0, &H2F80, &HEF41, &H2D00, &HEDC1, &HEC81, &H2C40, _ &HE401, &H24C0, &H2580, &HE541, &H2700, &HE7C1, &HE681, &H2640, _ &H2200, &HE2C1, &HE381, &H2340, &HE101, &H21C0, &H2080, &HE041) For i = 64 To 127 aCRC16Table(i) = vntA(i - 64) Next vntA = Array( _ &HA001, &H60C0, &H6180, &HA141, &H6300, &HA3C1, &HA281, &H6240, _ &H6600, &HA6C1, &HA781, &H6740, &HA501, &H65C0, &H6480, &HA441, _ &H6C00, &HACC1, &HAD81, &H6D40, &HAF01, &H6FC0, &H6E80, &HAE41, _ &HAA01, &H6AC0, &H6B80, &HAB41, &H6900, &HA9C1, &HA881, &H6840, _ &H7800, &HB8C1, &HB981, &H7940, &HBB01, &H7BC0, &H7A80, &HBA41, _ &HBE01, &H7EC0, &H7F80, &HBF41, &H7D00, &HBDC1, &HBC81, &H7C40, _ &HB401, &H74C0, &H7580, &HB541, &H7700, &HB7C1, &HB681, &H7640, _ &H7200, &HB2C1, &HB381, &H7340, &HB101, &H71C0, &H7080, &HB041) For i = 128 To 191 aCRC16Table(i) = vntA(i - 128) Next vntA = Array( _ &H5000, &H90C1, &H9181, &H5140, &H9301, &H53C0, &H5280, &H9241, _ &H9601, &H56C0, &H5780, &H9741, &H5500, &H95C1, &H9481, &H5440, _ &H9C01, &H5CC0, &H5D80, &H9D41, &H5F00, &H9FC1, &H9E81, &H5E40, _ &H5A00, &H9AC1, &H9B81, &H5B40, &H9901, &H59C0, &H5880, &H9841, _ &H8801, &H48C0, &H4980, &H8941, &H4B00, &H8BC1, &H8A81, &H4A40, _ &H4E00, &H8EC1, &H8F81, &H4F40, &H8D01, &H4DC0, &H4C80, &H8C41, _ &H4400, &H84C1, &H8581, &H4540, &H8701, &H47C0, &H4680, &H8641, _ &H8201, &H42C0, &H4380, &H8341, &H4100, &H81C1, &H8081, &H4040) For i = 192 To 255 aCRC16Table(i) = vntA(i - 192) Next End Function Public Function TestCRC16() ' Test suite answers: 'CRC16('123456789') = BB3D 'CRC16('hello world')=39C1 'CRC16('Hello world')=F96A 'CRC16('a') = E8C1 'CRC16(' ') = D801 Dim sMessage As String Dim iCRC As Integer Call CRC16Setup sMessage = "123456789" iCRC = crc16(sMessage) Debug.Print "crc16('" & sMessage & "')=" & Hex(iCRC) sMessage = "hello world" iCRC = crc16(sMessage) Debug.Print "crc16('" & sMessage & "')=" & Hex(iCRC) sMessage = "Hello world" iCRC = crc16(sMessage) Debug.Print "crc16('" & sMessage & "')=" & Hex(iCRC) sMessage = "a" iCRC = crc16(sMessage) Debug.Print "crc16('" & sMessage & "')=" & Hex(iCRC) sMessage = " " ' (space char) iCRC = crc16(sMessage) Debug.Print "crc16('" & sMessage & "')=" & Hex(iCRC) End Function