Discover MakerZone

MATLAB and Simulink resources for Arduino, LEGO, and Raspberry Pi

Learn more

Discover what MATLAB® can do for your career.

Opportunities for recent engineering grads.

Apply Today

Thread Subject:
Losing precision when Calculating CRC-CCITT

Subject: Losing precision when Calculating CRC-CCITT

From: Jean

Date: 11 Sep, 2010 01:02:20

Message: 1 of 2

Hi,

I am working with Simulink and I programmed a custom S-Function block in order to calculate the CRC on a packet I am receiving from an inertial measurement unit.

I have verified the CRC algorithm with some test samples in Matlab and everything works fine. However when I use this code in the Simulink environment, about half of the packets are dropped due to a bad CRC. I verified the CRC packet drop rate with another program that is working properly and it is not possible that such a large number of packets be dropped.

I believe that perhaps I am loosing precision through this Matlab implementation of the algorithm.

Below is the code used for the S-Function block. It would be very helpful if someone could review it and tell me if I am doing something wrong which could affect the precision of this algorithm.
______________________________________________________________________

function check_CRC(block)

setup(block);

function setup(block)

% Register number of ports
block.NumInputPorts = 1;
block.NumOutputPorts = 1;

% Setup port properties to be inherited or dynamic
block.SetPreCompInpPortInfoToDynamic;
block.SetPreCompOutPortInfoToDynamic;

% Behave consistently with C S-functions and suppress
% warnings about inconsistent sample times
block.SetAllowConstantSampleTime(false);

block.InputPort(1).Complexity = 'real';
block.InputPort(1).SamplingMode = 'Sample';
  
block.OutputPort(1).Complexity = 'real';
block.OutputPort(1).SamplingMode = 'Sample';

block.InputPort(1).Dimensions = [1 27]; % The data packet (27 bytes)
block.OutputPort(1).Dimensions = [1 1]; % CRC flag (1 for a match, 2 for a mismatch)


% No parameters
block.NumDialogPrms = 0;

%% Set the block simStateComliance to default (i.e., same as a built-in block)
block.SimStateCompliance = 'DefaultSimState';

block.SetAccelRunOnTLC(false);

%% Register methods
block.RegBlockMethod('CheckParameters', @CheckPrms);
block.RegBlockMethod('InitializeConditions', @InitializeConditions);
block.RegBlockMethod('Start', @Start);
block.RegBlockMethod('Outputs', @Outputs);
block.RegBlockMethod('Terminate', @Terminate);

% Inherit datatype id for non-built-in datatypes
block.RegBlockMethod('SetInputPortDataType', @SetInpPortDataType);
block.RegBlockMethod('SetOutputPortDataType', @SetOutputPortDataType);

function SetOutputPortDataType(block, idx, dt)
  
  block.OutputPort(1).DataTypeID = 5; %uint16
  
function SetInpPortDataType(block, idx, dt)

  block.InputPort(1).DataTypeID = 5; %uint16
  
function CheckPrms(block)
  

function Start(block)
  

function InitializeConditions(block)
  

function Outputs(block)

 % Obtaining the byte array required for CRC calculations.
  packet = block.InputPort(1).Data; % The Crossbow bytes required for CRC calculations
  %Adding two bytes of Header data that are lost in the Serial receive
  %block
  a = uint16 (83);
  b = uint16 (49);
  packet = [a b packet]; % Adding the "S1" Bytes that were taken away in the Serial Receive block
  
% Code below calculates the CRC-CCITT 16 BIT for a byte packet.
% Packet is an array of bytes (1 Byte = 8 bits).
% StartIndex is the byte index where the CRC calculation will start.
% EndIndex is the byte index where the CRC calculation will start

crc = hex2dec('1D0F'); % Non-augmented initial value equivalent to augmented initial value 0xFFFF
polynomial = hex2dec('1021'); % Polynomial

for i = 1:(length(packet)-2) % Not taking the last 2 bytes because they are the CRC.
    crc = bitxor(crc, bitshift(packet(i), 8));
    for j = 1:8
        if bitand(crc, hex2dec('8000'))
            crc = bitxor(bitshift(crc, 1), polynomial);
        else
            crc = bitshift(crc, 1);
        end
    end
end

packetcrc = uint16 (packet(length(packet)-1) * 256) + uint16 (packet(length(packet)));
% Check if the calculated CRC matches the one in the packet.
if(packetcrc == crc)
    block.OutputPort(1).Data = uint16 (1); % Should return 1 most of the time
else
    block.OutputPort(1).Data = uint16 (2); % For some odd reason, the CRC's dont match quite often (50%)
end

function Terminate(block)
 

Subject: Losing precision when Calculating CRC-CCITT

From: Roger Stafford

Date: 11 Sep, 2010 03:36:23

Message: 2 of 2

"Jean " <jean507@gmail.com> wrote in message <i6ekes$ig6$1@fred.mathworks.com>...
> Hi,
>
> I am working with Simulink and I programmed a custom S-Function block in order to calculate the CRC on a packet I am receiving from an inertial measurement unit.
>
> I have verified the CRC algorithm with some test samples in Matlab and everything works fine. However when I use this code in the Simulink environment, about half of the packets are dropped due to a bad CRC. I verified the CRC packet drop rate with another program that is working properly and it is not possible that such a large number of packets be dropped.
> ......
- - - - - - - - - - - -
  What guarantee do you have that in Simulink the presumed "bytes" of uint16 class in 'packet' will all actually be restricted to the lower eight bits - that is, all lie in the range 0 to 255? If somewhere along the line an eight-bit quantity were interpreted as a signed integer, the upper eight bits of the corresponding uint16 quantity might be all ones. This presumably wouldn't affect your crc computations in the nested loops because the upper eight bits are always shifted out, but the line

packetcrc = uint16 (packet(length(packet)-1) * 256) + uint16 (packet(length(packet)));

could well be in error a certain percentage of the time.

  I confess I am just speculating here. However I cannot think of any other kind of problem that would give errors about half the time. Errors in the crc iteration itself would produce a mismatch almost all the time.

Roger Stafford

Tags for this Thread

What are tags?

A tag is like a keyword or category label associated with each thread. Tags make it easier for you to find threads of interest.

Anyone can tag a thread. Tags are public and visible to everyone.

Contact us