Skip to content

Commit

Permalink
Improved README and refactored crc16.m for better readability.
Browse files Browse the repository at this point in the history
firefirefirefirefire committed Dec 11, 2023
1 parent 556ae47 commit 0bf2405
Showing 4 changed files with 109 additions and 58 deletions.
54 changes: 44 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,50 @@
# Table-based implementation of CRC16
# Table-Driven Implementation of CRC-16

CRC16 is a very readable implementation of CRC-16 compatible with MATLAB and GNU Octave. The algorithm is parameterized to support a large number of CRC-16 variants. The following parameters can be specified.
* poly - CRC polynomial specified as a 16-bit hex value (default=0x1021)
* init - Initial shift register value specified as a 16-bit hex value (default=0)
* refin - Boolean input reflection (default=false)
* refout - Boolean output reflection (default=false)
* xorout - Value to XOR with the final CRC before returning, specified as 16-bit hex (default=0)
CRC16 is a very readable implementation of CRC-16 which is compatible with MATLAB and GNU Octave. The algorithm is parameterized to support a large number of CRC-16 variants. The following parameters can be specified.
* poly - CRC polynomial specified as a 16-bit integer (default=0x1021)
* init - Initial shift register value specified as a 16-bit integer (default=0)
* refin - Reflect (bit-reverse) input bytes, specified as a boolean (default=false)
* refout - Reflect output CRC, specified as a boolean (default=false)
* xorout - Value to XOR with the final CRC before returning, specified as a 16-bit integer (default=0)

The implementation uses only primitive functions without dependencies on MATLAB toolboxes or GNU Octave packages. Because of this it will likely run on most any version. It has been tested with MATLAB versions R2019b, R2020b, and R2022b as well as GNU Octave versions 3.8.2, 6.4.2, and 8.3.0.
The implementation uses only primitive functions without any dependencies on MATLAB toolboxes or GNU Octave packages. Because of this it will likely run on most any version. It has been tested with MATLAB versions R2019b, R2020b, and R2022b as well as GNU Octave versions 3.8.2, 6.4.2, and 8.3.0.

# Files
* crc16.m - Table-based CRC-16 algorithm
* test_crc16.m - Test harness which verifies the algorithm against Greg Cook's catalogue of parametrised CRC algorithms with 16 bits
* crc16.m - Table-based CRC-16 algorithm; see the file's embedded help for customizing parameters and usage examples.
* test_crc16.m - Test harness which verifies the algorithm against Greg Cook's *Catalogue of parametrised CRC algorithms with 16 bits*.

![Transcript of test_crc16.m](./images/crc16.png "Transcript of test_crc16.m")

# Examples
### 1. CRC16 using default parameters corresponding to CRC-16/XMODEM

~~~~
crc = crc16(uint8('123456789'));
disp(dec2hex(crc))
31C3
~~~~

### 2. CRC-16/KERMIT, often identified as CRC-16/CCITT

~~~~
crc = crc16(uint8('123456789'), struct('refin',1,'refout',1));
disp(dec2hex(crc))
2189
~~~~

### 3. CRC-16/MODBUS

~~~~
cfg = struct('poly',0x8005,'init',0xffff,'refin',1,'refout',1,'xorout',0);
crc = crc16(uint8('123456789'),cfg);
disp(dec2hex(crc))
4B37
~~~~

# References
1. **[Greg Cook's CRC-16 Catalog](https://reveng.sourceforge.io/crc-catalogue/16.htm)**
2. **[Dr. Dobb's Understanding CRCs](https://www.drdobbs.com/tools/understanding-crcs/184410177)**
3. **[Sunshine Online CRC Calculator](http://www.sunshine2k.de/coding/javascript/crc/crc_js.html)**
4. **[Online CRC-8 CRC-16 CRC-32 Calculator](https://www.drdobbs.com/tools/understanding-crcs/184410177)**

> Written with [StackEdit](https://stackedit.io/).
111 changes: 64 additions & 47 deletions crc16.m
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
function [crc,cfgout,crctable] = crc16(octets,cfg)
% Usage: [crc,cfgout,crctable] = crc16(octets,cfg)
function [crc,cfg,crctable] = crc16(octets,cfgin)
% Usage: [crc,cfg,crctable] = crc16(octets,cfgin)
%
% Compute CRC-16 (CCITT) of a vector of unsigned bytes
% Compute CRC-16 of a vector of unsigned bytes
%
% octets.............input vector of unsigned bytes
% cfg................optional struct to customize CRC-16 parameters
% cfgin..............optional struct to customize CRC-16 parameters
% poly.............scalar CRC polynomial [0-0xffff] (default=0x1021)
% init.............scalar initial shift register value [0-0xffff] (default=0)
% refin............bool input reflection [0 or 1] (default=0)
% refout...........bool output reflection [0 or 1] (default=0)
% xorout...........scalar XOR'd with final CRC before returning (default=0)
% crc................output: computed CRC-16
% cfgout.............output: struct of configuration used to compute CRC
% cfgout contains the same members as cfg input struct
% cfg................output: struct of configuration used to compute CRC
% cfg contains the same members as cfgin input struct
% crctable...........output: lookup table for fast CRC calculation
%
% CRC default parameters:
@@ -22,58 +22,51 @@
% - output reflection: no
% - output Xor: no
%
% Note: If the length of your data in bits is not an integer
% number of bytes, prepend 0 bits to get a multiple
% of 8 bits.
% Examples:
%
% Example:
% 1. CRC16 using default parameters corresponding to CRC-16/XMODEM:
% crc = crc16(uint8('123456789'));
% disp(dec2hex(crc))
% 31C3
%
% in = hex2dec(['31';'32';'33';'34';'35';'36';'37';'38';'39'])
% crc = crc16(in);
% dec2hex(crc)
% ans =
% '31C3'
% 2. CRC-16/KERMIT often identified as CRC-16/CCITT:
% crc = crc16(uint8('123456789'), struct('refin',1,'refout',1));
% disp(dec2hex(crc))
% 2189
%
% Compare to:
% 3. CRC-16/MODBUS:
% cfg = struct('poly',0x8005,'init',0xffff,'refin',1,'refout',1,'xorout',0);
% crc = crc16(uint8('123456789'),cfg);
% disp(dec2hex(crc))
% 4B37
%
% Compare to the following online calculators:
% http://www.sunshine2k.de/coding/javascript/crc/crc_js.html
% and/or:
% https://reveng.sourceforge.io/crc-catalogue/16.htm
% and/or:
% https://crccalc.com/
%
% Reference:
% References:
% https://reveng.sourceforge.io/crc-catalogue/16.htm
% https://www.drdobbs.com/tools/understanding-crcs/184410177
%

persistent Crc16Table
persistent lastPoly

% Inputs
narginchk(1,2);
if nargin == 1
% Validate inputs
narginchk(0,2);
if nargin == 0 || ~isa(cfgin,'struct')
crc = zeros(0,1);
cfg = struct();
cfg.poly = 4129; % 0x1021
cfg.init = 0;
cfg.refin = 0;
cfg.refout = 0;
cfg.xorout = 0;
end
if ~isfield(cfg,'poly')
cfg.poly = 4129; % 0x1021
end
if ~isfield(cfg,'init')
cfg.init = 0;
end
if ~isfield(cfg,'refin')
cfg.refin = 0;
crctable = [];
help crc16
return
elseif nargin == 1
cfgin = struct();
end
if ~isfield(cfg,'refout')
cfg.refout = 0;
end
if ~isfield(cfg,'xorout')
cfg.xorout = 0;
end
cfgout = cfg;

% Setup algorithm parameters
cfg = parse_inputs(cfgin,nargin);
octets = double(uint8(octets)); % cast avoids bitxor() warnings

% CRC LUT
if isempty(Crc16Table) || length(Crc16Table) ~= 256 ...
@@ -84,7 +77,7 @@

% Input reflection
if cfg.refin
octets = reflect(uint8(octets));
octets = reflect(octets);
end

% CRC-16
@@ -95,7 +88,6 @@
idx = bitand(bitxor(bitshift(crc, -8), octets(ii)), ff);
crc = bitand(bitxor(Crc16Table(idx + 1), bitshift(crc, 8)), ffff);
end
crc = bitand(crc, ffff);

% Output reflection
if cfg.refout
@@ -109,7 +101,7 @@

end % function

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Generate CRC16 fast lookup table
function lut = buildTable(poly)
@@ -166,5 +158,30 @@
else % treat as uint8
ref = reflTable(d(:)+1);
end
end % function

% Setup algorithm parameters
function cfg = parse_inputs(cfg,N)
if N == 1
cfg.poly = 4129; % 0x1021
cfg.init = 0;
cfg.refin = 0;
cfg.refout = 0;
cfg.xorout = 0;
end
if ~isfield(cfg,'poly')
cfg.poly = 4129; % 0x1021
end
if ~isfield(cfg,'init')
cfg.init = 0;
end
if ~isfield(cfg,'refin')
cfg.refin = 0;
end
if ~isfield(cfg,'refout')
cfg.refout = 0;
end
if ~isfield(cfg,'xorout')
cfg.xorout = 0;
end
end % function
Binary file added images/crc16.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion test_crc16.m
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@ function test_crc16()
% https://reveng.sourceforge.io/crc-catalogue/16.htm
%

in = double(0x31:0x39);
in = uint8('123456789');
lines = reference();
for kk = 1:size(lines,1)
eval(lines(kk,:));

0 comments on commit 0bf2405

Please sign in to comment.