|
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)
|