Project

General

Profile

Files » inst.c

Frédéric Blanc, 2016-01-29 10:30

 
/*****************************************************************************
/*=CHANGE:===============================================================*
Change the copyright note.
*=======================================================================*
* Copyright 2009, National Instruments, Corporation. All Rights Reserved. *
*****************************************************************************/

/*****************************************************************************
/*=CHANGE:===============================================================*
INSTRUCTIONS TO THE INSTRUMENT DRIVER DEVELOPER
READ THESE INSTRUCTIONS FIRST!
*=======================================================================*
Congratulations! You have successfully created all the files needed
for your instrument driver - *.c, *.h, *.fp, and *.sub. These
files give you a framework to build your complete instrument driver
with the following features:
- IVI compliance
- VXIplug&play compliance
- Attribute model
- State caching
- Simulation
- Multithread safety
Before you can begin using this driver, you must perform the following
manual changes.
- If you are developing a driver for a register-based device,
remove the function panels for the inst_WriteInstrData
and inst_ReadInstrData functions. These functions
are for use with message-based instruments.
- Device-specific changes are marked with the comment "CHANGE".
Search for all occurrences of the word "CHANGE" and make the changes
for your specific instrument. Delete the comments after you complete
the changes.
- The IVI wizard might not properly align the code it generates.
Review the resulting *.h and *.c files and reformat them as necessary.
- Read the help text for the functions and attributes to understand
the functionality you must implement in this driver. The easiest
way to view the help text is by using the inst.fp
function panels in "operate" mode. You can view the help text for
the attributes in any of the inst_GetAttribute
function panels.

- Many of the functions contain extensive code examples within
comment blocks. These code examples contain embedded comments.
The only way to embed comments is by using double slashes (//).
Some C compilers do not accept double slashes. If you are developing
this driver for general use, convert the double slashes to
traditional C comment markers.
- Edit the Function Panel help. Pay close attention to the default
values and valid ranges for each parameter. If you change the
default value for a control, you also need to change the default
value in the help for the control. Also, search for the comment
"CHANGE" in the help text, and make the appropriate changes.
- Edit the help for all attributes with the attribute editor. Pay close
attention to the valid range information. The Set/Get/Check attribute
function panels automatically display valid range information for
attributes that have range tables of type IVI_VAL_DISCRETE or
IVI_VAL_COERCED. You must edit/create the valid range information
in the description of an attribute if any of the following conditions
is true:
* The attribute does not have a range table.
* The attribute has a range table of type IVI_VAL_RANGED.
* The attribute uses multiple static range tables or a dynamic
range table.
Also, look for "CHANGE" comments in the help text, and make the
appropriate changes.
- Verify that all values that the header file defines are valid for
your instrument. Delete the values that your instrument does not
use.
- Delete these instructions and save the modified program.

*============================================================END=CHANGE=*/

/*****************************************************************************
* inst Instrument Driver
* LabWindows/CVI Instrument Driver
* Original Release: lundi 17 octobre 2011
* By: ,
* PH. Fax
*
* Modification History:
*
* lundi 17 octobre 2011 - Instrument Driver Created.
*
*****************************************************************************/

#include <string.h>
#include <stdio.h>
#include <formatio.h>
#include "inst.h"

/*****************************************************************************
*--------------------- Hidden Attribute Declarations -----------------------*
*****************************************************************************/

#define INST_ATTR_OPC_TIMEOUT (IVI_SPECIFIC_PRIVATE_ATTR_BASE + 1L) /* ViInt32 */
#define INST_ATTR_USE_SPECIFIC_SIMULATION (IVI_INHERENT_ATTR_BASE + 23L) /* ViBoolean */
#define INST_ATTR_VISA_RM_SESSION (IVI_SPECIFIC_PRIVATE_ATTR_BASE + 5L) /* ViSession */
#define INST_ATTR_IO_SESSION (IVI_INHERENT_ATTR_BASE + 322L) /* ViSession */
#define INST_ATTR_OPC_CALLBACK (IVI_SPECIFIC_PRIVATE_ATTR_BASE + 6L) /* ViAddr */
#define INST_ATTR_CHECK_STATUS_CALLBACK (IVI_SPECIFIC_PRIVATE_ATTR_BASE + 7L) /* ViAddr */
#define INST_ATTR_USER_INTERCHANGE_CHECK_CALLBACK (IVI_SPECIFIC_PRIVATE_ATTR_BASE + 8L) /* ViAddr */

/*****************************************************************************
*---------------------------- Useful Macros --------------------------------*
*****************************************************************************/

/*- I/O buffer size -----------------------------------------------------*/
#define BUFFER_SIZE 512L

/*=CHANGE:=============================================================*
NOTE TO THE DEVELOPER: The attribute for which this value is defined
is obsolete and may not be supported in future versions of IVI drivers.
If you DO NOT want this driver to be compliant with NI's Ivi Driver
Toolset 1.1, remove this value definition.

If you DO want this driver to be compliant with NI's IVI Driver Toolset
1.1, remove the comments around this attribute value definition.

#define INST_IO_SESSION_TYPE IVI_VAL_VISA_SESSION_TYPE
*==========================================================END=CHANGE=*/

/*- 488.2 Event Status Register (ESR) Bits ------------------------------*/
#define IEEE_488_2_ERROR_MASK 0x3C


/*****************************************************************************
*-------------- Utility Function Declarations (Non-Exported) ---------------*
*****************************************************************************/
static ViStatus inst_IviInit (ViRsrc resourceName, ViBoolean IDQuery,
ViBoolean reset, ViSession vi);
static ViStatus inst_IviClose (ViSession vi);

static ViStatus inst_InitAttributes (ViSession vi);
static ViStatus inst_DefaultInstrSetup (ViSession openInstrSession);
static ViStatus inst_CheckStatus (ViSession vi);
static ViStatus inst_WaitForOPC (ViSession vi, ViInt32 maxTime);

/*- File I/O Utility Functions -*/
static ViStatus inst_ReadToFile (ViSession vi, ViConstString filename,
ViInt32 maxBytesToRead, ViInt32 fileAction, ViInt32 *totalBytesWritten);
static ViStatus inst_WriteFromFile (ViSession vi, ViConstString filename,
ViInt32 maxBytesToWrite, ViInt32 byteOffset,
ViInt32 *totalBytesWritten);

/*****************************************************************************
*----------------- Callback Declarations (Non-Exported) --------------------*
*****************************************************************************/

/*- Global Session Callbacks --------------------------------------------*/
static ViStatus _VI_FUNC inst_CheckStatusCallback (ViSession vi, ViSession io);
static ViStatus _VI_FUNC inst_WaitForOPCCallback (ViSession vi, ViSession io);

/*- Attribute callbacks -------------------------------------------------*/

static ViStatus _VI_FUNC instAttrDriverRevision_ReadCallback (ViSession vi,
ViSession io,
ViConstString channelName,
ViAttr attributeId,
const ViConstString cacheValue);
static ViStatus _VI_FUNC instAttrInstrumentManufacturer_ReadCallback (ViSession vi,
ViSession io,
ViConstString channelName,
ViAttr attributeId,
const ViConstString cacheValue);
static ViStatus _VI_FUNC instAttrInstrumentModel_ReadCallback (ViSession vi,
ViSession io,
ViConstString channelName,
ViAttr attributeId,
const ViConstString cacheValue);


/*****************************************************************************
*------------ User-Callable Functions (Exportable Functions) ---------------*
*****************************************************************************/

/*****************************************************************************
* Function: inst_init
* Purpose: VXIplug&play required function. Calls the
* inst_InitWithOptions function.
*****************************************************************************/
ViStatus _VI_FUNC inst_init (ViRsrc resourceName, ViBoolean IDQuery,
ViBoolean resetDevice, ViSession *newVi)
{
ViStatus error = VI_SUCCESS;

if (newVi == VI_NULL)
{
Ivi_SetErrorInfo (VI_NULL, VI_FALSE, IVI_ERROR_INVALID_PARAMETER,
VI_ERROR_PARAMETER4, "Null address for Instrument Handle");
checkErr( IVI_ERROR_INVALID_PARAMETER);
}

checkErr( inst_InitWithOptions (resourceName, IDQuery, resetDevice,
"", newVi));

Error:
return error;
}

/*****************************************************************************
* Function: inst_InitWithOptions
* Purpose: This function creates a new IVI session and calls the
* IviInit function.
*****************************************************************************/
ViStatus _VI_FUNC inst_InitWithOptions(
ViRsrc resourceName,
ViBoolean IDQuery,
ViBoolean resetDevice,
ViConstString optionString,
ViSession *newVi
)
{
ViStatus error = VI_SUCCESS;
ViSession vi = VI_NULL;
ViChar newResourceName[IVI_MAX_MESSAGE_BUF_SIZE];
ViChar newOptionString[IVI_MAX_MESSAGE_BUF_SIZE];
ViBoolean isLogicalName;
if (newVi == VI_NULL)
{
Ivi_SetErrorInfo (VI_NULL, VI_FALSE, IVI_ERROR_INVALID_PARAMETER,
VI_ERROR_PARAMETER5, "Null address for Instrument Handle");
checkErr( IVI_ERROR_INVALID_PARAMETER);
}

*newVi = VI_NULL;
checkErr( Ivi_GetInfoFromResourceName( resourceName, (ViString)optionString,
newResourceName,
newOptionString,
&isLogicalName));
/* create a new interchangeable driver */
checkErr( Ivi_SpecificDriverNew ("inst", newOptionString, &vi));
if (!isLogicalName)
{
ViInt32 oldFlag = 0;
checkErr (Ivi_GetAttributeFlags (vi, IVI_ATTR_IO_RESOURCE_DESCRIPTOR, &oldFlag));
checkErr (Ivi_SetAttributeFlags (vi, IVI_ATTR_IO_RESOURCE_DESCRIPTOR, oldFlag & 0xfffb | 0x0010));
checkErr (Ivi_SetAttributeViString (vi, "", IVI_ATTR_IO_RESOURCE_DESCRIPTOR, 0, newResourceName));
}
/* init the driver */
checkErr( inst_IviInit (newResourceName, IDQuery, resetDevice, vi));
if (isLogicalName)
checkErr( Ivi_ApplyDefaultSetup (vi));
*newVi = vi;
Error:
if (error < VI_SUCCESS)
Ivi_Dispose (vi);
return error;
}

/*****************************************************************************
* Function: inst_close
* Purpose: This function closes the instrument.
*
* Note: This function must unlock the session before calling
* Ivi_Dispose.
*****************************************************************************/
ViStatus _VI_FUNC inst_close (ViSession vi)
{
ViStatus error = VI_SUCCESS;
checkErr( Ivi_LockSession (vi, VI_NULL));
checkErr( inst_IviClose (vi));

Error:
Ivi_UnlockSession (vi, VI_NULL);
Ivi_Dispose (vi);

return error;
}

/*****************************************************************************
* Function: inst_reset
* Purpose: This function resets the instrument.
*****************************************************************************/
ViStatus _VI_FUNC inst_reset (ViSession vi)
{
ViStatus error = VI_SUCCESS;

checkErr( Ivi_LockSession (vi, VI_NULL));

checkErr( inst_DefaultInstrSetup (vi));
if ( error == VI_SUCCESS )
viCheckWarn( VI_WARN_NSUP_RESET);

Error:
Ivi_UnlockSession (vi, VI_NULL);
return error;
}

/*****************************************************************************
* Function: inst_ResetWithDefaults
* Purpose: This function resets the instrument and applies default settings
* from the IVI Configuration Store based on the logical name
* from which the session was created.
*****************************************************************************/
ViStatus _VI_FUNC inst_ResetWithDefaults (ViSession vi)
{
ViStatus error = VI_SUCCESS;
checkErr( Ivi_LockSession (vi, VI_NULL));
checkErr( inst_reset(vi));
checkErr( Ivi_ApplyDefaultSetup(vi));
Error:
Ivi_UnlockSession(vi, VI_NULL);
return error;
}

/****************************************************************************
* Function: inst_Disable
* Purpose: This function places the instrument in a quiescent state as
* quickly as possible.
****************************************************************************/
ViStatus _VI_FUNC inst_Disable (ViSession vi)
{
ViStatus error = VI_SUCCESS;
checkErr( Ivi_LockSession (vi, VI_NULL));
if (!Ivi_Simulating(vi))
{
/*=CHANGE:===============================================================*

Modify this example code to disable the instrument.

ViSession io = Ivi_IOSession(vi); // call only when locked

checkErr( Ivi_SetNeedToCheckStatus (vi, VI_TRUE));

viCheckErr( viPrintf (io, ":OPER:CH:ALL:OFF;"));
*============================================================END=CHANGE=*/
}
Error:
Ivi_UnlockSession (vi, VI_NULL);
return error;
}

/*****************************************************************************
* Function: inst_self_test
* Purpose: This function executes the instrument self-test and returns the
* result.
*****************************************************************************/
ViStatus _VI_FUNC inst_self_test (ViSession vi, ViInt16 *testResult,
ViChar testMessage[])
{
ViStatus error = VI_SUCCESS;

checkErr( Ivi_LockSession (vi, VI_NULL));

if (testResult == VI_NULL)
viCheckParm( IVI_ERROR_INVALID_PARAMETER, 2, "Null address for Test Result");
if (testMessage == VI_NULL)
viCheckParm( IVI_ERROR_INVALID_PARAMETER, 3, "Null address for Test Message");

viCheckWarn( VI_WARN_NSUP_SELF_TEST);

Error:
Ivi_UnlockSession(vi, VI_NULL);
return error;
}

/*****************************************************************************
* Function: inst_revision_query
* Purpose: This function returns the driver and instrument revisions.
*****************************************************************************/
ViStatus _VI_FUNC inst_revision_query (ViSession vi, ViChar driverRev[],
ViChar instrRev[])
{
ViStatus error = VI_SUCCESS;
checkErr( Ivi_LockSession (vi, VI_NULL));

if (driverRev == VI_NULL)
viCheckParm( IVI_ERROR_INVALID_PARAMETER, 2, "Null address for Driver Revision");
if (instrRev == VI_NULL)
viCheckParm( IVI_ERROR_INVALID_PARAMETER, 3, "Null address for Instrument Revision");

checkErr( Ivi_GetAttributeViString (vi, "", INST_ATTR_SPECIFIC_DRIVER_REVISION,
0, 256, driverRev));
checkErr( Ivi_GetAttributeViString (vi, "", INST_ATTR_INSTRUMENT_FIRMWARE_REVISION,
0, 256, instrRev));
checkErr( inst_CheckStatus (vi));
viCheckWarn( VI_WARN_NSUP_REV_QUERY);

Error:
Ivi_UnlockSession(vi, VI_NULL);
return error;
}

/*****************************************************************************
* Function: inst_error_query
* Purpose: This function queries the instrument error queue and returns
* the result.
*****************************************************************************/
ViStatus _VI_FUNC inst_error_query (ViSession vi, ViInt32 *errCode,
ViChar errMessage[])
{
ViStatus error = VI_SUCCESS;
checkErr( Ivi_LockSession (vi, VI_NULL));
if (errCode == VI_NULL)
viCheckParm( IVI_ERROR_INVALID_PARAMETER, 2, "Null address for Error Code");
if (errMessage == VI_NULL)
viCheckParm( IVI_ERROR_INVALID_PARAMETER, 3, "Null address for Error Message");

viCheckWarn( VI_WARN_NSUP_ERROR_QUERY);

Error:
Ivi_UnlockSession(vi, VI_NULL);
return error;
}

/*****************************************************************************
* Function: inst_error_message
* Purpose: This function translates the error codes returned by this
* instrument driver into user-readable strings.
*
* Note: The caller can pass VI_NULL for the vi parameter. This
* is useful if one of the init functions fail.
*****************************************************************************/
ViStatus _VI_FUNC inst_error_message (ViSession vi, ViStatus errorCode,
ViChar errorMessage[256])
{
ViStatus error = VI_SUCCESS;
static IviStringValueTable errorTable =
{
/*=CHANGE:================================================================*
Insert instrument driver specific error codes here. Example:

{INST_ERROR_TOO_MANY_SAMPLES, "Sample Count cannot exceed 512."},
*=============================================================END=CHANGE=*/
{VI_NULL, VI_NULL}
};
if (vi)
Ivi_LockSession(vi, VI_NULL);

/* all VISA and IVI error codes are handled as well as codes in the table */
if (errorMessage == VI_NULL)
viCheckParm( IVI_ERROR_INVALID_PARAMETER, 3, "Null address for Error Message");

checkErr( Ivi_GetSpecificDriverStatusDesc(vi, errorCode, errorMessage, errorTable));

Error:
if (vi)
Ivi_UnlockSession(vi, VI_NULL);
return error;
}

/*****************************************************************************
* Function: inst_InvalidateAllAttributes
* Purpose: This function invalidates the cached value of all attributes.
*****************************************************************************/
ViStatus _VI_FUNC inst_InvalidateAllAttributes (ViSession vi)
{
return Ivi_InvalidateAllAttributes(vi);
}

/*- Obsolete Error Handling Functions ----------------------------*/
/*=CHANGE:=============================================================*
NOTE TO THE DEVELOPER: These functions are obsolete and may not be
supported in future versions of IVI drivers.
If you DO NOT want this driver to be compliant with NI's Ivi Driver
Toolset 1.1, remove these function definitions.

If you DO want this driver to be compliant with NI's IVI Driver Toolset
1.1, remove the comments around these functions definitions.

ViStatus _VI_FUNC inst_GetErrorInfo (ViSession vi, ViStatus *primaryError,
ViStatus *secondaryError, ViChar errorElaboration[256])
{
return Ivi_GetErrorInfo(vi, primaryError, secondaryError, errorElaboration);
}
ViStatus _VI_FUNC inst_ClearErrorInfo (ViSession vi)
{
return Ivi_ClearErrorInfo (vi);
}
*==========================================================END=CHANGE=*/

/*****************************************************************************
* Function: inst_GetError and inst_ClearError Functions
* Purpose: These functions enable the instrument driver user to
* get or clear the error information the driver associates with the
* IVI session.
*****************************************************************************/
ViStatus _VI_FUNC inst_GetError (ViSession vi,
ViStatus *errorCode,
ViInt32 bufferSize,
ViChar description[])
{
ViStatus error = VI_SUCCESS;
ViStatus primary = VI_SUCCESS,
secondary = VI_SUCCESS;
ViChar elaboration[256] = "";
ViChar errorMessage[1024] = "";
ViChar *appendPoint = errorMessage;
ViInt32 actualSize = 0;
ViBoolean locked = VI_FALSE;

/* Lock Session */
if (vi != 0)
{
checkErr( Ivi_LockSession(vi, &locked));
}

/* Test for nulls and acquire error data */
if (bufferSize != 0)
{
if (errorCode == VI_NULL)
{
viCheckParm( IVI_ERROR_INVALID_PARAMETER, 2, "Null address for Error");
}
if (description == VI_NULL)
{
viCheckParm( IVI_ERROR_INVALID_PARAMETER, 4, "Null address for Description");
}
checkErr( Ivi_GetErrorInfo (vi, &primary, &secondary, elaboration));
}

else
{
checkErr( Ivi_GetAttributeViString(vi, VI_NULL, IVI_ATTR_ERROR_ELABORATION, 0, 256, elaboration));
checkErr( Ivi_GetAttributeViInt32(vi, VI_NULL, IVI_ATTR_SECONDARY_ERROR, 0, &secondary));
checkErr( Ivi_GetAttributeViInt32(vi, VI_NULL, IVI_ATTR_PRIMARY_ERROR, 0, &primary));
}
/* Format data */
if (primary != VI_SUCCESS)
{
ViChar msg[256] = "";
checkErr( inst_error_message (vi, primary, msg));
appendPoint += sprintf(appendPoint, "Primary Error: (Hex 0x%08X) %s\n", primary, msg);
}
if (secondary != VI_SUCCESS)
{
ViChar msg[256] = "";
checkErr( inst_error_message (vi, secondary, msg));
appendPoint += sprintf(appendPoint, "Secondary Error: (Hex 0x%08X) %s\n", secondary, msg);
}
if (elaboration[0])
{
sprintf(appendPoint, "Elaboration: %s", elaboration);
}
actualSize = (ViInt32)(strlen(errorMessage) + 1);
/* Prepare return values */
if (bufferSize == 0)
{
error = actualSize;
}
else
{
if (bufferSize > 0)
{
if (actualSize > bufferSize)
{
error = actualSize;
actualSize = bufferSize;
}
}
memcpy(description, errorMessage, actualSize-1);
description[actualSize-1] = '\0';
}
if (errorCode)
{
*errorCode = primary;
}
Error:
/* Unlock Session */
Ivi_UnlockSession (vi, &locked);
return error;
}

ViStatus _VI_FUNC inst_ClearError (ViSession vi)
{
return Ivi_ClearErrorInfo (vi);
}

/*****************************************************************************
* Function: inst_GetNextCoercionRecord
* Purpose: This function enables the instrument driver user to obtain
* the coercion information associated with the IVI session.
* This function retrieves and clears the oldest instance in which
* the instrument driver coerced a value the instrument driver user
* specified to another value.
*****************************************************************************/
ViStatus _VI_FUNC inst_GetNextCoercionRecord (ViSession vi,
ViInt32 bufferSize,
ViChar record[])
{
return Ivi_GetNextCoercionString (vi, bufferSize, record);
}

/****************************************************************************
* Function: inst_GetNextInterchangeWarning,
* inst_ResetInterchangeCheck, and
* inst_ClearInterchangeWarnings
* Purpose: These functions allow the user to retrieve interchangeability
* warnings, reset the driver's interchangeability checking
* state, and clear all previously logged interchangeability warnings.
****************************************************************************/
ViStatus _VI_FUNC inst_GetNextInterchangeWarning (ViSession vi,
ViInt32 bufferSize,
ViChar warnString[])
{
return Ivi_GetNextInterchangeCheckString (vi, bufferSize, warnString);
}

ViStatus _VI_FUNC inst_ResetInterchangeCheck (ViSession vi)
{
return Ivi_ResetInterchangeCheck (vi);
}

ViStatus _VI_FUNC inst_ClearInterchangeWarnings (ViSession vi)
{
return Ivi_ClearInterchangeWarnings (vi);
}

/*****************************************************************************
* Function: inst_LockSession and inst_UnlockSession Functions
* Purpose: These functions enable the instrument driver user to lock the
* session around a sequence of driver calls during which other
* execution threads must not disturb the instrument state.
*
* NOTE: The callerHasLock parameter must be a local variable
* initialized to VI_FALSE and passed by reference, or you can pass
* VI_NULL.
*****************************************************************************/
ViStatus _VI_FUNC inst_LockSession (ViSession vi, ViBoolean *callerHasLock)
{
return Ivi_LockSession(vi,callerHasLock);
}
ViStatus _VI_FUNC inst_UnlockSession (ViSession vi, ViBoolean *callerHasLock)
{
return Ivi_UnlockSession(vi,callerHasLock);
}


/*****************************************************************************
* Function: inst_GetAttribute<type> Functions
* Purpose: These functions enable the instrument driver user to get
* attribute values directly. There are typesafe versions for
* ViInt32, ViInt64, ViReal64, ViString, ViBoolean, and ViSession
* attributes.
*****************************************************************************/
/*=CHANGE:=============================================================*

NOTE TO THE DEVELOPER: The ViInt64 functions (_GetAttributeViInt64,
_SetAttributeViInt64, and _CheckAttributeViInt64) are only required
if your driver implements a ViInt64 attribute. They can be removed
otherwise.
Note: NI's LabWindows/CVI versions earlier than 8.5 do not support
function panel files that have ViInt64 parameters. If you add a
ViInt64 attribute in your driver, the functions can be added to the
function panel file but the file will only be usable in
LabWindows/CVI 8.5 and later.

*==========================================================END=CHANGE=*/
ViStatus _VI_FUNC inst_GetAttributeViInt32 (ViSession vi, ViConstString channelName,
ViAttr attributeId, ViInt32 *value)
{
return Ivi_GetAttributeViInt32 (vi, channelName, attributeId, IVI_VAL_DIRECT_USER_CALL,
value);
}
ViStatus _VI_FUNC inst_GetAttributeViInt64 (ViSession vi, ViConstString channelName,
ViAttr attributeId, ViInt64 *value)
{
return Ivi_GetAttributeViInt64 (vi, channelName, attributeId, IVI_VAL_DIRECT_USER_CALL,
value);
}
ViStatus _VI_FUNC inst_GetAttributeViReal64 (ViSession vi, ViConstString channelName,
ViAttr attributeId, ViReal64 *value)
{
return Ivi_GetAttributeViReal64 (vi, channelName, attributeId, IVI_VAL_DIRECT_USER_CALL,
value);
}
ViStatus _VI_FUNC inst_GetAttributeViString (ViSession vi, ViConstString channelName,
ViAttr attributeId, ViInt32 bufSize,
ViChar value[])
{
return Ivi_GetAttributeViString (vi, channelName, attributeId, IVI_VAL_DIRECT_USER_CALL,
bufSize, value);
}
ViStatus _VI_FUNC inst_GetAttributeViBoolean (ViSession vi, ViConstString channelName,
ViAttr attributeId, ViBoolean *value)
{
return Ivi_GetAttributeViBoolean (vi, channelName, attributeId, IVI_VAL_DIRECT_USER_CALL,
value);
}
ViStatus _VI_FUNC inst_GetAttributeViSession (ViSession vi, ViConstString channelName,
ViAttr attributeId, ViSession *value)
{
return Ivi_GetAttributeViSession (vi, channelName, attributeId, IVI_VAL_DIRECT_USER_CALL,
value);
}

/*****************************************************************************
* Function: inst_SetAttribute<type> Functions
* Purpose: These functions enable the instrument driver user to set
* attribute values directly. There are typesafe versions for
* ViInt32, ViInt64, ViReal64, ViString, ViBoolean, and ViSession
* datatypes.
*****************************************************************************/
/*=CHANGE:=============================================================*

NOTE TO THE DEVELOPER: The ViInt64 functions (_GetAttributeViInt64,
_SetAttributeViInt64, and _CheckAttributeViInt64) are only required
if your driver implements a ViInt64 attribute. They can be removed
otherwise.
Note: NI's LabWindows/CVI versions earlier than 8.5 do not support
function panel files that have ViInt64 parameters. If you add a
ViInt64 attribute in your driver, the functions can be added to the
function panel file but the file will only be usable in
LabWindows/CVI 8.5 and later.

*==========================================================END=CHANGE=*/
ViStatus _VI_FUNC inst_SetAttributeViInt32 (ViSession vi, ViConstString channelName,
ViAttr attributeId, ViInt32 value)
{
return Ivi_SetAttributeViInt32 (vi, channelName, attributeId, IVI_VAL_DIRECT_USER_CALL,
value);
}
ViStatus _VI_FUNC inst_SetAttributeViInt64 (ViSession vi, ViConstString channelName,
ViAttr attributeId, ViInt64 value)
{
return Ivi_SetAttributeViInt64 (vi, channelName, attributeId, IVI_VAL_DIRECT_USER_CALL,
value);
}
ViStatus _VI_FUNC inst_SetAttributeViReal64 (ViSession vi, ViConstString channelName,
ViAttr attributeId, ViReal64 value)
{
return Ivi_SetAttributeViReal64 (vi, channelName, attributeId, IVI_VAL_DIRECT_USER_CALL,
value);
}
ViStatus _VI_FUNC inst_SetAttributeViString (ViSession vi, ViConstString channelName,
ViAttr attributeId, ViConstString value)
{
return Ivi_SetAttributeViString (vi, channelName, attributeId, IVI_VAL_DIRECT_USER_CALL,
value);
}
ViStatus _VI_FUNC inst_SetAttributeViBoolean (ViSession vi, ViConstString channelName,
ViAttr attributeId, ViBoolean value)
{
return Ivi_SetAttributeViBoolean (vi, channelName, attributeId, IVI_VAL_DIRECT_USER_CALL,
value);
}
ViStatus _VI_FUNC inst_SetAttributeViSession (ViSession vi, ViConstString channelName,
ViAttr attributeId, ViSession value)
{
return Ivi_SetAttributeViSession (vi, channelName, attributeId, IVI_VAL_DIRECT_USER_CALL,
value);
}

/*****************************************************************************
* Function: inst_CheckAttribute<type> Functions
* Purpose: These functions enable the instrument driver user to check
* attribute values directly. These functions check the value you
* specify even if you set the INST_ATTR_RANGE_CHECK
* attribute to VI_FALSE. There are typesafe versions for ViInt32,
* ViInt64, ViReal64, ViString, ViBoolean, and ViSession datatypes.
*****************************************************************************/
/*=CHANGE:=============================================================*

NOTE TO THE DEVELOPER: The ViInt64 functions (_GetAttributeViInt64,
_SetAttributeViInt64, and _CheckAttributeViInt64) are only required
if your driver implements a ViInt64 attribute. They can be removed
otherwise.
Note: NI's LabWindows/CVI versions earlier than 8.5 do not support
function panel files that have ViInt64 parameters. If you add a
ViInt64 attribute in your driver, the functions can be added to the
function panel file but the file will only be usable in
LabWindows/CVI 8.5 and later.

*==========================================================END=CHANGE=*/
ViStatus _VI_FUNC inst_CheckAttributeViInt32 (ViSession vi, ViConstString channelName,
ViAttr attributeId, ViInt32 value)
{
return Ivi_CheckAttributeViInt32 (vi, channelName, attributeId, IVI_VAL_DIRECT_USER_CALL,
value);
}
ViStatus _VI_FUNC inst_CheckAttributeViInt64 (ViSession vi, ViConstString channelName,
ViAttr attributeId, ViInt64 value)
{
return Ivi_CheckAttributeViInt64 (vi, channelName, attributeId, IVI_VAL_DIRECT_USER_CALL,
value);
}
ViStatus _VI_FUNC inst_CheckAttributeViReal64 (ViSession vi, ViConstString channelName,
ViAttr attributeId, ViReal64 value)
{
return Ivi_CheckAttributeViReal64 (vi, channelName, attributeId, IVI_VAL_DIRECT_USER_CALL,
value);
}
ViStatus _VI_FUNC inst_CheckAttributeViString (ViSession vi, ViConstString channelName,
ViAttr attributeId, ViConstString value)
{
return Ivi_CheckAttributeViString (vi, channelName, attributeId, IVI_VAL_DIRECT_USER_CALL,
value);
}
ViStatus _VI_FUNC inst_CheckAttributeViBoolean (ViSession vi, ViConstString channelName,
ViAttr attributeId, ViBoolean value)
{
return Ivi_CheckAttributeViBoolean (vi, channelName, attributeId, IVI_VAL_DIRECT_USER_CALL,
value);
}
ViStatus _VI_FUNC inst_CheckAttributeViSession (ViSession vi, ViConstString channelName,
ViAttr attributeId, ViSession value)
{
return Ivi_CheckAttributeViSession (vi, channelName, attributeId, IVI_VAL_DIRECT_USER_CALL,
value);
}


/*****************************************************************************
* Function: WriteInstrData and ReadInstrData Functions
* Purpose: These functions enable the instrument driver user to
* write and read commands directly to and from the instrument.
*
* Note: These functions bypass the IVI attribute state caching.
* WriteInstrData invalidates the cached values for all
* attributes.
*****************************************************************************/
ViStatus _VI_FUNC inst_WriteInstrData (ViSession vi, ViConstString writeBuffer)
{
return Ivi_WriteInstrData (vi, writeBuffer);
}
ViStatus _VI_FUNC inst_ReadInstrData (ViSession vi, ViInt32 numBytes,
ViChar rdBuf[], ViInt32 *bytesRead)
{
return Ivi_ReadInstrData (vi, numBytes, rdBuf, bytesRead);
}

/*****************************************************************************
*-------------------- Utility Functions (Not Exported) ---------------------*
*****************************************************************************/


/*****************************************************************************
* Function: inst_IviInit
* Purpose: This function is called by inst_InitWithOptions
* or by an IVI class driver. This function initializes the I/O
* interface, optionally resets the device, optionally performs an
* ID query, and sends a default setup to the instrument.
*****************************************************************************/
static ViStatus inst_IviInit (ViRsrc resourceName, ViBoolean IDQuery,
ViBoolean reset, ViSession vi)
{
ViStatus error = VI_SUCCESS;
ViSession io = VI_NULL;
char config[255];
char name[255];
char type[5];
char location;
unsigned int baud=9600;
char bits =8 ;
char stop=1;
char parite='N';
char flux='N';
char termchar=0;
/* Add attributes */
// checkErr( smu_InitAttributes (vi));

if (!Ivi_Simulating(vi))
{
ViSession rmSession = VI_NULL;

/* Open instrument session */
checkErr( Ivi_GetAttributeViSession (vi, VI_NULL, IVI_ATTR_VISA_RM_SESSION, 0,&rmSession));
strncpy(type,resourceName,4);
type[4]=0;
if(strcmp(type,"ASRL")==0)
{
sprintf(config,"%s",strrchr (resourceName,':' ));
resourceName[strlen(resourceName)-strlen(config)-1]=0;
sscanf(config,":%d-%c-%c-%c-%c-%c",&baud,&bits,&parite,&stop,&flux,&termchar);
bits=bits-48;
}
viCheckErr( viOpen (rmSession, resourceName, VI_NULL, VI_NULL, &io));
/* Configure VISA Formatted I/O */
if(strcmp(type,"ASRL")==0)
{
viCheckErr( viSetAttribute (io, VI_ATTR_ASRL_BAUD,baud )); //BAUD
viCheckErr( viSetAttribute (io, VI_ATTR_ASRL_DATA_BITS,bits )); //DATA BITS
switch (parite)
{
case 'N':
viCheckErr( viSetAttribute (io, VI_ATTR_ASRL_PARITY,VI_ASRL_PAR_NONE ));
break;
case 'O':
viCheckErr( viSetAttribute (io, VI_ATTR_ASRL_PARITY,VI_ASRL_PAR_ODD ));
break;
case 'E':
viCheckErr( viSetAttribute (io, VI_ATTR_ASRL_PARITY,VI_ASRL_PAR_EVEN ));
break;
case 'M':
viCheckErr( viSetAttribute (io, VI_ATTR_ASRL_PARITY,VI_ASRL_PAR_MARK ));
break;
case 'S':
viCheckErr( viSetAttribute (io, VI_ATTR_ASRL_PARITY,VI_ASRL_PAR_SPACE ));
break;
}
switch (flux) //FLOW_CNTRL
{
case 'N':
viCheckErr( viSetAttribute (io, VI_ATTR_ASRL_FLOW_CNTRL,VI_ASRL_FLOW_NONE ));
break;
case 'X':
viCheckErr( viSetAttribute (io, VI_ATTR_ASRL_FLOW_CNTRL,VI_ASRL_FLOW_XON_XOFF ));
break;
case 'R':
viCheckErr( viSetAttribute (io, VI_ATTR_ASRL_FLOW_CNTRL,VI_ASRL_FLOW_RTS_CTS ));
break;
case 'D':
viCheckErr( viSetAttribute (io, VI_ATTR_ASRL_FLOW_CNTRL,VI_ASRL_FLOW_DTR_DSR ));
break;
}
switch (stop)//STOP_BITS
{
case '1':
viCheckErr( viSetAttribute (io, VI_ATTR_ASRL_STOP_BITS,VI_ASRL_STOP_ONE ));
break;
case '5'://1.5
viCheckErr( viSetAttribute (io, VI_ATTR_ASRL_STOP_BITS,VI_ASRL_STOP_ONE5 ));
break;
case '2':
viCheckErr( viSetAttribute (io, VI_ATTR_ASRL_STOP_BITS,VI_ASRL_STOP_TWO ));
break;
}
if(termchar!=0)
{
viCheckErr( viSetAttribute (io, VI_ATTR_TERMCHAR,termchar)); //0x0d CR
viCheckErr( viSetAttribute (io, VI_ATTR_ASRL_END_IN, VI_ASRL_END_TERMCHAR ));
viCheckErr( viSetAttribute (io, VI_ATTR_ASRL_END_OUT, VI_ASRL_END_TERMCHAR ));//terminaison on
}else
{
viCheckErr( viSetAttribute (io, VI_ATTR_ASRL_END_IN, VI_ASRL_END_NONE ));
viCheckErr( viSetAttribute (io, VI_ATTR_ASRL_END_OUT, VI_ASRL_END_NONE ));
}
}
viCheckErr( viSetAttribute (io, VI_ATTR_TMO_VALUE, 500 )); //duree time out
viCheckErr( viSetBuf (io, VI_READ_BUF | VI_WRITE_BUF, 4000));
viCheckErr( viSetAttribute (io, VI_ATTR_WR_BUF_OPER_MODE, VI_FLUSH_ON_ACCESS));
viCheckErr( viSetAttribute (io, VI_ATTR_RD_BUF_OPER_MODE, VI_FLUSH_ON_ACCESS));
}
/* io session owned by driver now */
checkErr( Ivi_SetAttributeViSession (vi, VI_NULL, IVI_ATTR_IO_SESSION, 0, io));
/*- Reset instrument ----------------------------------------------------*/
// if (reset)
// checkErr( smu_reset (vi));
// else /*- Send Default Instrument Setup ---------------------------------*/
// checkErr( smu_DefaultInstrSetup (vi));

// checkErr( smu_CheckStatus (vi));
if (IDQuery)
viCheckWarn( VI_WARN_NSUP_ID_QUERY);
if (reset && error == VI_SUCCESS )
viCheckWarn( VI_WARN_NSUP_RESET);

Error:
if (error < VI_SUCCESS)
{
if (!Ivi_Simulating (vi) && io)
viClose (io);
}
return error;
}
/*****************************************************************************
* Function: inst_IviClose
* Purpose: This function performs all of the drivers clean-up operations
* except for closing the IVI session. This function is called by
* inst_close or by an IVI class driver.
*
* Note: This function must close the I/O session and set
* IVI_ATTR_IO_SESSION to 0.
*****************************************************************************/
static ViStatus inst_IviClose (ViSession vi)
{
ViStatus error = VI_SUCCESS;
ViSession io = VI_NULL;

/* Do not lock here. The caller manages the lock. */

checkErr( Ivi_GetAttributeViSession (vi, VI_NULL, IVI_ATTR_IO_SESSION, 0, &io));

Error:
Ivi_SetAttributeViSession (vi, VI_NULL, IVI_ATTR_IO_SESSION, 0, VI_NULL);
if(io)
{
viClose (io);
}
return error;
}

/*****************************************************************************
* Function: inst_CheckStatus
* Purpose: This function checks the status of the instrument to detect
* whether the instrument has encountered an error. This function
* is called at the end of most exported driver functions. If the
* instrument reports an error, this function returns
* IVI_ERROR_INSTRUMENT_SPECIFIC. The user can set the
* INST_ATTR_QUERY_INSTRUMENT_STATUS attribute to VI_FALSE to disable this
* check and increase execution speed.
*
* Note: Call this function only when the session is locked.
*****************************************************************************/
static ViStatus inst_CheckStatus (ViSession vi)
{
ViStatus error = VI_SUCCESS;

if (Ivi_QueryInstrStatus (vi) && Ivi_NeedToCheckStatus (vi) && !Ivi_Simulating (vi))
{
checkErr( inst_CheckStatusCallback (vi, Ivi_IOSession(vi)));
checkErr( Ivi_SetNeedToCheckStatus (vi, VI_FALSE));
}
Error:
return error;
}

/*****************************************************************************
* Function: inst_WaitForOPC
* Purpose: This function waits for the instrument to complete the
* execution of all pending operations. This function is a
* wrapper for the WaitForOPCCallback. It can be called from
* other instrument driver functions.
*
* The maxTime parameter specifies the maximum time to wait for
* operation complete in milliseconds.
*
* Note: Call this function only when the session is locked.
*****************************************************************************/
static ViStatus inst_WaitForOPC (ViSession vi, ViInt32 maxTime)
{
ViStatus error = VI_SUCCESS;

if (!Ivi_Simulating(vi))
{
ViInt32 oldOPCTimeout;
checkErr( Ivi_GetAttributeViInt32 (vi, VI_NULL, INST_ATTR_OPC_TIMEOUT,
0, &oldOPCTimeout));
Ivi_SetAttributeViInt32 (vi, VI_NULL, INST_ATTR_OPC_TIMEOUT,
0, maxTime);

error = inst_WaitForOPCCallback (vi, Ivi_IOSession(vi));

Ivi_SetAttributeViInt32 (vi, VI_NULL, INST_ATTR_OPC_TIMEOUT,
0, oldOPCTimeout);
viCheckErr( error);
}
Error:
return error;
}

/*****************************************************************************
* Function: inst_DefaultInstrSetup
* Purpose: This function sends a default setup to the instrument. The
* inst_reset function calls this function. The
* inst_IviInit function calls this function when the
* user passes VI_FALSE for the reset parameter. This function is
* useful for configuring settings that other instrument driver
* functions require.
*
* Note: Call this function only when the session is locked.
*****************************************************************************/
static ViStatus inst_DefaultInstrSetup (ViSession vi)
{
ViStatus error = VI_SUCCESS;
/* Invalidate all attributes */
checkErr( Ivi_InvalidateAllAttributes (vi));
if (!Ivi_Simulating(vi))
{
ViSession io = Ivi_IOSession(vi); /* call only when locked */

checkErr( Ivi_SetNeedToCheckStatus (vi, VI_TRUE));
/*=CHANGE:===============================================================*
Change the following command string so that it executes the default
setup for your instrument. The example does the following:
*CLS clears the event/status registers
*ESE 1 sets the standard event status enable register to recognize
operation complete.
*SRE 32 sets the service request register to enable a service
request on operation complete
These settings are required for the default implementation of the
WaitForOPCCallback to work correctly.
viCheckErr( viPrintf (io, "*CLS;*ESE 1;*SRE 32"));
*============================================================END=CHANGE=*/
viCheckErr( viPrintf (io, ":HEADERS OFF"));
}
Error:
return error;
}


/*****************************************************************************
* Function: ReadToFile and WriteFromFile Functions
* Purpose: Functions for instrument driver developers to read/write
* instrument data to/from a file.
*****************************************************************************/
static ViStatus inst_ReadToFile (ViSession vi, ViConstString filename,
ViInt32 maxBytesToRead, ViInt32 fileAction,
ViInt32 *totalBytesWritten)
{
return Ivi_ReadToFile (vi, filename, maxBytesToRead, fileAction, totalBytesWritten);
}
static ViStatus inst_WriteFromFile (ViSession vi, ViConstString filename,
ViInt32 maxBytesToWrite, ViInt32 byteOffset,
ViInt32 *totalBytesWritten)
{
return Ivi_WriteFromFile (vi, filename, maxBytesToWrite, byteOffset, totalBytesWritten);
}

/*****************************************************************************
*------------------------ Global Session Callbacks -------------------------*
*****************************************************************************/

/*****************************************************************************
* Function: inst_CheckStatusCallback
* Purpose: This function queries the instrument to determine if it has
* encountered an error. If the instrument has encountered an
* error, this function returns the IVI_ERROR_INSTRUMENT_SPECIFIC
* error code. This function is called by the
* inst_CheckStatus utility function. The
* Ivi_SetAttribute and Ivi_GetAttribute functions invoke this
* function when the optionFlags parameter includes the
* IVI_VAL_DIRECT_USER_CALL flag.
*
* The user can disable calls to this function by setting the
* INST_QUERY_INSTRUMENT_STATUS attribute to VI_FALSE. The driver can
* disable the check status callback for a particular attribute by
* setting the IVI_VAL_DONT_CHECK_STATUS flag.
*****************************************************************************/
static ViStatus _VI_FUNC inst_CheckStatusCallback (ViSession vi, ViSession io)
{
ViStatus error = VI_SUCCESS;
/* Query instrument status */
/*=CHANGE:===============================================================*
Change the *ESR? to the query command that requests the instrument to
indicate whether it has encountered an error. The following example
code is based on IEEE 488.2 Common System Commands. Example:
ViInt16 esr = 0;
viCheckErr( viQueryf (io, "*ESR?", "%hd", &esr));
if (esr & IEEE_488_2_ERROR_MASK)
{
viCheckErr( IVI_ERROR_INSTR_SPECIFIC);
}
*============================================================END=CHANGE=*/
Error:
return error;
}

/*****************************************************************************
* Function: inst_WaitForOPCCallback
* Purpose: This function waits until the instrument has finished processing
* all pending operations. This function is called by the
* inst_WaitForOPC utility function. The IVI engine invokes
* this function in the following two cases:
* - Before invoking the read callback for attributes for which the
* IVI_VAL_WAIT_FOR_OPC_BEFORE_READS flag is set.
* - After invoking the write callback for attributes for which the
* IVI_VAL_WAIT_FOR_OPC_AFTER_WRITES flag is set.
*****************************************************************************/
static ViStatus _VI_FUNC inst_WaitForOPCCallback (ViSession vi, ViSession io)
{
ViStatus error = VI_SUCCESS;
/*=CHANGE:===============================================================*
Change this function to wait for operation complete for your specific
instrument. This example function is based on the IEEE 488.2 Common
System Commands. This example shows how to use the
INST_ATTR_OPC_TIMEOUT hidden attribute to control the
length of time this function waits. This function assumes that the
instrument does not generate service requests for other reasons. This
example performs the following operations:
- Enables the service request event.
- Sends a command that forces the instrument to generate a service
request.
- Waits for the service request.
- Cleans up after the service request.

ViInt32 opcTimeout;
ViUInt16 statusByte;

checkErr( Ivi_GetAttributeViInt32 (vi, VI_NULL, INST_ATTR_OPC_TIMEOUT,
0, &opcTimeout));

viCheckErr( viEnableEvent (io, VI_EVENT_SERVICE_REQ, VI_QUEUE, VI_NULL));

viCheckErr( viPrintf (io, "*OPC"));

// wait for SRQ
viCheckErr( viWaitOnEvent (io, VI_EVENT_SERVICE_REQ, opcTimeout, VI_NULL, VI_NULL));
viCheckErr( viDisableEvent (io, VI_EVENT_SERVICE_REQ, VI_QUEUE));

// clean up after SRQ
viCheckErr( viBufWrite (io, "*CLS", 4, VI_NULL));
viCheckErr( viReadSTB (io, &statusByte));
Error:
viDiscardEvents (io, VI_EVENT_SERVICE_REQ, VI_QUEUE);
*============================================================END=CHANGE=*/

return error;
}

/*****************************************************************************
*----------------- Attribute Range Tables and Callbacks --------------------*
*****************************************************************************/
/*- INST_ATTR_SPECIFIC_DRIVER_REVISION -*/

static ViStatus _VI_FUNC instAttrDriverRevision_ReadCallback (ViSession vi,
ViSession io,
ViConstString channelName,
ViAttr attributeId,
const ViConstString cacheValue)
{
ViStatus error = VI_SUCCESS;
ViChar driverRevision[256];
sprintf (driverRevision,
"Driver: inst %d.%d, Compiler: %s %3.2f, "
"Components: IVIEngine %.2f, VISA-Spec %.2f",
INST_MAJOR_VERSION, INST_MINOR_VERSION,
IVI_COMPILER_NAME, IVI_COMPILER_VER_NUM,
IVI_ENGINE_MAJOR_VERSION + IVI_ENGINE_MINOR_VERSION/1000.0,
Ivi_ConvertVISAVer(VI_SPEC_VERSION));

checkErr( Ivi_SetValInStringCallback (vi, attributeId, driverRevision));
Error:
return error;
}






/*****************************************************************************
* Function: inst_InitAttributes
* Purpose: This function adds attributes to the IVI session, initializes
* instrument attributes, and sets attribute invalidation
* dependencies.
*****************************************************************************/
static ViStatus inst_InitAttributes (ViSession vi)
{
ViStatus error = VI_SUCCESS;
ViInt32 flags = 0;
/*=CHANGE:=============================================================*

NOTE TO THE DEVELOPER: You can add additional parameters to the
prototype of this function. This is useful when you want to pass
information from the initialization functions. The Attribute Editor
in LabWindows/CVI requires that the name of this function be
inst_InitAttributes.

*==========================================================END=CHANGE=*/
/*- Initialize instrument attributes --------------------------------*/
/*=CHANGE:=============================================================*
NOTE TO THE DEVELOPER: These attributes are obsolete and may not be
supported in future versions of IVI drivers.
If you DO NOT want this driver to be compliant with NI's Ivi Driver
Toolset 1.1, remove these attribute initalizations.

If you DO want this driver to be compliant with NI's IVI Driver Toolset
1.1, remove the comments around these attribute initalizations.

checkErr( Ivi_SetAttributeViInt32 (vi, "", INST_ATTR_SPECIFIC_DRIVER_MAJOR_VERSION,
0, INST_MAJOR_VERSION));
checkErr( Ivi_SetAttributeViInt32 (vi, "", INST_ATTR_SPECIFIC_DRIVER_MINOR_VERSION,
0, INST_MINOR_VERSION));
checkErr( Ivi_SetAttributeViString (vi, "", INST_ATTR_IO_SESSION_TYPE,
0, INST_IO_SESSION_TYPE));
*==========================================================END=CHANGE=*/

checkErr( Ivi_SetAttrReadCallbackViString (vi, INST_ATTR_SPECIFIC_DRIVER_REVISION,
instAttrDriverRevision_ReadCallback));
checkErr( Ivi_SetAttributeViInt32 (vi, "", INST_ATTR_SPECIFIC_DRIVER_CLASS_SPEC_MAJOR_VERSION,
0, INST_CLASS_SPEC_MAJOR_VERSION));
checkErr( Ivi_SetAttributeViInt32 (vi, "", INST_ATTR_SPECIFIC_DRIVER_CLASS_SPEC_MINOR_VERSION,
0, INST_CLASS_SPEC_MINOR_VERSION));
checkErr( Ivi_SetAttributeViString (vi, "", INST_ATTR_SUPPORTED_INSTRUMENT_MODELS,
0, INST_SUPPORTED_INSTRUMENT_MODELS));



/*=CHANGE:===============================================================*

Replace the "Instrument Manufacturer" here with the actual manufacturer
*============================================================END=CHANGE=*/
checkErr( Ivi_SetAttributeViString (vi, "", INST_ATTR_INSTRUMENT_MANUFACTURER,
0, "Instrument Manufacturer"));

/*=CHANGE:===============================================================*

Replace the "Instrument Model" here with the actual instrument model:
*============================================================END=CHANGE=*/

checkErr( Ivi_SetAttributeViString (vi, "", INST_ATTR_INSTRUMENT_MODEL,
0, "Instrument Model"));

checkErr( Ivi_SetAttributeViString (vi, "", INST_ATTR_SPECIFIC_DRIVER_VENDOR,
0, INST_DRIVER_VENDOR));
checkErr( Ivi_SetAttributeViString (vi, "", INST_ATTR_SPECIFIC_DRIVER_DESCRIPTION,
0, INST_DRIVER_DESCRIPTION));
checkErr( Ivi_SetAttributeViAddr (vi, VI_NULL, IVI_ATTR_OPC_CALLBACK, 0,
inst_WaitForOPCCallback));
checkErr( Ivi_SetAttributeViAddr (vi, VI_NULL, IVI_ATTR_CHECK_STATUS_CALLBACK, 0,
inst_CheckStatusCallback));


/*=CHANGE:===============================================================*
Set the group capabilities attribute, Remove the extension groups
this driver does not support, and add additional code to dynamically
determine how the presence of specific instrument options may affect
this attribute.
*============================================================END=CHANGE=*/
checkErr( Ivi_SetAttributeViString (vi, "", INST_ATTR_GROUP_CAPABILITIES, 0,
"None"));
/*- Add instrument-specific attributes ------------------------------*/
checkErr( Ivi_AddAttributeViInt32 (vi, INST_ATTR_OPC_TIMEOUT,
"INST_ATTR_OPC_TIMEOUT",
5000, IVI_VAL_HIDDEN | IVI_VAL_DONT_CHECK_STATUS,
VI_NULL, VI_NULL, VI_NULL));
checkErr( Ivi_AddAttributeViSession (vi,
INST_ATTR_VISA_RM_SESSION,
"INST_ATTR_VISA_RM_SESSION",
VI_NULL,
IVI_VAL_HIDDEN | IVI_VAL_DONT_CHECK_STATUS,
VI_NULL, VI_NULL));
checkErr( Ivi_AddAttributeViAddr (vi, INST_ATTR_OPC_CALLBACK,
"INST_ATTR_OPC_CALLBACK",
VI_NULL,
IVI_VAL_HIDDEN | IVI_VAL_DONT_CHECK_STATUS,
VI_NULL, VI_NULL));
checkErr( Ivi_AddAttributeViAddr (vi,
INST_ATTR_CHECK_STATUS_CALLBACK,
"INST_ATTR_CHECK_STATUS_CALLBACK",
VI_NULL,
IVI_VAL_HIDDEN | IVI_VAL_DONT_CHECK_STATUS,
VI_NULL, VI_NULL));
checkErr( Ivi_AddAttributeViAddr (vi,
INST_ATTR_USER_INTERCHANGE_CHECK_CALLBACK,
"INST_ATTR_USER_INTERCHANGE_CHECK_CALLBACK",
VI_NULL,
IVI_VAL_HIDDEN | IVI_VAL_DONT_CHECK_STATUS,
VI_NULL, VI_NULL));
/*- Setup attribute invalidations -----------------------------------*/

/*=CHANGE:===============================================================*
Set attribute dependencies by calling the additional
Ivi_AddAttributeInvalidation functions here. Remove the dependencies
that do not apply to your instrument by deleting the calls to
Ivi_AddAttributeInvalidation.
When you initially add an attribute, it applies to all channels / repeated
capability instances. If you want it to apply to only a subset, call the
Ivi_RestrictAttrToChannels or Ivi_RestrictAttrToInstances function.

*============================================================END=CHANGE=*/

Error:
return error;
}

/*****************************************************************************
*------------------- End Instrument Driver Source Code ---------------------*
*****************************************************************************/
(7-7/25)