/*****************************************************************************
 *
 * File: Common9.ddl
 * Version: 9.2.1
 *
 *****************************************************************************
 * Copyright (c) 2010, HART Communication Foundation, All Rights Reserved
 *****************************************************************************
 *
 * Description: This file contains the DDL based model of the Common Practice
 *      Command Soecification Rev.9.0.  There were significant changes in this 
 *      model reflecting the increasing focus on the device variable. This 
 *      resulted in a hierachal model that matches the one taught in the 
 *      Writing Device Description Workshop and the Command Summary 
 *      Specification.
 *
 * Source Specifications
 *      Command Practice Command Specification      Rev.9.1
 *      Command Summary Specification               Rev.9.0
 *      Universal Command Specification             Rev.7.1
 *      Common Tables Specification                 Rev.19.0
 *
 *****************************************************************************
 */

/*****************************************************************************
 * The manufacturer line
 *****************************************************************************
 */
MANUFACTURER  STANDARD, DEVICE_TYPE _COMMON_PRACTICE, DEVICE_REVISION 9, DD_REVISION 2

/*****************************************************************************
 * Include Files
 *****************************************************************************
 */
#include "macros.h"
#include "methods.h"

/*****************************************************************************
 * Definitions (#define, typedef, enum)
 *****************************************************************************
 */
#define UPDATE_IN_PROGRESS      8
#define DEVICE_BUSY             32
#define MAXIMUM_RESET_RETRIES   10
/*
#ifndef _PDM_
IMPORT STANDARD _UNIVERSAL, DEVICE_REVISION 7, DD_REVISION 2      
#else
IMPORT "Univ7.ddl"
#endif
*/
IMPORT "Univ7.ddl"
{
    VARIABLE device_specific_status_0;
    VARIABLE device_specific_status_1;
    VARIABLE device_specific_status_2;
    VARIABLE device_specific_status_3;
    VARIABLE device_specific_status_4;
    VARIABLE device_specific_status_5;
    VARIABLE device_specific_status_14;
    VARIABLE device_specific_status_15;
    VARIABLE device_specific_status_16;
    VARIABLE device_specific_status_17;
    VARIABLE device_specific_status_18;
    VARIABLE device_specific_status_19;
    VARIABLE device_specific_status_20;
    VARIABLE device_specific_status_21;
    VARIABLE device_specific_status_22;
    VARIABLE device_specific_status_23;
    VARIABLE device_specific_status_24;
    VARIABLE config_change_counter;
}

/*
 *****************************************************************************
 * Common Practice Command Spec
 * Section 6.1
 * Data Link Layer Commands.  The commands affect the operation of the Data
 * Layer or Enhances its capabilities
 *
 * Commands 59 72 73
 */

COMMAND write_number_of_response_preambles
{
    NUMBER 59;
    OPERATION WRITE;
    TRANSACTION
    {
        REQUEST
        {
            response_preambles
        }
        REPLY
        {
            response_code, device_status, response_preambles
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,            [no_command_specific_errors];
        3,  DATA_ENTRY_ERROR,   [passed_parameter_too_large];
        4,  DATA_ENTRY_ERROR,   [passed_parameter_too_small];
        5,  DATA_ENTRY_ERROR,   [too_few_data_bytes_recieved];
        6,  MISC_ERROR,         [xmtr_specific_command_error];
        7,  MODE_ERROR,         [in_write_protect_mode];
        8,  DATA_ENTRY_WARNING, [set_to_nearest_possible_value];
        16, MODE_ERROR,         [access_restricted];
        32, MODE_ERROR,         [busy];
    }
}

/*
 *****************************************************************************
 * This Command causes the Field Device to visually or mechanically indicate
 * the reception of the command.  It assists in troubleshooting wiring or in
 * the identification of the field device
 */
COMMAND squawk
{
    NUMBER 72;
    OPERATION COMMAND;
    TRANSACTION
    {
        REQUEST {}
        REPLY
        {
            response_code, device_status
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,    [no_command_specific_errors];
        6,  MISC_ERROR, [xmtr_specific_command_error];
        9,  MODE_ERROR, [unable_to_squawk];
        16, MODE_ERROR, [access_restricted];
        32, MODE_ERROR, [busy];
    }
}

METHOD makeItSquawk 
{
    LABEL [squawk];
    HELP [squawk_field_device_help];
    DEFINITION 
    {
        char status[STATUS_SIZE];
        char disp_string1[60];
        char disp_string2[60];
        int  count,     /* how many time to send the squawk command */
             exit,      /* flags when it is time to leave */
             i;         /* for loop counter */
        int  slen1;
        int  slen2;
        int  choice;

        exit  = 1;
        count = 5;
        slen1 = 60;
        slen2 = 60;

        while ( exit ) 
        {
            get_dictionary_string(begin_squawk, disp_string1, slen1);
            get_dictionary_string(choices_number_squawk_exit, disp_string2, slen2);

            choice = SELECT_FROM_LIST(disp_string1, disp_string2);

            switch (choice) 
            {
            case 0:
                get_dictionary_string(change_number_of_squawks, disp_string1, slen1);
                GET_LOCAL_VAR_VALUE(disp_string1, count);
                break;
            case 1:
                get_dictionary_string(squawk_in_process, disp_string1, slen1);
                for (i = 0; i < count ; i++) 
                {
                    send(72, status);
                    DELAY(1, disp_string1);
                }
                break;
            case 2:
                exit = 0;
                break;
            }
        }
    }
}

/*
 *****************************************************************************
 * This Command allows for mechanical identification of a field device
 */
COMMAND findDevice
{
    NUMBER 73;
    OPERATION COMMAND;
    TRANSACTION
    {
        REQUEST {}
        REPLY
        {
            IDENTIFY_REPLY_7
        }
    }
    RESPONSE_CODES 
    {
        0,  SUCCESS,    [no_command_specific_errors];
    }
}

/*
 *****************************************************************************
 * Common Practice Command Spec
 * Section 6.2
 * PV Range Commands.  The commands affect the scaling of the digital value
 * to/from the loop current
 *
 * Commands 35, 36, 37
 */

/*
 *****************************************************************************
 * Write PV Range Values  changes the scaling relationship between the loop
 * current and the PV Digital Value
 *
 *NOTE: As per the Protocol Specification the Engineering Units Can be different
 *  from the PV Units.  The Units sent to the device must not affect the PV 
 *  Units Use Command 44 for this purpose
 */
COMMAND write_pv_range_values
{
    NUMBER 35;
    OPERATION WRITE;
    TRANSACTION 
    {
        REQUEST
        {
            PV.RANGING.RANGE_UNITS (INFO), PV.RANGING.UPPER_RANGE_VALUE, PV.RANGING.LOWER_RANGE_VALUE
        }
        REPLY
        {
            response_code, device_status,
            PV.RANGING.RANGE_UNITS (INFO), PV.RANGING.UPPER_RANGE_VALUE, PV.RANGING.LOWER_RANGE_VALUE
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,            [no_command_specific_errors];
        2,  DATA_ENTRY_ERROR,   [invalid_selection];
        5,  DATA_ENTRY_ERROR,   [too_few_data_bytes_recieved];
        6,  MISC_ERROR,         [xmtr_specific_command_error];
        7,  MODE_ERROR,         [in_write_protect_mode];
        8,  DATA_ENTRY_WARNING, [set_to_nearest_possible_value];
        9,  DATA_ENTRY_ERROR,   [lower_range_value_too_high];
        10, DATA_ENTRY_ERROR,   [lower_range_value_too_low];
        11, DATA_ENTRY_ERROR,   [upper_range_value_too_high];
        12, DATA_ENTRY_ERROR,   [upper_range_value_too_low];
        13, DATA_ENTRY_ERROR,   [URV_and_LRV_out_of_limits];
        14, DATA_ENTRY_WARNING, [span_too_small];
        16, MODE_ERROR,         [access_restricted];
        18, DATA_ENTRY_ERROR,   [invalid_units];
        29, DATA_ENTRY_ERROR,   [invalid_span];
        32, MODE_ERROR,         [busy]; 
    }
}

/*
 *****************************************************************************
 * This Command sets the URV to the current conditions.  Sets the 100 Percent
 * Range operating point
 */
COMMAND set_pv_upper_range_value
{
    NUMBER 36;
    OPERATION COMMAND;
    TRANSACTION
    {
        REQUEST {}
        REPLY
        {
            response_code, device_status
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,            [no_command_specific_errors];
        6,  MISC_ERROR,         [xmtr_specific_command_error];
        7,  MODE_ERROR,         [in_write_protect_mode];
        8,  DATA_ENTRY_WARNING, [set_to_nearest_possible_value];
        9,  PROCESS_ERROR,      [applied_process_too_high];
        10, PROCESS_ERROR,      [applied_process_too_low];
        14, DATA_ENTRY_WARNING, [span_too_small];
        16, MODE_ERROR,         [access_restricted];
        29, DATA_ENTRY_ERROR,   [invalid_span];
        32, MODE_ERROR,         [busy];
    }
}

/*
 *****************************************************************************
 * This Command sets the URV to the current conditions.  Sets the 0 Percent
 * Range operating point
 */
COMMAND set_pv_lower_range_value
{
    NUMBER 37;
    OPERATION COMMAND;
    TRANSACTION
    {
        REQUEST {}
        REPLY
        {
            response_code, device_status
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,            [no_command_specific_errors];
        6,  MISC_ERROR,         [xmtr_specific_command_error];
        7,  MODE_ERROR,         [in_write_protect_mode];
        9,  PROCESS_ERROR,      [applied_process_too_high];
        10, PROCESS_ERROR,      [applied_process_too_low];
        14, DATA_ENTRY_WARNING, [new_LRV_pushed_URV_over_USL];
        16, MODE_ERROR,         [access_restricted];
        29, DATA_ENTRY_ERROR,   [invalid_span];
        32, MODE_ERROR,         [busy];
    }
}

METHOD applied_rerange
{
    LABEL [apply_values];
    HELP [applied_values_help];
    DEFINITION
    {
        char status[STATUS_SIZE];
        char disp_string1[60];
        char disp_string2[60];
        long varid[3];
        int choice;
        int slen1;
        int slen2;

        slen1 = 60;
        slen2 = 60;

        IGNORE_ALL_RESPONSE_CODES();
        IGNORE_ALL_DEVICE_STATUS();
        XMTR_IGNORE_ALL_RESPONSE_CODES();
        XMTR_IGNORE_ALL_DEVICE_STATUS();

        get_dictionary_string(remove_loop_from_auto, disp_string1, slen1);
        ACKNOWLEDGE(disp_string1);
        add_abort_method(return_to_normal);

        varid[0] = VARID(PV.DEVICE_VARIABLE.DIGITAL_VALUE);
        varid[1] = VARID(PV.DEVICE_VARIABLE.DIGITAL_UNITS);

        while (1)
        {
            get_dictionary_string(set_the, disp_string1, slen1);
            get_dictionary_string(choice_4_20_exit, disp_string2, slen2);

            switch (SELECT_FROM_LIST(disp_string1, disp_string2))
            {
                case 0:
                    get_dictionary_string(apply_new_4ma_input, disp_string1,slen1);
                    ACKNOWLEDGE(disp_string1);

                    do 
                    {
                        send_command(1);

                        get_dictionary_string(current_applied_process_val, disp_string1, slen1);
                        get_dictionary_string(set_4ma_read_new_leave, disp_string2, slen2);

                        choice = select_from_list(disp_string1, varid, disp_string2);

                    } while (choice == 1);

                    if (choice == 0)
                    {
                        send(37, status);

                        if (status[STATUS_RESPONSE_CODE])
                        {
                            display_response_status(37, status[STATUS_RESPONSE_CODE]);
                        }

                        send_command(15);
                    }
                    break ;

                case 1:
                    get_dictionary_string(apply_new_20ma_input, disp_string1, slen1);
                    ACKNOWLEDGE(disp_string1);

                    do
                    {
                        send_command(1);

                        get_dictionary_string(current_applied_process_val, disp_string1, slen1);
                        get_dictionary_string(set_20ma_read_new_leave, disp_string2, slen2);

                        choice = select_from_list(disp_string1, varid,disp_string2);

                    } while (choice == 1);

                    if (choice == 0)
                    {
                        send(36,status);

                        if (status[STATUS_RESPONSE_CODE])
                        {
                            display_response_status(36, status[STATUS_RESPONSE_CODE]);
                        }

                        send_command(15);
                    }
                    break;

                case 2:
                    process_abort();

                default:
                    process_abort();
            }
        }
    }
}

/*
 *****************************************************************************
 * Common Practice Command Spec
 * Section 6.3
 * Loop Current Commands
 *
 * Commands 40, 45, 46
 */

COMMAND enter_exit_fixed_pv_current_mode
{
    NUMBER 40;
    OPERATION COMMAND;
    TRANSACTION
    {
        REQUEST
        {
            PV.DAQ.ANALOG_VALUE
        }
        REPLY
        {
            response_code, device_status, PV.DAQ.ANALOG_VALUE
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        3,  DATA_ENTRY_ERROR, [passed_parameter_too_large];
        4,  DATA_ENTRY_ERROR, [passed_parameter_too_small];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        6,  MISC_ERROR,       [xmtr_specific_command_error];
        7,  MODE_ERROR,       [in_write_protect_mode];
        11, MODE_ERROR,       [in_multidrop_mode];
        16, MODE_ERROR,       [access_restricted];
        32, MODE_ERROR,       [busy];
    }
}

COMMAND trim_pv_current_dac_zero
{
    NUMBER 45;
    OPERATION COMMAND;
    TRANSACTION
    {
        REQUEST
        {
            PV.DAQ.ANALOG_VALUE
        }
        REPLY
        {
            response_code, device_status, PV.DAQ.ANALOG_VALUE
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        3,  DATA_ENTRY_ERROR, [passed_parameter_too_large];
        4,  DATA_ENTRY_ERROR, [passed_parameter_too_small];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        6,  MISC_ERROR,       [xmtr_specific_command_error];
        7,  MODE_ERROR,       [in_write_protect_mode];
        9,  MODE_ERROR,       [not_in_proper_current_mode];
        11, MODE_ERROR,       [in_multidrop_mode];
        16, MODE_ERROR,       [access_restricted];
        32, MODE_ERROR,       [busy];
    }
}

COMMAND trim_pv_current_dac_gain
{
    NUMBER 46;
    OPERATION COMMAND;
    TRANSACTION
    {
        REQUEST
        {
            PV.DAQ.ANALOG_VALUE
        }
        REPLY
        {
            response_code, device_status, PV.DAQ.ANALOG_VALUE
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        3,  DATA_ENTRY_ERROR, [passed_parameter_too_large];
        4,  DATA_ENTRY_ERROR, [passed_parameter_too_small];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        6,  MISC_ERROR,       [xmtr_specific_command_error];
        7,  MODE_ERROR,       [in_write_protect_mode];
        9,  MODE_ERROR,       [not_in_proper_current_mode];
        11, MODE_ERROR,       [in_multidrop_mode];
        16, MODE_ERROR,       [access_restricted];
        32, MODE_ERROR,       [busy];
    }
}
 
METHOD transmitter_loop_test
{
    LABEL [loop_test];
    HELP [loop_test_help];
    DEFINITION
    {
        char status[STATUS_SIZE];
        char disp_string1[60];
        char disp_string2[60];
        long var_id[1];
        int use_abort_method;
        int choice;
        int slen1;
        int slen2;

        slen1 = 60;
        slen2 = 60;

        IGNORE_ALL_RESPONSE_CODES();
        IGNORE_ALL_DEVICE_STATUS();
        XMTR_IGNORE_ALL_DEVICE_STATUS();
        XMTR_IGNORE_ALL_RESPONSE_CODES();

        get_dictionary_string(remove_loop_from_auto, disp_string1, slen1);
        ACKNOWLEDGE(disp_string1);
        add_abort_method(return_to_normal);

        /* 
         * Here comes the standard part for analog outputs, e.g. transmitters 
         */
        use_abort_method = 0;

        do 
        {
            get_dictionary_string(choose_analog_output_level, disp_string1, slen1);
            get_dictionary_string(choices_4_20_other_end, disp_string2, slen2);

            choice = SELECT_FROM_LIST(disp_string1, disp_string2);

            switch (choice)
            {
            case 0:
                assign_float(PV.DAQ.ANALOG_VALUE,4.0);
                break;

            case 1:
                assign_float(PV.DAQ.ANALOG_VALUE,20.0);
                break;

            case 2:
                get_dictionary_string(loop_output, disp_string1, slen1);
                GET_DEV_VAR_VALUE(disp_string1, PV.DAQ.ANALOG_VALUE);
                break;

            case 3:
            default:
                process_abort();
                break;
            }

            send(40, status);

            if (!use_abort_method)
            {
                if ((status[STATUS_RESPONSE_CODE] != 0)
                        && ( status[STATUS_RESPONSE_CODE] != 3)
                        && ( status[STATUS_RESPONSE_CODE] != 4))
                {
                    display_response_status(40,status[STATUS_RESPONSE_CODE]);
                    get_dictionary_string(abort_last_error, disp_string1, slen1);
                    DELAY(2, disp_string1);
                    process_abort();
                }

                if (status[STATUS_RESPONSE_CODE] == 0)
                {
                    remove_abort_method(return_to_normal);
                    add_abort_method(leave_fixed_current_mode);
                    use_abort_method =1;
                }
            }

            if (status[STATUS_RESPONSE_CODE])
            {
                /* 
                 * Display the resonse code from the error 
                 */
                display_response_status(40, status[STATUS_RESPONSE_CODE]);

                /* 
                 * If the response code is either 3 or 4, meaning the value
                 * was either too large or too small, do not abort method.
                 * Allow the user to try again. 
                 */ 
                if ((status[STATUS_RESPONSE_CODE] != 3)
                        && ( status[STATUS_RESPONSE_CODE] != 4))
                {
                    get_dictionary_string(abort_last_error, disp_string1, slen1);
                    DELAY(2, disp_string1);
                    process_abort();
                }
            }
            else
            {
                var_id[0] = VARID(PV.DAQ.ANALOG_VALUE);
                get_dictionary_string(fld_dev_otpt_fixed, disp_string1, slen1);
                acknowledge(disp_string1, var_id);
            }
        } while (choice < 3);

        process_abort();
    }
}

METHOD transmitter_dac_trim
{
    LABEL [DAC_trim];
    HELP [digital_to_analog_trim_help];
/*  APPHELP "This type of calibration is usually used to compensate for"
            " drifting or aging output electronics"; */
    DEFINITION
    {
        char status[STATUS_SIZE];
        char disp_string1[60];
        char disp_string2[60];
        long var_id[1];
        int retry;
        int slen1;
        int slen2;

        slen1 = 60;
        slen2 = 60;

        IGNORE_ALL_DEVICE_STATUS();
        IGNORE_ALL_RESPONSE_CODES();
        XMTR_IGNORE_ALL_DEVICE_STATUS();
        XMTR_IGNORE_ALL_RESPONSE_CODES();

        get_dictionary_string(remove_loop_from_auto, disp_string1, slen1);
        ACKNOWLEDGE(disp_string1);
        add_abort_method(return_to_normal);

        get_dictionary_string(connect_reference_meter, disp_string1, slen1);
        ACKNOWLEDGE(disp_string1);

        get_dictionary_string(setting_fld_dev_4_ma, disp_string1, slen1);
        ACKNOWLEDGE(disp_string1);

        assign_float(PV.DAQ.ANALOG_VALUE,4.0);
        send(40, status);

        if (status[STATUS_RESPONSE_CODE])
        {
            display_response_status(40,status[STATUS_RESPONSE_CODE]);
            get_dictionary_string(abort_last_error, disp_string1, slen1);
            DELAY(2, disp_string1);
            process_abort();
        }

        remove_abort_method(return_to_normal);
        add_abort_method(leave_fixed_current_mode);

        var_id[0] = VARID(PV.DAQ.ANALOG_VALUE);

        do
        {
            get_dictionary_string(enter_meter_value, disp_string1, slen1);
            GET_DEV_VAR_VALUE(disp_string1, PV.DAQ.ANALOG_VALUE);

            send(45, status);

            assign_float(PV.DAQ.ANALOG_VALUE, 4.0);  /*Put the previous value back */

            if (( status[STATUS_RESPONSE_CODE] == 3) || (status[STATUS_RESPONSE_CODE] == 4))
            {
                display_response_status(45, status[STATUS_RESPONSE_CODE]);
                retry = 1;
            }
            else if (status[STATUS_RESPONSE_CODE])
            {
                display_response_status(45, status[STATUS_RESPONSE_CODE]);
                get_dictionary_string(abort_last_error, disp_string1, slen1);
                DELAY(2, disp_string1);
                process_abort();
            }
            else
            {
                get_dictionary_string(fld_dev_otpt_equal_ref_meter, disp_string1, slen1);
                get_dictionary_string(yes_no, disp_string2, slen2);
                retry = select_from_list(disp_string1, var_id, disp_string2);
            }
        } while (retry);

        get_dictionary_string(setting_fld_dev_20_ma, disp_string1,slen1);
        ACKNOWLEDGE(disp_string1);

        assign_float(PV.DAQ.ANALOG_VALUE, 20.0);

        send(40, status);

        if ( status[STATUS_RESPONSE_CODE])
        {
            display_response_status(40, status[STATUS_RESPONSE_CODE]);
            get_dictionary_string(abort_last_error, disp_string1, slen1);
            DELAY(2, disp_string1);
            process_abort();
        }

        do
        {
            get_dictionary_string(enter_meter_value, disp_string1, slen1);
            GET_DEV_VAR_VALUE(disp_string1, PV.DAQ.ANALOG_VALUE);

            send(46,status);

            assign_float(PV.DAQ.ANALOG_VALUE, 20.0);  /*Put the previous value back */

            if ((status[STATUS_RESPONSE_CODE] == 3 ) || (status[STATUS_RESPONSE_CODE] == 4))
            {
                display_response_status(46, status[STATUS_RESPONSE_CODE]);
                retry = 1;
            }
            else if ( status[STATUS_RESPONSE_CODE])
            {
                display_response_status(46, status[STATUS_RESPONSE_CODE]);
                get_dictionary_string(abort_last_error, disp_string1, slen1);
                DELAY(2, disp_string1);
                process_abort();
            }
            else
            {
                get_dictionary_string(fld_dev_otpt_equal_ref_meter, disp_string1, slen1);
                get_dictionary_string(yes_no, disp_string2, slen2);
                retry = select_from_list(disp_string1, var_id, disp_string2);
            }
        } while (retry);

        process_abort() ;
    }
}

METHOD valve_loop_test
{
    LABEL [loop_test];
    HELP [valve_loop_test_help];
    DEFINITION
    {
        char status[STATUS_SIZE];
        char disp_string1[77];
        char disp_string2[60];
        long var_id[1];
        int use_abort_method;
        int choice;
        int slen1;
        int slen2;
        float current;

        slen1 = 77;
        slen2 = 60;

        IGNORE_ALL_RESPONSE_CODES();
        IGNORE_ALL_DEVICE_STATUS();
        XMTR_IGNORE_ALL_DEVICE_STATUS();
        XMTR_IGNORE_ALL_RESPONSE_CODES();

        get_dictionary_string(remove_loop_from_auto, disp_string1, slen1);
        ACKNOWLEDGE(disp_string1);
        add_abort_method(return_to_normal);

        var_id[0] = VARID(PV.DAQ.ANALOG_VALUE);

        /* 
         * Here comes the standard part for analog inputs, e.g. valves 
         */
        do
        {
            get_dictionary_string(choose_analog_input_level, disp_string1, slen1);
            get_dictionary_string(choices_4_20_other_end, disp_string2, slen2);

            choice = SELECT_FROM_LIST(disp_string1, disp_string2);

            switch (choice)
            {
            case 0:
                current = 4.0;
                get_dictionary_string(apply_current_input_to_value, disp_string1, slen1);
                break;

            case 1:
                current = 20.0;
                get_dictionary_string(apply_current_input_to_value, disp_string1, slen1);
                break;

            case 2:
                get_dictionary_string(apply_current_input_to_desired_value, disp_string1, slen1);
                break;

            case 3:
            default:
                process_abort();
                break;
            }

            send(2, status);     /*Test the device to see if all is ok */

            if ((status[STATUS_RESPONSE_CODE] != 0) && (status[STATUS_RESPONSE_CODE] != 8))
            {
                /* 
                 * Only abort if the response code something value other
                 * than 0 (sucess) or 8 (warning)  
                 */
                display_response_status(2, status[STATUS_RESPONSE_CODE]);
                get_dictionary_string(abort_last_error, disp_string1, slen1);
                DELAY(2, disp_string1);
                process_abort();
            }

            acknowledge(disp_string1, var_id); /* disp_string1 is defined in switch/case above */

        } while (choice < 3);

        process_abort();
    }
}

METHOD valve_adc_trim
{
    LABEL [adc_trim];
    HELP [analog_to_digital_trim_help];
/*  APPHELP "This type of calibration is usually used to compensate for"
            " drifting or aging output electronics"; */
    DEFINITION
    {
        char status[STATUS_SIZE];
        char disp_string1[77];
        char disp_string2[60];
        long var_id[1];
        int retry;
        int slen1;
        int slen2;
        float current;

        slen1 = 77;
        slen2 = 60;

        IGNORE_ALL_DEVICE_STATUS();
        IGNORE_ALL_RESPONSE_CODES();
        XMTR_IGNORE_ALL_DEVICE_STATUS();
        XMTR_IGNORE_ALL_RESPONSE_CODES();

        get_dictionary_string(remove_loop_from_auto, disp_string1, slen1);
        ACKNOWLEDGE(disp_string1);
        add_abort_method(return_to_normal);

        get_dictionary_string(connect_reference_meter, disp_string1, slen1);
        ACKNOWLEDGE(disp_string1);

        var_id[0] = VARID(PV.DAQ.ANALOG_VALUE);

        /*
         * 4 mA test
         */
        current = 4.0;

        send(2, status);     /*Test the device to see if all is ok */

        if ((status[STATUS_RESPONSE_CODE] != 0) && (status[STATUS_RESPONSE_CODE] != 8))
        {
            display_response_status(2, status[STATUS_RESPONSE_CODE]);
            get_dictionary_string(abort_last_error, disp_string1, slen1);
            DELAY(2, disp_string1);
            process_abort();
        }

        get_dictionary_string(apply_current_input_to_value, disp_string1, slen1);
        acknowledge(disp_string1, var_id); 
  
        do
        {
            get_dictionary_string(enter_meter_value, disp_string1, slen1);
            GET_DEV_VAR_VALUE(disp_string1, PV.DAQ.ANALOG_VALUE);

            send(45, status);

            assign_float(PV.DAQ.ANALOG_VALUE, 4.0);

            if ((status[STATUS_RESPONSE_CODE] == 3 ) || (status[STATUS_RESPONSE_CODE] == 4))
            {
                display_response_status(45, status[STATUS_RESPONSE_CODE]);
                retry = 1;
            }
            else if (status[STATUS_RESPONSE_CODE])
            {
                display_response_status(45, status[STATUS_RESPONSE_CODE]);
                get_dictionary_string(abort_last_error, disp_string1, slen1);
                DELAY(2, disp_string1);
                process_abort();
            }
            else
            {
                get_dictionary_string(fld_dev_current_equal_ref_meter, disp_string1, slen1);
                get_dictionary_string(yes_no, disp_string2, slen2);
                retry = select_from_list(disp_string1, var_id, disp_string2);
            }
        } while (retry);

        /*
         * 20 mA test
         */
        current = 20.0;

        send(2, status);     /*Test the device to see if all is ok */

        if ((status[STATUS_RESPONSE_CODE] != 0) && (status[STATUS_RESPONSE_CODE] != 8))
        {
            display_response_status(2, status[STATUS_RESPONSE_CODE]);
            get_dictionary_string(abort_last_error, disp_string1, slen1);
            DELAY(2, disp_string1);
            process_abort();
        }

        get_dictionary_string(apply_current_input_to_value, disp_string1, slen1);
        acknowledge(disp_string1, var_id);

        do
        {
            get_dictionary_string(enter_meter_value, disp_string1, slen1);
            GET_DEV_VAR_VALUE(disp_string1, PV.DAQ.ANALOG_VALUE);

            send(46, status);

            assign_float(PV.DAQ.ANALOG_VALUE, 20.0);

            if ((status[STATUS_RESPONSE_CODE] == 3 ) || (status[STATUS_RESPONSE_CODE] == 4))
            {
                display_response_status(46, status[STATUS_RESPONSE_CODE]);
                retry = 1;
            }
            else if (status[STATUS_RESPONSE_CODE])
            {
                display_response_status(46, status[STATUS_RESPONSE_CODE]);
                get_dictionary_string(abort_last_error, disp_string1, slen1);
                DELAY(2, disp_string1);
                process_abort();
            }
            else
            {
                get_dictionary_string(fld_dev_current_equal_ref_meter, disp_string1, slen1);
                get_dictionary_string(yes_no, disp_string2, slen2);
                retry = select_from_list(disp_string1, var_id, disp_string2);
            }
        } while (retry);

        process_abort();
    }
}

METHOD leave_fixed_current_mode
{
    LABEL [leaving_fixed_current_mode];
    HELP [leaving_fixed_current_mode_help_2];
    DEFINITION
    {
        char status[STATUS_SIZE];
        char disp_string1[60];
        long var_id[1];
        int slen1;

        slen1 = 60;

        IGNORE_ALL_RESPONSE_CODES();

        assign_float(PV.DAQ.ANALOG_VALUE, 0.0);
        
        do
        {
            get_dictionary_string(return_fld_dev_to_orig_otpt, disp_string1, slen1);
            DELAY(3, disp_string1);

            send(40, status);

            if (status[STATUS_RESPONSE_CODE])
            {
                display_response_status(40, status[STATUS_RESPONSE_CODE]);
            }

        } while (status[STATUS_RESPONSE_CODE]);

        get_dictionary_string(loop_may_be_returned_to_auto, disp_string1, slen1);
        ACKNOWLEDGE(disp_string1);
    }
}

/*
 *****************************************************************************
 * Common Practice Command Spec
 * Section 6.4
 * Device management Commands
 *
 * Commands 41, 42, 71, 76, 89, 90, 95, 512, 513
 */

COMMAND perform_self_test  /* took out transmitter */
{
    NUMBER 41;
    OPERATION COMMAND;
    TRANSACTION
    {
        REQUEST {}
        REPLY
        {
            response_code, device_status
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,    [no_command_specific_errors];
        6,  MISC_ERROR, [xmtr_specific_command_error];
        16, MODE_ERROR, [access_restricted];
        32, MODE_ERROR, [busy];
    }
}

COMMAND perform_device_reset
{
    NUMBER 42;
    OPERATION COMMAND;
    TRANSACTION
    {
        REQUEST {}
        REPLY
        {
            response_code, device_status
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,    [no_command_specific_errors];
        6,  MISC_ERROR, [xmtr_specific_command_error];
        16, MODE_ERROR, [access_restricted];
        32, MODE_ERROR, [busy];
    }
}


COMMAND lock_device
{
    NUMBER 71;
    OPERATION COMMAND;
    TRANSACTION
    {
        REQUEST
        {
            lock_device_code
        }
        REPLY
        {
            response_code, device_status, lock_device_code
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        6,  MISC_ERROR,       [xmtr_specific_command_error];
        10, DATA_ENTRY_ERROR, [invalid_lock_code];
        11, MODE_ERROR,       [cannot_lock_device];
        16, MODE_ERROR,       [access_restricted];
        32, MODE_ERROR,       [busy];
        33, MODE_ERROR,       [delayed_response_initiated];
        34, MODE_ERROR,       [delayed_response_running];
        35, MODE_ERROR,       [delayed_response_dead];
        36, MODE_ERROR,       [delayed_response_conflict];
    }
}

COMMAND read_lock_device_state
{
    NUMBER 76;
    OPERATION READ;
    TRANSACTION
    {
        REQUEST {}
        REPLY
        {
            response_code, device_status, lock_device_status_code
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,    [no_command_specific_errors];
        6,  MISC_ERROR, [xmtr_specific_command_error];
        16, MODE_ERROR, [access_restricted];
        32, MODE_ERROR, [busy];
    }
}

/*
 * Methods for lock device, self test, device reset
 */

METHOD lock_unlock_device
{
    LABEL [lock_unlock_device];
    HELP  [lock_unlock_device_help];
    DEFINITION 
    {  
        char status[STATUS_SIZE];
        char disp_string1[60];
        char disp_string2[60];
        long var_id[1];
        int use_abort_method;
        int choice;
        int result;
        int locked;
        int slen1;
        int slen2;

        slen1 = 60;
        slen2 = 60;

        IGNORE_ALL_DEVICE_STATUS();
        IGNORE_ALL_RESPONSE_CODES();
        XMTR_IGNORE_ALL_DEVICE_STATUS();
        XMTR_IGNORE_ALL_RESPONSE_CODES();

        /* 
         * Send command 76 to read the lock device state
         */
        send(76, status);

        if(status[STATUS_RESPONSE_CODE])
        {
            display_response_status(76, status[STATUS_RESPONSE_CODE]);
            get_dictionary_string(abort_last_error, disp_string1, slen1);             
            DELAY(2, disp_string1);
            process_abort();
        }

        do
        {
            locked = (ivar_value(lock_device_status_code) & 0x01);

            if (locked)
            {
                /*  locked = 1 */
                get_dictionary_string(device_locked, disp_string1, slen1);
            }
            else
            {
                /* locked = 0 */
                get_dictionary_string(device_unlocked, disp_string1, slen1);
            }

            get_dictionary_string(yes_no, disp_string2, slen2);

            choice = SELECT_FROM_LIST(disp_string1, disp_string2);

            if (choice == 0)      /* If yes, user wants to change the lock state */
            {
                if (locked == 0)    /* If it is not locked */
                {
                    /* Lock the device */

                    /* 
                     * Determine if user wants to lock the device, Temporarly or Permanently 
                     */
                    get_dictionary_string(make_permanent, disp_string1, slen1);

                    result = SELECT_FROM_LIST(disp_string1, disp_string2);

                    if (result == 0)      /* If yes */
                    {
                        /* 
                         * Lock it Permanently
                         */
                        lassign (lock_device_code, 2);
                    }
                    else
                    {
                        /* 
                         * Lock it Temporarly
                         */
                        lassign (lock_device_code, 1);
                    }
                }
                else
                {
                    /* 
                     * Unlock the device
                     */
                    lassign (lock_device_code, 0);
                }

                /*
                 * Send command 71 to lock or Unlock the device
                 */
                send(71, status);
    
                if(status[STATUS_RESPONSE_CODE])
                {
                    display_response_status(71, status[STATUS_RESPONSE_CODE]);
                    get_dictionary_string(abort_last_error, disp_string1, slen1);             
                    DELAY(2, disp_string1);
                    process_abort();
                }

                /* 
                 * Send command 76 to read the lock device state to update it as a result of
                 * sending command 71
                 */
                send(76, status); 

                if(status[STATUS_RESPONSE_CODE])
                {
                    display_response_status(76, status[STATUS_RESPONSE_CODE]);
                    get_dictionary_string(abort_last_error, disp_string1, slen1);             
                    DELAY(2, disp_string1);
                    process_abort();
                }
            }
        } while(!choice);
    }
}

METHOD device_self_test 
{
    LABEL [selftest];
    HELP [selftest_help];
    DEFINITION
    {
        char status[STATUS_SIZE];
        char xmtr_status[MAX_XMTR_STATUS_LEN];
        char disp_string1[60];             
        long x;
        int number_of_tries;
        int slen1;

        slen1 = 60;

        get_dictionary_string(remove_loop_from_auto, disp_string1, slen1); 
        ACKNOWLEDGE(disp_string1);
        add_abort_method(return_to_normal);

        get_dictionary_string(about_to_perform_limited_selftest, disp_string1, slen1);
        ACKNOWLEDGE(disp_string1);

        get_dictionary_string(performing_selftest, disp_string1, slen1);
        PUT_MESSAGE(disp_string1);

        send(41, status);

        if(status[STATUS_RESPONSE_CODE])
        {
            display_response_status(41, status[STATUS_RESPONSE_CODE]);
            get_dictionary_string(abort_last_error, disp_string1, slen1);             
            DELAY(2, disp_string1);
            process_abort();
        }

        RETRY_ON_NO_DEVICE();
        number_of_tries = 0;

        do
        {
            get_more_status(status, xmtr_status);
        } while (((status[STATUS_RESPONSE_CODE] == DEVICE_BUSY)
                || (status[STATUS_RESPONSE_CODE] == UPDATE_IN_PROGRESS))
                && (number_of_tries++ < MAXIMUM_RESET_RETRIES));

        if ((status[STATUS_RESPONSE_CODE] == DEVICE_BUSY)
                || (status[STATUS_RESPONSE_CODE] == UPDATE_IN_PROGRESS))
        {
            get_dictionary_string(device_stuck_in_self_test, disp_string1, slen1);
            ACKNOWLEDGE(disp_string1);
        }
        else if (status[STATUS_RESPONSE_CODE])
        {
            display_response_status(48, status[STATUS_RESPONSE_CODE]);
            get_dictionary_string(abort_last_error, disp_string1, slen1);             
            DELAY(2, disp_string1);
        }
        else if (xmtr_status[0])
        {
            for (x=1; x < 0x100; x <<= 1)
            {
                if (xmtr_status[0] & x)
                {
                    display_xmtr_status(device_specific_status_0, x);
                }
            }
        }
        else
        {
            get_dictionary_string(self_test_ok, disp_string1, slen1);
            ACKNOWLEDGE(disp_string1);
        }

        process_abort();        /* this will call return_to_normal */
    }
}

METHOD device_master_reset 
{
    LABEL [device_reset];
    HELP [device_reset_help];
    DEFINITION 
    {
        char status[STATUS_SIZE];
        char xmtr_status[MAX_XMTR_STATUS_LEN];
        char disp_string1[60];             
        long x;
        int number_of_tries;
        int slen1;

        slen1 = 60;

        get_dictionary_string(remove_loop_from_auto, disp_string1, slen1); 
        ACKNOWLEDGE(disp_string1);
        add_abort_method(return_to_normal);

        get_dictionary_string(about_to_perform_device_reset, disp_string1, slen1);
        ACKNOWLEDGE(disp_string1);

        get_dictionary_string(device_reset_in_progress, disp_string1, slen1);
        PUT_MESSAGE(disp_string1);

        send(42, status);

        if(status[STATUS_RESPONSE_CODE])
        {
            display_response_status(42, status[STATUS_RESPONSE_CODE]);
            get_dictionary_string(abort_last_error, disp_string1, slen1);             
            DELAY(2, disp_string1);
            process_abort();
        }

        RETRY_ON_NO_DEVICE();
        number_of_tries = 0;

        do 
        {
            get_more_status(status, xmtr_status);
        } while (((status[STATUS_RESPONSE_CODE] == DEVICE_BUSY)
                || (status[STATUS_RESPONSE_CODE] == UPDATE_IN_PROGRESS))
                && (number_of_tries++ < MAXIMUM_RESET_RETRIES));

        if ((status[STATUS_RESPONSE_CODE] == DEVICE_BUSY)
                || (status[STATUS_RESPONSE_CODE] == UPDATE_IN_PROGRESS))
        {
            get_dictionary_string(device_stuck_in_device_reset, disp_string1, slen1);
            ACKNOWLEDGE(disp_string1);
        }
        else if (status[STATUS_RESPONSE_CODE])
        {
            display_response_status(48, status[STATUS_RESPONSE_CODE]);
            get_dictionary_string(abort_last_error, disp_string1, slen1);             
            DELAY(2, disp_string1);
        }
        else if (xmtr_status[0])
        {
            for (x=1; x < 0x100; x <<= 1)
            {
                if (xmtr_status[0] & x)
                {
                    display_xmtr_status(device_specific_status_0, x);
                }
            }
        }
        else
        {
            get_dictionary_string(device_reset_ok, disp_string1, slen1);
            ACKNOWLEDGE(disp_string1);
        }

        process_abort();        /* this will call return_to_normal */
    }
}

#if __TOKVER__ >= 800
// Real time clock commands 89 and 90

VARIABLE current_date
{
    LABEL "Current Date";
    HELP "Current Date based upon the real-time clock in the field device";
    CLASS DEVICE & DYNAMIC;
    HANDLING READ;
    TYPE DATE;
}

VARIABLE current_time 
{
    LABEL "Current Time";
    HELP "Current Time based upon the real-time clock in the field device";
    CLASS DEVICE & DYNAMIC;
    HANDLING READ;
    TYPE TIME_VALUE;
}

VARIABLE last_clock_date
{
    LABEL "Set Clock Date";
    HELP "Date to set the real-time clock in the field device to, or date that the real-time clock was last set";
    CLASS DEVICE;
    HANDLING READ & WRITE;
    TYPE DATE;
}

VARIABLE last_clock_time 
{
    LABEL "Set Clock Time";
    HELP "Time to set the real time clock in the field device to, or time that the real-time clock was last set";
    CLASS DEVICE;
    HANDLING READ & WRITE;
    TYPE TIME_VALUE;
}

COMMAND set_real_time_clock
{
    NUMBER 89;
    OPERATION COMMAND;
    TRANSACTION
    {
        REQUEST
        {
            time_set(INFO), last_clock_date, last_clock_time, 0, 0
        }
        REPLY
        {
            response_code, device_status,
            time_set(INFO), last_clock_date, last_clock_time
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        2,  DATA_ENTRY_ERROR, [invalid_selection];  
        3,  DATA_ENTRY_ERROR, [passed_parameter_too_large];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        6,  MISC_ERROR,       [xmtr_specific_command_error];
        7,  MODE_ERROR,       [in_write_protect_mode];
        16, MODE_ERROR,       [access_restricted];
    }
}

COMMAND read_real_time_clock
{
    NUMBER 90;
    OPERATION READ;
    TRANSACTION
    {
        REQUEST {}
        REPLY
        {
            response_code, device_status,
            current_date, current_time, last_clock_date, 
            last_clock_time, real_time_clock_flag
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        6,  MISC_ERROR,       [xmtr_specific_command_error];
    }
}
#endif

// Device Communication Statistics Command 95

VARIABLE STX_count
{
    LABEL "STX Count";
    HELP  "Count of STX messages received by this device";
    CLASS HART & DYNAMIC;
    HANDLING READ;
    TYPE UNSIGNED_INTEGER(2);
}

VARIABLE ACK_count
{
    LABEL "ACK Count";
    HELP  "Count of ACK messages received by this device";
    CLASS HART & DYNAMIC;
    HANDLING READ;
    TYPE UNSIGNED_INTEGER(2);
}

VARIABLE BACK_count
{
    LABEL "BACK Count";
    HELP  "Count of BACK messages received by this device";
    CLASS HART & DYNAMIC;
    HANDLING READ;
    TYPE UNSIGNED_INTEGER(2);
}

COMMAND read_device_communication_statistics
{
    NUMBER 95;
    OPERATION READ;
    TRANSACTION
    {
        REQUEST {}
        REPLY
        {
            response_code, device_status,
            STX_count, ACK_count, BACK_count
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,    [no_command_specific_errors];
        6,  MISC_ERROR, [xmtr_specific_command_error];
    }
}

/**********************
* Country Code Commands
*/

COMMAND read_country_code
{
    NUMBER 512;
    OPERATION READ;
    TRANSACTION
    {
        REQUEST {}
        REPLY
        {
            response_code, device_status,
            country_code, si_control        // se common tables DD
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,    [no_command_specific_errors];
        6,  MISC_ERROR, [xmtr_specific_command_error];
    }
}

COMMAND write_country_code
{
    NUMBER 513;
    OPERATION WRITE;
    TRANSACTION
    {
        REQUEST
        {
            country_code, si_control        // see common tables DD
        }        
        REPLY
        {
            response_code, device_status,
            country_code, si_control
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        2,  DATA_ENTRY_ERROR, [invalid_selection];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        7,  MODE_ERROR,       [in_write_protect_mode];
        16, MODE_ERROR,       [access_restricted];
        32, MODE_ERROR,       [busy];
        33, MODE_ERROR,       [delayed_response_initiated];
        34, MODE_ERROR,       [delayed_response_running];
        35, MODE_ERROR,       [delayed_response_dead];
        36, MODE_ERROR,       [delayed_response_conflict];
    }
}

/*
 *****************************************************************************
 * Common Practice Command Spec
 * Section 6.5
 * Transducer trim Commands
 *
 * Commands 80 81 82 83 
 */

VARIABLE device_variable_trim_code
{
    LABEL "Variable to trim";
    HELP [device_variable_trim_code_help];
    CLASS LOCAL;
    TYPE INDEX deviceVariables;
}

COMMAND read_device_variable_trim_point
{
    NUMBER 80;
    OPERATION READ;
    TRANSACTION
    {
        REQUEST
        {
            device_variable_trim_code (INFO,INDEX)
        }
        REPLY
        {
            response_code, device_status,
            device_variable_trim_code (INFO,INDEX),
            deviceVariables[device_variable_trim_code].TRIM_POINT_UNITS,
            deviceVariables[device_variable_trim_code].LOWER_TRIM_POINT,
            deviceVariables[device_variable_trim_code].UPPER_TRIM_POINT
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        17, DATA_ENTRY_ERROR, [invalid_device_variable];
        19, DATA_ENTRY_ERROR, [device_variable_not_allowed];
        32, MODE_ERROR,       [busy];
    }
}

COMMAND read_device_variable_trim_guidelines
{
    NUMBER 81;
    OPERATION READ;
    TRANSACTION
    {
        REQUEST
        {
            device_variable_trim_code (INFO,INDEX)
        }
        REPLY
        {
            response_code, device_status,
            device_variable_trim_code (INFO,INDEX),
            deviceVariables[device_variable_trim_code].TRIM_POINT_SUPPORT,
            deviceVariables[device_variable_trim_code].TRIM_POINT_UNITS,
            deviceVariables[device_variable_trim_code].MINIMUM_LOWER_TRIM_POINT,
            deviceVariables[device_variable_trim_code].MAXIMUM_LOWER_TRIM_POINT,
            deviceVariables[device_variable_trim_code].MINIMUM_UPPER_TRIM_POINT,
            deviceVariables[device_variable_trim_code].MAXIMUM_UPPER_TRIM_POINT,
            deviceVariables[device_variable_trim_code].MINIMUM_TRIM_DIFFERENTIAL
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        17, DATA_ENTRY_ERROR, [invalid_device_variable];
        19, DATA_ENTRY_ERROR, [device_variable_not_allowed];
        32, MODE_ERROR,       [busy];
    }
}

COMMAND write_device_variable_trim_point
{
    NUMBER 82;
    OPERATION WRITE;
    TRANSACTION
    {
        REQUEST
        {
            device_variable_trim_code (INFO,INDEX)
            deviceVariables[device_variable_trim_code].TRIM_POINT_SUPPORT (INFO),
            deviceVariables[device_variable_trim_code].TRIM_POINT_UNITS,
            deviceVariables[device_variable_trim_code].DIGITAL_VALUE
        }
        REPLY
        {
            response_code, device_status,
            device_variable_trim_code (INFO,INDEX),
            deviceVariables[device_variable_trim_code].TRIM_POINT_SUPPORT (INFO),
            deviceVariables[device_variable_trim_code].TRIM_POINT_UNITS,
            deviceVariables[device_variable_trim_code].DIGITAL_VALUE
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,            [no_command_specific_errors];
        2,  DATA_ENTRY_ERROR,   [invalid_selection];
        3,  DATA_ENTRY_ERROR,   [passed_parameter_too_large];
        4,  DATA_ENTRY_ERROR,   [passed_parameter_too_small];
        5,  DATA_ENTRY_ERROR,   [too_few_data_bytes_recieved];
        6,  MISC_ERROR,         [xmtr_specific_command_error];
        7,  MODE_ERROR,         [in_write_protect_mode];
        9,  PROCESS_ERROR,      [applied_process_too_high];
        10, PROCESS_ERROR,      [applied_process_too_low];
        11, MISC_ERROR,         [excess_correction_attempted];
        13, MISC_ERROR,         [computational_error];
        14, DATA_ENTRY_WARNING, [span_too_small];
        16, MODE_ERROR,         [access_restricted];
        17, DATA_ENTRY_ERROR,   [invalid_device_variable];
        18, DATA_ENTRY_ERROR,   [invalid_units];
        19, DATA_ENTRY_ERROR,   [device_variable_not_allowed];
        32, MODE_ERROR,         [busy];
        33, MODE_ERROR,         [delayed_response_initiated];
        34, MODE_ERROR,         [delayed_response_running];
        35, MODE_ERROR,         [delayed_response_dead];
        36, MODE_ERROR,         [delayed_response_conflict];
    }
}

COMMAND reset_device_variable_trim
{
    NUMBER 83;
    OPERATION COMMAND;
    TRANSACTION
    {
        REQUEST
        {
            device_variable_trim_code (INFO,INDEX)
        }
        REPLY
        {
            response_code, device_status,
            device_variable_trim_code (INFO,INDEX)
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        2,  DATA_ENTRY_ERROR, [invalid_selection];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        7,  MODE_ERROR,       [in_write_protect_mode];
        16, MODE_ERROR,       [access_restricted];
        17, DATA_ENTRY_ERROR, [invalid_device_variable];
        19, DATA_ENTRY_ERROR, [device_variable_not_allowed];
        32, MODE_ERROR,       [busy];
        33, MODE_ERROR,       [delayed_response_initiated];
        34, MODE_ERROR,       [delayed_response_running];
        35, MODE_ERROR,       [delayed_response_dead];
        36, MODE_ERROR,       [delayed_response_conflict];
    }
}

METHOD zero_trim
{
    LABEL [zero_trim];
    HELP [zero_trim_help];
    DEFINITION
    {
        char status[STATUS_SIZE];
        char disp_string1[60];
        char disp_string2[60];
        int retry;
        int slen1;
        int slen2;

        slen1 = 60;
        slen2 = 60;

        IGNORE_ALL_RESPONSE_CODES();

        get_dictionary_string(remove_loop_from_auto, disp_string1, slen1);
        ACKNOWLEDGE(disp_string1);

        add_abort_method(return_to_normal);

        get_dictionary_string(this_will_affect_snsr_cal, disp_string1, slen1);
        ACKNOWLEDGE(disp_string1);

        do
        {
            get_dictionary_string(apply_0_input_to_snsr, disp_string1, slen1);
            ACKNOWLEDGE(disp_string1);

            get_dictionary_string(snsr_input_stabilizing, disp_string1, slen1);
            DELAY(3, disp_string1);

            send(43, status);

            if (status[STATUS_RESPONSE_CODE])
            {
                display_response_status(43, status[STATUS_RESPONSE_CODE]);

                if ((status[STATUS_RESPONSE_CODE] != 9)
                        && (status[STATUS_RESPONSE_CODE] != 10))
                {
                    get_dictionary_string(abort_last_error, disp_string1, slen1);
                    DELAY(2, disp_string1);
                    process_abort();
                }

                get_dictionary_string(zero_the_input_and_try_again, disp_string1, slen1);
                get_dictionary_string(yes_no, disp_string2, slen2);
                retry = SELECT_FROM_LIST(disp_string1, disp_string2);
            }
            else
            {
                get_dictionary_string(snsr_zero_succeeded, disp_string1, slen1);
                DELAY(3, disp_string1);
                process_abort();
            }
        } while (!retry);

        process_abort();
    }
}

METHOD return_to_normal
{
    LABEL [aborting_return_to_normal];
    DEFINITION
    {
        char disp_string1[60];
        int slen1;

        slen1 = 60;

        get_dictionary_string(loop_may_be_returned_to_auto, disp_string1, slen1);
        ACKNOWLEDGE(disp_string1);
    }
}

METHOD warning_message
{
    LABEL [set_loop_to_manual];
    DEFINITION
    {
        char disp_string1[125];
        int slen1;

        slen1 = 125;

        get_dictionary_string(remove_from_auto_befor_send, disp_string1, slen1);
        ACKNOWLEDGE(disp_string1);
    }
}

METHOD device_variable_zero_trim
{
    LABEL [field_device_variable_zero_trim];
    HELP [zero_trim_help];
    DEFINITION
    {
        char status[STATUS_SIZE];
        char disp_string1[60];
        char disp_string2[60];
        int tv;
        int retry;
        int slen1;
        int slen2;

        slen1 = 60;
        slen2 = 60;

        IGNORE_ALL_RESPONSE_CODES();

        get_dictionary_string(remove_loop_from_auto, disp_string1, slen1);
        ACKNOWLEDGE(disp_string1);

        add_abort_method(return_to_normal);

        get_dictionary_string(this_will_affect_snsr_cal, disp_string1, slen1);
        ACKNOWLEDGE(disp_string1);

        get_dictionary_string(select_fld_dev_var_snsr_trim, disp_string1, slen1);
        GET_DEV_VAR_VALUE(disp_string1, device_variable_code);

        do
        {
            get_dictionary_string(apply_0_input_to_snsr, disp_string1, slen1);
            ACKNOWLEDGE(disp_string1);

            get_dictionary_string(snsr_input_stabilizing, disp_string1, slen1);
            DELAY(3, disp_string1);

            send(52, status);

            if (status[STATUS_RESPONSE_CODE])
            {
                display_response_status(52, status[STATUS_RESPONSE_CODE]);

                if ((status[STATUS_RESPONSE_CODE] != 2)
                        && (status[STATUS_RESPONSE_CODE] != 9)
                        && (status[STATUS_RESPONSE_CODE] != 10))
                {
                    get_dictionary_string(abort_last_error, disp_string1, slen1);
                    DELAY(2, disp_string1);
                    process_abort();
                }

                get_dictionary_string(zero_the_input_and_try_again, disp_string1, slen1);
                get_dictionary_string(yes_no, disp_string2, slen2);

                retry = SELECT_FROM_LIST(disp_string1, disp_string2);

                if (!retry)
                {
                    if (status[STATUS_RESPONSE_CODE] == 2)
                    {
                        do
                        {
                            tv = ivar_value(device_variable_code);
                            get_dictionary_string(select_fld_dev_var_snsr_trim, disp_string1, slen1);

                            GET_DEV_VAR_VALUE(disp_string1, device_variable_code);

                            if (tv == ivar_value(device_variable_code))
                            {
                                get_dictionary_string(invalid_value_try_again, disp_string1, slen1);
                                DELAY(2, disp_string1);
                            }
                        } while (tv == ivar_value(device_variable_code));
                    }
                }
            }
            else
            {
                get_dictionary_string(snsr_zero_succeeded, disp_string1, slen1);
                DELAY(3, disp_string1);
                process_abort();
            }
        } while (!retry);

        process_abort();
    }
}

METHOD device_variable_trim
{
    LABEL [device_variable_trim];
    HELP [device_variable_trim_help];
    DEFINITION
    {
        char status[STATUS_SIZE];
        char disp_string1[135];
        char disp_string2[60];
        long var_id[2];
        int trim_code;
        int doneLowTrim;
        int retry;
        int slen1;
        int slen2;
        float trim_point;
        float trim_min;
        float trim_max;

        slen1 = 135;
        slen2 = 60;

        IGNORE_ALL_DEVICE_STATUS();
        IGNORE_ALL_RESPONSE_CODES();
        XMTR_IGNORE_ALL_DEVICE_STATUS();
        XMTR_IGNORE_ALL_RESPONSE_CODES();

        get_dictionary_string(remove_loop_from_auto, disp_string1, slen1);
        ACKNOWLEDGE(disp_string1);
        add_abort_method(return_to_normal);

        get_dictionary_string(this_will_affect_snsr_cal, disp_string1, slen1);
        ACKNOWLEDGE(disp_string1);

        get_dictionary_string(connect_reference_meter_trim_dv, disp_string1, slen1);
        ACKNOWLEDGE(disp_string1);

        do
        {
            doneLowTrim = 0; /* Low trim has not been performed on this device variable */

            do
            {
                retry = 1; /* Device variable has not been found */

                /*
                 * Get the device variable "to trim" from the user
                 */
                get_dictionary_string(select_fld_dev_var_snsr_trim, disp_string1, slen1);
                GET_DEV_VAR_VALUE(disp_string1, device_variable_trim_code);  
        
                /*
                 * Issue Command 81 (Read Device Variable Trim Guidelines) to determine the number of
                 * applicable trim points and their acceptable limits (if any) for this device variable
                 */
                send(81, status);
    
                if (status[STATUS_RESPONSE_CODE])
                {
                    display_response_status(81, status[STATUS_RESPONSE_CODE]);

                    if ((status[STATUS_RESPONSE_CODE] != 17) && (status[STATUS_RESPONSE_CODE] != 19))
                    {
                        get_dictionary_string(abort_last_error, disp_string1, slen1);
                        DELAY(2, disp_string1);
                        process_abort();
                    }
                }
                else
                {
                    retry = 0; /* A valid device variable to trim has been found */
                }
            } while (retry);

            var_id[0] = VARID(deviceVariables[ivar_value(device_variable_trim_code)].DIGITAL_VALUE);
            var_id[1] = VARID(deviceVariables[ivar_value(device_variable_trim_code)].DIGITAL_UNITS);

            /*
             *  Find out what trim points this device variable supports
             */
            trim_code = ivar_value(deviceVariables[ivar_value(device_variable_trim_code)].TRIM_POINT_SUPPORT);

            /*
             * Do the lower trim (Single or two trim point supported)
             */
            do
            {
                /*
                 * Issue Command 80 (Read Device Variable Trim Points) to retrieve the last trim points
                 * used.  These should be used as default values for a new trim operation.  If the trim 
                 * code supports a two point trim, them perform the low trim first.  If the code supports
                 * a single trim (lower trim or upper trim), perform only the lower trim.  
                 */
                send(80, status);
    
                if (status[STATUS_RESPONSE_CODE])
                {
                    display_response_status(80, status[STATUS_RESPONSE_CODE]);
                    get_dictionary_string(abort_last_error, disp_string1, slen1);
                    DELAY(2, disp_string1);
                    process_abort();
                }
    
                /*
                 * Prompt the user to set the variable input to a value within acceptable limits for the
                 * lower trim point
                 */
                trim_point = fvar_value(deviceVariables[ivar_value(device_variable_trim_code)].LOWER_TRIM_POINT);
                trim_min = fvar_value(deviceVariables[ivar_value(device_variable_trim_code)].MINIMUM_LOWER_TRIM_POINT);
                trim_max = fvar_value(deviceVariables[ivar_value(device_variable_trim_code)].MAXIMUM_LOWER_TRIM_POINT);

                get_dictionary_string(apply_lower_trim_input, disp_string1, slen1);
                acknowledge(disp_string1, var_id);
    
                /* 
                 * First get PV to use for an editing starting point.  This should be very close to the
                 * trim_point value retrieved from the Command 80 above
                 */
                get_dictionary_string(enter_meter_value, disp_string1, slen1);
                GET_DEV_VAR_VALUE(disp_string1, deviceVariables[ivar_value(device_variable_trim_code)].DIGITAL_VALUE);
    
                /* 
                 * We are triming the lower point value so make sure the code = 1
                 * See Table 22
                 */
                if (trim_code == 3)
                {
                    iassign(deviceVariables[ivar_value(device_variable_trim_code)].TRIM_POINT_SUPPORT, 1);   /* lower point value */
                }

                /*
                 * Write the trim point 
                 */
                send(82, status);
    
                if (status[STATUS_RESPONSE_CODE])
                {
                    display_response_status(82, status[STATUS_RESPONSE_CODE]);

                    if (status[STATUS_RESPONSE_CODE]  == 3 || status[STATUS_RESPONSE_CODE]  == 4 || 
                        status[STATUS_RESPONSE_CODE]  == 9 || status[STATUS_RESPONSE_CODE]  == 10)
                    {
                        /* 
                         * Value out of range
                         */
                        retry = 1;  /* Let's try this again */
                    }
                    else
                    {
                        get_dictionary_string(abort_last_error, disp_string1, slen1);
                        DELAY(2, disp_string1);
                        process_abort();
                    }
                }
                else     /* Success */
                {
                    /*
                     * If the upper trim needs to be peformed and user aborts after the lower
                     * trim, show a warning message to the user
                     */
                    if (!doneLowTrim && trim_code == 3)
                    {
                        remove_abort_method(return_to_normal);
                        add_abort_method(trim_warning);
                        add_abort_method(return_to_normal);
                    }
    
                    doneLowTrim = 1;  /* Indicate that the lower (or single) trim has been performed */
    
                    get_dictionary_string(applied_process_equal_ref_meter, disp_string1, slen1);
                    get_dictionary_string(yes_no, disp_string2, slen2);
                    retry = select_from_list(disp_string1, var_id, disp_string2);
                }
            } while (retry);

            /*
             * Now, do the upper trim (if two trim points are supported)
             */
            if (trim_code == 3)
            {
                do
                {
                    /*
                     * Issue Command 80 (Read Device Variable Trim Points) to retrieve the last trim points
                     * used.  These should be used as default values for a new trim operation.  If the value
                     * supports a two point trim, perfrom the upper trim after the lower trim is performed.
                     */
                    send(80, status);
        
                    if (status[STATUS_RESPONSE_CODE])
                    {
                        display_response_status(80, status[STATUS_RESPONSE_CODE]);
                        get_dictionary_string(abort_last_error, disp_string1, slen1);
                        DELAY(2, disp_string1);
                        process_abort();
                    }

                    /*
                     * Prompt the user to set the variable input to a value within acceptable limits for the
                     * upper trim point
                     */
                    trim_point = fvar_value(deviceVariables[ivar_value(device_variable_trim_code)].UPPER_TRIM_POINT);
                    trim_min = fvar_value(deviceVariables[ivar_value(device_variable_trim_code)].MINIMUM_UPPER_TRIM_POINT);
                    trim_max = fvar_value(deviceVariables[ivar_value(device_variable_trim_code)].MAXIMUM_UPPER_TRIM_POINT);
    
                    get_dictionary_string(apply_upper_trim_input, disp_string1, slen1);
                    acknowledge(disp_string1, var_id);

                    /* 
                     * First get PV to use for an editing starting point.  This should be very close to the
                     * trim_point value retrieved from the Command 80 above
                     */
                    get_dictionary_string(enter_meter_value, disp_string1, slen1);
                    GET_DEV_VAR_VALUE(disp_string1, deviceVariables[ivar_value(device_variable_trim_code)].DIGITAL_VALUE);
    
                    /* 
                     * We are triming the upper point value so make sure the code = 2
                     * See Table 22
                     */
                    iassign(deviceVariables[ivar_value(device_variable_trim_code)].TRIM_POINT_SUPPORT, 2);   /* upper point value */

                    /*
                     * Write the trim point 
                     */
                    send(82, status);
    
                    if (status[STATUS_RESPONSE_CODE])
                    {
                        display_response_status(82, status[STATUS_RESPONSE_CODE]);
    
                        if (status[STATUS_RESPONSE_CODE]  == 3 || status[STATUS_RESPONSE_CODE]  == 4 || 
                            status[STATUS_RESPONSE_CODE]  == 9 || status[STATUS_RESPONSE_CODE]  == 10)
                        {
                            /* 
                             * Value out of range
                             */
                            retry = 1;  /* Let's try this again */
                        }
                        else
                        {
                            get_dictionary_string(abort_last_error, disp_string1, slen1);
                            DELAY(2, disp_string1);
                            process_abort();
                        }
                    }
                    else     /* Success */
                    {
                        remove_abort_method(trim_warning);
                        get_dictionary_string(applied_process_equal_ref_meter, disp_string1, slen1);
                        get_dictionary_string(yes_no, disp_string2, slen2);
                        retry = select_from_list(disp_string1, var_id, disp_string2);
                    }
                } while (retry);
            }

            /*
             *  Send command 80 to re-read the lower trim point and/or
             *  upper trim point to update it as a result of sending
             *  command 82
             */
            send(80, status); 

            get_dictionary_string(trim_another_device_variable, disp_string1, slen1);
            get_dictionary_string(yes_no, disp_string2, slen2);
            retry = SELECT_FROM_LIST(disp_string1, disp_string2);
        } while (!retry);

        process_abort();
    }
}

METHOD trim_warning
{
    LABEL [trim_warning];
    DEFINITION
    {
        char disp_string1[90];
        int slen1;

        slen1 = 90;

        get_dictionary_string(trim_not_complete, disp_string1, slen1);
        ACKNOWLEDGE(disp_string1);
    }
}

METHOD device_variable_trim_reset
{
    LABEL [device_variable_trim_reset];
    HELP [device_variable_trim_reset_help];           
    DEFINITION
    {
        char status[STATUS_SIZE];
        char disp_string1[100];
        char disp_string2[60];
        char ack;
        long var_id[2];
        int slen1;
        int slen2;
        float lower_trim_point;
        float upper_trim_point;

        slen1 = 100;
        slen2 = 60;

        IGNORE_ALL_DEVICE_STATUS();
        IGNORE_ALL_RESPONSE_CODES();
        XMTR_IGNORE_ALL_DEVICE_STATUS();
        XMTR_IGNORE_ALL_RESPONSE_CODES();

        get_dictionary_string(remove_loop_from_auto, disp_string1, slen1);
        ACKNOWLEDGE(disp_string1);
        add_abort_method(return_to_normal);

        get_dictionary_string(this_will_affect_snsr_cal, disp_string1, slen1);
        ACKNOWLEDGE(disp_string1);

        /*
         * Get the device variable "to trim" from the user
         */
        get_dictionary_string(select_fld_dev_var_snsr_trim, disp_string1, slen1);
        GET_DEV_VAR_VALUE(disp_string1, device_variable_trim_code);  

        /* 
         * Display current trim points
         */
        send(80, status);

        if (status[STATUS_RESPONSE_CODE])
        {
            display_response_status(80, status[STATUS_RESPONSE_CODE]);
            get_dictionary_string(abort_last_error, disp_string1, slen1);
            DELAY(2, disp_string1);
            process_abort();
        }

        /* 
         * Current trim point values
         */
        lower_trim_point = fvar_value(deviceVariables[ivar_value(device_variable_trim_code)].LOWER_TRIM_POINT);
        upper_trim_point = fvar_value(deviceVariables[ivar_value(device_variable_trim_code)].UPPER_TRIM_POINT);

        /*
         * Units
         */
        var_id[0] = VARID(deviceVariables[ivar_value(device_variable_trim_code)].TRIM_POINT_UNITS);

        /* Ask for acknowledgement */
        get_dictionary_string(current_trimpoints, disp_string1, slen1);
        get_dictionary_string(yes_no, disp_string2, slen2);
        ack = select_from_list(disp_string1, var_id, disp_string2);

        /*
         * If yes, then the user wants to reset the device variable trim points
         */
        if(ack == 0)
        {
            /*
             * Issue Command 83 (Reset Device Variable Trim) to reset the device variable to the
             * default factory trim
             */
            send(83,status);
    
            if(status[STATUS_RESPONSE_CODE])
            {
                display_response_status(83, status[STATUS_RESPONSE_CODE]);
                get_dictionary_string(abort_last_error, disp_string1, slen1);             
                DELAY(2, disp_string1);
            }

            /*
             *  Send command 80 to re-read the lower trim point and/or
             *  upper trim point to update it as a result of sending
             *  command 83
             */
            send(80, status);
        }
    }
}

/*
 *****************************************************************************
 * Common Practice Command Spec
 * Section 6.6
 * Device Variable Mapping Commands
 *
 * Commands 50 51
 */

VARIABLE primary_variable_code
{
    LABEL [primary_variable_is];
    HELP [primary_variable_code_is_help];
    CLASS HART;
    TYPE INDEX deviceVariables;
    POST_EDIT_ACTIONS
    {
        warning_message
    }
}

VARIABLE secondary_variable_code
{
    LABEL [secondary_variable_is];
    HELP [secondary_variable_code_is_help];
    CLASS HART;
    TYPE INDEX deviceVariables;
    POST_EDIT_ACTIONS
    {
        warning_message
    }
}

VARIABLE tertiary_variable_code
{
    LABEL [tertiary_variable_is];
    HELP [tertiary_variable_code_is_help];
    CLASS HART;
    TYPE INDEX deviceVariables;
    POST_EDIT_ACTIONS
    {
        warning_message
    }
}

VARIABLE quaternary_variable_code
{
    LABEL [quaternary_variable_is];
    HELP [quaternary_variable_code_is_help];
    CLASS HART;
    TYPE INDEX deviceVariables;
    POST_EDIT_ACTIONS
    {
        warning_message
    }
}

COMMAND read_device_variable_assignments
{
    NUMBER 50;
    OPERATION READ;
    TRANSACTION
    {
        REQUEST {}
        REPLY
        {
            response_code, device_status,
            primary_variable_code, secondary_variable_code,
            tertiary_variable_code, quaternary_variable_code
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,    [no_command_specific_errors];
        6,  MISC_ERROR, [xmtr_specific_command_error];
        16, MODE_ERROR, [access_restricted];
    }
}

COMMAND write_device_variable_assignments
{
    NUMBER 51;
    OPERATION WRITE;
    TRANSACTION
    {
        REQUEST
        {
            primary_variable_code, secondary_variable_code,
            tertiary_variable_code, quaternary_variable_code
        }
        REPLY
        {
            response_code, device_status,
            primary_variable_code, secondary_variable_code,
            tertiary_variable_code, quaternary_variable_code
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        2,  DATA_ENTRY_ERROR, [invalid_selection];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        6,  MISC_ERROR,       [xmtr_specific_command_error];
        7,  MODE_ERROR,       [in_write_protect_mode];
        16, MODE_ERROR,       [access_restricted];
        32, MODE_ERROR,       [busy];
    }
}

/*
 *****************************************************************************
 * Common Practice Command Spec
 * Section 6.7
 * PV Commands
 *
 * Commands 34 43 44 47 49
 */

COMMAND write_pv_damping_value
{
    NUMBER 34;
    OPERATION WRITE;
    TRANSACTION
    {
        REQUEST
        {
            PV.DEVICE_VARIABLE.DAMPING_VALUE
        }
        REPLY
        {
            response_code, device_status, PV.DEVICE_VARIABLE.DAMPING_VALUE
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,            [no_command_specific_errors];
        3,  DATA_ENTRY_ERROR,   [passed_parameter_too_large];
        4,  DATA_ENTRY_ERROR,   [passed_parameter_too_small];
        5,  DATA_ENTRY_ERROR,   [too_few_data_bytes_recieved];
        6,  MISC_ERROR,         [xmtr_specific_command_error];
        7,  MODE_ERROR,         [in_write_protect_mode];
        8,  DATA_ENTRY_WARNING, [set_to_nearest_possible_value];
        16, MODE_ERROR,         [access_restricted];
        32, MODE_ERROR,         [busy];
    }
}

COMMAND set_pv_zero
{
    NUMBER 43;
    OPERATION COMMAND;
    TRANSACTION
    {
        REQUEST {}
        REPLY
        {
            response_code, device_status
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,       [no_command_specific_errors];
        6,  MISC_ERROR,    [xmtr_specific_command_error];
        7,  MODE_ERROR,    [in_write_protect_mode];
        9,  PROCESS_ERROR, [applied_process_too_high];
        10, PROCESS_ERROR, [applied_process_too_low];
        16, MODE_ERROR,    [access_restricted];
        32, MODE_ERROR,    [busy];
    }
}

COMMAND write_pv_units
{
    NUMBER 44;
    OPERATION WRITE;
    TRANSACTION
    {
        REQUEST
        {
            PV.DEVICE_VARIABLE.DIGITAL_UNITS
        }
        REPLY
        {
            response_code, device_status, PV.DEVICE_VARIABLE.DIGITAL_UNITS
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        2,  DATA_ENTRY_ERROR, [invalid_selection];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        6,  MISC_ERROR,       [xmtr_specific_command_error];
        7,  MODE_ERROR,       [in_write_protect_mode];
        16, MODE_ERROR,       [access_restricted];
        32, MODE_ERROR,       [busy];
    }
}

COMMAND write_pv_transfer_function
{
    NUMBER 47;
    OPERATION WRITE;
    TRANSACTION
    {
        REQUEST
        {
            PV.RANGING.TRANSFER_FUNCTION
        }
        REPLY
        {
            response_code, device_status, PV.RANGING.TRANSFER_FUNCTION
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        2,  DATA_ENTRY_ERROR, [invalid_selection];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        6,  MISC_ERROR,       [xmtr_specific_command_error];
        7,  MODE_ERROR,       [in_write_protect_mode];
        16, MODE_ERROR,       [access_restricted];
        32, MODE_ERROR,       [busy];
    }
}

COMMAND write_pv_sensor_serial_number
{
    NUMBER 49;
    OPERATION WRITE;
    TRANSACTION
    {
        REQUEST
        {
            PV.DEVICE_VARIABLE.SENSOR_SERIAL_NUMBER
        }
        REPLY
        {
            response_code, device_status, PV.DEVICE_VARIABLE.SENSOR_SERIAL_NUMBER
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        6,  MISC_ERROR,       [xmtr_specific_command_error];
        7,  MODE_ERROR,       [in_write_protect_mode];
        16, MODE_ERROR,       [access_restricted];
        32, MODE_ERROR,       [busy];
    }
}


/*
 *****************************************************************************
 * Common Practice Command Spec
 * Section 6.8
 * Device Variable Commands.  The commands allow access to the Device
 * Variables in the Field Device
 *
 * Commands 33, 52-56, 79, 113, 114
 *
 */

COMMAND read_device_variables
{
    NUMBER 33;
    OPERATION READ;
    TRANSACTION
    {
        REQUEST
        {
            device_variable_code_1 (INFO,INDEX),
            device_variable_code_2 (INFO,INDEX),
            device_variable_code_3 (INFO,INDEX),
            device_variable_code_4 (INFO,INDEX)
        }
        REPLY
        {
            response_code, device_status,
            device_variable_code_1 (INFO,INDEX),
            deviceVariables[device_variable_code_1].DIGITAL_UNITS,
            deviceVariables[device_variable_code_1].DIGITAL_VALUE,
            device_variable_code_2 (INFO,INDEX),
            deviceVariables[device_variable_code_2].DIGITAL_UNITS,
            deviceVariables[device_variable_code_2].DIGITAL_VALUE,
            device_variable_code_3 (INFO,INDEX),
            deviceVariables[device_variable_code_3].DIGITAL_UNITS,
            deviceVariables[device_variable_code_3].DIGITAL_VALUE,
            device_variable_code_4 (INFO,INDEX),
            deviceVariables[device_variable_code_4].DIGITAL_UNITS,
            deviceVariables[device_variable_code_4].DIGITAL_VALUE
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        2,  DATA_ENTRY_ERROR, [invalid_selection];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        6,  MISC_ERROR,       [xmtr_specific_command_error];
        8,  MISC_WARNING,     [update_failure];
        16, MODE_ERROR,       [access_restricted];
    }
}

VARIABLE device_variable_code
{
    LABEL "Device Variable";
    HELP [index_into_dynamic_variables_array_help];
/*  APPHELP "This variable can represent measured or calculated type variables."
            "The numeric assigned to a Field Device variable can never be"
            "changed. If it is changed this would be a violation of the Forward"
            "Compatibility rules."
            "HART_VAR:XMTR VAR CODE"; */
    CLASS LOCAL;
    TYPE INDEX deviceVariables;
}

COMMAND set_device_variable_zero
{
    NUMBER 52;
    OPERATION COMMAND;
    TRANSACTION
    {
        REQUEST
        {
            device_variable_code
        }
        REPLY
        {
            response_code, device_status, device_variable_code
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        2,  DATA_ENTRY_ERROR, [invalid_selection];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        6,  MISC_ERROR,       [xmtr_specific_command_error];
        7,  MODE_ERROR,       [in_write_protect_mode];
        9,  PROCESS_ERROR,    [applied_process_too_high];
        10, PROCESS_ERROR,    [applied_process_too_low];
        16, MODE_ERROR,       [access_restricted];
        32, MODE_ERROR,       [busy];
    }
}

COMMAND write_device_variable_units
{
    NUMBER 53;
    OPERATION WRITE;
    TRANSACTION
    {
        REQUEST
        {
            device_variable_code (INFO,INDEX),
            deviceVariables[device_variable_code].DIGITAL_UNITS
        }
        REPLY
        {
            response_code, device_status, device_variable_code (INFO,INDEX),
            deviceVariables[device_variable_code].DIGITAL_UNITS
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        6,  MISC_ERROR,       [xmtr_specific_command_error];
        7,  MODE_ERROR,       [in_write_protect_mode];
        11, DATA_ENTRY_ERROR, [invalid_device_variable];
        12, DATA_ENTRY_ERROR, [invalid_units];
        16, MODE_ERROR,       [access_restricted];
        32, MODE_ERROR,       [busy];
    }
}

COMMAND read_device_variable_information
{
    NUMBER 54;
    OPERATION READ;
    TRANSACTION
    {
        REQUEST
        {
            device_variable_code (INFO,INDEX)
        }
        REPLY
        {
            response_code, device_status, device_variable_code (INFO,INDEX),
            deviceVariables[device_variable_code].SENSOR_SERIAL_NUMBER,
            deviceVariables[device_variable_code].DIGITAL_UNITS,
            deviceVariables[device_variable_code].UPPER_SENSOR_LIMIT,
            deviceVariables[device_variable_code].LOWER_SENSOR_LIMIT,
            deviceVariables[device_variable_code].DAMPING_VALUE,
            deviceVariables[device_variable_code].MINIMUM_SPAN,
            deviceVariables[device_variable_code].CLASSIFICATION,
            deviceVariables[device_variable_code].DEVICE_FAMILY,
            deviceVariables[device_variable_code].UPDATE_TIME_PERIOD
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        2,  DATA_ENTRY_ERROR, [invalid_selection];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        6,  MISC_ERROR,       [xmtr_specific_command_error];
        16, MODE_ERROR,       [access_restricted];
        32, MODE_ERROR,       [busy];
    }
}

COMMAND write_device_variable_damping_value
{
    NUMBER 55;
    OPERATION WRITE;
    TRANSACTION
    {
        REQUEST
        {
            device_variable_code (INFO,INDEX),
            deviceVariables[device_variable_code].DAMPING_VALUE
        }
        REPLY
        {
            response_code, device_status, device_variable_code (INFO,INDEX),
            deviceVariables[device_variable_code].DAMPING_VALUE
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,            [no_command_specific_errors];
        2,  DATA_ENTRY_ERROR,   [invalid_selection];
        3,  DATA_ENTRY_ERROR,   [passed_parameter_too_large];
        4,  DATA_ENTRY_ERROR,   [passed_parameter_too_small];
        5,  DATA_ENTRY_ERROR,   [too_few_data_bytes_recieved];
        6,  MISC_ERROR,         [xmtr_specific_command_error];
        7,  MODE_ERROR,         [in_write_protect_mode];
        8,  DATA_ENTRY_WARNING, [set_to_nearest_possible_value];
        16, MODE_ERROR,         [access_restricted];
        32, MODE_ERROR,         [busy];
    }
}

COMMAND write_device_variable_sensor_serial_number
{
    NUMBER 56;
    OPERATION WRITE;
    TRANSACTION
    {
        REQUEST
        {
            device_variable_code (INFO,INDEX),
            deviceVariables[device_variable_code].SENSOR_SERIAL_NUMBER
        }
        REPLY
        {
            response_code, device_status, device_variable_code (INFO,INDEX),
            deviceVariables[device_variable_code].SENSOR_SERIAL_NUMBER
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        2,  DATA_ENTRY_ERROR, [invalid_selection];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        6,  MISC_ERROR,       [xmtr_specific_command_error];
        7,  MODE_ERROR,       [in_write_protect_mode];
        16, MODE_ERROR,       [access_restricted];
        32, MODE_ERROR,       [busy];
    }
}

COMMAND write_device_variable
{
    NUMBER 79;
    OPERATION WRITE;
    TRANSACTION
    {
        REQUEST
        {
            device_variable_code (INFO, INDEX),
            deviceVariables[device_variable_code].SIMULATED,
            deviceVariables[device_variable_code].DIGITAL_UNITS,
            deviceVariables[device_variable_code].DIGITAL_VALUE,
            deviceVariables[device_variable_code].DATA_QUALITY <0xC0>,
            deviceVariables[device_variable_code].LIMIT_STATUS <0x30>,
            deviceVariables[device_variable_code].DEVICE_FAMILY_STATUS <0x0F>

        }
        REPLY
        {
            response_code, device_status,
            device_variable_code (INFO,INDEX),
            deviceVariables[device_variable_code].SIMULATED,
            deviceVariables[device_variable_code].DIGITAL_UNITS,
            deviceVariables[device_variable_code].DIGITAL_VALUE,
            deviceVariables[device_variable_code].DATA_QUALITY <0xC0>,
            deviceVariables[device_variable_code].LIMIT_STATUS <0x30>,
            deviceVariables[device_variable_code].DEVICE_FAMILY_STATUS <0x0F>
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        2,  DATA_ENTRY_ERROR, [invalid_selection];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        6,  MISC_ERROR,       [xmtr_specific_command_error];
        7,  MODE_ERROR,       [in_write_protect_mode];
        10, DATA_ENTRY_ERROR, [invalid_write_device_variable];
        16, MODE_ERROR,       [access_restricted];
        17, DATA_ENTRY_ERROR, [invalid_device_variable];
        18, DATA_ENTRY_ERROR, [invalid_units];
        19, DATA_ENTRY_ERROR, [device_variable_not_allowed];
        32, MODE_ERROR,       [busy];
        33, MODE_ERROR,       [delayed_response_initiated];
        34, MODE_ERROR,       [delayed_response_running];
        35, MODE_ERROR,       [delayed_response_dead];
        36, MODE_ERROR,       [delayed_response_conflict];
    }
}

VARIABLE destination_device_variable_code
{
    LABEL "Device Variable";
    HELP [destination_device_variable_code_help];
    CLASS LOCAL;
    TYPE INDEX deviceVariables;
}

COMMAND catch_device_variable
{
    NUMBER 113;
    OPERATION WRITE;
    TRANSACTION
    {
        REQUEST
        {
            destination_device_variable_code (INFO,INDEX), 
            deviceVariables[destination_device_variable_code].CAPTURE_MODE, 
            deviceVariables[destination_device_variable_code].SOURCE_MANUFACTURER,
            deviceVariables[destination_device_variable_code].SOURCE_DEVICE_TYPE,
            deviceVariables[destination_device_variable_code].SOURCE_DEVICE_ID,
            deviceVariables[destination_device_variable_code].SOURCE_COMMAND_NUMBER,
            deviceVariables[destination_device_variable_code].SOURCE_SLOT_NUMBER,
            deviceVariables[destination_device_variable_code].SHED_TIME
        }
        REPLY
        {
            response_code, device_status,
            destination_device_variable_code (INFO,INDEX), 
            deviceVariables[destination_device_variable_code].CAPTURE_MODE,
            deviceVariables[destination_device_variable_code].SOURCE_MANUFACTURER,
            deviceVariables[destination_device_variable_code].SOURCE_DEVICE_TYPE,
            deviceVariables[destination_device_variable_code].SOURCE_DEVICE_ID,
            deviceVariables[destination_device_variable_code].SOURCE_COMMAND_NUMBER,
            deviceVariables[destination_device_variable_code].SOURCE_SLOT_NUMBER,
            deviceVariables[destination_device_variable_code].SHED_TIME
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        6,  MISC_ERROR,       [xmtr_specific_command_error];
        7,  MODE_ERROR,       [in_write_protect_mode];
        10, DATA_ENTRY_ERROR, [invalid_capture_mode_code];
        11, DATA_ENTRY_ERROR, [invalid_slot_number];
        12, DATA_ENTRY_ERROR, [command_number_not_supported];
        16, MODE_ERROR,       [access_restricted];
        17, DATA_ENTRY_ERROR, [invalid_device_variable];
        19, DATA_ENTRY_ERROR, [device_variable_not_allowed];
        32, MODE_ERROR,       [busy];
        33, MODE_ERROR,       [delayed_response_initiated];
        34, MODE_ERROR,       [delayed_response_running];
        35, MODE_ERROR,       [delayed_response_dead];
        36, MODE_ERROR,       [delayed_response_conflict];

    }
}

COMMAND read_caught_device_variable
{
    NUMBER 114;
    OPERATION READ;
    TRANSACTION
    {
        REQUEST
        {
            destination_device_variable_code (INFO,INDEX) 
        }
        REPLY
        {
            response_code, device_status,
            destination_device_variable_code (INFO,INDEX), 
            deviceVariables[destination_device_variable_code].CAPTURE_MODE,
            deviceVariables[destination_device_variable_code].SOURCE_MANUFACTURER,
            deviceVariables[destination_device_variable_code].SOURCE_DEVICE_TYPE,
            deviceVariables[destination_device_variable_code].SOURCE_DEVICE_ID,
            deviceVariables[destination_device_variable_code].SOURCE_COMMAND_NUMBER,
            deviceVariables[destination_device_variable_code].SOURCE_SLOT_NUMBER,
            deviceVariables[destination_device_variable_code].SHED_TIME
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        17, DATA_ENTRY_ERROR, [invalid_device_variable];
        19, DATA_ENTRY_ERROR, [device_variable_not_allowed];
        32, MODE_ERROR,       [busy];
        33, MODE_ERROR,       [delayed_response_initiated];
        34, MODE_ERROR,       [delayed_response_running];
        35, MODE_ERROR,       [delayed_response_dead];
        36, MODE_ERROR,       [delayed_response_conflict];
    }
}
 
COMMAND flush_delayed_responses
{
    NUMBER 106;
    OPERATION COMMAND;
    TRANSACTION
    {
        REQUEST {}
        REPLY
        {
            response_code, device_status
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        8,  MISC_WARNING,     [all_but_running_flushed]; 
        16, MODE_ERROR,       [access_restricted];
        32, MODE_ERROR,       [busy];
    }
}

METHOD catchDeviceVariable
{
    LABEL [catch_device_variable];
    HELP [catch_device_variable_help];
    DEFINITION
    {
        char status[STATUS_SIZE];
        char disp_string1[140];
        char disp_string2[60];
        long var_id[8];
        int mode;
        int choice;
        int slot;
        int retry;
        int slen1;
        int slen2;
        float shed;

        slen1 = 140;
        slen2 = 60;

        IGNORE_ALL_DEVICE_STATUS();
        IGNORE_ALL_RESPONSE_CODES();
        XMTR_IGNORE_ALL_DEVICE_STATUS();
        XMTR_IGNORE_ALL_RESPONSE_CODES();

        /* 
         * Choose device variable 
         *
         * NOTE: This method assumes that only one device variable needs to catch data
         * The method will need to be executed again for the mapping of any additional
         * device variable.
         */
        do
        {
            retry = 1; /* Device variable has not been found */

            /* 
             * Get the device variable "to catch" from the user 
             */
            get_dictionary_string(select_device_variable_catch, disp_string1, slen1);
            GET_DEV_VAR_VALUE(disp_string1, destination_device_variable_code);

            /* 
             * Send Command 114 (Read Caught Device Variable) to determine if the specified variable
             * supports catching 
             */
            send(114, status);

            if (status[STATUS_RESPONSE_CODE])
            {
                display_response_status(114, status[STATUS_RESPONSE_CODE]);

                if ((status[STATUS_RESPONSE_CODE] != 17) && (status[STATUS_RESPONSE_CODE] != 19))
                {
                    get_dictionary_string(abort_last_error, disp_string1, slen1);
                    DELAY(5, disp_string1);
                    process_abort();
                }
            }
            else
            {
                retry = 0;  /* A valid device variable to catch has been found */
            }
        } while (retry);

        /* 
         * A valid device variable to catch has been found 
         */
        var_id[0] = VARID(destination_device_variable_code);

        /*
         * Get the current capture mode of the device variable
         */
        mode = ivar_value(deviceVariables[ivar_value(destination_device_variable_code)].CAPTURE_MODE);

        /* 
         * Set catch info 
         */
        do
        {
            retry = 1;  /* New values have not been set */
            /* 
             * Get Capture mode 
             */
            get_dictionary_string(select_catch_dv_capture_mode, disp_string1, slen1);
            GET_DEV_VAR_VALUE(disp_string1, deviceVariables[ivar_value(destination_device_variable_code)].CAPTURE_MODE);

            choice = ivar_value(deviceVariables[ivar_value(destination_device_variable_code)].CAPTURE_MODE);

            if (choice > 0)    /* No need to ask more if catching will be disabled */
            { 
                if (choice == 1)    /* Only ask for address for address match mode */
                { 
                    /* 
                     * Get Manufacturer ID
                     *
                     * NOTE: deviceVariables[destination_device_variable_code].SOURCE_MANUFACTURER should reference an ENUMERATED
                     * variable based on same manufacturer choices as those specified in variable manufacturer_id
                     * (defined in Tabl15_1.ddl). 
                     */
                    get_dictionary_string(select_src_manufacturer, disp_string1, slen1);
                    GET_DEV_VAR_VALUE(disp_string1, deviceVariables[ivar_value(destination_device_variable_code)].SOURCE_MANUFACTURER);

                    var_id[1] = VARID(deviceVariables[ivar_value(destination_device_variable_code)].SOURCE_MANUFACTURER);

                    /* 
                     * Get Device Type
                     * NOTE: deviceVariables[destination_device_variable_code].SOURCE_DEVICE_TYPE must (at a minimum) reference an
                     * UNSIGNED_INTEGER variable.
                     */
                    get_dictionary_string(select_src_device_type, disp_string1, slen1);
                    GET_DEV_VAR_VALUE(disp_string1, deviceVariables[ivar_value(destination_device_variable_code)].SOURCE_DEVICE_TYPE);

                    var_id[2] = VARID(deviceVariables[ivar_value(destination_device_variable_code)].SOURCE_DEVICE_TYPE);

                    /* 
                     * Get Device Id
                     * NOTE: deviceVariables[destination_device_variable_code].SOURCE_DEVICE_ID must (at a minimum) reference an 
                     * UNSIGNED_INTEGER variable of size 3. 
                     */
                    get_dictionary_string(any_device_matching_mfr_dev_type, disp_string1, slen1);
                    get_dictionary_string(yes_no, disp_string2, slen2);

                    if (!select_from_list(disp_string1, var_id, disp_string2))
                    {
                        /* 
                         * Set to zero to indicate any field device matching the Manufacturer ID and Device Type
                         * is to act as a data source 
                         */
                        iassign(deviceVariables[ivar_value(destination_device_variable_code)].SOURCE_DEVICE_ID, 0);
                    }
                    else
                    {
                        /*
                         * The user chooses the device id
                         */
                        get_dictionary_string(choose_src_device_id, disp_string1, slen1);
                        GET_DEV_VAR_VALUE(disp_string1, deviceVariables[ivar_value(destination_device_variable_code)].SOURCE_DEVICE_ID);
                    }

                    var_id[3] = VARID(deviceVariables[ivar_value(destination_device_variable_code)].SOURCE_DEVICE_ID);
                }
                else if (choice == 2)
                {
                    /*
                     * Set the address to zero since the data source is a bursting slave
                     */
                    iassign(deviceVariables[ivar_value(destination_device_variable_code)].SOURCE_MANUFACTURER, 0);
                    iassign(deviceVariables[ivar_value(destination_device_variable_code)].SOURCE_DEVICE_TYPE, 0);
                    iassign(deviceVariables[ivar_value(destination_device_variable_code)].SOURCE_DEVICE_ID, 0);
                }
                else
                {
                    /* 
                     * Not a valid selection (negative enteries not accepted)
                     */
                    get_dictionary_string(invalid_selection, disp_string1, slen1);
                    DELAY(5, disp_string1);
                    process_abort();
                }

                /* 
                 * Get the command number
                 *
                 * NOTE: deviceVariables[destination_device_variable_code].SOURCE_COMMAND_NUMBER must reference a variable in your DD
                 * based on same Command choices as those specified in variable burst_command_number.  It should be an ENUMERATED
                 * variable. 
                 */
                get_dictionary_string(select_src_command, disp_string1, slen1);
                GET_DEV_VAR_VALUE(disp_string1, deviceVariables[ivar_value(destination_device_variable_code)].SOURCE_COMMAND_NUMBER);

                var_id[4] = VARID(deviceVariables[ivar_value(destination_device_variable_code)].SOURCE_COMMAND_NUMBER);

                /* 
                 * Get data slot from user based on the command number
                 */
                get_dictionary_string(select_dv_catch_data, disp_string1, slen1);

                switch (ivar_value(deviceVariables[ivar_value(destination_device_variable_code)].SOURCE_COMMAND_NUMBER))
                {
                    case 1: /* Command 1 */
                        slot = 0;
                        /*
                         * Source slot is always PV
                         */
                        break;

                    case 2: /* Command 2 */
                        get_dictionary_string(choice_current_percent_range, disp_string2, slen2);
                        slot = SELECT_FROM_LIST(disp_string1,disp_string2);
                        break;

                    case 3: /* Command 3 */
                        get_dictionary_string(choice_dynamic_variables, disp_string2, slen2);
                        slot = SELECT_FROM_LIST(disp_string1,disp_string2);
                        break;

                    case 9: /* Command 9 */
                    case 33: /* Command 33 */
                        get_dictionary_string(choice_device_variables, disp_string2, slen2);
                        slot = SELECT_FROM_LIST(disp_string1,disp_string2);
                        break;

                    default: 
                        /* 
                         * Not a valid selection
                         */
                        get_dictionary_string(invalid_selection, disp_string1, slen1);
                        DELAY(5, disp_string1);
                        process_abort();
                        break;
                }

                /*
                 * Set the slot value based upon the choices above (see Table 2 in Command 113 - Common Practice Spec 8.0)
                 */
                iassign(deviceVariables[ivar_value(destination_device_variable_code)].SOURCE_SLOT_NUMBER, slot+1);

                /* 
                 * Get the shed time 
                 */
                get_dictionary_string(choose_shed_time, disp_string1, slen1);
                GET_DEV_VAR_VALUE(disp_string1, deviceVariables[ivar_value(destination_device_variable_code)].SHED_TIME);

                /* 
                 * Confirm new setting 
                 */
                if(choice == 1)  /* address match mode */
                {
                    get_dictionary_string(enable_catch_data_using_specified_device, disp_string1, slen1);

                }
                else            /* catch burst */
                {
                    get_dictionary_string(enable_catch_data_using_burst_device, disp_string1, slen1);
                }

                /* 
                 * Confirm enabling 
                 */
                get_dictionary_string(yes_no, disp_string2, slen2);
                retry = select_from_list(disp_string1, var_id, disp_string2);
            }
            else if (choice == 0)   /* Choice = 0 */
            {
                /* 
                 * Determine if it is already disabled
                 */
                if (mode != 0)
                {
                    /* 
                     * Confirm disabling 
                     */
                    get_dictionary_string(disable_catch_data, disp_string1, slen1);
                    get_dictionary_string(yes_no, disp_string2, slen2);
                    retry = select_from_list(disp_string1, var_id, disp_string2);
                }
            }
            else
            {
                /* 
                 * Not a valid selection (only values 0, 1, or 2 are accepted)
                 */
                get_dictionary_string(invalid_selection, disp_string1, slen1);
                DELAY(5, disp_string1);
                process_abort();
            }
        } while (retry);

        /* 
         * Send Command 113 (Catch Device Variable)
         * Only act when new settings are confirmed from enabling or disabling above
         */
        send(113, status);

        if (status[STATUS_RESPONSE_CODE])
        {
            display_response_status(112, status[STATUS_RESPONSE_CODE]);

            get_dictionary_string(abort_last_error, disp_string1, slen1);
            DELAY(5, disp_string1);
            process_abort();
        } 
    }
}
 
/*
 *****************************************************************************
 * Common Practice Command Spec
 * Section 6.9
 * Burst mode Commands
 *
 * Commands 103-105, 107-109
 */

VARIABLE burst_command_number
{
    LABEL "Burst Command";
    HELP [burst_command_number_help];
    CLASS HART;
    TYPE ENUMERATED (2)
    { 
        {1,  [read_primary_variable], [pv_help] }, 
        {2,  [read_percent_range_and_current], [percent_rnge_help] }, 
        {3,  [read_dyn_vars_and_current], [all_process_var_help] }, 
        {9,  [read_device_variables_with_status], [read_device_variables_with_status_help] }, 
        {33, [read_device_variables],[read_device_variables_help] },
        {48, "Cmd 48: Read Additional Device Status", "Read Additional Device - This command reads additional device status information"}
    }
}

#if __TOKVER__ >= 800
VARIABLE update_period 
{
    LABEL "Update Period";
    HELP "Update period for burst message";
    CLASS DEVICE;
    TYPE TIME_VALUE
    { 
        DISPLAY_FORMAT "5.3f" ;
        TIME_SCALE SECONDS ;
    }
}

VARIABLE max_update_period 
{
    LABEL "Max Update Period";
    HELP "Maxium update period for burst message";
    CLASS DEVICE;
    TYPE TIME_VALUE
    { 
        DISPLAY_FORMAT "5.3f" ;
        TIME_SCALE SECONDS ;
    }
}

#else

VARIABLE update_period_int 
{
    LABEL "Update Period";
    HELP "Update period for burst message";
    CLASS DEVICE;
    TYPE UNSIGNED_INTEGER(4)
    {
        SCALING_FACTOR 0.00003125;
    }
    CONSTANT_UNIT "s";
}

VARIABLE max_update_period_int 
{
    LABEL "Max Update Period";
    HELP "Maxium update period for burst message";
    CLASS DEVICE;
    TYPE UNSIGNED_INTEGER(4)
    {
        SCALING_FACTOR 0.00003125;
    }
    CONSTANT_UNIT "s";
}
#endif

#if __TOKVER__ >= 800
VARIABLE burst_variable_code
{
    LABEL "Burst Variable Code";
    HELP "Burst Variable Slot - Device variable code assigned to the slot to be read in burst mode.";
    CLASS HART;
    TYPE INDEX deviceVariables;
}

ARRAY burst_variable_codes
{
    LABEL "Burst Variable Codes";
    HELP "";
    TYPE burst_variable_code;
    NUMBER_OF_ELEMENTS 8;
}

VARIABLE burst_subdevice_index
{
    LABEL "Subdevice Index";
    HELP "";
    CLASS DEVICE;
    TYPE INDEX (2) subdevice_list;
}

#else

/* Assume backward compatible burst mode for older tokenized binaries */
VARIABLE burst_subdevice_index_int
{
    LABEL "Subdevice Index";
    HELP "";
    CLASS DEVICE;
    TYPE UNSIGNED_INTEGER (2);
}

VARIABLE burst_variable_code_1
{
    LABEL [burst_variable_1];
    HELP [burst_variable_1_help];
    CLASS HART;
    TYPE INDEX deviceVariables;
}

VARIABLE burst_variable_code_2
{
    LABEL [burst_variable_2];
    HELP [burst_variable_2_help];
    CLASS HART;
    TYPE INDEX deviceVariables;
}

VARIABLE burst_variable_code_3
{
    LABEL [burst_variable_3];
    HELP [burst_variable_3_help];
    CLASS HART;
    TYPE INDEX deviceVariables;
}

VARIABLE burst_variable_code_4
{
    LABEL [burst_variable_4];
    HELP [burst_variable_4_help];
    CLASS HART;
    TYPE INDEX deviceVariables;
}

VARIABLE burst_variable_code_5
{
    LABEL "Burst var 5 is";
    HELP "Burst Variable Slot 5- Device variable code assigned to slot 5 to be read in burst mode.";
    CLASS HART;
    TYPE INDEX deviceVariables;
}

VARIABLE burst_variable_code_6
{
    LABEL "Burst var 6 is";
    HELP "Burst Variable Slot 6- Device variable code assigned to slot 6 to be read in burst mode.";
    CLASS HART;
    TYPE INDEX deviceVariables;
}

VARIABLE burst_variable_code_7
{
    LABEL "Burst var 7 is";
    HELP "Burst Variable Slot 7- Device variable code assigned to slot 7 to be read in burst mode.";
    CLASS HART;
    TYPE INDEX deviceVariables;
}

VARIABLE burst_variable_code_8
{
    LABEL "Burst var 8 is";
    HELP "Burst Variable Slot 8- Device variable code assigned to slot 8 to be read in burst mode.";
    CLASS HART;
    TYPE INDEX deviceVariables;
}
#endif

VARIABLE trigger_level
{
    LABEL "Burst Trigger Level";
    HELP  "";
    CLASS DEVICE;
    HANDLING READ & WRITE;
    TYPE FLOAT;
}

#if __TOKVER__ >= 600
COLLECTION burst_message_collection
#else
COLLECTION OF VARIABLE burst_message_collection
#endif
{
    MEMBERS {
#if __TOKVER__ >= 800
        BURST_VAR,              burst_variable_codes;
        UPDATE_PERIOD,          update_period;
        MAX_UPDATE_PERIOD,      max_update_period;
#else
        UPDATE_PERIOD,          update_period_int;
        MAX_UPDATE_PERIOD,      max_update_period_int;
#endif
        COMMAND_NUMBER,         burst_command_number;
        BURST_MODE_SELECT,      burst_mode_select;
        BURST_TRIGGER_MODE,     burst_message_trigger_mode;
        BURST_CLASSIFICATION,   burst_trigger_classification;
        BURST_UNIT,             burst_trigger_units;
        TRIGGER_LEVEL,          trigger_level;
        SUB_DEVICE_MISSING,     subdevice_missing;       //Uses MSBit of subdev index to determine status of subdevice mapping (per Wally P)
#if __TOKVER__ >= 800
        SUB_DEVICE_MAPPING,     burst_subdevice_index;   //remove this member for non-adapters
#else
        SUB_DEVICE_MAPPING,     burst_subdevice_index_int;   //remove this member for non-adapters
#endif

    }
}

/* Earlier tokenizers can't handle value-arrays or
   references to value-arrays in COMMANDs */
#if __TOKVER__ >= 800
ARRAY burst_messages 
{
    NUMBER_OF_ELEMENTS 3;
    TYPE burst_message_collection;
}

VARIABLE burst_message_number
{
    LABEL "Burst Message Number";
    HELP "";
    CLASS LOCAL;
    TYPE INDEX burst_messages;
}
#endif

COMMAND write_burst_period
{
    NUMBER 103;
    OPERATION WRITE;
    TRANSACTION
    {
#if __TOKVER__ >= 800
        REQUEST
        {
            burst_message_number (INFO, INDEX),
            burst_messages[burst_message_number].UPDATE_PERIOD,
            burst_messages[burst_message_number].MAX_UPDATE_PERIOD
        }
        REPLY
        {
            response_code, device_status,
            burst_message_number (INFO, INDEX),
            burst_messages[burst_message_number].UPDATE_PERIOD,
            burst_messages[burst_message_number].MAX_UPDATE_PERIOD

        }
#else
        REQUEST
        {
            0,
            burst_message_collection.UPDATE_PERIOD,
            burst_message_collection.MAX_UPDATE_PERIOD
        }
        REPLY
        {
            response_code, device_status,
            0,
            burst_message_collection.UPDATE_PERIOD,
            burst_message_collection.MAX_UPDATE_PERIOD

        }
#endif
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,            [no_command_specific_errors];
        5,  DATA_ENTRY_ERROR,   [too_few_data_bytes_recieved];
        6,  MISC_ERROR,         [xmtr_specific_command_error];
        7,  MODE_ERROR,         [in_write_protect_mode];
        8,  MISC_WARNING,       "Update time adjusted";
        9,  MISC_ERROR,         "Invalid burst message";
        16, MODE_ERROR,         [access_restricted];
        32, MODE_ERROR,         [busy];
        33, MODE_ERROR,         [delayed_response_initiated];
        34, MODE_ERROR,         [delayed_response_running];
        35, MODE_ERROR,         [delayed_response_dead];
        36, MODE_ERROR,         [delayed_response_conflict];
    }
}

COMMAND write_burst_trigger
{
    NUMBER 104;
    OPERATION WRITE;
    TRANSACTION
    {
#if __TOKVER__ >= 800
        REQUEST
        {
            burst_message_number (INFO, INDEX),
            burst_messages[burst_message_number].BURST_TRIGGER_MODE,
            burst_messages[burst_message_number].BURST_CLASSIFICATION,
            burst_messages[burst_message_number].BURST_UNIT,
            burst_messages[burst_message_number].TRIGGER_LEVEL
        }
        REPLY
        {
            response_code, device_status,
            burst_message_number (INFO, INDEX),
            burst_messages[burst_message_number].BURST_TRIGGER_MODE,
            burst_messages[burst_message_number].BURST_CLASSIFICATION,
            burst_messages[burst_message_number].BURST_UNIT,
            burst_messages[burst_message_number].TRIGGER_LEVEL
        }
#else
        REQUEST
        {
            0,
            burst_message_collection.BURST_TRIGGER_MODE,
            burst_message_collection.BURST_CLASSIFICATION,
            burst_message_collection.BURST_UNIT,
            burst_message_collection.TRIGGER_LEVEL
        }
        REPLY
        {
            response_code, device_status,
            0,
            burst_message_collection.BURST_TRIGGER_MODE,
            burst_message_collection.BURST_CLASSIFICATION,
            burst_message_collection.BURST_UNIT,
            burst_message_collection.TRIGGER_LEVEL
        }
#endif
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,            [no_command_specific_errors];
        2,  DATA_ENTRY_ERROR,   [invalid_selection];
        3,  DATA_ENTRY_ERROR,   [passed_parameter_too_large];
        4,  DATA_ENTRY_ERROR,   [passed_parameter_too_small];
        5,  DATA_ENTRY_ERROR,   [too_few_data_bytes_recieved];
        6,  MISC_ERROR,         [xmtr_specific_command_error];
        7,  MODE_ERROR,         [in_write_protect_mode];
        9,  MISC_ERROR,         "Invalid burst message";
        11, DATA_ENTRY_ERROR,   "Invalid device variable classification";
        12, DATA_ENTRY_ERROR,   [invalid_units];
        13, DATA_ENTRY_ERROR,   "Invalid burst trigger mode selection code";
        16, MODE_ERROR,         [access_restricted];
        32, MODE_ERROR,         [busy];
        33, MODE_ERROR,         [delayed_response_initiated];
        34, MODE_ERROR,         [delayed_response_running];
        35, MODE_ERROR,         [delayed_response_dead];
        36, MODE_ERROR,         [delayed_response_conflict];
    }
}

VARIABLE total_number_burst_messages
{
    LABEL "Total Burst Msgs";
    HELP  "Total number of burst messages supported by this device";
    CLASS DEVICE;
    HANDLING READ;
    TYPE UNSIGNED_INTEGER;
#if __TOKVER__ >= 600
    DEFAULT_VALUE 3;
#endif
}

COMMAND read_burst_mode_configuration
{
    NUMBER 105;
    OPERATION READ;
    TRANSACTION
    {
#if __TOKVER__ >= 800
        REQUEST 
        {
            burst_message_number (INFO, INDEX)
        }
        REPLY
        {
            response_code, device_status,
            burst_messages[burst_message_number].BURST_MODE_SELECT,
            0x1F,
            burst_messages[burst_message_number].BURST_VAR[0],        
            burst_messages[burst_message_number].BURST_VAR[1],        
            burst_messages[burst_message_number].BURST_VAR[2],        
            burst_messages[burst_message_number].BURST_VAR[3],        
            burst_messages[burst_message_number].BURST_VAR[4],        
            burst_messages[burst_message_number].BURST_VAR[5],        
            burst_messages[burst_message_number].BURST_VAR[6],        
            burst_messages[burst_message_number].BURST_VAR[7], 
            burst_message_number (INFO, INDEX),
            total_number_burst_messages,
            burst_messages[burst_message_number].COMMAND_NUMBER,
            burst_messages[burst_message_number].UPDATE_PERIOD,
            burst_messages[burst_message_number].MAX_UPDATE_PERIOD,
            burst_messages[burst_message_number].BURST_TRIGGER_MODE,
            burst_messages[burst_message_number].BURST_CLASSIFICATION,
            burst_messages[burst_message_number].BURST_UNIT,
            burst_messages[burst_message_number].TRIGGER_LEVEL
        }
#else
        REQUEST 
        {
            0
        }
        REPLY
        {
            response_code, device_status,
            burst_message_collection.BURST_MODE_SELECT,
            0x1F,
            burst_variable_code_1,        
            burst_variable_code_2,        
            burst_variable_code_3,        
            burst_variable_code_4,        
            burst_variable_code_5,        
            burst_variable_code_6,        
            burst_variable_code_7,        
            burst_variable_code_8,        
            0,
            total_number_burst_messages,
            burst_message_collection.COMMAND_NUMBER,
            burst_message_collection.UPDATE_PERIOD,
            burst_message_collection.MAX_UPDATE_PERIOD,
            burst_message_collection.BURST_TRIGGER_MODE,
            burst_message_collection.BURST_CLASSIFICATION,
            burst_message_collection.BURST_UNIT,
            burst_message_collection.TRIGGER_LEVEL
        }
#endif
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        6,  MISC_ERROR,       [xmtr_specific_command_error];
        9,  MISC_ERROR,       "Invalid burst message";
        32, MODE_ERROR,       [busy];
    }
}

COMMAND write_burst_device_variables
{
    NUMBER 107;
    OPERATION WRITE;
    TRANSACTION
    {
#if __TOKVER__ >= 800
        REQUEST
        {
               burst_messages[burst_message_number].BURST_VAR[0],        
               burst_messages[burst_message_number].BURST_VAR[1],        
               burst_messages[burst_message_number].BURST_VAR[2],        
               burst_messages[burst_message_number].BURST_VAR[3],        
               burst_messages[burst_message_number].BURST_VAR[4],        
               burst_messages[burst_message_number].BURST_VAR[5],        
               burst_messages[burst_message_number].BURST_VAR[6],        
               burst_messages[burst_message_number].BURST_VAR[7], 
               burst_message_number (INFO, INDEX)
        }
        REPLY
        {
            response_code, device_status,
               burst_messages[burst_message_number].BURST_VAR[0],        
               burst_messages[burst_message_number].BURST_VAR[1],        
               burst_messages[burst_message_number].BURST_VAR[2],        
               burst_messages[burst_message_number].BURST_VAR[3],        
               burst_messages[burst_message_number].BURST_VAR[4],        
               burst_messages[burst_message_number].BURST_VAR[5],        
               burst_messages[burst_message_number].BURST_VAR[6],        
               burst_messages[burst_message_number].BURST_VAR[7], 
               burst_message_number (INFO, INDEX)
        }
#else
        REQUEST
        {
            burst_variable_code_1,        
            burst_variable_code_2,        
            burst_variable_code_3,        
            burst_variable_code_4,        
            burst_variable_code_5,        
            burst_variable_code_6,        
            burst_variable_code_7,        
            burst_variable_code_8, 
            0
        }
        REPLY
        {
            response_code, device_status,
            burst_variable_code_1,        
            burst_variable_code_2,        
            burst_variable_code_3,        
            burst_variable_code_4,        
            burst_variable_code_5,        
            burst_variable_code_6,        
            burst_variable_code_7,        
            burst_variable_code_8, 
            0
        }
#endif
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        2,  DATA_ENTRY_ERROR, [invalid_selection];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        6,  MISC_ERROR,       [xmtr_specific_command_error];
        7,  MODE_ERROR,       [in_write_protect_mode];
        8,  MISC_WARNING,     "Burst condition conflict";
        9,  DATA_ENTRY_ERROR, "Invalid burst message";
    }
}

COMMAND write_burst_command_number
{
    NUMBER 108;
    OPERATION WRITE;
    TRANSACTION
    {
#if __TOKVER__ >= 800
        REQUEST
        {
            burst_messages[burst_message_number].COMMAND_NUMBER,
            burst_message_number (INFO, INDEX)
        }
        REPLY
        {
            response_code, device_status,
            burst_messages[burst_message_number].COMMAND_NUMBER,
            burst_message_number (INFO, INDEX)
        }
#else
        REQUEST
        {
            burst_message_collection.COMMAND_NUMBER,
            0
        }
        REPLY
        {
            response_code, device_status,
            burst_message_collection.COMMAND_NUMBER,
            0
        }
#endif
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        2,  DATA_ENTRY_ERROR, [invalid_selection];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        6,  MISC_ERROR,       [xmtr_specific_command_error];
        7,  MODE_ERROR,       [in_write_protect_mode];
        8,  MISC_WARNING,     "Burst condition conflict";
        9,  DATA_ENTRY_ERROR, "Invalid burst message";
    }
}

COMMAND burst_mode_control
{
    NUMBER 109;
    OPERATION WRITE;
    TRANSACTION
    {
#if __TOKVER__ >= 800
        REQUEST
        {
            burst_messages[burst_message_number].BURST_MODE_SELECT,
            burst_message_number (INFO, INDEX)
        }
        REPLY
        {
            response_code, device_status,
            burst_messages[burst_message_number].BURST_MODE_SELECT,
            burst_message_number (INFO, INDEX)
        }
#else
        REQUEST
        {
            burst_message_collection.BURST_MODE_SELECT,
            0
        }
        REPLY
        {
            response_code, device_status,
            burst_message_collection.BURST_MODE_SELECT,
            0
        }
#endif
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        2,  DATA_ENTRY_ERROR, [invalid_selection];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        6,  MISC_ERROR,       [xmtr_specific_command_error];
        7,  MODE_ERROR,       [in_write_protect_mode];
        8,  MISC_WARNING,     "Update period increased";
        9,  MODE_ERROR,       "Insufficient bandwidth";
        16, MODE_ERROR,       [access_restricted];
        32, MODE_ERROR,       [busy];
        33, MODE_ERROR,       [delayed_response_initiated];
        34, MODE_ERROR,       [delayed_response_running];
        35, MODE_ERROR,       [delayed_response_dead];
        36, MODE_ERROR,       [delayed_response_conflict];
    }
}


 /*****************************************************************************
 * Common Practice Command Spec
 * Section 6.10
 * Event Notification Commands
 *
 * Commands 115-119
 *
 * zzzz how could we make events useful to DD Host?  Events are fundamentally
 *      published not polled...
 */
device_specific_status_0_mask  LIKE VARIABLE device_specific_status_0
{
    REDEFINE LABEL "Device Specific Status 0 Mask";
    REDEFINE HELP "";
    REDEFINE CLASS DEVICE & DIAGNOSTIC;
    REDEFINE HANDLING READ & WRITE;
}

device_specific_status_1_mask  LIKE VARIABLE device_specific_status_1
{
    REDEFINE LABEL "Device Specific Status 1 Mask";
    REDEFINE HELP "";
    REDEFINE CLASS DEVICE & DIAGNOSTIC;
    REDEFINE HANDLING READ & WRITE;
}

device_specific_status_2_mask  LIKE VARIABLE device_specific_status_2
{
    REDEFINE LABEL "Device Specific Status 2 Mask";
    REDEFINE HELP "";
    REDEFINE CLASS DEVICE & DIAGNOSTIC;
    REDEFINE HANDLING READ & WRITE;
}

device_specific_status_3_mask  LIKE VARIABLE device_specific_status_3
{
    REDEFINE LABEL "Device Specific Status 3 Mask";
    REDEFINE HELP "";
    REDEFINE CLASS DEVICE & DIAGNOSTIC;
    REDEFINE HANDLING READ & WRITE;
}

device_specific_status_4_mask  LIKE VARIABLE device_specific_status_4
{
    REDEFINE LABEL "Device Specific Status 4 Mask";
    REDEFINE HELP "";
    REDEFINE CLASS DEVICE & DIAGNOSTIC;
    REDEFINE HANDLING READ & WRITE;
}

device_specific_status_5_mask  LIKE VARIABLE device_specific_status_5
{
    REDEFINE LABEL "Device Specific Status 5 Mask";
    REDEFINE HELP "";
    REDEFINE CLASS DEVICE & DIAGNOSTIC;
    REDEFINE HANDLING READ & WRITE;
}

device_specific_status_14_mask LIKE VARIABLE device_specific_status_14
{
    REDEFINE LABEL "Device Specific Status 14 Mask";
    REDEFINE HELP "";
    REDEFINE CLASS DEVICE & DIAGNOSTIC;
    REDEFINE HANDLING READ & WRITE;
}

device_specific_status_15_mask LIKE VARIABLE device_specific_status_15
{
    REDEFINE LABEL "Device Specific Status 15 Mask";
    REDEFINE HELP "";
    REDEFINE CLASS DEVICE & DIAGNOSTIC;
    REDEFINE HANDLING READ & WRITE;
}

device_specific_status_16_mask LIKE VARIABLE device_specific_status_16
{
    REDEFINE LABEL "Device Specific Status 16 Mask";
    REDEFINE HELP "";
    REDEFINE CLASS DEVICE & DIAGNOSTIC;
    REDEFINE HANDLING READ & WRITE;
}

device_specific_status_17_mask LIKE VARIABLE device_specific_status_17
{
    REDEFINE LABEL "Device Specific Status 17 Mask";
    REDEFINE HELP "";
    REDEFINE CLASS DEVICE & DIAGNOSTIC;
    REDEFINE HANDLING READ & WRITE;
}

device_specific_status_18_mask LIKE VARIABLE device_specific_status_18
{
    REDEFINE LABEL "Device Specific Status 18 Mask";
    REDEFINE HELP "";
    REDEFINE CLASS DEVICE & DIAGNOSTIC;
    REDEFINE HANDLING READ & WRITE;
}

device_specific_status_19_mask LIKE VARIABLE device_specific_status_19
{
    REDEFINE LABEL "Device Specific Status 19 Mask";
    REDEFINE HELP "";
    REDEFINE CLASS DEVICE & DIAGNOSTIC;
    REDEFINE HANDLING READ & WRITE;
}

device_specific_status_20_mask LIKE VARIABLE device_specific_status_20
{
    REDEFINE LABEL "Device Specific Status 20 Mask";
    REDEFINE HELP "";
    REDEFINE CLASS DEVICE & DIAGNOSTIC;
    REDEFINE HANDLING READ & WRITE;
}

device_specific_status_21_mask LIKE VARIABLE device_specific_status_21
{
    REDEFINE LABEL "Device Specific Status 21 Mask";
    REDEFINE HELP "";
    REDEFINE CLASS DEVICE & DIAGNOSTIC;
    REDEFINE HANDLING READ & WRITE;
}

device_specific_status_22_mask LIKE VARIABLE device_specific_status_22
{
    REDEFINE LABEL "Device Specific Status 22 Mask";
    REDEFINE HELP "";
    REDEFINE CLASS DEVICE & DIAGNOSTIC;
    REDEFINE HANDLING READ & WRITE;
}

device_specific_status_23_mask LIKE VARIABLE device_specific_status_23
{
    REDEFINE LABEL "Device Specific Status 23 Mask";
    REDEFINE HELP "";
    REDEFINE CLASS DEVICE & DIAGNOSTIC;
    REDEFINE HANDLING READ & WRITE;
}

device_specific_status_24_mask LIKE VARIABLE device_specific_status_24
{
    REDEFINE LABEL "Device Specific Status 24 Mask";
    REDEFINE HELP "";
    REDEFINE CLASS DEVICE & DIAGNOSTIC;
    REDEFINE HANDLING READ & WRITE;
}

device_specific_status_0_latched_value  LIKE VARIABLE device_specific_status_0
{
    REDEFINE LABEL "Latched Device Specific Status 0";
    REDEFINE HELP "";
    REDEFINE CLASS DEVICE & DIAGNOSTIC;
    REDEFINE HANDLING WRITE;
}

device_specific_status_1_latched_value  LIKE VARIABLE device_specific_status_1
{
    REDEFINE LABEL "Latched Device Specific Status 1";
    REDEFINE HELP "";
    REDEFINE CLASS DEVICE & DIAGNOSTIC;
    REDEFINE HANDLING WRITE;
}

device_specific_status_2_latched_value  LIKE VARIABLE device_specific_status_2
{
    REDEFINE LABEL "Latched Device Specific Status 2";
    REDEFINE HELP "";
    REDEFINE CLASS DEVICE & DIAGNOSTIC;
    REDEFINE HANDLING WRITE;
}

device_specific_status_3_latched_value  LIKE VARIABLE device_specific_status_3
{
    REDEFINE LABEL "Latched Device Specific Status 3";
    REDEFINE HELP "";
    REDEFINE CLASS DEVICE & DIAGNOSTIC;
    REDEFINE HANDLING WRITE;
}

device_specific_status_4_latched_value  LIKE VARIABLE device_specific_status_4
{
    REDEFINE LABEL "Latched Device Specific Status 4";
    REDEFINE HELP "";
    REDEFINE CLASS DEVICE & DIAGNOSTIC;
    REDEFINE HANDLING WRITE;
}

device_specific_status_5_latched_value  LIKE VARIABLE device_specific_status_5
{
    REDEFINE LABEL "Latched Device Specific Status 5";
    REDEFINE HELP "";
    REDEFINE CLASS DEVICE & DIAGNOSTIC;
    REDEFINE HANDLING WRITE;
}

device_specific_status_14_latched_value LIKE VARIABLE device_specific_status_14
{
    REDEFINE LABEL "Latched Device Specific Status 14";
    REDEFINE HELP "";
    REDEFINE CLASS DEVICE & DIAGNOSTIC;
    REDEFINE HANDLING WRITE;
}

device_specific_status_15_latched_value LIKE VARIABLE device_specific_status_15
{
    REDEFINE LABEL "Latched Device Specific Status 15";
    REDEFINE HELP "";
    REDEFINE CLASS DEVICE & DIAGNOSTIC;
    REDEFINE HANDLING WRITE;
}

device_specific_status_16_latched_value LIKE VARIABLE device_specific_status_16
{
    REDEFINE LABEL "Latched Device Specific Status 16";
    REDEFINE HELP "";
    REDEFINE CLASS DEVICE & DIAGNOSTIC;
    REDEFINE HANDLING WRITE;
}

device_specific_status_17_latched_value LIKE VARIABLE device_specific_status_17
{
    REDEFINE LABEL "Latched Device Specific Status 17";
    REDEFINE HELP "";
    REDEFINE CLASS DEVICE & DIAGNOSTIC;
    REDEFINE HANDLING WRITE;
}

device_specific_status_18_latched_value LIKE VARIABLE device_specific_status_18
{
    REDEFINE LABEL "Latched Device Specific Status 18";
    REDEFINE HELP "";
    REDEFINE CLASS DEVICE & DIAGNOSTIC;
    REDEFINE HANDLING WRITE;
}

device_specific_status_19_latched_value LIKE VARIABLE device_specific_status_19
{
    REDEFINE LABEL "Latched Device Specific Status 19";
    REDEFINE HELP "";
    REDEFINE CLASS DEVICE & DIAGNOSTIC;
    REDEFINE HANDLING WRITE;
}

device_specific_status_20_latched_value LIKE VARIABLE device_specific_status_20
{
    REDEFINE LABEL "Latched Device Specific Status 20";
    REDEFINE HELP "";
    REDEFINE CLASS DEVICE & DIAGNOSTIC;
    REDEFINE HANDLING WRITE;
}

device_specific_status_21_latched_value LIKE VARIABLE device_specific_status_21
{
    REDEFINE LABEL "Latched Device Specific Status 21";
    REDEFINE HELP "";
    REDEFINE CLASS DEVICE & DIAGNOSTIC;
    REDEFINE HANDLING WRITE;
}

device_specific_status_22_latched_value LIKE VARIABLE device_specific_status_22
{
    REDEFINE LABEL "Latched Device Specific Status 22";
    REDEFINE HELP "";
    REDEFINE CLASS DEVICE & DIAGNOSTIC;
    REDEFINE HANDLING WRITE;
}

device_specific_status_23_latched_value LIKE VARIABLE device_specific_status_23
{
    REDEFINE LABEL "Latched Device Specific Status 23";
    REDEFINE HELP "";
    REDEFINE CLASS DEVICE & DIAGNOSTIC;
    REDEFINE HANDLING WRITE;
}

device_specific_status_24_latched_value LIKE VARIABLE device_specific_status_24
{
    REDEFINE LABEL "Latched Device Specific Status 24";
    REDEFINE HELP "";
    REDEFINE CLASS DEVICE & DIAGNOSTIC;
    REDEFINE HANDLING WRITE;
}

config_change_counter_latched_value LIKE VARIABLE config_change_counter
{
    REDEFINE LABEL "Latched Cfg chng count";
    REDEFINE HELP "";
    REDEFINE CLASS DEVICE;
    REDEFINE HANDLING WRITE;
}

 /*****************************************************************************
 */

VARIABLE number_events_supported
{
    LABEL "Number of Events Supported";
    HELP "";
    CLASS DEVICE;
    HANDLING READ;
    TYPE UNSIGNED_INTEGER
    {
        MIN_VALUE 1;
    }
}

#if __TOKVER__ >= 800
VARIABLE time_of_first_unack_event
{
    LABEL "Time First Unack Event Triggered";
    HELP "The time when the first unacknowledged event was triggered";
    CLASS DEVICE & SERVICE;
    HANDLING READ;
    TYPE TIME_VALUE;
}

VARIABLE event_notification_retry_time_event
{
    LABEL "Event Notification Retry Time";
    HELP "";
    CLASS HART;
    TYPE TIME_VALUE
    { 
        DISPLAY_FORMAT "5.3f" ;
        TIME_SCALE SECONDS ;
    }
}

VARIABLE max_update_time_event
{
    LABEL "Max Update Time";
    HELP "";
    CLASS HART;
    TYPE TIME_VALUE
    { 
        DISPLAY_FORMAT "5.3f" ;
        TIME_SCALE SECONDS ;
    }
}

VARIABLE event_debounce_interval_event
{
    LABEL "Event Debounce Interval";
    HELP "";
    CLASS HART;
    TYPE TIME_VALUE
    { 
        DISPLAY_FORMAT "5.3f" ;
        TIME_SCALE SECONDS ;
    }
}

VARIABLE event_subdevice_index
{
    LABEL "Event Subdevice Index";
    HELP "";
    CLASS DEVICE;
    TYPE INDEX (2) subdevice_list;
}


COLLECTION OF VARIABLE event_control
{
    MEMBERS
    {
        EVENT_STATUS,                               event_status;
        EVENT_NOTIFICATION_CONTROL,                 event_notification_control_n;
        TIME_OF_FIRST_UNACK_EVENT,                  time_of_first_unack_event;
        EVENT_NOTIFICATION_RETRY_TIME,              event_notification_retry_time_event;
        MAX_UPDATE_TIME,                            max_update_time_event;
        EVENT_DEBOUNCE_INTERVAL,                    event_debounce_interval_event;
        SUB_DEVICE_MISSING,                         subdevice_missing;                  //Uses MSBit of subdev index to determine status of subdevice mapping 
        SUB_DEVICE_MAPPING,                         event_subdevice_index;              //remove this member for non-adapters
    }
}

#else

VARIABLE time_of_first_unack_event_int
{
    LABEL "Time First Unack Event Triggered";
    HELP "The time when the first unacknowledged event was triggered";
    CLASS DEVICE & SERVICE;
    HANDLING READ;
    TYPE UNSIGNED_INTEGER(4);
}

VARIABLE event_notification_retry_time_event_int
{
    LABEL "Event Notification Retry Time";
    HELP "";
    CLASS HART;
    TYPE UNSIGNED_INTEGER(4)
    {
        SCALING_FACTOR 0.00003125;
        EDIT_FORMAT "4.2f";
        DISPLAY_FORMAT "4.2f";
        MIN_VALUE (0.1 * 32000);
    }
    CONSTANT_UNIT "s";
}

VARIABLE max_update_time_event_int
{
    LABEL "Max Update Time";
    HELP "";
    CLASS HART;
    TYPE UNSIGNED_INTEGER(4)
    {
        SCALING_FACTOR 0.00003125;
        DISPLAY_FORMAT "4.2f";
        EDIT_FORMAT "4.2f";
    }
    CONSTANT_UNIT "s";
}

VARIABLE event_debounce_interval_event_int
{
    LABEL "Event Debounce Interval";
    HELP "";
    CLASS HART;
    TYPE UNSIGNED_INTEGER(4)
    {
        SCALING_FACTOR 0.00003125;
        DISPLAY_FORMAT "4.2f";
        EDIT_FORMAT "4.2f";
    }
    CONSTANT_UNIT "s";
}

VARIABLE event_subdevice_index_int
{
    LABEL "Event Subdevice Index";
    HELP "";
    CLASS DEVICE;
    TYPE UNSIGNED_INTEGER (2);
}

COLLECTION OF VARIABLE event_control
{
    MEMBERS
    {
        EVENT_STATUS,                               event_status;
        EVENT_NOTIFICATION_CONTROL,                 event_notification_control_n;
        TIME_OF_FIRST_UNACK_EVENT,                  time_of_first_unack_event_int;
        EVENT_NOTIFICATION_RETRY_TIME,              event_notification_retry_time_event_int;
        MAX_UPDATE_TIME,                            max_update_time_event_int;
        EVENT_DEBOUNCE_INTERVAL,                    event_debounce_interval_event_int;
        SUB_DEVICE_MISSING,                         subdevice_missing;                  //Uses MSBit of subdev index to determine status of subdevice mapping
        SUB_DEVICE_MAPPING,                         event_subdevice_index_int;          //remove this member for non-adapters
    }
}

#endif

COLLECTION OF COLLECTION event
{
    MEMBERS
    {
        EVENT_CONTROL,      event_control;
        EVENT_MASK,         event_mask;
        EVENT_REPORT,       event_report;
    }
}


COLLECTION OF VARIABLE event_mask
{
    MEMBERS
    {
        DEVICE_STATUS_MASK ,                        device_status_mask;
        DEVICE_SPECIFIC_STATUS_0_MASK,              device_specific_status_0_mask;
        DEVICE_SPECIFIC_STATUS_1_MASK,              device_specific_status_1_mask; 
        DEVICE_SPECIFIC_STATUS_2_MASK,              device_specific_status_2_mask;
        DEVICE_SPECIFIC_STATUS_3_MASK,              device_specific_status_3_mask; 
        DEVICE_SPECIFIC_STATUS_4_MASK,              device_specific_status_4_mask; 
        DEVICE_SPECIFIC_STATUS_5_MASK,              device_specific_status_5_mask;

        EXTENDED_FLD_DEVICE_STATUS_MASK,            extended_fld_device_status_mask;

        STANDARDIZED_STATUS_0_MASK,                 standardized_status_0_mask;
        STANDARDIZED_STATUS_1_MASK,                 standardized_status_1_mask;
        STANDARDIZED_STATUS_2_MASK,                 standardized_status_2_mask;
        STANDARDIZED_STATUS_3_MASK,                 standardized_status_3_mask;

        ANALOG_CHANNEL_FIXED1_MASK,                 analog_channel_fixed1_mask;
        ANALOG_CHANNEL_SATURATED1_MASK,             analog_channel_saturated1_mask;
        DEV_OPERATING_MODE_MASK,                    dev_operating_mode_mask;

        DEVICE_SPECIFIC_STATUS_14_MASK,             device_specific_status_14_mask;
        DEVICE_SPECIFIC_STATUS_15_MASK,             device_specific_status_15_mask;
        DEVICE_SPECIFIC_STATUS_16_MASK,             device_specific_status_16_mask;
        DEVICE_SPECIFIC_STATUS_17_MASK,             device_specific_status_17_mask;
        DEVICE_SPECIFIC_STATUS_18_MASK,             device_specific_status_18_mask;
        DEVICE_SPECIFIC_STATUS_19_MASK,             device_specific_status_19_mask;
        DEVICE_SPECIFIC_STATUS_20_MASK,             device_specific_status_20_mask;
        DEVICE_SPECIFIC_STATUS_21_MASK,             device_specific_status_21_mask;
        DEVICE_SPECIFIC_STATUS_22_MASK,             device_specific_status_22_mask;
        DEVICE_SPECIFIC_STATUS_23_MASK,             device_specific_status_23_mask;
        DEVICE_SPECIFIC_STATUS_24_MASK,             device_specific_status_24_mask;
    }
}

COLLECTION OF VARIABLE event_report {
    MEMBERS
    {
        DEVICE_STATUS_LATCHED_VALUE ,               device_status_latched_value; 
        DEVICE_SPECIFIC_STATUS_0_LATCHED_VALUE,     device_specific_status_0_latched_value;
        DEVICE_SPECIFIC_STATUS_1_LATCHED_VALUE,     device_specific_status_1_latched_value; 
        DEVICE_SPECIFIC_STATUS_2_LATCHED_VALUE,     device_specific_status_2_latched_value;
        DEVICE_SPECIFIC_STATUS_3_LATCHED_VALUE,     device_specific_status_3_latched_value; 
        DEVICE_SPECIFIC_STATUS_4_LATCHED_VALUE,     device_specific_status_4_latched_value; 
        DEVICE_SPECIFIC_STATUS_5_LATCHED_VALUE,     device_specific_status_5_latched_value;

        EXTENDED_FLD_DEVICE_STATUS_LATCHED_VALUE,   extended_fld_device_status_latched_value;

        STANDARDIZED_STATUS_0_LATCHED_VALUE,        standardized_status_0_latched_value;
        STANDARDIZED_STATUS_1_LATCHED_VALUE,        standardized_status_1_latched_value;
        STANDARDIZED_STATUS_2_LATCHED_VALUE,        standardized_status_2_latched_value;
        STANDARDIZED_STATUS_3_LATCHED_VALUE,        standardized_status_3_latched_value;

        ANALOG_CHANNEL_SATURATED1_LATCHED_VALUE,    analog_channel_saturated1_latched_value;
        ANALOG_CHANNEL_FIXED1_LATCHED_VALUE,        analog_channel_fixed1_latched_value;
        DEV_OPERATING_MODE_LATCHED_VALUE,           dev_operating_mode_latched_value;

        DEVICE_SPECIFIC_STATUS_14_LATCHED_VALUE,    device_specific_status_14_latched_value;
        DEVICE_SPECIFIC_STATUS_15_LATCHED_VALUE,    device_specific_status_15_latched_value;
        DEVICE_SPECIFIC_STATUS_16_LATCHED_VALUE,    device_specific_status_16_latched_value;
        DEVICE_SPECIFIC_STATUS_17_LATCHED_VALUE,    device_specific_status_17_latched_value;
        DEVICE_SPECIFIC_STATUS_18_LATCHED_VALUE,    device_specific_status_18_latched_value;
        DEVICE_SPECIFIC_STATUS_19_LATCHED_VALUE,    device_specific_status_19_latched_value;
        DEVICE_SPECIFIC_STATUS_20_LATCHED_VALUE,    device_specific_status_20_latched_value;
        DEVICE_SPECIFIC_STATUS_21_LATCHED_VALUE,    device_specific_status_21_latched_value;
        DEVICE_SPECIFIC_STATUS_22_LATCHED_VALUE,    device_specific_status_22_latched_value;
        DEVICE_SPECIFIC_STATUS_23_LATCHED_VALUE,    device_specific_status_23_latched_value;
        DEVICE_SPECIFIC_STATUS_24_LATCHED_VALUE,    device_specific_status_24_latched_value;

        CONFIG_CHANGE_COUNTER_LATCHED_VALUE,        config_change_counter_latched_value;       
    }
}

/* Older tokenizers don't like value arrays or
   references to value-arrays within COMMANDS. */
#if __TOKVER__ >= 800
ARRAY events
{
    NUMBER_OF_ELEMENTS 1;
    TYPE event;
}

VARIABLE eventNumber
{
    LABEL "Event Number";
    HELP "";
    CLASS LOCAL;
    TYPE INDEX events;

}
#endif

COMMAND read_event_notification_summary
{
    NUMBER 115;
    OPERATION READ;
    TRANSACTION
    {
#if __TOKVER__ >= 800
        REQUEST
        {
            eventNumber (INFO, INDEX)
        }
        REPLY
        {
            response_code, device_status,
            eventNumber (INFO, INDEX),
            number_events_supported,
            events[eventNumber].EVENT_CONTROL.EVENT_STATUS<0xf0>, 
            events[eventNumber].EVENT_CONTROL.EVENT_NOTIFICATION_CONTROL<0x0f>,
            events[eventNumber].EVENT_CONTROL.TIME_OF_FIRST_UNACK_EVENT,
            events[eventNumber].EVENT_CONTROL.EVENT_NOTIFICATION_RETRY_TIME,
            events[eventNumber].EVENT_CONTROL.MAX_UPDATE_TIME,
            events[eventNumber].EVENT_CONTROL.EVENT_DEBOUNCE_INTERVAL,
            events[eventNumber].EVENT_MASK.DEVICE_STATUS_MASK, 
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_0_MASK,  
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_1_MASK,  
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_2_MASK, 
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_3_MASK,  
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_4_MASK,  
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_5_MASK, 
            events[eventNumber].EVENT_MASK.EXTENDED_FLD_DEVICE_STATUS_MASK, 
            events[eventNumber].EVENT_MASK.DEV_OPERATING_MODE_MASK,
            events[eventNumber].EVENT_MASK.STANDARDIZED_STATUS_0_MASK, 
            events[eventNumber].EVENT_MASK.STANDARDIZED_STATUS_1_MASK, 
            events[eventNumber].EVENT_MASK.ANALOG_CHANNEL_SATURATED1_MASK, 
            events[eventNumber].EVENT_MASK.STANDARDIZED_STATUS_2_MASK, 
            events[eventNumber].EVENT_MASK.STANDARDIZED_STATUS_3_MASK, 
            events[eventNumber].EVENT_MASK.ANALOG_CHANNEL_FIXED1_MASK, 
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_14_MASK, 
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_15_MASK, 
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_16_MASK, 
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_17_MASK, 
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_18_MASK, 
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_19_MASK, 
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_20_MASK, 
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_21_MASK, 
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_22_MASK, 
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_23_MASK, 
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_24_MASK
        }
#else
        REQUEST
        {
            0
        }
        REPLY
        {
            response_code, device_status,
            0,
            number_events_supported,
            event.EVENT_CONTROL.EVENT_STATUS<0xf0>, 
            event.EVENT_CONTROL.EVENT_NOTIFICATION_CONTROL<0x0f>,
            event.EVENT_CONTROL.TIME_OF_FIRST_UNACK_EVENT,
            event.EVENT_CONTROL.EVENT_NOTIFICATION_RETRY_TIME,
            event.EVENT_CONTROL.MAX_UPDATE_TIME,
            event.EVENT_CONTROL.EVENT_DEBOUNCE_INTERVAL,
            event.EVENT_MASK.DEVICE_STATUS_MASK, 
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_0_MASK,  
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_1_MASK,  
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_2_MASK, 
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_3_MASK,  
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_4_MASK,  
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_5_MASK, 
            event.EVENT_MASK.EXTENDED_FLD_DEVICE_STATUS_MASK, 
            event.EVENT_MASK.DEV_OPERATING_MODE_MASK,
            event.EVENT_MASK.STANDARDIZED_STATUS_0_MASK, 
            event.EVENT_MASK.STANDARDIZED_STATUS_1_MASK, 
            event.EVENT_MASK.ANALOG_CHANNEL_SATURATED1_MASK, 
            event.EVENT_MASK.STANDARDIZED_STATUS_2_MASK, 
            event.EVENT_MASK.STANDARDIZED_STATUS_3_MASK, 
            event.EVENT_MASK.ANALOG_CHANNEL_FIXED1_MASK, 
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_14_MASK, 
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_15_MASK, 
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_16_MASK, 
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_17_MASK, 
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_18_MASK, 
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_19_MASK, 
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_20_MASK, 
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_21_MASK, 
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_22_MASK, 
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_23_MASK, 
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_24_MASK
        }
#endif
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        2,  DATA_ENTRY_ERROR, [invalid_selection];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        6,  MISC_ERROR,       [xmtr_specific_command_error];
    }
}

COMMAND write_event_notification_bit_mask
{
    NUMBER 116;
    OPERATION WRITE;
    TRANSACTION
    {
#if __TOKVER__ >= 800
        REQUEST
        {
            eventNumber (INFO, INDEX),
            events[eventNumber].EVENT_MASK.DEVICE_STATUS_MASK, 
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_0_MASK,  
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_1_MASK,  
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_2_MASK, 
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_3_MASK,  
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_4_MASK,  
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_5_MASK,
            events[eventNumber].EVENT_MASK.EXTENDED_FLD_DEVICE_STATUS_MASK, 
            events[eventNumber].EVENT_MASK.DEV_OPERATING_MODE_MASK,
            events[eventNumber].EVENT_MASK.STANDARDIZED_STATUS_0_MASK, 
            events[eventNumber].EVENT_MASK.STANDARDIZED_STATUS_1_MASK, 
            events[eventNumber].EVENT_MASK.ANALOG_CHANNEL_SATURATED1_MASK, 
            events[eventNumber].EVENT_MASK.STANDARDIZED_STATUS_2_MASK, 
            events[eventNumber].EVENT_MASK.STANDARDIZED_STATUS_3_MASK, 
            events[eventNumber].EVENT_MASK.ANALOG_CHANNEL_FIXED1_MASK, 
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_14_MASK, 
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_15_MASK, 
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_16_MASK, 
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_17_MASK, 
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_18_MASK, 
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_19_MASK, 
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_20_MASK, 
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_21_MASK, 
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_22_MASK, 
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_23_MASK, 
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_24_MASK        
        }
        REPLY
        {
            response_code, device_status,
            eventNumber (INFO, INDEX),
            events[eventNumber].EVENT_MASK.DEVICE_STATUS_MASK, 
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_0_MASK,  
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_1_MASK,  
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_2_MASK, 
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_3_MASK,  
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_4_MASK,  
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_5_MASK, 
            events[eventNumber].EVENT_MASK.EXTENDED_FLD_DEVICE_STATUS_MASK, 
            events[eventNumber].EVENT_MASK.DEV_OPERATING_MODE_MASK,
            events[eventNumber].EVENT_MASK.STANDARDIZED_STATUS_0_MASK, 
            events[eventNumber].EVENT_MASK.STANDARDIZED_STATUS_1_MASK, 
            events[eventNumber].EVENT_MASK.ANALOG_CHANNEL_SATURATED1_MASK, 
            events[eventNumber].EVENT_MASK.STANDARDIZED_STATUS_2_MASK, 
            events[eventNumber].EVENT_MASK.STANDARDIZED_STATUS_3_MASK, 
            events[eventNumber].EVENT_MASK.ANALOG_CHANNEL_FIXED1_MASK, 
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_14_MASK, 
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_15_MASK, 
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_16_MASK, 
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_17_MASK, 
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_18_MASK, 
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_19_MASK, 
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_20_MASK, 
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_21_MASK, 
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_22_MASK, 
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_23_MASK, 
            events[eventNumber].EVENT_MASK.DEVICE_SPECIFIC_STATUS_24_MASK
        }
    }
#else
        REQUEST
        {
            0,
            event.EVENT_MASK.DEVICE_STATUS_MASK, 
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_0_MASK,  
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_1_MASK,  
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_2_MASK, 
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_3_MASK,  
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_4_MASK,  
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_5_MASK,
            event.EVENT_MASK.EXTENDED_FLD_DEVICE_STATUS_MASK, 
            event.EVENT_MASK.DEV_OPERATING_MODE_MASK,
            event.EVENT_MASK.STANDARDIZED_STATUS_0_MASK, 
            event.EVENT_MASK.STANDARDIZED_STATUS_1_MASK, 
            event.EVENT_MASK.ANALOG_CHANNEL_SATURATED1_MASK, 
            event.EVENT_MASK.STANDARDIZED_STATUS_2_MASK, 
            event.EVENT_MASK.STANDARDIZED_STATUS_3_MASK, 
            event.EVENT_MASK.ANALOG_CHANNEL_FIXED1_MASK, 
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_14_MASK, 
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_15_MASK, 
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_16_MASK, 
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_17_MASK, 
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_18_MASK, 
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_19_MASK, 
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_20_MASK, 
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_21_MASK, 
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_22_MASK, 
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_23_MASK, 
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_24_MASK        
        }
        REPLY
        {
            response_code, device_status,
            0,
            event.EVENT_MASK.DEVICE_STATUS_MASK, 
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_0_MASK,  
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_1_MASK,  
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_2_MASK, 
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_3_MASK,  
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_4_MASK,  
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_5_MASK, 
            event.EVENT_MASK.EXTENDED_FLD_DEVICE_STATUS_MASK, 
            event.EVENT_MASK.DEV_OPERATING_MODE_MASK,
            event.EVENT_MASK.STANDARDIZED_STATUS_0_MASK, 
            event.EVENT_MASK.STANDARDIZED_STATUS_1_MASK, 
            event.EVENT_MASK.ANALOG_CHANNEL_SATURATED1_MASK, 
            event.EVENT_MASK.STANDARDIZED_STATUS_2_MASK, 
            event.EVENT_MASK.STANDARDIZED_STATUS_3_MASK, 
            event.EVENT_MASK.ANALOG_CHANNEL_FIXED1_MASK, 
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_14_MASK, 
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_15_MASK, 
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_16_MASK, 
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_17_MASK, 
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_18_MASK, 
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_19_MASK, 
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_20_MASK, 
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_21_MASK, 
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_22_MASK, 
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_23_MASK, 
            event.EVENT_MASK.DEVICE_SPECIFIC_STATUS_24_MASK
        }
    }
#endif
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        2,  DATA_ENTRY_ERROR, [invalid_selection];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        6,  MISC_ERROR,       [xmtr_specific_command_error];
        7,  MODE_ERROR,       [in_write_protect_mode];
        16, MODE_ERROR,       [access_restricted];
    }
}
COMMAND write_event_notification_timing
{
    NUMBER 117;
    OPERATION WRITE;
    TRANSACTION
    {
#if __TOKVER__ >= 800
        REQUEST
        {
            eventNumber (INFO, INDEX),
            events[eventNumber].EVENT_CONTROL.EVENT_NOTIFICATION_RETRY_TIME,
            events[eventNumber].EVENT_CONTROL.MAX_UPDATE_TIME,
            events[eventNumber].EVENT_CONTROL.EVENT_DEBOUNCE_INTERVAL
        }
        REPLY
        {
            response_code, device_status,
            eventNumber (INFO, INDEX),
            events[eventNumber].EVENT_CONTROL.EVENT_NOTIFICATION_RETRY_TIME,
            events[eventNumber].EVENT_CONTROL.MAX_UPDATE_TIME,
            events[eventNumber].EVENT_CONTROL.EVENT_DEBOUNCE_INTERVAL
        }
#else
        REQUEST
        {
            0,
            event.EVENT_CONTROL.EVENT_NOTIFICATION_RETRY_TIME,
            event.EVENT_CONTROL.MAX_UPDATE_TIME,
            event.EVENT_CONTROL.EVENT_DEBOUNCE_INTERVAL
        }
        REPLY
        {
            response_code, device_status,
            0,
            event.EVENT_CONTROL.EVENT_NOTIFICATION_RETRY_TIME,
            event.EVENT_CONTROL.MAX_UPDATE_TIME,
            event.EVENT_CONTROL.EVENT_DEBOUNCE_INTERVAL
        }
#endif
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        6,  MISC_ERROR,       [xmtr_specific_command_error];
        7,  MODE_ERROR,       [in_write_protect_mode];
        8,  MISC_WARNING,     "Update period or debounce interval adjusted";
        9,  DATA_ENTRY_ERROR, "Invalid burst message"; // shouldn't this be event, not burst??
        16, MODE_ERROR,       [access_restricted];
        32, MODE_ERROR,       [busy];
        33, MODE_ERROR,       [delayed_response_initiated];
        34, MODE_ERROR,       [delayed_response_running];
        35, MODE_ERROR,       [delayed_response_dead];
        36, MODE_ERROR,       [delayed_response_conflict];
    }
}

COMMAND event_notification_control
{
    NUMBER 118;
    OPERATION WRITE;
    TRANSACTION
    {
#if __TOKVER__ >= 800
        REQUEST
        {
            eventNumber (INFO, INDEX),
            events[eventNumber].EVENT_CONTROL.EVENT_NOTIFICATION_CONTROL
        }
        REPLY
        {
            response_code, device_status,
            eventNumber (INFO, INDEX),
            events[eventNumber].EVENT_CONTROL.EVENT_NOTIFICATION_CONTROL
        }
#else
        REQUEST
        {
            0,
            event.EVENT_CONTROL.EVENT_NOTIFICATION_CONTROL
        }
        REPLY
        {
            response_code, device_status,
            0,
            event.EVENT_CONTROL.EVENT_NOTIFICATION_CONTROL
        }
#endif
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        2,  DATA_ENTRY_ERROR, [invalid_selection];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        6,  MISC_ERROR,       [xmtr_specific_command_error];
        7,  MODE_ERROR,       [in_write_protect_mode];
        8,  MISC_WARNING,     "Update times adjusted";
        14, MISC_WARNING,     "Update rate uncertain";  //only allowed when not connect to network
        16, MODE_ERROR,       [access_restricted];
        32, MODE_ERROR,       [busy];
        33, MODE_ERROR,       [delayed_response_initiated];
        34, MODE_ERROR,       [delayed_response_running];
        35, MODE_ERROR,       [delayed_response_dead];
        36, MODE_ERROR,       [delayed_response_conflict];
    }
}

COMMAND acknowledge_event_notification
{
    NUMBER 119;
    OPERATION COMMAND;
    TRANSACTION 0  //used to get the latest outstanding event
    {
#if __TOKVER__ >= 800
        REQUEST
        {
            eventNumber (INFO, INDEX)
        }
        REPLY
        {
            response_code, device_status,
            eventNumber (INFO, INDEX),
            events[eventNumber].EVENT_CONTROL.TIME_OF_FIRST_UNACK_EVENT,
            events[eventNumber].EVENT_REPORT.CONFIG_CHANGE_COUNTER_LATCHED_VALUE
            events[eventNumber].EVENT_REPORT.DEVICE_STATUS_LATCHED_VALUE, 
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_0_LATCHED_VALUE,  
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_1_LATCHED_VALUE,  
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_2_LATCHED_VALUE, 
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_3_LATCHED_VALUE,  
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_4_LATCHED_VALUE,  
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_5_LATCHED_VALUE, 
            events[eventNumber].EVENT_REPORT.EXTENDED_FLD_DEVICE_STATUS_LATCHED_VALUE, 
            events[eventNumber].EVENT_REPORT.DEV_OPERATING_MODE_LATCHED_VALUE,
            events[eventNumber].EVENT_REPORT.STANDARDIZED_STATUS_0_LATCHED_VALUE, 
            events[eventNumber].EVENT_REPORT.STANDARDIZED_STATUS_1_LATCHED_VALUE, 
            events[eventNumber].EVENT_REPORT.ANALOG_CHANNEL_SATURATED1_LATCHED_VALUE, 
            events[eventNumber].EVENT_REPORT.STANDARDIZED_STATUS_2_LATCHED_VALUE, 
            events[eventNumber].EVENT_REPORT.STANDARDIZED_STATUS_3_LATCHED_VALUE, 
            events[eventNumber].EVENT_REPORT.ANALOG_CHANNEL_FIXED1_LATCHED_VALUE, 
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_14_LATCHED_VALUE, 
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_15_LATCHED_VALUE, 
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_16_LATCHED_VALUE, 
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_17_LATCHED_VALUE, 
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_18_LATCHED_VALUE, 
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_19_LATCHED_VALUE, 
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_20_LATCHED_VALUE, 
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_21_LATCHED_VALUE, 
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_22_LATCHED_VALUE, 
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_23_LATCHED_VALUE, 
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_24_LATCHED_VALUE
        }
#else
        /* For older tokenizers - a single event is defined so that METHODS can
           send command 119 and read the response from the device. */
        REQUEST
        {
            0
        }
        REPLY
        {
            response_code, device_status,
            0,
            event.EVENT_CONTROL.TIME_OF_FIRST_UNACK_EVENT,
            event.EVENT_REPORT.CONFIG_CHANGE_COUNTER_LATCHED_VALUE
            event.EVENT_REPORT.DEVICE_STATUS_LATCHED_VALUE, 
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_0_LATCHED_VALUE,  
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_1_LATCHED_VALUE,  
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_2_LATCHED_VALUE, 
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_3_LATCHED_VALUE,  
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_4_LATCHED_VALUE,  
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_5_LATCHED_VALUE, 
            event.EVENT_REPORT.EXTENDED_FLD_DEVICE_STATUS_LATCHED_VALUE, 
            event.EVENT_REPORT.DEV_OPERATING_MODE_LATCHED_VALUE,
            event.EVENT_REPORT.STANDARDIZED_STATUS_0_LATCHED_VALUE, 
            event.EVENT_REPORT.STANDARDIZED_STATUS_1_LATCHED_VALUE, 
            event.EVENT_REPORT.ANALOG_CHANNEL_SATURATED1_LATCHED_VALUE, 
            event.EVENT_REPORT.STANDARDIZED_STATUS_2_LATCHED_VALUE, 
            event.EVENT_REPORT.STANDARDIZED_STATUS_3_LATCHED_VALUE, 
            event.EVENT_REPORT.ANALOG_CHANNEL_FIXED1_LATCHED_VALUE, 
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_14_LATCHED_VALUE, 
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_15_LATCHED_VALUE, 
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_16_LATCHED_VALUE, 
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_17_LATCHED_VALUE, 
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_18_LATCHED_VALUE, 
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_19_LATCHED_VALUE, 
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_20_LATCHED_VALUE, 
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_21_LATCHED_VALUE, 
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_22_LATCHED_VALUE, 
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_23_LATCHED_VALUE, 
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_24_LATCHED_VALUE
        }
#endif
    }
    TRANSACTION 1  //Used to ACK an outstanding event
    {
#if __TOKVER__ >= 800
        REQUEST
        {
            eventNumber (INFO, INDEX),
            events[eventNumber].EVENT_CONTROL.TIME_OF_FIRST_UNACK_EVENT (INFO),
            events[eventNumber].EVENT_REPORT.CONFIG_CHANGE_COUNTER_LATCHED_VALUE (INFO),
            events[eventNumber].EVENT_REPORT.DEVICE_STATUS_LATCHED_VALUE (INFO), 
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_0_LATCHED_VALUE (INFO),  
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_1_LATCHED_VALUE (INFO),  
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_2_LATCHED_VALUE (INFO), 
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_3_LATCHED_VALUE (INFO),  
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_4_LATCHED_VALUE (INFO),  
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_5_LATCHED_VALUE (INFO), 
            events[eventNumber].EVENT_REPORT.EXTENDED_FLD_DEVICE_STATUS_LATCHED_VALUE (INFO), 
            events[eventNumber].EVENT_REPORT.DEV_OPERATING_MODE_LATCHED_VALUE (INFO),
            events[eventNumber].EVENT_REPORT.STANDARDIZED_STATUS_0_LATCHED_VALUE (INFO), 
            events[eventNumber].EVENT_REPORT.STANDARDIZED_STATUS_1_LATCHED_VALUE (INFO), 
            events[eventNumber].EVENT_REPORT.ANALOG_CHANNEL_SATURATED1_LATCHED_VALUE (INFO), 
            events[eventNumber].EVENT_REPORT.STANDARDIZED_STATUS_2_LATCHED_VALUE (INFO), 
            events[eventNumber].EVENT_REPORT.STANDARDIZED_STATUS_3_LATCHED_VALUE (INFO), 
            events[eventNumber].EVENT_REPORT.ANALOG_CHANNEL_FIXED1_LATCHED_VALUE (INFO), 
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_14_LATCHED_VALUE (INFO), 
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_15_LATCHED_VALUE (INFO), 
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_16_LATCHED_VALUE (INFO), 
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_17_LATCHED_VALUE (INFO), 
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_18_LATCHED_VALUE (INFO), 
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_19_LATCHED_VALUE (INFO), 
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_20_LATCHED_VALUE (INFO), 
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_21_LATCHED_VALUE (INFO), 
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_22_LATCHED_VALUE (INFO), 
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_23_LATCHED_VALUE (INFO), 
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_24_LATCHED_VALUE (INFO)  
        }
        REPLY
        {
            response_code, device_status,
            eventNumber (INFO, INDEX),
            events[eventNumber].EVENT_CONTROL.TIME_OF_FIRST_UNACK_EVENT (INFO),
            events[eventNumber].EVENT_REPORT.CONFIG_CHANGE_COUNTER_LATCHED_VALUE (INFO),
            events[eventNumber].EVENT_REPORT.DEVICE_STATUS_LATCHED_VALUE (INFO), 
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_0_LATCHED_VALUE (INFO),  
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_1_LATCHED_VALUE (INFO),  
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_2_LATCHED_VALUE (INFO), 
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_3_LATCHED_VALUE (INFO),  
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_4_LATCHED_VALUE (INFO),  
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_5_LATCHED_VALUE (INFO), 
            events[eventNumber].EVENT_REPORT.EXTENDED_FLD_DEVICE_STATUS_LATCHED_VALUE (INFO), 
            events[eventNumber].EVENT_REPORT.DEV_OPERATING_MODE_LATCHED_VALUE (INFO),
            events[eventNumber].EVENT_REPORT.STANDARDIZED_STATUS_0_LATCHED_VALUE (INFO), 
            events[eventNumber].EVENT_REPORT.STANDARDIZED_STATUS_1_LATCHED_VALUE (INFO), 
            events[eventNumber].EVENT_REPORT.ANALOG_CHANNEL_SATURATED1_LATCHED_VALUE (INFO), 
            events[eventNumber].EVENT_REPORT.STANDARDIZED_STATUS_2_LATCHED_VALUE (INFO), 
            events[eventNumber].EVENT_REPORT.STANDARDIZED_STATUS_3_LATCHED_VALUE (INFO), 
            events[eventNumber].EVENT_REPORT.ANALOG_CHANNEL_FIXED1_LATCHED_VALUE (INFO), 
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_14_LATCHED_VALUE (INFO), 
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_15_LATCHED_VALUE (INFO), 
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_16_LATCHED_VALUE (INFO), 
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_17_LATCHED_VALUE (INFO), 
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_18_LATCHED_VALUE (INFO), 
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_19_LATCHED_VALUE (INFO), 
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_20_LATCHED_VALUE (INFO), 
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_21_LATCHED_VALUE (INFO), 
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_22_LATCHED_VALUE (INFO), 
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_23_LATCHED_VALUE (INFO), 
            events[eventNumber].EVENT_REPORT.DEVICE_SPECIFIC_STATUS_24_LATCHED_VALUE (INFO)
        }
#else
        REQUEST
        {
            0,
            event.EVENT_CONTROL.TIME_OF_FIRST_UNACK_EVENT (INFO),
            event.EVENT_REPORT.CONFIG_CHANGE_COUNTER_LATCHED_VALUE (INFO),
            event.EVENT_REPORT.DEVICE_STATUS_LATCHED_VALUE (INFO), 
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_0_LATCHED_VALUE (INFO),  
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_1_LATCHED_VALUE (INFO),  
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_2_LATCHED_VALUE (INFO), 
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_3_LATCHED_VALUE (INFO),  
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_4_LATCHED_VALUE (INFO),  
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_5_LATCHED_VALUE (INFO), 
            event.EVENT_REPORT.EXTENDED_FLD_DEVICE_STATUS_LATCHED_VALUE (INFO), 
            event.EVENT_REPORT.DEV_OPERATING_MODE_LATCHED_VALUE (INFO),
            event.EVENT_REPORT.STANDARDIZED_STATUS_0_LATCHED_VALUE (INFO), 
            event.EVENT_REPORT.STANDARDIZED_STATUS_1_LATCHED_VALUE (INFO), 
            event.EVENT_REPORT.ANALOG_CHANNEL_SATURATED1_LATCHED_VALUE (INFO), 
            event.EVENT_REPORT.STANDARDIZED_STATUS_2_LATCHED_VALUE (INFO), 
            event.EVENT_REPORT.STANDARDIZED_STATUS_3_LATCHED_VALUE (INFO), 
            event.EVENT_REPORT.ANALOG_CHANNEL_FIXED1_LATCHED_VALUE (INFO), 
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_14_LATCHED_VALUE (INFO), 
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_15_LATCHED_VALUE (INFO), 
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_16_LATCHED_VALUE (INFO), 
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_17_LATCHED_VALUE (INFO), 
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_18_LATCHED_VALUE (INFO), 
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_19_LATCHED_VALUE (INFO), 
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_20_LATCHED_VALUE (INFO), 
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_21_LATCHED_VALUE (INFO), 
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_22_LATCHED_VALUE (INFO), 
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_23_LATCHED_VALUE (INFO), 
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_24_LATCHED_VALUE (INFO)  
        }
        REPLY
        {
            response_code, device_status,
            0,
            event.EVENT_CONTROL.TIME_OF_FIRST_UNACK_EVENT (INFO),
            event.EVENT_REPORT.CONFIG_CHANGE_COUNTER_LATCHED_VALUE (INFO),
            event.EVENT_REPORT.DEVICE_STATUS_LATCHED_VALUE (INFO), 
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_0_LATCHED_VALUE (INFO),  
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_1_LATCHED_VALUE (INFO),  
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_2_LATCHED_VALUE (INFO), 
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_3_LATCHED_VALUE (INFO),  
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_4_LATCHED_VALUE (INFO),  
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_5_LATCHED_VALUE (INFO), 
            event.EVENT_REPORT.EXTENDED_FLD_DEVICE_STATUS_LATCHED_VALUE (INFO), 
            event.EVENT_REPORT.DEV_OPERATING_MODE_LATCHED_VALUE (INFO),
            event.EVENT_REPORT.STANDARDIZED_STATUS_0_LATCHED_VALUE (INFO), 
            event.EVENT_REPORT.STANDARDIZED_STATUS_1_LATCHED_VALUE (INFO), 
            event.EVENT_REPORT.ANALOG_CHANNEL_SATURATED1_LATCHED_VALUE (INFO), 
            event.EVENT_REPORT.STANDARDIZED_STATUS_2_LATCHED_VALUE (INFO), 
            event.EVENT_REPORT.STANDARDIZED_STATUS_3_LATCHED_VALUE (INFO), 
            event.EVENT_REPORT.ANALOG_CHANNEL_FIXED1_LATCHED_VALUE (INFO), 
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_14_LATCHED_VALUE (INFO), 
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_15_LATCHED_VALUE (INFO), 
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_16_LATCHED_VALUE (INFO), 
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_17_LATCHED_VALUE (INFO), 
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_18_LATCHED_VALUE (INFO), 
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_19_LATCHED_VALUE (INFO), 
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_20_LATCHED_VALUE (INFO), 
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_21_LATCHED_VALUE (INFO), 
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_22_LATCHED_VALUE (INFO), 
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_23_LATCHED_VALUE (INFO), 
            event.EVENT_REPORT.DEVICE_SPECIFIC_STATUS_24_LATCHED_VALUE (INFO)
        }
#endif
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        2,  DATA_ENTRY_ERROR, [invalid_selection];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];  //Only generated if the event number is not in the request data
        6,  MISC_ERROR,       [xmtr_specific_command_error];
        8,  MISC_WARNING,     "Not all events cleared";
    }
}

/*
 *****************************************************************************
 * Common Practice Command Spec
 * Section 6.11
 * I/O and Subdevice Commands
 *
 * Commands 91 92 93
 *
 */

// Read Trend Configuration Command 91
/* Earlier tokenizers can't handle value-arrays or
   references to value-arrays in COMMANDs */
#if __TOKVER__ >= 800
VARIABLE trend_sample_interval 
{
    LABEL "Trend Sample Interval";
    HELP "";
    CLASS DEVICE;
    TYPE TIME_VALUE;
}

VARIABLE trend_0_time_stamp 
{
    LABEL "Trend 0 TIME Stamp";
    HELP "";
    CLASS DEVICE;
    HANDLING READ;
    TYPE TIME_VALUE;
}

VARIABLE trend_0_date_stamp 
{
    LABEL "Trend 0 Date Stamp";
    HELP "";
    CLASS DEVICE;
    HANDLING READ;
    TYPE DATE;
}

VARIABLE trend_value
{
    LABEL "Trend Value";
    HELP "";
    CLASS DEVICE;
    HANDLING READ;
    TYPE FLOAT;
}

VARIABLE trend_value_data_quality
{
    LABEL "Trend Value Data Quality";
    HELP "";
    CLASS DEVICE;
    HANDLING READ;
    TYPE ENUMERATED
    {
        { 0, [bad] },  
        { 1, [manual_fixed] },
        { 2, [poor_accuracy] },
        { 3, [good] } 
    }
}

VARIABLE trend_value_limit_status
{
    LABEL "Trend Value Limit Status";
    HELP "";
    CLASS DEVICE;
    HANDLING READ;
    TYPE ENUMERATED
    {
        { 0, [not_limited] },  
        { 1, [low_limited] },
        { 2, [high_limited] },
        { 3, [constant] }
    }
}

VARIABLE trend_value_device_family_status
{
    LABEL "Trend Value Device Family Status";
    HELP "";
    CLASS DEVICE;
    HANDLING READ;
    TYPE ENUMERATED
    {
        { 0x08, [more_device_family_status_available]}
    }
}

COLLECTION OF VARIABLE trend_data
{
    MEMBERS
    {
       TREND_VALUE,    trend_value;
       QUALITY_STATUS, trend_value_data_quality;
       LIMIT_STATUS,   trend_value_limit_status;
       FAMILY_STATUS,  trend_value_device_family_status;
    }
}

ARRAY trend_values
{
    NUMBER_OF_ELEMENTS 12;
    TYPE trend_data;
}

UNIT trend_units_relation
{
    trend_array[0].TREND_DIGITAL_UNITS:
        trend_array[0].TREND_VALUES[0].TREND_VALUE,
        trend_array[0].TREND_VALUES[1].TREND_VALUE,
        trend_array[0].TREND_VALUES[2].TREND_VALUE,
        trend_array[0].TREND_VALUES[3].TREND_VALUE,
        trend_array[0].TREND_VALUES[4].TREND_VALUE,
        trend_array[0].TREND_VALUES[5].TREND_VALUE,
        trend_array[0].TREND_VALUES[6].TREND_VALUE,
        trend_array[0].TREND_VALUES[7].TREND_VALUE,
        trend_array[0].TREND_VALUES[8].TREND_VALUE,
        trend_array[0].TREND_VALUES[9].TREND_VALUE,
        trend_array[0].TREND_VALUES[10].TREND_VALUE,
        trend_array[0].TREND_VALUES[11].TREND_VALUE
}

// end trend declarations specific to tok ver 8 and later

ARRAY trend_array
{
    NUMBER_OF_ELEMENTS 1;
    TYPE trend;
}

VARIABLE trend_number
{
    LABEL "Trend Number";
    HELP "";
    CLASS LOCAL;
    TYPE INDEX trend_array; 
}

#else

VARIABLE trend_number_int
{
    LABEL "Trend Number";
    HELP "";
    CLASS LOCAL;
    TYPE UNSIGNED_INTEGER; 
}

VARIABLE trend_sample_interval_int 
{
    LABEL "Trend Sample Interval";
    HELP "";
    CLASS DEVICE;
    TYPE UNSIGNED_INTEGER(4)
    {
        SCALING_FACTOR 0.00003125;
    }
    CONSTANT_UNIT "s";
}

#endif

VARIABLE number_trends_supported
{
    LABEL "Number of Trends Supported";
    HELP "";
    CLASS HART;
    TYPE UNSIGNED_INTEGER {
        MIN_VALUE 1;
    }
    HANDLING READ;
}

VARIABLE trend_device_variable_code
{
    LABEL "Trend Device Variable";
    HELP "Trend Device Variable Code";
    CLASS DEVICE;
    TYPE INDEX deviceVariables;
}


UNIT burst_trigger_units_relation
{
    burst_trigger_units:
        trigger_level
}

#if __TOKVER__ >= 800
COLLECTION trend
{
    MEMBERS
    {
        TREND_CONTROL,              trend_control;
        TREND_DEVICE_VARIABLE_CODE, trend_device_variable_code;
        TREND_SAMPLE_INTERVAL,      trend_sample_interval;

        TREND_VALUES,               trend_values;
        TREND_0_TIME_STAMP,         trend_0_time_stamp;
        TREND_0_DATE_STAMP,         trend_0_date_stamp;
        TREND_CLASSIFICATION,       trend_classification;
        TREND_DIGITAL_UNITS,        trend_digital_units;
    }
}

#else

COLLECTION OF VARIABLE trend
{
    MEMBERS
    {
        TREND_CONTROL,              trend_control;
        TREND_DEVICE_VARIABLE_CODE, trend_device_variable_code;
        TREND_SAMPLE_INTERVAL,      trend_sample_interval_int;
    }
}
#endif

COMMAND read_trend_configuration
{
    NUMBER 91;
    OPERATION READ;
#if __TOKVER__ >= 800
    TRANSACTION
    {
        REQUEST
        {
            trend_number (INFO, INDEX)
        }
        REPLY
        {
            response_code, device_status,
            trend_number (INFO, INDEX),
            number_trends_supported,
            trend_array[trend_number].TREND_CONTROL,
            trend_array[trend_number].TREND_DEVICE_VARIABLE_CODE,
            trend_array[trend_number].TREND_SAMPLE_INTERVAL
        }
    }
#else
    TRANSACTION
    {
        REQUEST
        {
            trend_number_int (INFO)
        }
        REPLY
        {
            response_code, device_status,
            trend_number_int (INFO),
            number_trends_supported,
            trend.TREND_CONTROL,
            trend.TREND_DEVICE_VARIABLE_CODE,
            trend.TREND_SAMPLE_INTERVAL
        }
    }
#endif
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        6,  DATA_ENTRY_ERROR, [xmtr_specific_command_error];
        11, DATA_ENTRY_ERROR, "Invalid trend number";
    }
}

COMMAND write_trend_configuration
{
    NUMBER 92;
    OPERATION WRITE;
#if __TOKVER__ >= 800
    TRANSACTION
    {
        REQUEST
        {
            trend_number (INFO, INDEX),
            trend_array[trend_number].TREND_CONTROL,
            trend_array[trend_number].TREND_DEVICE_VARIABLE_CODE,
            trend_array[trend_number].TREND_SAMPLE_INTERVAL
        }
        REPLY
        {
            response_code, device_status,
            trend_number (INFO, INDEX),
            trend_array[trend_number].TREND_CONTROL,
            trend_array[trend_number].TREND_DEVICE_VARIABLE_CODE,
            trend_array[trend_number].TREND_SAMPLE_INTERVAL
        }
    }
#else
    TRANSACTION
    {
        REQUEST
        {
            trend_number_int (INFO),
            trend.TREND_CONTROL,
            trend.TREND_DEVICE_VARIABLE_CODE,
            trend.TREND_SAMPLE_INTERVAL
        }
        REPLY
        {
            response_code, device_status,
            trend_number_int (INFO),
            trend.TREND_CONTROL,
            trend.TREND_DEVICE_VARIABLE_CODE,
            trend.TREND_SAMPLE_INTERVAL
        }
    }
#endif
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        2,  DATA_ENTRY_ERROR, [invalid_selection];
        3,  DATA_ENTRY_ERROR, [passed_parameter_too_large];
        4,  DATA_ENTRY_ERROR, [passed_parameter_too_small];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        6,  DATA_ENTRY_ERROR, [xmtr_specific_command_error];
        7,  MODE_ERROR,       [in_write_protect_mode];
        8,  DATA_ENTRY_WARNING, [set_to_nearest_possible_value];
        11, DATA_ENTRY_ERROR, "Invalid trend number";
        16, MODE_ERROR,       [access_restricted];
        17, DATA_ENTRY_ERROR, [invalid_device_variable];
    }
}

#if __TOKVER__ >= 800
// Read Trend Command 93
// Note:  Trend values are not attainable with older tokenizers
COMMAND read_trend
{
    NUMBER 93;
    OPERATION READ;
    TRANSACTION
    {
        REQUEST
        {
            trend_number (INFO, INDEX)
        }
        REPLY
        {
            response_code, device_status,
            trend_number (INFO, INDEX),
            trend_array[trend_number].TREND_DEVICE_VARIABLE_CODE,
            trend_array[trend_number].TREND_CLASSIFICATION,
            trend_array[trend_number].TREND_DIGITAL_UNITS,
            trend_array[trend_number].TREND_0_DATE_STAMP,
            trend_array[trend_number].TREND_0_TIME_STAMP,
            trend_array[trend_number].TREND_VALUES[0].TREND_VALUE,
            trend_array[trend_number].TREND_VALUES[0].QUALITY_STATUS<0xC0>,
            trend_array[trend_number].TREND_VALUES[0].LIMIT_STATUS<0x30>,
            trend_array[trend_number].TREND_VALUES[0].FAMILY_STATUS<0x0F>,
            trend_array[trend_number].TREND_VALUES[1].TREND_VALUE,
            trend_array[trend_number].TREND_VALUES[1].QUALITY_STATUS<0xC0>,
            trend_array[trend_number].TREND_VALUES[1].LIMIT_STATUS<0x30>,
            trend_array[trend_number].TREND_VALUES[1].FAMILY_STATUS<0x0F>,
            trend_array[trend_number].TREND_VALUES[2].TREND_VALUE,
            trend_array[trend_number].TREND_VALUES[2].QUALITY_STATUS<0xC0>,
            trend_array[trend_number].TREND_VALUES[2].LIMIT_STATUS<0x30>,
            trend_array[trend_number].TREND_VALUES[2].FAMILY_STATUS<0x0F>,
            trend_array[trend_number].TREND_VALUES[3].TREND_VALUE,
            trend_array[trend_number].TREND_VALUES[3].QUALITY_STATUS<0xC0>,
            trend_array[trend_number].TREND_VALUES[3].LIMIT_STATUS<0x30>,
            trend_array[trend_number].TREND_VALUES[3].FAMILY_STATUS<0x0F>,
            trend_array[trend_number].TREND_VALUES[4].TREND_VALUE,
            trend_array[trend_number].TREND_VALUES[4].QUALITY_STATUS<0xC0>,
            trend_array[trend_number].TREND_VALUES[4].LIMIT_STATUS<0x30>,
            trend_array[trend_number].TREND_VALUES[4].FAMILY_STATUS<0x0F>,
            trend_array[trend_number].TREND_VALUES[5].TREND_VALUE,
            trend_array[trend_number].TREND_VALUES[5].QUALITY_STATUS<0xC0>,
            trend_array[trend_number].TREND_VALUES[5].LIMIT_STATUS<0x30>,
            trend_array[trend_number].TREND_VALUES[5].FAMILY_STATUS<0x0F>,
            trend_array[trend_number].TREND_VALUES[6].TREND_VALUE,
            trend_array[trend_number].TREND_VALUES[6].QUALITY_STATUS<0xC0>,
            trend_array[trend_number].TREND_VALUES[6].LIMIT_STATUS<0x30>,
            trend_array[trend_number].TREND_VALUES[6].FAMILY_STATUS<0x0F>,
            trend_array[trend_number].TREND_VALUES[7].TREND_VALUE,
            trend_array[trend_number].TREND_VALUES[7].QUALITY_STATUS<0xC0>,
            trend_array[trend_number].TREND_VALUES[7].LIMIT_STATUS<0x30>,
            trend_array[trend_number].TREND_VALUES[7].FAMILY_STATUS<0x0F>,
            trend_array[trend_number].TREND_VALUES[8].TREND_VALUE,
            trend_array[trend_number].TREND_VALUES[8].QUALITY_STATUS<0xC0>,
            trend_array[trend_number].TREND_VALUES[8].LIMIT_STATUS<0x30>,
            trend_array[trend_number].TREND_VALUES[8].FAMILY_STATUS<0x0F>,
            trend_array[trend_number].TREND_VALUES[9].TREND_VALUE,
            trend_array[trend_number].TREND_VALUES[9].QUALITY_STATUS<0xC0>,
            trend_array[trend_number].TREND_VALUES[9].LIMIT_STATUS<0x30>,
            trend_array[trend_number].TREND_VALUES[9].FAMILY_STATUS<0x0F>,
            trend_array[trend_number].TREND_VALUES[10].TREND_VALUE,
            trend_array[trend_number].TREND_VALUES[10].QUALITY_STATUS<0xC0>,
            trend_array[trend_number].TREND_VALUES[10].LIMIT_STATUS<0x30>,
            trend_array[trend_number].TREND_VALUES[10].FAMILY_STATUS<0x0F>,
            trend_array[trend_number].TREND_VALUES[11].TREND_VALUE,
            trend_array[trend_number].TREND_VALUES[11].QUALITY_STATUS<0xC0>,
            trend_array[trend_number].TREND_VALUES[11].LIMIT_STATUS<0x30>,
            trend_array[trend_number].TREND_VALUES[11].FAMILY_STATUS<0x0F>
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        6,  DATA_ENTRY_ERROR, [xmtr_specific_command_error];
        8,  MISC_WARNING,     "Trend not active";
        11, DATA_ENTRY_ERROR, "Invalid trend number";
    }
}
#endif

/*
 *****************************************************************************
 * Common Practice Command Spec
 * Section 6.12
 * I/O and Subdevice Commands
 *
 * Commands 74, 75, 77, 84-88, 94, 101, 102
 *
 */

VARIABLE max_io_cards
{
    LABEL "Max Number IO Cards";
    HELP "Maximum Number of I/O Cards";
    CLASS DEVICE;
    HANDLING READ;
    TYPE UNSIGNED_INTEGER
    {
        MIN_VALUE 1;
    }
}

VARIABLE max_channels_per_io_card
{
    LABEL "Max Channels per IO Card";
    HELP "Maximum number of channels per I/O card";
    CLASS DEVICE;
    HANDLING READ;
    TYPE UNSIGNED_INTEGER
    {
        MIN_VALUE 1;
    }
}

VARIABLE max_sub_dev_per_channel
{
    LABEL "Max Subdevices per Channel";
    HELP "Maximum number of Subdevices per channel";
    CLASS DEVICE;
    HANDLING READ;
    TYPE UNSIGNED_INTEGER
    {
        MIN_VALUE 1;
    }
}

VARIABLE devices_detected
{
    LABEL "Devices Detected";
    HELP "";
    CLASS DEVICE & DYNAMIC;
    HANDLING READ;
    TYPE UNSIGNED_INTEGER (2);
}

VARIABLE max_dr
{
    LABEL "Max Delayed Responses";
    HELP "";
    CLASS DEVICE;
    HANDLING READ;
    TYPE UNSIGNED_INTEGER
    {
        MIN_VALUE 2;
    }
}

VARIABLE retry_count
{
    LABEL "Retry Count";
    HELP "";
    CLASS HART;
    HANDLING READ & WRITE;
    TYPE UNSIGNED_INTEGER (1)
    {
        MIN_VALUE 2;
        MAX_VALUE 5;
    }
}

COMMAND read_io_system_capabilities
{
    NUMBER 74;
    OPERATION READ;
    TRANSACTION
    {
        REQUEST {}
        REPLY
        {
            response_code, device_status, 
            max_io_cards, 
            max_channels_per_io_card,
            max_sub_dev_per_channel,
            devices_detected,
            max_dr,
            master_mode,
            retry_count
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        6,  MISC_ERROR,       [xmtr_specific_command_error];
        16, MODE_ERROR,       [access_restricted];
        32, MODE_ERROR,       [busy];
    }
}

// Command 75 is beyond the scope of a simple DD definition, but will be used by hosts to poll for subdevices and store each subdevice's
// identify response. COMMAND 75 poll_subdevice - Need to add to symbol table only

// Command 77 is beyond the scope of a simple DD definition, but will be used by hosts to send commands through I/O systems to subdevices.
// I/O systems must implement command 77. COMMAND 77 send_command_to_subdevice - Need to add to symbol table only

// Command 78 read_aggregated_commands is beyond the scope of a simple DD definition  - Need to add to symbol table only
/* Older tokenizers do not like LISTs */
#if __TOKVER__ >= 800
LIST subdevice_list
{
    LABEL "List of Subdevices";
    COUNT devices_detected;
    TYPE  sub_device;
}

VARIABLE subdevice_number
{
    LABEL "Subdevice Index";
    HELP "";
    CLASS LOCAL;
    TYPE INDEX (2) subdevice_list;
}

#else

VARIABLE subdevice_number_int
{
    LABEL "Subdevice Index";
    HELP "";
    CLASS LOCAL;
    TYPE UNSIGNED_INTEGER (2); 
}
#endif

// subdevices:

VARIABLE subdev_IO_card
{
    LABEL "Subdevice I/O card";
    HELP "";
    CLASS DEVICE;
    HANDLING READ;
    TYPE UNSIGNED_INTEGER;
}

VARIABLE subdev_channel
{
    LABEL "Subdevice Channel";
    HELP "";
    CLASS DEVICE;
    HANDLING READ;
    TYPE UNSIGNED_INTEGER; 
}

VARIABLE subdev_device_id
{
    LABEL "Subdevice 1 Device ID";
    HELP "";
    CLASS DEVICE;
    HANDLING READ;
    TYPE UNSIGNED_INTEGER (3)
    {
       DISPLAY_FORMAT "06X";
    }
}

VARIABLE subdev_universal_command_revision
{
    LABEL "Subdevice Universal Revision";
    HELP "";
    CLASS DEVICE;
    HANDLING READ;
    TYPE UNSIGNED_INTEGER; 
}

VARIABLE subdev_long_tag
{
    LABEL "Subdevice Long Tag";
    HELP "";
    CLASS DEVICE;
    HANDLING READ;
    TYPE ASCII (32); 
}

VARIABLE stx_sent_to_subdev
{
    LABEL "Subdevice STX Sent";
    HELP "";
    CLASS HART & DYNAMIC;
    HANDLING READ;
    TYPE UNSIGNED_INTEGER (2); 
}

VARIABLE ack_received_from_subdev
{
    LABEL "Subdevice ACK Received";
    HELP "";
    CLASS HART & DYNAMIC;
    HANDLING READ;
    TYPE UNSIGNED_INTEGER (2); 
}

VARIABLE back_received_from_subdev
{
    LABEL "Subdevice BACK Received";
    HELP "";
    CLASS HART & DYNAMIC;
    HANDLING READ;
    TYPE UNSIGNED_INTEGER (2); 
}

COLLECTION OF VARIABLE subdev_identity
{
    MEMBERS
    {
        IO_CARD,            subdev_IO_card,                        "IO Card";
        CHANNEL,            subdev_channel,                        "Channel";
        MANUFID,            subdev_manufacturer_id,                "Mfg ID";
        EXP_DEV_TYPE,       subdev_expanded_device_type,           "Device Type";
        DEV_ID,             subdev_device_id,                      "Device ID";                
        UNIV_CMD_REV,       subdev_universal_command_revision,     "Univ Rev";
        LONG_TAG,           subdev_long_tag,                       "Long Tag";
    }
}

COLLECTION OF VARIABLE subdev_stats
{
    MEMBERS
    {
        STAT_STX_CNT,       stx_sent_to_subdev,                    "STX to Subdevice";
        STAT_ACK_CNT,       ack_received_from_subdev,              "ACK from Subdevice";
        STAT_BACK_CNT,      back_received_from_subdev,             "BACK from Subdevice";
    }
}

COLLECTION OF COLLECTION sub_device
{
    MEMBERS
    {
        IDENTITY,           subdev_identity,                        "Sub Device Identity";
        STATS,              subdev_stats,                           "Sub Device Statistics";
    }
}

// Command 84 Read Subdevice Identity Summary - Commands
COMMAND read_subdev_id_summary      
{
    NUMBER 84;
    OPERATION READ;
    TRANSACTION
    {
#if __TOKVER__ >= 800
        REQUEST
        {
            subdevice_number (INFO, INDEX)
        }
        REPLY
        {
            response_code, device_status, 
            subdevice_number (INFO, INDEX), 
            subdevice_list[subdevice_number].IDENTITY.IO_CARD,
            subdevice_list[subdevice_number].IDENTITY.CHANNEL,                  
            subdevice_list[subdevice_number].IDENTITY.MANUFID,                 
            subdevice_list[subdevice_number].IDENTITY.EXP_DEV_TYPE, 
            subdevice_list[subdevice_number].IDENTITY.DEV_ID,
            subdevice_list[subdevice_number].IDENTITY.UNIV_CMD_REV,  
            subdevice_list[subdevice_number].IDENTITY.LONG_TAG
         }
    }
#else
        REQUEST
        {
            subdevice_number_int (INFO)
        }
        REPLY
        {
            response_code, device_status, 
            subdevice_number_int (INFO), 
            sub_device.IDENTITY.IO_CARD,
            sub_device.IDENTITY.CHANNEL,                  
            sub_device.IDENTITY.MANUFID,                 
            sub_device.IDENTITY.EXP_DEV_TYPE, 
            sub_device.IDENTITY.DEV_ID,
            sub_device.IDENTITY.UNIV_CMD_REV,  
            sub_device.IDENTITY.LONG_TAG
         }
    }
#endif
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        2,  DATA_ENTRY_ERROR, [invalid_selection];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        6,  MISC_ERROR,       [xmtr_specific_command_error];
    }
}


VARIABLE constOne
{
    /* LABEL and HELP not defined - this is never displayed to a user! */
    CLASS LOCAL;
    TYPE UNSIGNED_INTEGER
    {
        MIN_VALUE 0x01;  //This is to help for hosts which do not implement DEFAULT_VALUE properly
    }
#if __TOKVER__ >= 600
    DEFAULT_VALUE 0x01;
#endif
}

VARIABLE constZero
{
    /* LABEL and HELP not defined - this is never displayed to a user! */
    CLASS LOCAL;
    TYPE UNSIGNED_INTEGER
    {
        MIN_VALUE 0x00;  //This is to help for hosts which do not implement DEFAULT_VALUE properly
    }
#if __TOKVER__ >= 600
    DEFAULT_VALUE 0x00;
#endif
}

/* if the MSBit of subdevice index (CMD 101) is set, that the subdevice mapped to a 
   burst message or event is not currently detected by the IO adapter.  This works 
   because an IO adapter is required to report  a subdevice index of 0xFFFF when the
   device is missing.  This does have the side-affect of limiting the max number 
   of subdevices to 32767. */
VARIABLE subdevice_missing
{
    LABEL "Subdevice Missing";
    HELP "";
    CLASS HART & DIAGNOSTIC;
    TYPE UNSIGNED_INTEGER(2);
}

COMMAND read_subdevice_burst_map      
{
    NUMBER 101;
    OPERATION READ;
#if __TOKVER__ >= 800
    TRANSACTION 0  //For Burst messages
    {
        REQUEST
        {
            constZero <0x80> (INFO), // MSB = 0 for burst messages
            burst_message_number <0x7F> (INFO, INDEX)
        }
        REPLY
        {
            response_code, device_status,
            constZero <0x80> (INFO),
            burst_message_number <0x7F> (INFO, INDEX),
            burst_messages[burst_message_number].SUB_DEVICE_MISSING <0x8000>,
            burst_messages[burst_message_number].SUB_DEVICE_MAPPING <0x7FFF>
        }
    }
    TRANSACTION 1  //For events
    {
        REQUEST
        {
            constOne <0x80> (INFO),   // MSB = 1 for events
            eventNumber <0x7F> (INFO, INDEX)
        }
        REPLY
        {
            response_code, device_status,
            constOne <0x80> (INFO),
            eventNumber <0x7F> (INFO, INDEX),
            events[eventNumber].EVENT_CONTROL.SUB_DEVICE_MISSING <0x8000>,
            events[eventNumber].EVENT_CONTROL.SUB_DEVICE_MAPPING <0x7FFF>
        }
    }
#else
    TRANSACTION 0  //For Burst messages
    {
        REQUEST
        {
            constZero <0x80> (INFO), // MSB = 0 for burst messages
            constZero <0x7F> (INFO)
        }
        REPLY
        {
            response_code, device_status,
            constZero <0x80> (INFO),
            constZero <0x7F> (INFO),
            burst_message_collection.SUB_DEVICE_MAPPING
        }
    }
    TRANSACTION 1  //For events
    {
        REQUEST
        {
            constOne <0x80> (INFO),   // MSB = 1 for events
            constZero <0x7F> (INFO)
        }
        REPLY
        {
            response_code, device_status,
            constOne <0x80> (INFO),
            constZero <0x7F> (INFO),
            event.EVENT_CONTROL.SUB_DEVICE_MAPPING
        }
    }
#endif
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        2,  DATA_ENTRY_ERROR, [invalid_selection];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        6,  MISC_ERROR,       [xmtr_specific_command_error];
    }
}

COMMAND write_subdevice_burst_map      
{
    NUMBER 102;
    OPERATION WRITE;
#if __TOKVER__ >= 800
    TRANSACTION 0  //For Burst messages
    {
        REQUEST
        {
            constZero <0x80> (INFO), // MSB = 0 for burst messages
            burst_message_number <0x7F> (INFO, INDEX),
            constZero <0x8000>,
            burst_messages[burst_message_number].SUB_DEVICE_MAPPING <0x7FFF>
        }
        REPLY
        {
            response_code, device_status,
            constZero <0x80> (INFO),
            burst_message_number <0x7F> (INFO, INDEX),
            burst_messages[burst_message_number].SUB_DEVICE_MISSING <0x8000>,
            burst_messages[burst_message_number].SUB_DEVICE_MAPPING <0x7FFF>
        }
    }
    TRANSACTION 1  //For events
    {
        REQUEST
        {
            constOne <0x80> (INFO),   // MSB = 1 for events
            eventNumber <0x7F> (INFO, INDEX),
            constZero <0x8000>,
            events[eventNumber].EVENT_CONTROL.SUB_DEVICE_MAPPING <0x7FFF>
        }
        REPLY
        {
            response_code, device_status,
            constOne <0x80> (INFO),
            eventNumber <0x7F> (INFO, INDEX),
            events[eventNumber].EVENT_CONTROL.SUB_DEVICE_MISSING <0x8000>,
            events[eventNumber].EVENT_CONTROL.SUB_DEVICE_MAPPING <0x7FFF>
        }
    }
#else
    TRANSACTION 0  //For Burst messages
    {
        REQUEST
        {
            constZero <0x80> (INFO), // MSB = 0 for burst messages
            constZero <0x7F> (INFO),
            burst_message_collection.SUB_DEVICE_MAPPING
        }
        REPLY
        {
            response_code, device_status,
            constZero <0x80> (INFO),
            constZero <0x7F> (INFO),
            burst_message_collection.SUB_DEVICE_MAPPING
        }
    }
    TRANSACTION 1  //For events
    {
        REQUEST
        {
            constOne <0x80> (INFO),   // MSB = 1 for events
            constZero <0x7F> (INFO),
            event.EVENT_CONTROL.SUB_DEVICE_MAPPING
        }
        REPLY
        {
            response_code, device_status,
            constOne <0x80> (INFO),
            constZero <0x7F> (INFO),
            event.EVENT_CONTROL.SUB_DEVICE_MAPPING
        }
    }
#endif
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        2,  DATA_ENTRY_ERROR, [invalid_selection];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        6,  MISC_ERROR,       [xmtr_specific_command_error];
        7,  MODE_ERROR,       [in_write_protect_mode];
        9,  DATA_ENTRY_ERROR, "Invalid subdevice index";
        16, MODE_ERROR,       [access_restricted];
    }
}

// I/O Channel/Card Statistics
VARIABLE io_channel_stx_sent
{
    LABEL "STX Sent";
    HELP "Count of STX messages sent by the I/O system on this channel";
    CLASS DEVICE & DYNAMIC;
    HANDLING READ;
    TYPE UNSIGNED_INTEGER(2);
}

VARIABLE io_channel_ack_received
{
    LABEL "ACK Received";
    HELP "Count of ACK messages recieved by the I/O system on this channel";
    CLASS DEVICE & DYNAMIC;
    HANDLING READ;
    TYPE UNSIGNED_INTEGER(2);
}

VARIABLE io_channel_ostx_received
{
    LABEL "OSTX Received";
    HELP "Count of OSTX messages recieved by the I/O system on this channel"; 
    CLASS DEVICE & DYNAMIC;
    HANDLING READ;
    TYPE UNSIGNED_INTEGER(2);
}

VARIABLE io_channel_oack_received
{
    LABEL "OACK Received";
    HELP "Count of OACK messages recieved by the I/O system on this channel";  
    CLASS DEVICE & DYNAMIC;
    HANDLING READ;
    TYPE UNSIGNED_INTEGER(2);
}

VARIABLE io_channel_back_received
{
    LABEL "BACK Received";
    HELP "Count of BACK messages recieved by the I/O system on this channel";    
    CLASS DEVICE & DYNAMIC;
    HANDLING READ;
    TYPE UNSIGNED_INTEGER(2);
}

COLLECTION OF VARIABLE io_stats
{
    LABEL "I/O Channel Statistics";
    MEMBERS
    {
        STX_SENT,           io_channel_stx_sent;
        ACK_RECEIVED,       io_channel_ack_received;
        OSTX_RECEIVED,      io_channel_ostx_received;
        OACK_RECEIVED,      io_channel_oack_received;
        BACK_RECEIVED,      io_channel_back_received;
    }
}

#if __TOKVER__ >= 800
ARRAY card0_channels
{
    LABEL "IO channels";
    TYPE  io_stats;
    NUMBER_OF_ELEMENTS 1;  //**Note - DD developer to re-define per max channels capable for their system
}

//For now SDC (and likely other hosts) do not support COMMANDS with multiple dimension arrays.
//Keep these definitions for future improvement to the protocol / host capabilirs.
// ARRAY card1_channels
// {
//     LABEL "IO channels";
//     TYPE  io_stats;
//     NUMBER_OF_ELEMENTS 1;  //**Note - MUST be same number of channels for ALL cardx_channels
// }
//
// ARRAY card2_channels
// {
//     LABEL "IO channels";
//     TYPE  io_stats;
//     NUMBER_OF_ELEMENTS 1;  //**Note - MUST be same number of channels for ALL cardx_channels
// }
//
// ARRAY card3_channels
// {
//     LABEL "IO channels";
//     TYPE  io_stats;
//     NUMBER_OF_ELEMENTS 1;  //**Note - MUST be same number of channels for ALL cardx_channels
// }

ARRAY OF ARRAY io_cards
{
    LABEL "IO cards";
    ELEMENTS
    {
        0, card0_channels;

        /* For now, DD lanuage and SDC fnctionality are limited to 1 IO card */
        //1, card1_channels;
        //2, card2_channels;
        //3, card3_channels;
    }
}

VARIABLE IO_card_number
{
    LABEL "Card Index";
    HELP "";
    CLASS LOCAL;
    TYPE INDEX io_cards;
}

VARIABLE IO_channel_number
{
    LABEL "Channel Index";
    HELP "";
    CLASS LOCAL;
    TYPE INDEX card0_channels;
}

#else

VARIABLE IO_card_number_int
{
    LABEL "Card Index";
    HELP "";
    CLASS LOCAL;
    TYPE UNSIGNED_INTEGER;
}

VARIABLE IO_channel_number_int
{
    LABEL "Channel Index";
    HELP "";
    CLASS LOCAL;
    TYPE UNSIGNED_INTEGER;
}
#endif

//For now SDC (and likely other hosts) do not support COMMANDS with multiple dimensions.
//Keep these definitions for future improvement to the protocol / host capabilirs.
/*********************************
* VARIABLE IO_channel_number_1   *
* {                              *
*     LABEL "Channel Index";     *
*     HELP "";                   *
*     CLASS LOCAL;               *
* #if __TOKVER__ >= 800          *
*      TYPE INDEX card1_channels;*
* #else                          *
*     TYPE UNSIGNED_INTEGER;     *
* #endif                         *
* }                              *
*                                *
* VARIABLE IO_channel_number_2   *
* {                              *
*     LABEL "Channel Index";     *
*     HELP "";                   *
*     CLASS LOCAL;               *
* #if __TOKVER__ >= 800          *
*     TYPE INDEX card2_channels; *
* #else                          *
*     TYPE UNSIGNED_INTEGER;     *
* #endif                         *
* }                              *
*                                *
* VARIABLE IO_channel_number_3   *
* {                              *
*     LABEL "Channel Index";     *
*     HELP "";                   *
*     CLASS LOCAL;      *
* #if __TOKVER__ >= 800          *
*     TYPE INDEX card3_channels; *
* #else                          *
*     TYPE UNSIGNED_INTEGER;     *
* #endif                         *
* }                              *
*                                *
*********************************/

COMMAND read_io_channel_stats   
{
    NUMBER 85;
    OPERATION READ;
    TRANSACTION 0
    {
#if __TOKVER__ >= 800
        REQUEST
        {
            0,  //SDC doesn't support double-index into a 2-dimensional array
            IO_channel_number (INFO, INDEX)
        }
        REPLY
        {
            response_code, device_status,
            0,
            IO_channel_number (INFO, INDEX),
            io_cards[0][IO_channel_number].STX_SENT,
            io_cards[0][IO_channel_number].ACK_RECEIVED,
            io_cards[0][IO_channel_number].OSTX_RECEIVED,
            io_cards[0][IO_channel_number].OACK_RECEIVED,
            io_cards[0][IO_channel_number].BACK_RECEIVED
        }
#else
        REQUEST
        {
            IO_card_number_int (INFO),
            IO_channel_number_int (INFO)
        }
        REPLY
        {
            response_code, device_status,
            IO_card_number_int (INFO),
            IO_channel_number_int (INFO),
            io_stats.STX_SENT,
            io_stats.ACK_RECEIVED,
            io_stats.OSTX_RECEIVED,
            io_stats.OACK_RECEIVED,
            io_stats.BACK_RECEIVED
        }
#endif
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        2,  DATA_ENTRY_ERROR, [invalid_selection];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        6,  MISC_ERROR,       [xmtr_specific_command_error];
        21, DATA_ENTRY_ERROR, "Invalid I/O card number";
        22, DATA_ENTRY_ERROR, "Invalid channel number";
        32, MODE_ERROR,       [busy];
    }
}

// 86 Read Subdevice Statistics - Command
COMMAND read_subdevice_statistics
{
    NUMBER 86;
    OPERATION READ;
    TRANSACTION
    {
#if __TOKVER__ >= 800
        REQUEST
        {
            subdevice_number (INFO, INDEX)
        }
        REPLY
        {
            response_code, device_status,
            subdevice_number (INFO, INDEX), 
            subdevice_list[subdevice_number].STATS.STAT_STX_CNT,                  
            subdevice_list[subdevice_number].STATS.STAT_ACK_CNT,                   
            subdevice_list[subdevice_number].STATS.STAT_BACK_CNT
        }
#else
        REQUEST
        {
            subdevice_number_int (INFO)
        }
        REPLY
        {
            response_code, device_status,
            subdevice_number_int (INFO), 
            sub_device.STATS.STAT_STX_CNT,                  
            sub_device.STATS.STAT_ACK_CNT,                   
            sub_device.STATS.STAT_BACK_CNT
        }
#endif
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        2,  DATA_ENTRY_ERROR, [invalid_selection];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        6,  MISC_ERROR,       [xmtr_specific_command_error];
    }
}

// Command 87 Write I/O System Master Mode - Vars and Command
COMMAND write_io_system_master_mode
{
    NUMBER 87;
    OPERATION WRITE;
    TRANSACTION
    {
        REQUEST
        {
            master_mode
        }
        REPLY
        {
            response_code, device_status,
            master_mode
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        2,  DATA_ENTRY_ERROR, [invalid_selection];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        6,  MISC_ERROR,       [xmtr_specific_command_error];
        7,  MODE_ERROR,       [in_write_protect_mode];
        16, MODE_ERROR,       [access_restricted];
    }
}

// Command 88 Write I/O System Retry Count - Vars and Command

COMMAND write_io_system_retry_count
{
    NUMBER 88;
    OPERATION WRITE;
    TRANSACTION
    {
        REQUEST
        {
            retry_count
        }
        REPLY
        {
            response_code, device_status,
            retry_count
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        3,  DATA_ENTRY_ERROR, [passed_parameter_too_large];
        4,  DATA_ENTRY_ERROR, [passed_parameter_too_small];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        6,  MISC_ERROR,       [xmtr_specific_command_error];
        7,  MODE_ERROR,       [in_write_protect_mode];
        16, MODE_ERROR,       [access_restricted];
    }
}

// I/O System Communication Statistics Command 94

VARIABLE messages_received
{
    LABEL "I/O System Messages Received";
    HELP  "Count of messages received through this host system interface";
    CLASS HART & DYNAMIC;
    HANDLING READ;
    TYPE UNSIGNED_INTEGER(4);
}

VARIABLE messages_returned
{
    LABEL "Messages Returned";
    HELP  "Count of messages returned to this host system";
    CLASS HART & DYNAMIC;
    HANDLING READ;
    TYPE UNSIGNED_INTEGER(4);
}

VARIABLE requests_forwarded
{
    LABEL "Requests Forwarded";
    HELP  "Count of requests forwarded to the I/O system";
    CLASS HART & DYNAMIC;
    HANDLING READ;
    TYPE UNSIGNED_INTEGER(4);
}

VARIABLE responses_returned
{
    LABEL "Responses Returned";
    HELP  "Count of responses returned by the I/O system";
    CLASS HART & DYNAMIC;
    HANDLING READ;
    TYPE UNSIGNED_INTEGER(4);
}

COMMAND read_io_client_side_communication_statistics
{
    NUMBER 94;
    OPERATION READ;
    TRANSACTION
    {
        REQUEST {}
        REPLY
        {
            response_code, device_status,
            messages_received, messages_returned, 
            requests_forwarded, responses_returned
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,    [no_command_specific_errors];
        6,  MISC_ERROR, [xmtr_specific_command_error];
        16, MODE_ERROR, [access_restricted];
    }
}

/*
 *****************************************************************************
 * Common Practice Command Spec
 * Section 6.13
 * Synchronized Device Action Commands
 *
 * Command 96 Read Synchronous Action
 * Command 97 Configure Synchronous Action
 * Command 98 Read Command Action
 * Command 99 Configure Command Action
 *
 * not implemented at this time.
 */


/*
 *****************************************************************************
 * Common Practice Command Spec
 * Section 6.14
 * Analog channel Commands
 *
 * Commands 60-70
 */

/*
 *****************************************************************************
 * Variable  analog_channel_number_code is used to specify the analog channel
 * for the following commands
 *
 * NOTE - Index = 0 is Primary Variable
 */
VARIABLE analog_channel_number_code
{
    LABEL "Analog Channel Number";
    HELP "Analog Channel Number- Index into an array of Analog Channels.";
    CLASS LOCAL;
    TYPE INDEX dynamic_variables;
}

COMMAND read_analog_output_and_percent_of_range
{
    NUMBER 60;
    OPERATION READ;
    TRANSACTION
    {
        REQUEST
        {
            analog_channel_number_code (INFO,INDEX)
        }
        REPLY
        {
            response_code, device_status, analog_channel_number_code (INFO,INDEX),
            dynamic_variables[analog_channel_number_code].DAQ.ANALOG_UNITS,
            dynamic_variables[analog_channel_number_code].DAQ.ANALOG_VALUE,
            dynamic_variables[analog_channel_number_code].RANGING.PERCENT_RANGE
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        2,  DATA_ENTRY_ERROR, [invalid_selection];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        6,  MISC_ERROR,       [xmtr_specific_command_error];
        8,  MISC_WARNING,     [update_failure];
        16, MODE_ERROR,       [access_restricted];
    }
}

VARIABLE analog_channel_number_code_1
{
    LABEL "Index 1 into Analog Channel Array";
    HELP "Index into Analog Channel Array- Is the first of an array of addresses, whose"
         " value is identified by the Analog Channel Code.";
/*  APPHELP "This variable is used to access more variables that relate to"
            " that Analog Output index."
            " NOTE - Index = 0 is not valid"
            " HART_VAR:SLOT #0 ANALOG OUTPUT NUMBER CODE"; */
    CLASS LOCAL;
    TYPE INDEX dynamic_variables;
}

VARIABLE analog_channel_number_code_2
{
    LABEL "Index 2 into Analog Channel Array";
    HELP "Index into Analog Channel Array- Is the second of an array of addresses, whose"
         " value is identified by the Analog Channel Code.";
/*  APPHELP "This variable is used to access more variables that relate to"
            " that Analog Output index."
            " NOTE - Index = 0 is not valid"
            " HART_VAR:SLOT #1 ANALOG OUTPUT NUMBER CODE"; */
    CLASS LOCAL;
    TYPE INDEX dynamic_variables;
}

VARIABLE analog_channel_number_code_3
{
    LABEL "Index 3 into Analog Channel Array";
    HELP "Index into Analog Channel Array- Is the third of an array of addresses, whose"
         " value is identified by the Analog Channel Code.";
/*  APPHELP "This variable is used to access more variables that relate to"
            " that Analog Output index."
            " NOTE - Index = 0 is not valid"
            " HART_VAR:SLOT #2 ANALOG OUTPUT NUMBER CODE"; */
    CLASS LOCAL;
    TYPE INDEX dynamic_variables;
}

VARIABLE analog_channel_number_code_4
{
    LABEL "Index 4 into Analog Channel Array";
    HELP "Index into Analog Channel Array- Is the fourth of an array of addresses, whose"
         " value is identified by the Analog Channel Code.";
/*  APPHELP "This variable is used to access more variables that relate to"
            " that Analog Output index."
            " NOTE - Index = 0 is not valid"
            " HART_VAR:SLOT #3 ANALOG OUTPUT NUMBER CODE"; */
    CLASS LOCAL;
    TYPE INDEX dynamic_variables;
}

COMMAND read_analog_channels
{
    NUMBER 62;
    OPERATION READ;
    TRANSACTION
    {
        REQUEST
        {
            analog_channel_number_code_1 (INFO,INDEX), analog_channel_number_code_2 (INFO,INDEX),
            analog_channel_number_code_3 (INFO,INDEX), analog_channel_number_code_4 (INFO,INDEX)
        }
        REPLY
        {
            response_code, device_status,
            analog_channel_number_code_1 (INFO,INDEX),
            dynamic_variables[analog_channel_number_code_1].DAQ.ANALOG_UNITS,
            dynamic_variables[analog_channel_number_code_1].DAQ.ANALOG_VALUE,
            analog_channel_number_code_2 (INFO,INDEX),
            dynamic_variables[analog_channel_number_code_2].DAQ.ANALOG_UNITS,
            dynamic_variables[analog_channel_number_code_2].DAQ.ANALOG_VALUE,
            analog_channel_number_code_3 (INFO,INDEX),
            dynamic_variables[analog_channel_number_code_3].DAQ.ANALOG_UNITS,
            dynamic_variables[analog_channel_number_code_3].DAQ.ANALOG_VALUE,
            analog_channel_number_code_4 (INFO,INDEX),
            dynamic_variables[analog_channel_number_code_4].DAQ.ANALOG_UNITS,
            dynamic_variables[analog_channel_number_code_4].DAQ.ANALOG_VALUE
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        2,  DATA_ENTRY_ERROR, [invalid_selection];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        8,  MISC_WARNING,     [update_failure];
    }
}

COMMAND read_analog_channel_information
{
    NUMBER 63;
    OPERATION READ;
    TRANSACTION
    {
        REQUEST
        {
            analog_channel_number_code (INFO,INDEX)
        }
        REPLY
        {
            response_code, device_status, analog_channel_number_code (INFO,INDEX),
            dynamic_variables[analog_channel_number_code].DAQ.ALARM_CODE,
            dynamic_variables[analog_channel_number_code].RANGING.TRANSFER_FUNCTION,
            dynamic_variables[analog_channel_number_code].RANGING.RANGE_UNITS,
            dynamic_variables[analog_channel_number_code].RANGING.UPPER_RANGE_VALUE,
            dynamic_variables[analog_channel_number_code].RANGING.LOWER_RANGE_VALUE,
            dynamic_variables[analog_channel_number_code].DAQ.ANALOG_DAMPING,
            dynamic_variables[analog_channel_number_code].DAQ.ANALOG_CHANNEL_FLAGS
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        2,  DATA_ENTRY_ERROR, [invalid_selection];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        6,  MISC_ERROR,       [xmtr_specific_command_error];
        16, MODE_ERROR,       [access_restricted];
        32, MODE_ERROR,       [busy];
    }
}

COMMAND write_analog_channel_additional_damping_value
{
    NUMBER 64;
    OPERATION WRITE;
    TRANSACTION
    {
        REQUEST
        {
            analog_channel_number_code (INFO,INDEX),
            dynamic_variables[analog_channel_number_code].DAQ.ANALOG_DAMPING
        }
        REPLY
        {
            response_code, device_status, analog_channel_number_code (INFO,INDEX),
            dynamic_variables[analog_channel_number_code].DAQ.ANALOG_DAMPING
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,            [no_command_specific_errors];
        2,  DATA_ENTRY_ERROR,   [invalid_selection];
        3,  DATA_ENTRY_ERROR,   [passed_parameter_too_large];
        4,  DATA_ENTRY_ERROR,   [passed_parameter_too_small];
        5,  DATA_ENTRY_ERROR,   [too_few_data_bytes_recieved];
        6,  MISC_ERROR,         [xmtr_specific_command_error];
        7,  MODE_ERROR,         [in_write_protect_mode];
        8,  DATA_ENTRY_WARNING, [set_to_nearest_possible_value];
        16, MODE_ERROR,         [access_restricted];
        32, MODE_ERROR,         [busy];
    }
}

COMMAND write_analog_channel_range_values
{
    NUMBER 65;
    OPERATION WRITE;
    TRANSACTION
    {
        REQUEST
        {
            analog_channel_number_code (INFO,INDEX),
            dynamic_variables[analog_channel_number_code].RANGING.RANGE_UNITS (INFO),
            dynamic_variables[analog_channel_number_code].RANGING.UPPER_RANGE_VALUE,
            dynamic_variables[analog_channel_number_code].RANGING.LOWER_RANGE_VALUE
        }
        REPLY
        {
            response_code, device_status, analog_channel_number_code (INFO,INDEX),
            dynamic_variables[analog_channel_number_code].RANGING.RANGE_UNITS (INFO),
            dynamic_variables[analog_channel_number_code].RANGING.UPPER_RANGE_VALUE,
            dynamic_variables[analog_channel_number_code].RANGING.LOWER_RANGE_VALUE
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,            [no_command_specific_errors];
        5,  DATA_ENTRY_ERROR,   [too_few_data_bytes_recieved];
        6,  MISC_ERROR,         [xmtr_specific_command_error];
        7,  MODE_ERROR,         [in_write_protect_mode];
        9,  DATA_ENTRY_ERROR,   [lower_range_value_too_high];
        10, DATA_ENTRY_ERROR,   [lower_range_value_too_low];
        11, DATA_ENTRY_ERROR,   [upper_range_value_too_high];
        12, DATA_ENTRY_ERROR,   [upper_range_value_too_low];
        13, DATA_ENTRY_ERROR,   [URV_and_LRV_out_of_limits];
        14, DATA_ENTRY_WARNING, [span_too_small];
        15, DATA_ENTRY_ERROR,   [invalid_analog_output_number_code];
        16, MODE_ERROR,         [access_restricted];
        28, DATA_ENTRY_ERROR,   [invalid_units];
        29, DATA_ENTRY_ERROR,   [invalid_span];
        32, MODE_ERROR,         [busy];
    }
}

COMMAND enter_exit_fixed_analog_channel_mode
{
    NUMBER 66;
    OPERATION COMMAND;
    TRANSACTION
    {
        REQUEST
        {
            analog_channel_number_code (INFO,INDEX),
            dynamic_variables[analog_channel_number_code].DAQ.ANALOG_UNITS,
            dynamic_variables[analog_channel_number_code].DAQ.ANALOG_VALUE
        }
        REPLY
        {
            response_code, device_status, analog_channel_number_code (INFO,INDEX),
            dynamic_variables[analog_channel_number_code].DAQ.ANALOG_UNITS,
            dynamic_variables[analog_channel_number_code].DAQ.ANALOG_VALUE
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        3,  DATA_ENTRY_ERROR, [passed_parameter_too_large];
        4,  DATA_ENTRY_ERROR, [passed_parameter_too_small];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        6,  MISC_ERROR,       [xmtr_specific_command_error];
        7,  MODE_ERROR,       [in_write_protect_mode];
        11, MODE_ERROR,       [in_multidrop_mode];
        12, DATA_ENTRY_ERROR, [invalid_units];
        15, DATA_ENTRY_ERROR, [invalid_analog_output_number_code];
        16, MODE_ERROR,       [access_restricted];
        32, MODE_ERROR,       [busy];
    }
}

COMMAND trim_analog_channel_zero
{
    NUMBER 67;
    OPERATION COMMAND;
    TRANSACTION
    {
        REQUEST
        {
            analog_channel_number_code (INFO,INDEX),
            dynamic_variables[analog_channel_number_code].DAQ.ANALOG_UNITS,
            dynamic_variables[analog_channel_number_code].DAQ.ANALOG_VALUE
        }
        REPLY
        {
            response_code, device_status, analog_channel_number_code (INFO,INDEX),
            dynamic_variables[analog_channel_number_code].DAQ.ANALOG_UNITS,
            dynamic_variables[analog_channel_number_code].DAQ.ANALOG_VALUE
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        3,  DATA_ENTRY_ERROR, [passed_parameter_too_large];
        4,  DATA_ENTRY_ERROR, [passed_parameter_too_small];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        6,  MISC_ERROR,       [xmtr_specific_command_error];
        7,  MODE_ERROR,       [in_write_protect_mode];
        9,  MODE_ERROR,       [not_in_proper_anlg_output_mode];
        11, MODE_ERROR,       [in_multidrop_mode];
        12, DATA_ENTRY_ERROR, [invalid_units];
        15, DATA_ENTRY_ERROR, [invalid_analog_output_number_code];
        16, MODE_ERROR,       [access_restricted];
        32, MODE_ERROR,       [busy];
    }
}

COMMAND trim_analog_channel_gain
{
    NUMBER 68;
    OPERATION COMMAND;
    TRANSACTION
    {
        REQUEST
        {
            analog_channel_number_code (INFO,INDEX),
            dynamic_variables[analog_channel_number_code].DAQ.ANALOG_UNITS,
            dynamic_variables[analog_channel_number_code].DAQ.ANALOG_VALUE
        }
        REPLY
        {
            response_code, device_status, analog_channel_number_code (INFO,INDEX),
            dynamic_variables[analog_channel_number_code].DAQ.ANALOG_UNITS,
            dynamic_variables[analog_channel_number_code].DAQ.ANALOG_VALUE
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        3,  DATA_ENTRY_ERROR, [passed_parameter_too_large];
        4,  DATA_ENTRY_ERROR, [passed_parameter_too_small];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        6,  MISC_ERROR,       [xmtr_specific_command_error];
        7,  MODE_ERROR,       [in_write_protect_mode];
        9,  MODE_ERROR,       [not_in_proper_anlg_output_mode];
        11, MODE_ERROR,       [in_multidrop_mode];
        12, DATA_ENTRY_ERROR, [invalid_units];
        15, DATA_ENTRY_ERROR, [invalid_analog_output_number_code];
        16, MODE_ERROR,       [access_restricted];
        32, MODE_ERROR,       [busy];
    }
}

COMMAND write_analog_channel_transfer_function
{
    NUMBER 69;
    OPERATION WRITE;
    TRANSACTION
    {
        REQUEST
        {
            analog_channel_number_code (INFO,INDEX),
            dynamic_variables[analog_channel_number_code].RANGING.TRANSFER_FUNCTION
        }

        REPLY
        {
            response_code, device_status, analog_channel_number_code (INFO,INDEX),
            dynamic_variables[analog_channel_number_code].RANGING.TRANSFER_FUNCTION
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        6,  MISC_ERROR,       [xmtr_specific_command_error];
        7,  MODE_ERROR,       [in_write_protect_mode];
        13, DATA_ENTRY_ERROR, [invalid_transfer_function_code];
        15, DATA_ENTRY_ERROR, [invalid_analog_output_number_code];
        16, MODE_ERROR,       [access_restricted];
        32, MODE_ERROR,       [busy];
    }
}

COMMAND read_analog_channel_endpoint_values
{
    NUMBER 70;
    OPERATION READ;
    TRANSACTION
    {
        REQUEST
        {
            analog_channel_number_code (INFO,INDEX)
        }
        REPLY
        {
            response_code, device_status, analog_channel_number_code (INFO,INDEX),
            dynamic_variables[analog_channel_number_code].DAQ.ANALOG_UNITS,
            dynamic_variables[analog_channel_number_code].DAQ.UPPER_ENDPOINT_VALUE,
            dynamic_variables[analog_channel_number_code].DAQ.LOWER_ENDPOINT_VALUE
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        2,  DATA_ENTRY_ERROR, [invalid_selection];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        6,  MISC_ERROR,       [xmtr_specific_command_error];
        16, MODE_ERROR,       [access_restricted];
        32, MODE_ERROR,       [busy];
    }
}

METHOD fixed_analog_output
{
    LABEL [fix_analog_output];
    HELP [fix_analog_output_help];
    DEFINITION
    {
        char status[STATUS_SIZE];
        char disp_string1[60];
        char disp_string2[60];
        long var_id[3];
        int use_abort_method;
        int choice;
        int slen1;
        int slen2;

        slen1 = 60;
        slen2 = 60;

        IGNORE_ALL_RESPONSE_CODES();
        XMTR_IGNORE_ALL_RESPONSE_CODES();
        IGNORE_ALL_DEVICE_STATUS();
        XMTR_IGNORE_ALL_DEVICE_STATUS();

        get_dictionary_string(remove_loop_from_auto, disp_string1, slen1);
        ACKNOWLEDGE(disp_string1);
        add_abort_method(return_to_normal);

        use_abort_method = 0;

        get_dictionary_string(select_analog_output_to_trim, disp_string1, slen1);
        GET_DEV_VAR_VALUE(disp_string1, analog_channel_number_code);

        get_dictionary_string(select_analog_output_units, disp_string1, slen1);
        GET_DEV_VAR_VALUE(disp_string1,dynamic_variables[ivar_value(analog_channel_number_code)].DAQ.ANALOG_UNITS);

        var_id[0] = VARID(analog_channel_number_code);
        var_id[2] = VARID(dynamic_variables[ivar_value(analog_channel_number_code)].DAQ.ANALOG_UNITS);

        do
        {
            if (ivar_value(dynamic_variables[ivar_value(analog_channel_number_code)].DAQ.ANALOG_UNITS)== 39)
            {
                get_dictionary_string(choose_analog_output_level, disp_string1, slen1);
                get_dictionary_string(choices_4_20_other_end, disp_string2, slen2);

                choice = SELECT_FROM_LIST(disp_string1, disp_string2);

                switch (choice)
                {
                case 0:
                    assign_float(dynamic_variables[ivar_value(analog_channel_number_code)].DAQ.ANALOG_VALUE, 4.0);
                    break;

                case 1:
                    assign_float(dynamic_variables[ivar_value(analog_channel_number_code)].DAQ.ANALOG_VALUE, 20.0);
                    break;

                case 2:
                    get_dictionary_string(enter_desired_analog_output, disp_string1, slen1);
                    GET_DEV_VAR_VALUE(disp_string1,
                            dynamic_variables[ivar_value(analog_channel_number_code)].DAQ.ANALOG_VALUE);
                    break;

                case 3:
                default:
                    process_abort();
                    break;
                }
            }
            else
            {
                get_dictionary_string(choose_analog_output_level, disp_string1, slen1);
                get_dictionary_string(new_value_end, disp_string2, slen2);

                choice = SELECT_FROM_LIST(disp_string1, disp_string2);

                switch(choice)
                {
                case 0:
                    get_dictionary_string(enter_desired_analog_output, disp_string1, slen1);
                    GET_DEV_VAR_VALUE(disp_string1,
                            dynamic_variables[ivar_value(analog_channel_number_code)].DAQ.ANALOG_VALUE);
                    break;
                case 1:
                    process_abort();
                    break;
                }
            }

            send(66,status);

            if (!use_abort_method)
            {
                if ((status[STATUS_RESPONSE_CODE] != 0)
                        && (status[STATUS_RESPONSE_CODE] != 3)
                        && (status[STATUS_RESPONSE_CODE] != 4))
                {
                    display_response_status(66, status[STATUS_RESPONSE_CODE]);
                    get_dictionary_string(abort_last_error, disp_string1, slen1);
                    DELAY(2, disp_string1);
                    process_abort();
                }
                if (status[STATUS_RESPONSE_CODE] == 0)
                {
                    use_abort_method = 1;
                    remove_abort_method(return_to_normal);
                    add_abort_method(leave_analog_fixed_current_mode);
                }
            }

            if (status[STATUS_RESPONSE_CODE])
            {
                display_response_status(66, status[STATUS_RESPONSE_CODE]);
                if ((status[STATUS_RESPONSE_CODE] != 3) && (status[STATUS_RESPONSE_CODE] != 4))
                {
                    get_dictionary_string(abort_last_error, disp_string1, slen1);
                    DELAY(2, disp_string1);
                    process_abort();
                }
            }
            else
            {
                var_id[1] = VARID(dynamic_variables[ivar_value(analog_channel_number_code)].DAQ.ANALOG_VALUE);
                get_dictionary_string(fld_dev_AO_is_fixed_at, disp_string1, slen1);
                acknowledge(disp_string1, var_id);
            }
        } while (choice < 3);
    }
}

METHOD analog_dac_trim
{
    LABEL [trim_analog_output];
    HELP [digital_to_analog_trim_help];
/*  APPHELP "This type of calibration is usually used to compensate for"
            " drifting or aging output electronics"; */
    DEFINITION
    {
        char status[STATUS_SIZE];
        char disp_string1[60];
        char disp_string2[60];
        long var_id[3];
        int retry;
        int slen1;
        int slen2;

        slen1 = 60;
        slen2 = 60;

        IGNORE_ALL_RESPONSE_CODES();
        XMTR_IGNORE_ALL_RESPONSE_CODES();
        IGNORE_ALL_DEVICE_STATUS();
        XMTR_IGNORE_ALL_DEVICE_STATUS();

        get_dictionary_string(remove_loop_from_auto, disp_string1, slen1);
        ACKNOWLEDGE(disp_string1);

        add_abort_method(return_to_normal);

        get_dictionary_string(connect_reference_meter, disp_string1, slen1);
        ACKNOWLEDGE(disp_string1);

        get_dictionary_string(select_analog_output_to_trim,disp_string1,slen1);
        GET_DEV_VAR_VALUE(disp_string1, analog_channel_number_code);
        get_dictionary_string(select_analog_output_units, disp_string1, slen1);

        GET_DEV_VAR_VALUE(disp_string1,
            dynamic_variables[ivar_value(analog_channel_number_code)].DAQ.ANALOG_UNITS);

        var_id[0] = VARID(dynamic_variables[ivar_value(analog_channel_number_code)].DAQ.ANALOG_VALUE);
        var_id[1] = VARID(dynamic_variables[ivar_value(analog_channel_number_code)].DAQ.ANALOG_UNITS); 

        assign_var(dynamic_variables[ivar_value(analog_channel_number_code)].DAQ.ANALOG_VALUE,
            dynamic_variables[ivar_value(analog_channel_number_code)].DAQ.LOWER_ENDPOINT_VALUE);

        get_dictionary_string(about_to_set_fld_dev_output, disp_string1, slen1);
        acknowledge(disp_string1, var_id);

        send(66, status);

        if (status[STATUS_RESPONSE_CODE])
        {
            display_response_status(66, status[STATUS_RESPONSE_CODE]);
            get_dictionary_string(abort_last_error, disp_string1, slen1);
            DELAY(2, disp_string1);
            process_abort();
        }
        else
        {
            remove_abort_method(return_to_normal);
            add_abort_method(leave_analog_fixed_current_mode);
        }

        do
        {
            assign_var(dynamic_variables[ivar_value(analog_channel_number_code)].DAQ.ANALOG_VALUE,
                dynamic_variables[ivar_value(analog_channel_number_code)].DAQ.LOWER_ENDPOINT_VALUE);

            get_dictionary_string(enter_meter_value, disp_string1, slen1);
            GET_DEV_VAR_VALUE(disp_string1,
                dynamic_variables[ivar_value(analog_channel_number_code)].DAQ.ANALOG_VALUE);

            send(67, status);

            if ((status[STATUS_RESPONSE_CODE] == 3) || (status[STATUS_RESPONSE_CODE] == 4))
            {
                display_response_status(67, status[STATUS_RESPONSE_CODE]);
                retry = 1;
            }
            else if (status[STATUS_RESPONSE_CODE])
            {
                display_response_status(67, status[STATUS_RESPONSE_CODE]);
                get_dictionary_string(abort_last_error, disp_string1, slen1);
                DELAY(2, disp_string1);
                process_abort();
            }
            else
            {
                get_dictionary_string(fld_dev_output_eq_ref_meter, disp_string1, slen1);
                get_dictionary_string(yes_no, disp_string2, slen2);
                retry = select_from_list(disp_string1, var_id, disp_string2);
            }
        } while (retry);

        assign_var(dynamic_variables[ivar_value(analog_channel_number_code)].DAQ.ANALOG_VALUE,
            dynamic_variables[ivar_value(analog_channel_number_code)].DAQ.UPPER_ENDPOINT_VALUE);

        get_dictionary_string(about_to_set_fld_dev_output, disp_string1, slen1);
        acknowledge(disp_string1, var_id);

        send(66, status);

        if (status[STATUS_RESPONSE_CODE])
        {
            display_response_status(66, status[STATUS_RESPONSE_CODE]);
            get_dictionary_string(abort_last_error, disp_string1, slen1);
            DELAY(2, disp_string1);
            process_abort();
        }

        do
        {
            assign_var(dynamic_variables[ivar_value(analog_channel_number_code)].DAQ.ANALOG_VALUE,
                dynamic_variables[ivar_value(analog_channel_number_code)].DAQ.UPPER_ENDPOINT_VALUE);

            get_dictionary_string(enter_meter_value, disp_string1, slen1);
            GET_DEV_VAR_VALUE(disp_string1,
                dynamic_variables[ivar_value(analog_channel_number_code)].DAQ.ANALOG_VALUE);

            send(68, status);
            if ((status[STATUS_RESPONSE_CODE] == 3) || (status[STATUS_RESPONSE_CODE] == 4))
            {
                display_response_status(68, status[STATUS_RESPONSE_CODE]);
                retry = 1;
            }
            else if (status[STATUS_RESPONSE_CODE])
            {
                display_response_status(68, status[STATUS_RESPONSE_CODE]);
                get_dictionary_string(abort_last_error, disp_string1, slen1);
                DELAY(2, disp_string1);
                process_abort();
            }
            else
            {
                get_dictionary_string(fld_dev_output_eq_ref_meter, disp_string1, slen1);
                get_dictionary_string(yes_no, disp_string2, slen2);
                retry = select_from_list(disp_string1, var_id, disp_string2);
            }
        } while (retry);

        process_abort();
    }
}

METHOD leave_analog_fixed_current_mode
{
    LABEL [leaving_fixed_current_mode];
    HELP [leaving_fixed_current_mode_help_1];
    DEFINITION
    {
        char status[STATUS_SIZE];
        char disp_string1[60];
        long var_id[1];
        int slen1;

        slen1 = 60;

        IGNORE_ALL_RESPONSE_CODES();
        XMTR_IGNORE_ALL_RESPONSE_CODES();
        IGNORE_ALL_DEVICE_STATUS();
        XMTR_IGNORE_ALL_DEVICE_STATUS();

        assign_float(dynamic_variables[ivar_value(analog_channel_number_code)].DAQ.ANALOG_VALUE,NaN);

        do
        {
            get_dictionary_string(return_fld_dev_to_orig_otpt, disp_string1, slen1);
            DELAY(3, disp_string1);

            send(66, status);

            if (status[STATUS_RESPONSE_CODE])
            {
                display_response_status(66, status[STATUS_RESPONSE_CODE]);
            }

        } while(status[STATUS_RESPONSE_CODE]);

        get_dictionary_string(loop_may_be_returned_to_auto, disp_string1, slen1);
        ACKNOWLEDGE(disp_string1);
    }
}

/*
 *****************************************************************************
 *The Following commands are obsolete and NOT RECOMMENDED for new Designs
 *
 */

VARIABLE eeprom_select
{
    LABEL [EEPROM_select];
    HELP [eeprom_select_help];
/*  APPHELP "For Burn requests, the Burn may not begin until the response that"
            " acknowledges the receipt of the variable has been sent back to the"
            " Master."
            " HART_VAR:EEPROM CONTROL"; */
    CLASS LOCAL;
    TYPE ENUMERATED
    { 
        { 0, [burn_eeprom] }, 
        { 1, [restore_shadow_ram] }
    }
}

COMMAND eeprom_control
{
    NUMBER 39;
    OPERATION COMMAND;
    TRANSACTION 
    {
        REQUEST
        {
            eeprom_select
        }
        REPLY
        {
            response_code, device_status, eeprom_select
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        2,  DATA_ENTRY_ERROR, [invalid_selection];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        6,  MISC_ERROR,       [xmtr_specific_command_error];
        7,  MODE_ERROR,       [in_write_protect_mode];
        16, MODE_ERROR,       [access_restricted];
        32, MODE_ERROR,       [busy];
    }
}

METHOD burn_eeprom
{
    LABEL [burn_eeprom];
    HELP [burn_eeprom_help];
    DEFINITION
    {
        char status[3];
        char disp_string1[60];
        int slen1;

        slen1 = 60;

        IGNORE_ALL_DEVICE_STATUS();
        XMTR_IGNORE_ALL_DEVICE_STATUS();

        assign_int(eeprom_select,0);

        get_dictionary_string(making_changes_permanent, disp_string1, slen1);
        DELAY(3, disp_string1);

        send(39, status);

        if (status[STATUS_RESPONSE_CODE])
        {
            display_response_status(39, status[STATUS_RESPONSE_CODE]);
            get_dictionary_string(previous_err_seen_brn_eeprom, disp_string1, slen1);
            ACKNOWLEDGE(disp_string1);
        }
    }
}

VARIABLE unit_tag
{
    LABEL [unit_tag];
    HELP [unit_tag_help];
/*  APPHELP "A Field Device may have sub applications that require being"
            " addressed individually. For this addressing the Tag variable"
            " associated with Command #11 should be used. This Tag is used to"
            " identify the application that controls the sub applications. This"
            " Text can be used by the user in any way. A recommended use is as"
            " a unique label to a plant that correlates to a Field Device label:"
            " a plant drawing, or on a Control System."
            " NOTE - HART does not recommend using this variable. If you have an"
            " application that controls the sub applications, all of these"
            " applications should be addressed using the HART Frame itself."
            " HART_VAR:UNIT TAG"; */
    CLASS DEVICE;
    TYPE PACKED_ASCII (8);
}

VARIABLE unit_descriptor
{
    LABEL [unit_descriptor];
    HELP [unit_descriptor_help];
/*  APPHELP "A Field Device may have sub applications that require being"
            " addressed individually. This Descriptor"
            " is used to identify the application that controls the sub"
            " applications. This text can be used by the user in any way. There is"
            " no recommended use.
            " NOTE - HART does not recommend using this variable. If you have an"
            " application that controls the sub applications, all of these"
            " applications should be addressed using the HART Frame itself."
            " HART_VAR:UNIT DESCR"; */
    CLASS DEVICE;
    TYPE PACKED_ASCII (16);
}

VARIABLE unit_date
{
    LABEL [unit_date];
    HELP [unit_date_help];
/*  APPHELP "A Field Device may have sub applications that require being"
            " addressed individually. This Date is used to"
            " identify the application that controls the sub applications."
            " This text can be used by the user in any way. There is"
            " no recommended use.
            " Format: Byte Closest to the Delimiter: Day, Next Byte: Month,
            " Byte Furthest from the Delimiter: Year-1900.
            " NOTE - HART does not recommend using this variable. If you have an"
            " application that controls the sub applications, all of these"
            " applications should be addressed using the HART Frame itself."
            " HART_VAR:UNIT DATE"; */
    CLASS DEVICE;
    TYPE DATE;
}

COMMAND read_unit_tag_descriptor_date
{
    NUMBER 57;
    OPERATION READ;
    TRANSACTION
    {
        REQUEST {}
        REPLY
        {
            response_code, device_status,
            unit_tag, unit_descriptor, unit_date
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,    [no_command_specific_errors];
        6,  MISC_ERROR, [xmtr_specific_command_error];
        16, MODE_ERROR, [access_restricted];
    }
}

COMMAND write_unit_tag_descriptor_date
{
    NUMBER 58;
    OPERATION WRITE;
    TRANSACTION
    {
        REQUEST
        {
            unit_tag, unit_descriptor, unit_date
        }
        REPLY
        {
            response_code, device_status,
            unit_tag, unit_descriptor, unit_date
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,          [no_command_specific_errors];
        5,  DATA_ENTRY_ERROR, [too_few_data_bytes_recieved];
        6,  MISC_ERROR,       [xmtr_specific_command_error];
        7,  MODE_ERROR,       [in_write_protect_mode];
        16, MODE_ERROR,       [access_restricted];
        32, MODE_ERROR,       [busy];
    }
}

/*****************************************************************************
 * The following commands are NOT RECOMMENDED FOR NEW DESIGNS
 */

COMMAND read_dynamic_variables_and_pv_analog_output
{
    NUMBER 61;
    OPERATION READ;
    TRANSACTION
    {
        REQUEST {}
        REPLY
        {
            response_code, device_status,
            PV.DAQ.ANALOG_UNITS, PV.DAQ.ANALOG_VALUE,
            PV.DEVICE_VARIABLE.DIGITAL_UNITS, PV.DEVICE_VARIABLE.DIGITAL_VALUE,
            SV.DEVICE_VARIABLE.DIGITAL_UNITS, SV.DEVICE_VARIABLE.DIGITAL_VALUE,
            TV.DEVICE_VARIABLE.DIGITAL_UNITS, TV.DEVICE_VARIABLE.DIGITAL_VALUE,
            QV.DEVICE_VARIABLE.DIGITAL_UNITS, QV.DEVICE_VARIABLE.DIGITAL_VALUE
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,        [no_command_specific_errors];
        6,  MISC_ERROR,     [xmtr_specific_command_error];
        8,  MISC_WARNING,   [update_failure];
        16, MODE_ERROR,     [access_restricted];
    }
}

COMMAND read_all_dynamic_variables
{
    NUMBER 110;
    OPERATION READ;
    TRANSACTION
    {
        REQUEST {}
        REPLY
        {
            response_code, device_status,
            PV.DEVICE_VARIABLE.DIGITAL_UNITS, PV.DEVICE_VARIABLE.DIGITAL_VALUE,
            SV.DEVICE_VARIABLE.DIGITAL_UNITS, SV.DEVICE_VARIABLE.DIGITAL_VALUE,
            TV.DEVICE_VARIABLE.DIGITAL_UNITS, TV.DEVICE_VARIABLE.DIGITAL_VALUE,
            QV.DEVICE_VARIABLE.DIGITAL_UNITS, QV.DEVICE_VARIABLE.DIGITAL_VALUE
        }
    }
    RESPONSE_CODES
    {
        0,  SUCCESS,        [no_command_specific_errors];
        6,  MISC_ERROR,     [xmtr_specific_command_error];
        7,  MODE_ERROR,     [in_write_protect_mode];
        8,  MISC_WARNING,   [update_failure];
        16, MODE_ERROR,     [access_restricted];
    }
}
