Attribute Callback Functions
For each attribute, an instrument driver can call up to six callback functions. The IVI Engine invokes these functions in the context of the state caching mechanism. Each of the six callbacks performs a specific task. The six callback types are read, write, check, coerce, compare, and range table. A driver can call the read and write callbacks when it creates the attribute using one of the Ivi_AddAttribute functions. Also, the IVI Engine contains functions that install each of the first five callback types for each of the attribute data types, such as Ivi_SetAttrReadCallbackViInt32 and Ivi_SetAttrCheckCallbackViReal64. The IVI Engine contains only one function, Ivi_SetAttrRangeTableCallback, which installs a range table callback.
Whether a driver installs a read and write callback for an attribute depends on what the driver uses the attribute for.
- Attributes that represent instrument settings always have read and write callbacks.
- Attributes that store internal driver data or software-only options generally do not have read or write callbacks. Instead, the driver uses the state caching mechanism to store the values. The driver must set the IVI_VAL_ALWAYS_CACHE flag on such attributes.
- Attributes that represent values that the driver recalculates upon each query have read callbacks but no write callbacks. The read callback performs the recalculation of the value. To ensure that the IVI Engine always invokes the read callback, the driver must set the IVI_VAL_NEVER_CACHE flag on such attributes.
In discussing the various callback types, the following sections assume that the attributes represent instrument settings.
Read Callback
The read callback function for an attribute obtains the current setting for the attribute from the instrument. Typically, this involves sending a query command to the instrument, reading the response from the instrument, and interpreting the response. The IVI Engine invokes the read callback function when you request the current value of the attribute and the attribute cache value is invalid.
If the instrument expresses the setting in units that are different from the units the driver uses, the read callback must translate the value it receives from the instrument. For example, oscilloscopes typically implement the VERTICAL_RANGE attribute in terms of volts-per-division, whereas oscilloscope instrument drivers use values that represent the overall voltage range. In this case, the read callback must translate volts-per-division values into overall voltage range values.
If you do not want the IVI Engine to invoke a read callback, specify VI_NULL for the readCallback parameter to the Ivi_AddAttribute function.
Write Callback
The write callback function for an attribute is responsible for sending a new attribute setting to the instrument. The IVI Engine invokes the write callback function when you specify a new value for the attribute and the cache value is invalid or is not equal to the new value.
If the instrument expresses the setting in units that are different from the units the driver uses, the write callback must translate the value before sending the value to the instrument. For example, oscilloscopes typically implement the VERTICAL_RANGE attribute in terms of volts-per-division, whereas oscilloscope instrument drivers use values that represent the overall voltage range. In this case, the read callback translates voltage range values into overall volts-per-division values.
For example, if the instrument uses volts-per-division but the driver uses VERTICAL_RANGE, the read callback translates the VERTICAL_RANGE value into a volts-per-division value before it formats the instrument command string.
If you do not want the IVI Engine to invoke a write callback, specify VI_NULL for the writeCallback parameter to the Ivi_AddAttribute function.
Check Callback
The check callback function for an attribute validates new values to which you attempt to set the attribute.
The IVI Engine supplies default check callbacks for ViInt32, ViInt64, and ViReal64 attributes. The default check callbacks use the range table or range table callback for the attribute to validate the value. The IVI Engine automatically installs one of the default check callbacks when you create a ViInt32, ViInt64, or ViReal64 attribute with a range table. The IVI Engine also installs the default check callback when you install a range table callback for the attribute and the attribute does not already have a check callback.
You can invoke the default check callback from your callback. To add functionality to one of the default check callbacks, install a check callback that performs the additional functionality before or after calling Ivi_DefaultCheckCallbackViInt32, Ivi_DefaultCheckCallbackViInt64, or Ivi_DefaultCheckCallbackViReal64.
Coerce Callback
The IVI Engine invokes the coerce callback function when you set an attribute to a new value. The IVI Engine invokes the coerce callback after the engine invokes the check callback. The coerce callback converts the value you specify into the value to send to the instrument.
In general, two cases exist in which an instrument driver must coerce attribute values. In these cases, the instrument defines a set of discrete values for an attribute, and it is possible to map a range of values onto each member of the discrete set. For example, a DMM might accept 10.0, 100.0, or 1,000.0 as the maximum reading voltage. If a user specifies 50.0 as the maximum voltage, the correct action is to set the DMM to 100.0.
In the first case, the instrument itself coerces values in this manner. It accepts values from 1.0 to 1,000.0 and coerces them to 10.0, 100.0, or 1,000.0. For the IVI state caching mechanism to work properly, the cache value for the attribute must reflect the coerced value in the instrument. For the cached value and the value in the instrument to be the same, the instrument driver must coerce the value before sending the value to the instrument. In the example, the instrument driver must coerce 50.0 to 100.0 and send 100.0 to the instrument. The IVI Engine caches the coerced value, which in this example is 100.0.
In the second case, the instrument does not coerce values. Instead, it accepts only the values in the discrete set. Although you can write the instrument driver so that it accepts only the discrete values, doing so is not feasible if you want the driver to comply with a standard class definition. In the previous example, the DMM in question might accept only 10.0, 100.0, or 1,000.0. However, another DMM might accept 10.0, 50.0, 100.0, 500.0, or 1,000.0. A third might accept a continuous range of values and coerce them to still another discrete set. Standard class definitions handle such cases by allowing users to specify a continuous set of values and requiring the instrument drivers to coerce them.
![]() |
Note A third case exists that seems to require value coercion but does not. In this case, the instrument expresses a setting in units that are different from the units a class definition uses. For example, oscilloscopes typically implement the VERTICAL_RANGE attribute in terms of volts-per-division; whereas, the oscilloscope class definition specifies values that represent the overall voltage range. The driver must translate between volts-per-division and overall voltage range before sending a new value to the instrument and after receiving the current setting from the instrument. Thus, it is best to do the translations in the read and write callbacks for the attribute. |
You can implement coercion through a coerced range table. Specify a coerced range table when you call Ivi_AddAttributeViInt32, Ivi_AddAttributeViInt64, or Ivi_AddAttributeViReal64. When you do so, the IVI Engine automatically installs a default coerce callback that uses the range table. It also installs the default coerce callback when you install a range table callback for the attribute, and the attribute does not already have a coerce callback.
You can invoke the default coerce callback from your own callback. To add functionality to one of the default coerce callbacks, install a coerce callback that performs the additional functionality before or after calling Ivi_DefaultCoerceCallbackViInt32, Ivi_DefaultCoerceCallbackViInt64, or Ivi_DefaultCoerceCallbackViReal64.
The IVI Engine also supplies a default coerce callback for ViBoolean attributes. The callback coerces all non zero values to VI_TRUE (1). The IVI Engine always installs the callback when you create a ViBoolean attribute.
Generally, ViString, ViSession, and ViAddr attributes do not have coerce callbacks. When you add one of these attribute data types, its coerce callback is VI_NULL.
Compare Callback
The IVI Engine invokes the compare callback function for an attribute only when comparing cache values it obtains from the instrument against new values to which you attempt to set the attribute. The IVI Engine invokes the compare callback after it invokes the check callback and the coerce callback. If the compare callback determines that the two values are equal, the IVI Engine does not call the write callback for the attribute. If the attribute does not have a compare callback, the IVI Engine makes the comparison based on strict equality.
When you create a ViReal64 attribute, the IVI Engine automatically installs a default compare callback. The default compare callback uses the degree of precision you pass to Ivi_AddAttributeViReal64. The IVI Engine installs the default compare callback for ViReal64 attributes rather than comparing based on strict equality because of differences between computer and instrument floating-point representations.
Typically, compare callbacks are necessary only for ViReal64 attributes.
Range Table Callback
Use the range table callback to dynamically determine which static range table you want to use for an attribute. You also can use the range table callback to modify the contents of a dynamic range table that you create with Ivi_RangeTableNew.
The IVI Engine invokes the range table callback only when Ivi_GetAttrRangeTable executes. If the attribute has a range table callback, Ivi_GetAttrRangeTable returns the range table pointer that the callback returns. Otherwise, it returns the range table pointer you associate with the attribute when you call Ivi_AddAttributeViInt32, Ivi_AddAttributeViInt64, Ivi_AddAttributeViReal64, or Ivi_SetStoredRangeTablePtr.
The IVI Engine calls Ivi_GetAttrRangeTable from the default check and coerces callbacks for ViInt32, ViInt64, and ViReal64 attributes. If you install your own check or coerce callback function, you can call Ivi_GetAttrRangeTable from your callback.