gusucode.com > vnt工具箱matlab源码程序 > vnt/vnt/+xcp/Utility.m

    classdef (Hidden) Utility
% Utility Class that implement utility methods for XCP.

% Authors: JDP
% Copyright 2012-2015 The MathWorks, Inc.

properties (Constant)
    % BYTES_IN_BYTE - The number of bytes in a byte.
    BYTES_IN_BYTE = 1;
    % BYTES_IN_WORD - The number of bytes in a word.
    BYTES_IN_WORD = 2;
    % BYTES_IN_DWORD - The number of bytes in a double word.
    BYTES_IN_DWORD = 4;
    % BYTES_IN_DLONG - The number of bytes in a double long.
    BYTES_IN_DLONG = 8;
    
    % CODE_FOR_POSITIVE_RESPONSE - Code for a positive response to an XCP command.
    CODE_FOR_POSITIVE_RESPONSE = hex2dec('FF');
    % CODE_FOR_NEGATIVE_RESPONSE - Code for a negative response to an XCP command.
    CODE_FOR_NEGATIVE_RESPONSE = hex2dec('FE');
    % CODE_FOR_SLAVE_EVENT - Code for an XCP slave event message.
    CODE_FOR_SLAVE_EVENT = hex2dec('FD');
    % CODE_FOR_SLAVE_SERVICE_REQUEST - Code for an XCP service request message.
    CODE_FOR_SLAVE_SERVICE_REQUEST = hex2dec('FC');
    
    % RESOURCE_CAL - Resource bit mask for calibration.
    RESOURCE_CAL = hex2dec('01');
    % RESOURCE_DAQ - Resource bit mask for DAQ.
    RESOURCE_DAQ = hex2dec('04');
    % RESOURCE_STIM - Resource bit mask for STIM.
    RESOURCE_STIM = hex2dec('08');
    % RESOURCE_PGM - Resource bit mask for programming.
    RESOURCE_PGM = hex2dec('10');
    
    % NORMAL_MODE - Indicates for the CONNECT command to use normal mode.
    NORMAL_MODE = hex2dec('00');
    
    % FIRST_ODT_ENTRY - Indicates for the SET_DAQ_PTR command the numeric
    %   value of the first ODT entry for the list.
    FIRST_ODT_ENTRY = hex2dec('00');
    
    % IGNORE_BIT_OFFSET - Indicates for the WRITE_DAQ command to ignore bit
    %   offsets for a measurement.
    IGNORE_BIT_OFFSET = hex2dec('FF');
    
    % NO_TRANSMISSION_RATE_PRESCALER - Indicates to the SET_DAQ_LIST_MODE
    %   command to not apply any prescaler to DAQ transmissions.
    NO_TRANSMISSION_RATE_PRESCALER = hex2dec('01');
    % LET_SLAVE_MANAGE_PRIORITY - Indicates to the SET_DAQ_LIST_MODE
    %   command to allow the slave to manage list priority itself.
    LET_SLAVE_MANAGE_PRIORITY = hex2dec('00');
    
    % SET_SYNCHRONIZED_START_STOP - Indicates to the START_STOP_DAQ_LIST
    % command to start the measurement lists together.
    SET_SYNCHRONIZED_START_STOP = hex2dec('02');
    
    % FIRST_PART_OF_SEED - Indication for the GET_SEED command that this is
    %   the first part of the seed value being sent.
    FIRST_PART_OF_SEED = hex2dec('00');
    % REMAINING_PART_OF_SEED - Indication for the GET_SEED command that
    %   this is the additional seed value bytes being sent.
    REMAINING_PART_OF_SEED = hex2dec('01');
    
    % SYNCH_STOP_ALL_LISTS - Indication for the START_STOP_SYNCH command to
    %   stop all lists.
    SYNCH_STOP_ALL_LISTS = hex2dec('00');
    % SYNCH_START_SELECTED_LISTS - Indication for the START_STOP_SYNCH 
    %   command to start only selected lists.
    SYNCH_START_SELECTED_LISTS = hex2dec('01');
    % SYNCH_STOP_SELECTED_LISTS - Indication for the START_STOP_SYNCH 
    %   command to stop only selected lists.
    SYNCH_STOP_SELECTED_LISTS = hex2dec('02');
    
    % MAX_KEY_BYTES_PER_CTO - The number of key bytes that fit into a single
    %   CTO message.
    MAX_KEY_BYTES_PER_CTO = 6;
    
    % IDENTIFICATION_FIELD_TYPE_ABSOLUTE - Defines the identification field
    %   as having only the absolute ODT number as a byte.
    IDENTIFICATION_FIELD_TYPE_ABSOLUTE = 'IDENTIFICATION_FIELD_TYPE_ABSOLUTE';
    % IDENTIFICATION_FIELD_TYPE_RELATIVE_BYTE - Defines the identification field
    %   as having a relative ODT number plus the absolute DAQ/STIM list
    %   number as a byte.
    IDENTIFICATION_FIELD_TYPE_RELATIVE_BYTE = 'IDENTIFICATION_FIELD_TYPE_RELATIVE_BYTE';
    % IDENTIFICATION_FIELD_TYPE_RELATIVE_WORD - Defines the identification field
    %   as having a relative ODT number plus the absolute DAQ/STIM list
    %   number as a word.
    IDENTIFICATION_FIELD_TYPE_RELATIVE_WORD = 'IDENTIFICATION_FIELD_TYPE_RELATIVE_WORD';
    % IDENTIFICATION_FIELD_TYPE_RELATIVE_WORD_ALIGNED - Defines the identification field
    %   as having a relative ODT number, a filler byte,  plus the absolute DAQ/STIM list
    %   number as a word.
    IDENTIFICATION_FIELD_TYPE_RELATIVE_WORD_ALIGNED = 'IDENTIFICATION_FIELD_TYPE_RELATIVE_WORD_ALIGNED';
    % MAP_IDENTIFICATION_FIELD_TYPE_BYTES_USED - A map that links the
    %   identification field type to the number of bytes used by the field
    %   within a given ODT.
    MAP_IDENTIFICATION_FIELD_TYPE_BYTES_USED = containers.Map( ...
        { 'IDENTIFICATION_FIELD_TYPE_ABSOLUTE', ...
        'IDENTIFICATION_FIELD_TYPE_RELATIVE_BYTE', ...
        'IDENTIFICATION_FIELD_TYPE_RELATIVE_WORD', ...
        'IDENTIFICATION_FIELD_TYPE_RELATIVE_WORD_ALIGNED' }, ...
        { 1, 2, 3, 4 } );
end

% Seed and key function response codes.
properties (Constant)
    SEED_KEY_SUCCESS = 0;
    SEED_KEY_ERROR_REQUESTED_PRIVILEGE_NOT_AVAILABLE = 1;
    SEED_KEY_ERROR_INVALID_SEED_LENGTH = 2;
    SEED_KEY_ERROR_INSUFFICIENT_KEY_LENGTH = 3;
    SEED_KEY_ERROR_LOAD_LIBRARY_FAILED = 4;
    SEED_KEY_ERROR_FUNCTION_NOT_FOUND = 5;
    
    MAP_SEED_KEY_RESPONSE_TO_NAME = containers.Map( ...
        { 0, 1, 2, 3, 4, 5 }, ...
        { 'SEED_KEY_SUCCESS', ...
        'SEED_KEY_ERROR_REQUESTED_PRIVILEGE_NOT_AVAILABLE', ...
        'SEED_KEY_ERROR_INVALID_SEED_LENGTH', ...
        'SEED_KEY_ERROR_INSUFFICIENT_KEY_LENGTH', ...
        'SEED_KEY_ERROR_LOAD_LIBRARY_FAILED', ...
        'SEED_KEY_ERROR_FUNCTION_NOT_FOUND' } );
end

% XCP error response code properties.
properties (Constant)
    ERR_CMD_SYNCH = hex2dec('00');
    ERR_CMD_BUSY = hex2dec('10');
    ERR_DAQ_ACTIVE = hex2dec('11');
    ERR_PGM_ACTIVE = hex2dec('12');
    ERR_CMD_UNKNOWN = hex2dec('20');
    ERR_CMD_SYNTAX = hex2dec('21');
    ERR_OUT_OF_RANGE = hex2dec('22');
    ERR_WRITE_PROTECTED = hex2dec('23');
    ERR_ACCESS_DENIED = hex2dec('24');
    ERR_ACCESS_LOCKED = hex2dec('25');
    ERR_PAGE_NOT_VALID = hex2dec('26');
    ERR_MODE_NOT_VALID = hex2dec('27');
    ERR_SEGMENT_NOT_VALID = hex2dec('28');
    ERR_SEQUENCE = hex2dec('29');
    ERR_DAQ_CONFIG = hex2dec('2A');
    ERR_MEMORY_OVERFLOW = hex2dec('30');
    ERR_GENERIC = hex2dec('31');
    ERR_VERIFY = hex2dec('32');
    ERR_RESOURCE_TEMPORARY_NOT_ACCESSIBLE = hex2dec('33');
    
    MAP_ERROR_CODE_TO_NAME = containers.Map( ...
        { hex2dec('00'), ...
        hex2dec('10'), ...
        hex2dec('11'), ...
        hex2dec('12'), ...
        hex2dec('20'), ...
        hex2dec('21'), ...
        hex2dec('22'), ...
        hex2dec('23'), ...
        hex2dec('24'), ...
        hex2dec('25'), ...
        hex2dec('26'), ...
        hex2dec('27'), ...
        hex2dec('28'), ...
        hex2dec('29'), ...
        hex2dec('2A'), ...
        hex2dec('30'), ...
        hex2dec('31'), ...
        hex2dec('32'), ...
        hex2dec('33') }, ...
        { 'ERR_CMD_SYNCH', ...
        'ERR_CMD_BUSY', ...
        'ERR_DAQ_ACTIVE', ...
        'ERR_PGM_ACTIVE', ...
        'ERR_CMD_UNKNOWN', ...
        'ERR_CMD_SYNTAX', ...
        'ERR_OUT_OF_RANGE', ...
        'ERR_WRITE_PROTECTED', ...
        'ERR_ACCESS_DENIED', ...
        'ERR_ACCESS_LOCKED', ...
        'ERR_PAGE_NOT_VALID', ...
        'ERR_MODE_NOT_VALID', ...
        'ERR_SEGMENT_NOT_VALID', ...
        'ERR_SEQUENCE', ...
        'ERR_DAQ_CONFIG', ...
        'ERR_MEMORY_OVERFLOW', ...
        'ERR_GENERIC', ...
        'ERR_VERIFY', ...
        'ERR_RESOURCE_TEMPORARY_NOT_ACCESSIBLE' } );

    MAP_ERROR_CODE_TO_EXPLANATION = containers.Map( ...
        { hex2dec('00'), ...
        hex2dec('10'), ...
        hex2dec('11'), ...
        hex2dec('12'), ...
        hex2dec('20'), ...
        hex2dec('21'), ...
        hex2dec('22'), ...
        hex2dec('23'), ...
        hex2dec('24'), ...
        hex2dec('25'), ...
        hex2dec('26'), ...
        hex2dec('27'), ...
        hex2dec('28'), ...
        hex2dec('29'), ...
        hex2dec('2A'), ...
        hex2dec('30'), ...
        hex2dec('31'), ...
        hex2dec('32'), ...
        hex2dec('33') }, ...
        { 'Command processor synchronization error.', ...
        'Command was not executed.', ...
        'Command was rejected because DAQ is running.', ...
        'Command was rejected because PGM is running.', ...
        'Unknown command or not implemented optional command.', ...
        'Command syntax is invalid.', ...
        'Command syntax was valid, but command paramater(s) are out of range.', ...
        'The memory location is write protected.', ...
        'The memory location is not accessible.', ...
        'Access denied because a seed and key unlock is required.', ...
        'The selected page is not available.', ...
        'The selected page mode is not available.', ...
        'The selected segment is not valid.', ...
        'A sequence error occurred.', ...
        'DAQ configuration is not valid.', ...
        'A memory overflow error occurred.', ...
        'A generic error occurred.', ...
        'The slave internal program verify routine detected an error.', ...
        'Access to the requested resource is temporarily not possible.' } );
end


methods (Static)
   
    function byteArray = packParameter(byteOrder, numberOfBytes, value)
    % packParameter Translates a parameter from decimal value to raw bytes.
    %
    %   This method is used to convert a parameter from a decimal value to
    %   a raw array of bytes for transmission in an XCP command message.
    %   Some command parameters are larger than a single byte and so the
    %   value requires proper handling to transmit. All parameters are
    %   unsigned integer types, so no special conversion handling is
    %   required.
        
        % Convert the input value to a properly sized hexadecimal string.
        hexString = dec2hex(value, numberOfBytes * 2);
        % Arrange the bytes according to the byte ordering.
        byteArray = xcp.Utility.arrangeBytes(byteOrder, numberOfBytes, hexString);
    end
    
    function value = unpackParameter(byteOrder, numberOfBytes, byteArray)
    % unpackParameter Translates a parameter from raw bytes to decimal value.
    %
    %   This method is used to convert a parameter from a raw array of
    %   bytes to a decimal value after being received in an XCP response
    %   message. Some command parameters are larger than a single byte and
    %   so bytes require proper handling to use. All parameters are
    %   unsigned integer types, so no special conversion handling is
    %   required.
        
        % Convert the input byte array to a hexadecimal string according to
        % the byte ordering.
        hexString = xcp.Utility.concatenateBytes(byteOrder, numberOfBytes, byteArray);
        % Convert the hexadecimal string to a decimal value.
        value = hex2dec(hexString);
    end
    
    
    function byteArray = packMeasurement(info, value)
    % packMeasurement Translates a measurement from decimal value to raw bytes.
    %
    %   This method is used a measurement is to be transmitted and the
    %   decimal value needs to be converted into a raw array of bytes. The
    %   method enforces engineering unit value limits from the A2L file. It
    %   then applies proper type casting and management to keep the
    %   integrity of the original value. Lastly, the array of bytes are
    %   properly order according to the A2L information.
    
        % Apply minimum and maximum limits.
        if value < info.LowerLimit
            value = info.LowerLimit;
        elseif value > info.UpperLimit
            value = info.UpperLimit;
        end
        
        % Turn the value into a hexadecimal string based on the data type.
        switch info.DataType
            case 'UBYTE'
                hexString = sprintf('%02X', uint8(value));
            case {'SBYTE', 'BYTE'}
                hexString = sprintf('%02X', typecast(int8(value), 'uint8'));
            case 'UWORD'
                hexString = sprintf('%04X', uint16(value));
            case {'SWORD', 'WORD'}
                hexString = sprintf('%04X', typecast(int16(value), 'uint16'));
            case {'UDWORD', 'ULONG'}
                hexString = sprintf('%08X', uint32(value));
            case {'SDWORD', 'DWORD', 'SLONG', 'LONG'}
                hexString = sprintf('%08X', typecast(int32(value), 'uint32'));
            case 'UDLONG'
                hexString = sprintf('%016X', uint64(value));
            case {'SDLONG', 'DLONG'}
                hexString = sprintf('%016X', typecast(int64(value), 'uint64'));
            case 'FLOAT32_IEEE'
                hexString = num2hex(single(value));
            case 'FLOAT64_IEEE'
                hexString = num2hex(double(value));
        end
        
        % Translate the value into bytes.
        byteArray = xcp.Utility.arrangeBytes(info.ByteOrder, info.SizeInBytes, hexString);
    end
    
    function value = unpackMeasurement(info, byteArray)
    % unpackMeasurement Translates a measurement from raw bytes to decimal value.
    %
    %   This method is used when a measurement is received from slave and
    %   the raw array of bytes needs to be converted into a decimal value.
    %   The method applies proper type casting and management as well as
    %   enforcing engineering unit value limits from the A2L file.
    
        % Translate the bytes into a single hex string.
        hexString = xcp.Utility.concatenateBytes(info.ByteOrder, info.SizeInBytes, byteArray);
        
        % Type cast the value to the appropriate type as a reinterpretive
        % conversion.
        switch info.DataType
            case 'UBYTE'
                value  = sscanf(hexString, '%x');
                value = cast(value, 'uint8');
            case {'SBYTE', 'BYTE'}
                value  = sscanf(hexString, '%lx');
                value = typecast(value, 'int8');
                value = value(1);
            case 'UWORD'
                value  = sscanf(hexString, '%x');
                value = cast(value, 'uint16');
            case {'SWORD', 'WORD'}
                value  = sscanf(hexString, '%lx');
                value = typecast(value, 'int16');
                value = value(1);
            case {'UDWORD', 'ULONG'}
                value  = sscanf(hexString, '%x');
                value = cast(value, 'uint32');
            case {'SDWORD', 'DWORD', 'SLONG', 'LONG'}
                value  = sscanf(hexString, '%lx');
                value = typecast(value, 'int32');
                value = value(1);
            case 'UDLONG'
                value  = sscanf(hexString, '%lx');
            case {'SDLONG', 'DLONG'}
                value  = sscanf(hexString, '%lx');
                value = typecast(value, 'int64');
            case 'FLOAT32_IEEE'
                value = uint32(hex2dec(hexString));
                value = typecast(value, info.MATLABType);
            case 'FLOAT64_IEEE'
                value = hex2num(hexString);
        end

        % Apply minimum and maximum limits.
        if value < info.LowerLimit
            value = info.LowerLimit;
        elseif value > info.UpperLimit
            value = info.UpperLimit;
        end
    end
    
    
    function outByteArray = arrangeBytes(byteOrder, numberOfBytes, inByteArray)
    % arrangeBytes Organizes an array of bytes to a given order.
    %
    %   This method is used to take a general array of bytes and arrange
    %   those bytes according to the specified ordering (big or little
    %   endian).
        
        % Initialize an empty array to store the converted bytes.
        outByteArray = [];
        
        % Pack the bytes depending on the byte ordering of the measurement.
        switch byteOrder
            case {'MSB_LAST', 'BYTE_ORDER_MSB_LAST'}
                % For MSB last, we organize the bytes so that subsequent
                % bytes are placed at the front of the numeric byte array.
                for ii = 1:numberOfBytes
                    outByteArray = [hex2dec(inByteArray(((ii * 2) - 1):(ii * 2))) outByteArray]; %#ok<AGROW>
                end
            case {'MSB_FIRST', 'BYTE_ORDER_MSB_FIRST'}
                % For MSB first, we organize the bytes so that subsequent
                % bytes are placed at the end of the numeric byte array.
                for ii = 1:numberOfBytes
                    outByteArray = [outByteArray hex2dec(inByteArray(((ii * 2) - 1):(ii * 2)))]; %#ok<AGROW>
                end
        end
    end
    
    function hexString = concatenateBytes(byteOrder, numberOfBytes, byteArray)
    % concatenateBytes Turns an array of bytes into a hexadecimal string.
    %
    %   This method is used to turned an array of bytes into a single 
    %   hexadecimal string that can by used by the calling function to 
    %   ultimately turn the byte array into a decimal value.
        
        % Initialize an empty string to store the hex digits.
        hexString = '';
        
        % Set the hex digits depending on the byte ordering of the measurement.
        switch byteOrder
            case {'MSB_LAST', 'BYTE_ORDER_MSB_LAST'}
                % For MSB last, we organize the bytes so that subsequent
                % bytes are placed at the front of the numeric byte array.
                for ii = 1:numberOfBytes
                    hexString = [dec2hex(byteArray(ii), 2) hexString]; %#ok<AGROW>
                end
            case {'MSB_FIRST', 'BYTE_ORDER_MSB_FIRST'}
                % For MSB first, we organize the bytes so that subsequent
                % bytes are placed at the end of the numeric byte array.
                for ii = 1:numberOfBytes
                    hexString = [hexString dec2hex(byteArray(ii), 2)]; %#ok<AGROW>
                end
        end
    end
    
end
    
end