Welcome to Nimbus Driver Studio

Nimbus Driver Studio is a complete set of development tools for building fully compliant, commercial-quality IVI.NET, IVI-COM, and IVI-C instrument drivers. The Nimbus suite includes code generation tools, auto-documenting facilities, driver testing utilities, built-in installer generation and a host of other productivity tools. Nimbus fully integrates with Visual Studio to provide end-to-end tool support during driver implementation, with features such as automatic code round-tripping.

In This Section

Nimbus Feature Highlights

Release Notes

Converting Driver Projects From Earlier Versions of Nimbus

Copyright

Getting Assistance

IVI Backgrounder

Understanding the Nimbus User Interface

Understanding IVI-C Driver Development Options

Developing an IVI.NET Driver

Developing an IVI-COM Driver

Developing an IVI-C Driver

Adding Support for Multiple Instrument Models

Creating a Driver Help File

Creating a Driver Installer

Copyright 2001-2022 Pacific MindWorks. All rights reserved.

Send comments on this topic to support@pacificmindworks.com


Nimbus Feature Highlights

Nimbus Driver Studio provides an extensive array of features for creating, documenting, deploying, and maintaining fully compliant IVI.NET, IVI-COM and IVI-C instrument drivers. This topic highlights some of the more compelling aspects of Nimbus.

Visual Studio Integration

Nimbus provides deep and seamless integration with Visual Studio, so that all phases of driver development can be accomplished without ever leaving the Visual Studio IDE.

IVI Compliance

Nimbus produces drivers that fully comply with all IVI Foundation specifications. Included in the Nimbus Class Library are pre-built implementations of all of the required IVI interfaces.

Automatic Code Round-tripping

Arguably one of the most powerful features of the Nimbus product is its ability to round-trip driver implementation code. This means that decisions made about the layout of methods, interfaces, and other driver characteristics can be completely changed at any point in the development process. Nimbus automatically manipulates the C# code to effect the desired changes.

IVI.NET, IVI-COM, and IVI-C Driver Development

Nimbus is the only IVI driver tool that allows development of all three kinds of IVI drivers -- IVI.NET, IVI-COM and IVI-C drivers. Customers who previously struggled with the choice of whether to standardize on IVI.NET or IVI-COM or IVI-C technology canuse Nimbus to supply them all to their customers.

Versatile State Caching and Range Checking Support

Nimbus provides powerful and flexible state caching and range checking features for IVI driver developers. Rather than requiring tedious coding from the developer, these features can be configured completely through intuitive dialogs and Code Wizards.

Help File Generation

Nimbus generates a complete help file that documents all methods, properties, interfaces, and enumerations in a driver. And, it generates both a classic standalone .chm file and a set of files for integrating with the Microsoft Help Viewer. Customizable help templates allow the look, feel, and content of the driver help files to be completely controlled by the driver developer.

Installer Generation

One of the most tedious tasks in driver development is creating and maintaining an IVI driver installer. Doing so requires intimate knowledge of not only Windows Installer technology, but also of the pages of specialized installation requirements imposed by the IVI specifications. Nimbus automatically creates a fully compliant IVI driver installer -- complete with a visual designer that allows for customizations, such as deploying sample programs.

Automated Unit Test Generation

Nimbus automatically generates a complete C# unit test that exercises every method and property in the driver. The unit test integrates directly with the Visual Studio unit testing framework so that the test-debug-edit cycle can be performed seamlessly. Nimbus roundtripping automatically updates the unit tests as methods and properties are added, removed, or renamed.

Multi-Instrument Model Support

Instrument vendors commonly develop products in families of related instrument models which support very similar functionality. Rather than requiring you to develop, test, and maintain separate IVI drivers for each instrument model, Nimbus supplies a powerful array of features to facilitate multi-model driver development with no additional coding.


Release Notes

This topic presents a summary of requirements, key features, and updates, as well as some known issues to be addressed in a future update.

Important note Important

Nimbus no longer uses serial numbers to validate usage of the product. Instead, you will be asked for your login credentials to validate your entitlement to use the product. Please have your Pacific MindWorks account username and password handy when using Nimbus on a machine for the first time.

Nimbus 6 Releases

  • 6.0.6

  • 6.0.5

  • 6.0.4

  • 6.0.3

  • 6.0.2

  • 6.0.1

  • 6.0.0

Earlier Releases

  • Nimbus 5 Release Notes

Nimbus Prerequisites

  • Windows 7 or newer (32-bit or 64-bit)

  • Microsoft .NET Framework 4.8 (or newer)

  • Microsoft .NET Framework 3.5

    Tip Tip

    The Microsoft .NET Framework 3.5 is not installed by default on Windows 10 systems. It can be installed via Control Panel -> Programs -> Programs and Features -> Turn Windows features on or off. There, check the box labeled .NET Framework 3.5 (includes .NET 2.0 and 3.0).

  • Microsoft .NET Core SDK 2.2 (or newer)

  • Visual Studio 2017, 2019, or 2022

    Any of Community, Professional, or Enterprise editions are supported.

    Important note Important

    It is highly recommended that the latest version of Visual Studio 2017 and/or 2019 are installed when running Nimbus. Microsoft frequently makes important updates within major Visual Studio releases and Nimbus is updated in turn to track these changes. Running earlier versions of Visual Studio can lead to faulty behavior and/or performance issues.

    Note Note

    The exact set of Visual Studio components and workloads required is presented in the Visual Studio Extension Manager and automatically installed when the Nimbus package is installed.

    For Visual Studio 2017, version 15.9 or later is required.

    For Visual Studio 2019, version 16.10 or later is required.

    For Visual Studio 2022, any currently released version is supported.

  • IVI Shared Componenents 3.0.0 (or newer)

  • IVI.NET Shared Componenents 2.0.0 (or newer)

Known Issues

  • Before converting a driver from an earlier Nimbus version, the .vs folder or the .suo file should be deleted. This is due to .suo file corruption issues with Visual Studio.

    Pacific MindWorks is working with the Visual Studio team to find a resolution to this issue.

  • When creating a new driver project, the option to Create a directory for solution must always be chosen. Attempting to manage a Nimbus driver solution with the .sln file inside the driver project folder (or any other Nimbus project folder) could lead to unpredictable results.

    In Visual Studio 2019 and greater, the option is expressed as Place solution and project in the same directory. This option should not be checked.

  • When a driver solution is opened, there are a variety of asynchronous operations that Visual Studio performs. One important operation is NuGet restore, which populates the project with all of the critical binaries and targets it needs to operate. If Driver Designer operations are attempted before the NuGet restore completes, then strange errors such as Undefined type Int32 could result.

    In practice, this is rarely an issue, as the NuGet restore typically completes within the first few seconds of opening a solution. You can see the status of the NuGet restore in the Output Window.

  • IVI-COM and IVI-C help and setup projects show "broken reference" annotations (yellow warning triangles) on the icon for their project references to the driver project. These references are required for these projects to operate, and the references are indeed intact, but MSBuild currently has a bug that manifests when any custom SDK-style project references a native (C++) project. The same driver project references appear normal in IVI.NET help and setup projects.

    These warning annotations are benign and can safely be ignored. Pacific MindWorks is working with Microsoft on mitigations for this MSBuild issue.

  • Merging of IVI.NET repeated capabilities is not currently supported in this release. All other aspects of IVI.NET repeated capabilities are fully implemented in this release.

Nimbus 6.0.6

Issues fixed in Nimbus 6.0.6

  • Implement multiple techniques for improving the performance of designer operations.

Nimbus 6.0.5

Issues fixed in Nimbus 6.0.5

  • Fix a crash that could occur when roundtripping C# unit tests for repeated capability properties when ranges were used to specify repeated capability instance names.

  • Remove usage of the std::binary_function from NRT since it is deprecated in newer versions of C++.

  • Update the NRT DriverSession::Initialize method so that it is not templatized and can thus be made virtual.

Nimbus 6.0.4

Issues fixed in Nimbus 6.0.4

  • Fix a crash that could occur in the Driver Designer item editors for IVI-COM drivers.

  • Ensure Driver Designer item editor text boxes are properly enabled/disabled and made read-only based on selection and other driver state.

  • Display the correct version number in the Visual Studio About Dialog.

Nimbus 6.0.3

Issues fixed in Nimbus 6.0.3

  • Ensure the user name text box is enabled in the user login dialog.

Nimbus 6.0.2

Issues fixed in Nimbus 6.0.2

  • Fix a deadlock when editing IVI-COM drivers with IVI-C wrappers in Visual Studio 17.2 or higher.

  • Update textbox styling to accommodate changes in Visual Studio 17.2 which would sometimes make the text unreadable in disabled text boxes.

Nimbus 6.0.1

Issues fixed in Nimbus 6.0.1

  • Fix a bug in the 4.2.5707 converter where the AssemblyInfo.cs attributes would not always get migrated to MSBuild project properties in VS2022.

  • Fix code navigation in C++ where some drivers might not navigate precisely in the embedded editors or the navigation commands.

  • Update prerequisites to include web extensions needed for hosting the HTML editor.

  • Fix some file locations in the IVI.NET and IVI-C help file templates.

  • Fix a WiX condition injected by the 5.2.0 setup project converter that produced build errors in converted setup projects.

  • Fix a bug whereby the repcap collection interface base interfaces were not always being handled properly resulting in some repcap add/remove operations failing.

Nimbus 6.0.0

What's new in Nimbus 6.0.0

  • Nimbus 6 brings support for 64-bit Visual Studio 2022.

  • IVI.NET drivers are built on the new IVI.NET Configuration Server, instead of the IVI-COM Configuration Server. This has several advantages:

    • The IVI.NET driver avoids having to use native code via COM interop.

    • Initialization of the IVI.NET driver is much faster, as the well-known performance issues with loading the Config Store via COM are avoided entirely.

    • The IVI-COM Configuration Server has a memory leak when used in certain scenarios and this is avoided entirely by use of the IVI.NET Configuration Server.

    Important note Important

    Because the IVI.NET Configuration Server first shipped with IVI.NET Shared Components 2.0.0, all IVI.NET drivers built with Nimbus 6 or greater will require IVI.NET Shared Components 2.0.0 or greater to be installed on the end user system for the driver to operate.

Issues fixed in Nimbus 6.0.0

  • Don't include the Windows SDK as a prerequisite. This requires specifying a particular version of the SDK, which would force users to potentially have multiple SDK versions on their machines.

  • Update the C++ project templates to use the latest version of the Windows SDK when building.

  • Fix a bug where conversions warnings would not be displayed.

  • Sort IVI.NET type member tree nodes by label in the Driver Designer, just as IVI-COM and IVI-C.

  • Fix a bug where moving IVI.NET repcaps would inappropriately rename the repcap and repcap collection interfaces.

    In some scenarios where the repcap or repcap collection interfaces were children of interfaces being moved, the IVI.NET editor would rename the repcap and repcap collection interfaces (and their children) such that the new names included parent interface names. Repcap interface names and repcap collection interface names should NOT include parent interface names, irrespective of where they are in the hierarchy.

  • Don't rename IVI.NET repcap collection interfaces when a parent reference property is renamed.

    The repcap interface and repcap collection interface names should be kept in sync with the repcap name. The repcap and repcap collection interfaces are only renamed when the repcap itself is renamed. This is also consistent with how IVI-COM already works.

  • Fix a bug in the IVI-COM 2.1.10 converter where help custom fields would not get migrated property and an invalid XML element would be created.

  • Fix a bug in the Driver Designer where output array parameters in the IVI.NET method would not produce array parameters at all in the IVI-C function.

  • Fix a bug in IVI.NET drivers with quoted values in simulation data.

  • Fix an issue in the IVI-COM driver converter where we needed to adjust the name of parent repcaps in instrument commands.

  • Fix a bug whereby properties were getting set in a platform/configuration-dependent manner when they should be set independent of configuration.

  • Allow editing of simulation, range-check, and state-caching data for class-compliant properties.

  • Fix a bug in the IVI-C Enums.h generator where excluded IVI-C enum members were still getting generated in the file.

  • Fix a bug where IVI-C enum member commands were not editable.

  • Allow renaming of IVI-C functions when only the casing changes.

  • Fix a bad return type in for the IVI-C PULSE_MODULATION_EXTERNAL_POLARITY attribute.

  • Fix a bad return type in for the IVI-C PULSE_MODULATION_SOURCE attribute.

  • Don't create unit tests for IVI-C attribute getters and setters. This makes the size of the unit test HUGE and adds no real value.

  • Fix a small bug in the IVI.NET options page where the option for creating an IVI-C C++ console app was wired to the option to create an IVI-C wrapper.

  • Fix a bug in the IVI.NET project wizard where the wizard attempted to use the IVI-C driver project to determine the target framework version when creating the IVI-C unit test project.

  • Fix a warning in NRT.h regarding integer size.

  • Update the project template files for setup to use the English language ID (1033) in the FileSearch element that checks for the IVI and IVI.NET and VISA.NET installations.

    If the language in the search doesn't match, then the search won't match. Previously, this was "working" because the file version for the IviSharedComponent.dll (and others) always had a non-zero value for the 4th digit of the version number. Our MininumIviSharedComponentVersion would only include 3 digits. So, that min version was always strictly less than the actual file version. In such a case, MSI has a strange (though spec'd) behavior where specifying a value of "0" for the language in the FileSearch would match any language if the comparison was strictly less than. It would not match if the comparison was equal, unless the language also matched. With the release of IVI Shared Components 3, the 4th digit of the file version number is zero, so our comparison of our 3-digit minimum version needs to work in the case of an exact version match. That only works if the language also matches.

  • Update the IVI.NET driver Setup.wxs so that the driver does not appear twice in the Add References Dialog on 64-bit machines.

  • Fix "Unlink IVI-C Driver" operation in the IVI.NET driver editor.

  • Don't add an interface prefix to IVi.NET member labels on interfaces in the Driver Designer.

    Only types that implement interfaces should prefix the implemented interface member with the interface name. Interfaces only show their direct members, not members from base interfaces, so there's never any need to prefix interface member labels.

  • Fix several bugs associated with editing methods and properties on free-standing IVI-COM interfaces.

  • Fix a bug in changing the IVI-C prefix for IVI-C drivers linked to IVI.NET as well as IVI-C wrappers on IVI-COM drivers.

See Also

Other Resources

Nimbus 5 Release Notes


Nimbus 5 Release Notes

Nimbus 5 is a major new release of the product. This topic presents a summary of requirements, key features, and updates, as well as some known issues to be addressed in a future update.

Important note Important

Nimbus no longer uses serial numbers to validate usage of the product. Instead, you will be asked for your login credentials to validate your entitlement to use the product. Please have your Pacific MindWorks account username and password handy when using Nimbus 5 on a machine for the first time.

Nimbus 5 Releases

  • 5.2.0

  • 5.1.6

  • 5.1.5

  • 5.1.4

  • 5.1.3

  • 5.1.2

  • 5.1.1

  • 5.1.0

  • 5.0.4

  • 5.0.3

  • 5.0.2

  • 5.0.1

  • 5.0.0

  • Preview 5.0.0.631

  • Preview 5.0.0.628

  • Preview 5.0.0.603

  • Preview 5.0.0.549

  • Preview 5.0.0.530

  • Preview 5.0.0.520

  • Preview 5.0.0.510

Nimbus Prerequisites

  • Windows 7 or newer (32-bit or 64-bit)

  • Microsoft .NET Framework 4.7.2 (or newer)

  • Microsoft .NET Framework 3.5

    Tip Tip

    The Microsoft .NET Framework 3.5 is not installed by default on Windows 10 systems. It can be installed via Control Panel -> Programs -> Programs and Features -> Turn Windows features on or off. There, check the box labeled .NET Framework 3.5 (includes .NET 2.0 and 3.0).

  • Microsoft .NET Core SDK 2.2 (or newer)

  • Visual Studio 2017 or Visual Studio 2019

    Any of Community, Professional, or Enterprise editions are supported.

    Important note Important

    It is highly recommended that the latest version of Visual Studio 2017 and/or 2019 are installed when running Nimbus. Microsoft frequently makes important updates within major Visual Studio releases and Nimbus is updated in turn to track these changes. Running earlier versions of Visual Studio can lead to faulty behavior and/or performance issues.

    Note Note

    The exact set of Visual Studio components and workloads required is presented in the Visual Studio Extension Manager and automatically installed when the Nimbus package is installed.

  • IVI Shared Componenents 2.6.1 (or newer)

  • IVI.NET Shared Componenents 1.4.1 (or newer)

Key New Features and Updates

Visual Studio 2017 and 2019 Support

  • Nimbus now supports Visual Studio 2017 and Visual Studio 2019. Visual Studio Community, Professional, and Enterprise are all fully supported with all Nimbus features available.

  • Nimbus now supports side-by-side installation. Multiple versions of Nimbus can be installed on a per-Visual Studio basis. For example, you can install Nimbus 4.2 into Visual Studio 2015 on the same computer where you have Nimbus 5 installed into Visual Studio 2017/2019. The same computer may also have multiple Visual Studio 2017/2019 installations. Each of those can house an independent version of Nimbus.

    No additional licenses are required to use multiple versions of Nimbus on the same computer, as long as all product instances are in use by the same person.

All New WPF-Based User Interface

The Nimbus user interface has been completely re-written from scratch in WPF. This offers a host of benefits:

  • Much better integration with Visual Studio itself. More and more of Visual Studio is WPF-based, so integrators need to use the same platform in order to maintain a seamless, embedded end-user experience with their tooling.

  • Theming. Nimbus now dynamically inverts colors to match the currently select Visual Studio themes. Control colors, text, backgrounds, and icons are all tied to the selected theme and use colors native to the official Visual Studio official color palette.

  • Scaling and High-DPI Support. Nimbus controls scale with any DPI. All icons and graphics assets are vectorized, themed, scalable, and crisp at all resolutions.

  • The overall layout and spacing has been refreshed for usability. There is less dead space and better use of environment window real estate within Visual Studio itself.

Visual Studio Marketplace Distribution

Nimbus is now distributed via the Visual Studio Marketplace. This greatly simplifies acquiring and managing Nimbus installations and provides for additional features, such as prerequisite handling and automatic update notifications.

Roslyn-Based Refactoring

Roslyn is the new compiler platform from Microsoft. The Nimbus roundtripping engine has been completely re-written to use Roslyn to perform surgical code roundtripping that is much more reliable and transactional.

Another important benefit of this migration is that we have full fidelity C# language support in IVI.NET drivers. Previous versions of Nimbus would crash if any project in the solution contained any C# 5.0 (or greater) language syntax. This was a limitation that was becoming increasingly problematic, and the solution is to use the compiler itself as it has full knowledge on the syntax and semantics of code.

SDK-Style Projects

With the introduction of MSBuild 15.0 and Visual Studio 2017, Microsoft introduced the notion of a "project SDK", which is a package of binaries, tools, targets, and other assets required to build a project. Applications reference that use an SDK for their fundamental build definition are referred to as SDK-style projects. For example, projects that want to build a desktop application targeting a specific version of the .NET Framework simply declare the SDK and version required, and MSBuild handles all of the acquisition of binaries, injection of targets, and version management.

A fully functional .NET application targeting version 4.5 of the .NET Framework now only requires the following MSBuild code in the project file:

XML
Copy
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net45</TargetFramework>
  </PropertyGroup>
</Project>

Nimbus uses SDK-style projects for all .NET projects that it generates. This results in a dramatic reduction in the size and complexity of project files. Rather than explicitly referencing source files and other project file items, the project file defines file globs. These file globs allow you to use a simple, but powerful, wildcard syntax for defining the items in a project. A project file, such as the large Nimbus help project files, that would be hundreds of lines long, are often reduced to only a handful of lines.

SDK projects also greatly simplify version management of the Nimbus Build Tools. When a new project is created, or a project is converted, a global.json file is added that specifies the Nimbus Build Tools version.

Nimbus Build Tools as a NuGet Package

The Nimbus Build Tools are now provided as a NuGet package on nuget.org.

This greatly simplifies build scenarios, as there is nothing to install and NuGet implicitly supports side-by-side versioning, as well as version range specifications and a host of other features.

Online Help

Nimbus help is now provided online at docs.pacificmindworks.com/nimbus.

Online documentation allows Pacific MindWorks to provide richer, more up-to-date content quickly, without forcing users to install Nimbus upgrades themselves just to get documentation updates.

Honoring the Selected .NET Target Framework

In previous versions of Nimbus, the .NET Target Framework was always set to 2.0 for IVI.NET drivers, C# unit tests, and C# and Visual Basic console applications. Changing to a newer version required a set of manual steps on each .NET project in the solution.

Though .NET 2.0 is still officially the "recommended" .NET Target Framework for IVI.NET drivers as per the IVI Foundation specifications, this is expected to change in the near future. This is primarily due to the fact that .NET 2.0 is not installed by default on most modern operating systems. To use a .NET 2.0 driver, end users must navigate to the Control Panel and add the Windows Feature for .NET Framework 3.5 (including .NET 2.0 and 3.0). Consequently, many vendors are already targeting .NET Framework 4.0 or greater.

With this change, Nimbus now creates all of the .NET projects in a new solution according to the selection made in the Framework combo box in the New Project Dialog.

Caution note Caution

It is important to pay attention to the setting of the Framework combo box when creating new driver solutions. Visual Studio typically sets that value based on whatever value was previously selected the last time a project was created.

Though many users have long expected this behavior because it is consistent with the behavior of all other project system in Visual Studio, some users may have become accustomed to the Nimbus default behavior, which was driven by official IVI recommendations. Thus, users may inadvertently create a driver that targets a higher .NET Framework version than intended.

IVI.NET Driver Reference Capabilities

Previous versions of Nimbus required any assembly referenced by the IVI.NET driver to be loaded in the Global Assembly Cache (GAC). This placed non-trivial limitations on driver developers. With Nimbus 5, IVI.NET drivers support the full range of reference types. Drivers can reference assemblies in the GAC, assemblies on disk, project references, and even NuGet package references. Types defined in assemblies in any of these locations can now be used in the Driver Designer.

Nimbus uses the same facilities within Visual Studio to resolve the set of assemblies an IVI.NET driver references. Consequently, it is no longer necessary to explicitly add an assembly reference using the Driver Designer. Nimbus is able to automatically resolve the name of any type in any assembly referenced by the driver. See the topic Understanding Type Name Resolution in Nimbus for additional details.

Other Changes

  • Important note Important

    No additional licenses or serial numbers are required for this release of Nimbus 5. A time-limit license is automatically applied. Customers will need to acquire a new license when the time-limit license expires on 6/1/2020. Pacific MindWorks will be releasing additional details on licensing in that timeframe.

  • In previous Nimbus versions, the IVI.NET unit test method names would typically be longer than seemed necessary. For example, a method named Configure with three parameters, might have an associated unit test method that looked like the following:

    C#
    Copy
    [TestMethod]
public void Configure_Int32_String_Double()
{
  // ...
}

    This was done to avoid collisions when such methods were overloaded. Since overloading is actually fairly rare in IVI.NET drivers, this long form of the name is only used when the method is actually overloaded in that interface. Otherwise, the short name Configure is used. Nimbus automatically switches from the long form to the short form (or vice versa) as appropriate when driver methods are modified, copy/pasted, etc.

    The net result is a much cleaner and easier-to-understand set of driver unit tests.

  • The version of WiX used to create driver installers has been updated to WiX 3.11

  • Nimbus now creates driver solutions that direct their build output to a unified build folder located as a sibling to the other projects in the solution. Intermediate build output is directed to the obj sub folder, with project-specific intermediate output segregated under that folder according to project name. The key project outputs are consolidated under build\<Configuration>\<Platform>, where the <Platform> folder may not exist for Any CPU projects. Consolidating build output under a unified folder greatly simplifies management of build artifacts, installer build operations, and facilitates better incremental build behavior.

    As an example, the folder structure of an IVI.NET driver after a build would look something like the following (not all files or folders shown):

    Acme4302.sln
    Acme4302.design
    global.json
    build
    build\obj\Acme4302Driver\Debug
    build\obj\Acme4302Help\Debug
    build\obj\Acme4302Setup\Debug
    build\obj\Acme4302UnitTest\Debug
    build\obj\Acme4302CsConsoleApplication\Debug\x86
    build\obj\Acme4302IviCDriver\Debug\x86
    build\Debug\Acme.Acme4302.Fx45.dll
    build\Debug\Acme.Acme4302.Fx45.xml
    build\Debug\Acme.Acme4302Version.dll
    build\Debug\Acme.Acme4302Version.dll
    build\Debug\Acme4302UnitTest.dll
    build\Debug\Acme4302.chm
    build\Debug\Acme4302.msha
    build\Debug\Acme4302.cab
    build\Debug\x86\Acme4302CsConsoleApplication.exe
    build\Debug\x86\Acme4302-x86.msi
    build\Debug\x64\Acme4302-x64.msi

  • Nimbus now provides a single editor for modifying all of the driver's repeated capabilities. This new editor can be found on the Repeated Capabilities tab of the Driver Settings Editor editor. Previous versions of Nimbus displayed individual repeated capabilities under the Nimbus node in Solution Explorer, and a combination of gestures would take you from Solution Explorer to the Properties Window to a dialog window.

    The new Repeated Capabilities Editor makes it much easier to view and edit driver repeated capabilities.

  • Nimbus generates a global.json file as part of a new driver solution. This file must be maintained in source control alongside the .sln and .design files. It specifies the version of the Nimbus Build Tools to use to build the driver.

    Use of the global.json allows the Nimbus Build Tools version to be different than the Nimbus version used to create the driver (as specified by the <NimbusVersion> element in the .design file and in various project files). Previous versions of Nimbus always required these versions to exactly match. With Nimbus 5, certain categories of fixes and updates can be quickly introduced into the build tools without requiring a new install of Nimbus itself. And, since the Nimbus Build Tools are delivered via NuGet, there is nothing to install. Indeed, no explicit action is required on the part of the user to consume such updates. The global.json is used to opt-in (or out) of version updates.

    The global.json file even has the ability to control an entire set of drivers arranged in a folder hierarchy on disk.

  • Because Nimbus now installs as a VSIX package on a per-Visual Studio basis, it can no longer use the <ProgramFiles> folder to deploy the instrument class files (.iviproj) or the help template files. Instead, the instrument class files are and custom help templates are now deployed to <ProgramData>\Pacific MindWorks\Nimbus\<version>.

    Note Note

    In previous versions of Nimbus, the pre-built help templates were installed in the same folder as the custom help templates. Now, the <ProgramData> folder houses only custom help templates that the user defines. The pre-built templates installed with Nimbus must necessarily reside in the per-Visual Studio Extensions folder.

    To locate the pre-built help templates for purposes of creating custom help templates, navigate to the folowing folder:

    <ProgramFiles32>\Microsoft Visual Studio\2019\Enterprise\Common7\IDE\Extensions

    There you will see a series of seemingly random folder names. Search for "MindWork.Nimbus.Core". This will take you to the Extensions folder that houses the Nimbus Visual Studio extension. The HelpTemplates folder is located in this folder.

  • Nimbus driver help projects no longer support MSHelp 2. This help format targets Visual Studio 2005 and Visual Studio 2008, neither of which are supported any longer by Microsoft.

  • Nimbus driver help projects no longer support MS Help Viewer 1.0. This version of the Help Viewer only services Visual Studio 2010 prior to Service Pack 1. All versions of the Help Viewer from Visual Studio 2010 with Service Pack 1 to Visual Studio 2019 are fully supported. Only Visual Studio 2010 users without Service Pack 1 installing a driver would be affected, and the mitigation would be to simply apply the Service Pack 1 upgrade.

  • The driver help template that ships with Nimbus has been renamed from "VS2005" to "Classic".

  • The Help Viewer content manifest file (.msha) was previously required by the Help Viewer to be named HelpContentSetup.msha. That restriction no longer exists, so Nimbus names this file <driverName>.msha.

  • Previous versions of Nimbus used C++/CLI unit test projects. Nimbus 5 deprecates this style of unit test projects in favor of the newer and more robust native C++ unit test framework in Visual Studio. Nimbus IVI-C drivers have always used the native unit testing framework, and IVI-COM unit tests now use this same framework.

    Importantly, existing C++/CLI unit test projects remain fully supported. They will be roundtripped in an existing driver solution just as with previous versions of Nimbus. However, the New Project Wizard always creates native C++ unit tests for IVI-COM drivers. There is no longer a facility for creating C++/CLI unit tests.

    Pacific MindWorks has not established a timeline for obsolescence of C++/CLI unit tests, but all customers are encouraged to migrate to native C++ unit tests.

Known Issues

  • Before converting a driver from an earlier Nimbus version, the .vs folder or the .suo file should be deleted. This is due to .suo file corruption issues with Visual Studio.

    Pacific MindWorks is working with the Visual Studio team to find a resolution to this issue.

  • When creating a new driver project, the option to Create a directory for solution must always be chosen. Attempting to manage a Nimbus driver solution with the .sln file inside the driver project folder (or any other Nimbus project folder) could lead to unpredictable results.

    In Visual Studio 2019, the option is expressed as Place solution and project in the same directory. This option should not be checked.

  • When a driver solution is opened, there are a variety of asynchronous operations that Visual Studio performs. One important operation is NuGet restore, which populates the project with all of the critical binaries and targets it needs to operate. If Driver Designer operations are attempted before the NuGet restore completes, then strange errors such as Undefined type Int32 could result.

    In practice, this is rarely an issue, as the NuGet restore typically completes within the first few seconds of opening a solution. You can see the status of the NuGet restore in the Output Window.

  • For IVI.NET drivers that used a custom ConfigStore.xml file to customize the driver's IVI Configuration Store registration process, the only change required is that the file must be included in the project as a <Content> item type. Previous versions of Nimbus would also process the custom ConfigStore.xml file if it was included as a <None> item type.

  • The FxCop-based analysis rules have been removed. Microsoft's new Roslyn-based compiler platform offers a far superior technology for creating code analyzers, including the ability for customers to author analyzers that enforce domain-specific rules on their own drivers. Pacific MindWorks will be migrating to Roslyn-based analyzers in a future release.

  • IVI-COM and IVI-C help and setup projects show "broken reference" annotations (yellow warning triangles) on the icon for their project references to the driver project. These references are required for these projects to operate, and the references are indeed intact, but MSBuild currently has a bug that manifests when any custom SDK-style project references a native (C++) project. The same driver project references appear normal in IVI.NET help and setup projects.

    These warning annotations are benign and can safely be ignored. Pacific MindWorks is working with Microsoft on mitigations for this MSBuild issue.

  • For a fresh machine that has never used Nimbus 5, the initial project creation requires internet access. The Nimbus build system resides in a NuGet package that is hosted on nuget.org. When a Nimbus project is created, the project is typically restored from the locally cached copy of the Nimbus Build Tools. However, in the unlikely event that an offline user has installed the Nimbus Driver Studio Visual Studio extensions, but has never created any project of that version of Nimbus and then attempts the first project creation while offline, the project creation will fail with a General Exception (E_FAIL).

    Nimbus includes special facilities for handling this exact scenario. However, the NuGet client installed by Visual Studio does not function properly in this scenario. Pacific MindWorks is working with Microsoft on possible mitigations.

    There are two very simple workarounds for this issue:

    1. Always ensure a project has been created on any machine that will use Nimbus offline.

    2. Download the Nimbus Build Tools NuGet package (.nupkg) to the local system before going offline.

  • Merging of IVI.NET repeated capabilities is not currently supported in this release. All other aspects of IVI.NET repeated capabilities are fully implemented in this release.

Nimbus 5.2.0

What's new in Nimbus 5.2.0

  • Nimbus now includes embedded editors for directly editing implementation code as well as test code -- all from within the driver designer. New Code item editors and Test item editors host the native Visual Studio core editor and functions just as the standard non-embedded editors. All edits are automatically kept in sync with the underlying project source code.

    Editor for Implementation
    Editor for Unit Test
    Code Editor-Unit Test

  • Nimbus now implements a Visual Studio CodeLens provider that surfaces navigation commands directly within the Visual Studio code editor. The current release allows direct navigation to the Driver Designer, implementation code, and unit test code.

    Nimbus CodeLens Provider
    Code Lens 1
    Nimbus CodeLens Navigation Commands
    Code Lens 2
    Important note Important

    The Nimbus CodeLens feature is only available in Visual Studio 2019. The Microsoft infrastructure for CodeLens for Visual Studio 2017 has a major design flaw that prevents extensions from supplying CodeLens customizations.

    Note Note

    The Nimbus CodeLens provider can be disabled separately for C# and C++ code files in the Tools -> Options settings under Nimbus Driver Studio.

  • In addition to navigation using the CodeLens provider, Nimbus provides the same set of navigation commands directly from the code editor context menu. Simply right-click within a method implementation, a header file, a unit test method, or even from within an IDL file.

    Context Menu Navigation from a Driver Method
    Code Window Navigation 1
    Context Menu Navigation from a Unit Test
    Code Window Navigation 2

  • The MSBuild Imports tree is now displayed for Nimbus help and setup projects when the Show All Files toggle button is enabled in Solution Explorer. The Imports tree is very useful in understanding the detailed structure of a project's build settings.

    Imports Tree

Issues fixed in Nimbus 5.2.0

  • Navigation from the Driver Designer to C++ code elements properly centers the desired code in the code editor. The name of the code element is also highlight for quick identification.

  • Fix a build error that would occur in IVI.NET drivers when using repeated capability ranges.

  • The .design file is no longer shown unless Show All Files is selected.

  • The Models Selector is no longer shown by default, since most operations are not model-specific.

  • Fix a bug where the previously selected item editor was not being restored after closing and then re-opening the driver designer.

  • Fix a null reference exception that could occur in IVI.NET drivers in some circumstances when adding members directly to an interface instead of to the hierarchy.

  • Don't throw an exception when marking a second instrument family as not being supported by a particular IVI.NET type member.

Nimbus 5.1.6

Issues fixed in Nimbus 5.1.6

  • Update licensing infrastructure for 2021.

Nimbus 5.1.5

Issues fixed in Nimbus 5.1.5

  • Fix a bug in IVI-COM drivers where the DriverSetup string could get wiped out when initializing with a logical name.

  • Ensure that IVI.NET drivers update properly when the driver version is changed.

Nimbus 5.1.4

Issues fixed in Nimbus 5.1.4

  • Implement a workaround for a breaking change in the Roslyn parser introduced with Roslyn 3.7.0 and Visual Studio 16.7.X.

  • Prevent invalid repeated capabilities from being added at any level beneath a repeated capability collection interface.

  • Add virtual destructors to NRT DriverSession and IoSession to avoid potential memory leaks.

  • Fix a null reference exception that would occur when using Navigate to All without a driver project document being active.

  • Fix a bug in the setup designer whereby assemblies added to the GAC would not always include the correct attributes and would not always be in their own Component element.

  • Fix a bug in NRT where all-numeric repcap identifiers were not being accepted.

  • Update policy files when the driver version changes.

  • Update the IVI-COM setup project appropriately when an instrument class is added or removed.

  • Update the IVI-COM setup project appropriately when a class, interface, or enum is added, removed, or renamed.

Nimbus 5.1.3

Issues fixed in Nimbus 5.1.3

  • Fix a bug in the setup project properties where the DistributeDriverSource property would be persisted with the wrong casing.

  • Fix a bug where the Nimbus node would not appear if all Nimbus projects were placed beneath a solution folder.

  • Remove an unnecessary .bak file from the IVI-COM help template.

  • Fix a crash that could occur when switching IVI-COM help projects to the "Classic" help template.

Nimbus 5.1.2

Issues fixed in Nimbus 5.1.2

  • Add more project type tags to the New Project Dialog to improve search within that dialog.

  • Don't thrown an exception when creating an IVI-COM driver if no IVI-C prefix is specified and no IVI-C wrapper is desired.

  • Fix driver designer navigation from IVI-C to IVI.NET when repeated capabilities are involved.

  • Fix a deadlock in VS2017 when converting certain versions of IVI.NET drivers.

  • Workaround an issue with Visual Studio project loading in VS2017 project loading where C# projects would not load properly immediately after creating an IVI-COM solution.

  • Enable correct source control support when using TFVC source control.

Nimbus 5.1.1

Issues fixed in Nimbus 5.1.1

  • Fix a bug in the IVI-COM setup project targets where interop assembly policy files would not always get included after conversion.

  • Automatically show scroll bars in the settings editor if the visible area does not show all of the controls.

  • Generate a unique Id for IVI.NET enum members when copy/pasting.

  • Refresh the driver designer when an exception is pasted.

  • Fix exceptions that are thrown when creating IVI.NET driver solutions with setup projects included.

  • Generate unit tests for IVI.NET classes (and other types) that are pasted.

  • Fix a bug where copy/pasting an IVI.NET property immediately after creating it would not always create the associated IVI-C attribute.

  • Don't produce a build error in the help and setup projects if a driver project references another driver project, such as IVI.NET wrapping IVI-C.

  • Add mergemod.cub to the build tools NuGet package to enable building merge modules.

  • Fix a bug in the user login dialog where the dialog could be shown with a white title bar and reduced visibility of error messages. This fix also addresses the issue with the dialog not being closeable from the Cancel button or Close button.

  • Fix a bug in the Nimbus converter where IVI-COM help projects templates were not getting updated with all IVI-C help template files requierd to build in some scenarios.

  • Fix a bug where the prefix.nimbus.cpp file would not always be up-to-date immediately after changing an IVI-COM property type.

Nimbus 5.1.0

What's new in Nimbus 5.1.0

  • The licensing system used by Nimbus is completely new. Nimbus licensing now relies upon user credentials to validate a license rather than serial numbers tied to specific machines. Serial numbers are no longer used at all starting with Nimbus 5.1. This model closely mimics the licensing and validation scheme used by Visual Studio itself, and Pacific MindWorks consulted with the Visual Studio team to align our methodology with that used by Visual Studio to ensure a frictionless experience for our users.

    When using Nimbus for the first time on a machine, you will be prompted for the email and password associated with your Pacific MindWorks online account. Our secure server will validate your credentials and license entitlements automatically. Typically, this will be done only once for a particular machine.

    As a consequence of this new user-based licensing mechanism, there is no "activate" or "deactivate" functionality, as that feature was linked to the use of serial numbers. Users can simply log on to their account on a different machine to enable usage of Nimbus on that machine for that user. As long as it is the same user working with Nimbus, usage across machines is allowed.

  • Nimbus now provides the ability to automatically generate IVI-C getter and setter functions for each IVI-C driver attribute. These functions are automatically implemented by Nimbus and updated as the definition of the associated IVI-C attribute changes.

    IVI-C getter and setter functions greatly simplify usage of IVI-C drivers relative to the traditional technique of using the attribute accessors, such as GetAttributeViReal64.

    See the topic Adding Attribute Getter and Setter Functions for details.

  • Nimbus now supports IVI-C callback functions as defined in the IVI specifications.

    See the topic Adding Callback Functions for additional details.

    Important note Important

    For drivers that use IVI-C callback functions, the driver help template must be updated to the latest Classic help template that ships with Nimbus. The updated help templates include the required template files for generating help content for IVI-C callback functions.

  • Nimbus now generates the IVI-C driver header file (<prefix>.h) based on a new Nimbus text template (.ntt) file. This provides a simple and flexible mechanism for customizing the contents of the IVI-C driver header. For example, additional include files or custom macro definitions can be added to the driver header file without disrupting any of the standard auto-generated code Nimbus produces.

    See the topic Customizing the Driver Header File for additional details.

  • IVI-COM help templates that include an IVI-C wrapper now use template files from the IVI-C template for portions of the driver help file. This eliminates a large amount of duplication, as separate sets of IVI-C content templates prevously needed to be maintained for IVI-COM and IVI-C even though the content (and, hence, the desired customizations) would necessarily be the same.

    The following folders within the IVI-C template are used by the IVI-COM help template:

    • IviCAttribute

    • IviCBranch

    • IviCCallbackFunction

    • IviCErrorsWarnings

    • IviCFunction

    • IviCLibrary

  • The Driver Designer now includes a search box for searching and filtering items in the design. You can quickly navigate to the search box by typing CTRL+E.

    See the topic Using the Nimbus Driver Designer for additional details.

  • Nimbus now integrates directly with the native Visual Studio "Go To All" feature. By typing CTRL+, or CTRL+t, the Visual Studio "Go To All" dialog appears. In addition to locating standard Visual Studio files, classes, and other items, you can now navigate directly to a driver method, property, enum, or other item.

    See the topic Using the Nimbus Driver Designer for additional details.

  • When adding enums, the enum and its members can be defined all at once. Similarly, multiple enum members can be added all at once to an existing enum.

    See the topic Adding an Enumeration for details.

  • Enums can be created inline when editing property types, parameter types, and return value types.

    See the topic Defining New Data Types Inline for details.

  • Enum members can now be added from the enum member context menu, instead of only from the parent enum context menu.

  • The Driver Designer now allows the numeric values for enum members to be entered in hexadecimal format. It also allows displaying members in either hexadecimal or decimal format, independently of how the values are entered.

  • The tree view control used throughout Nimbus previously only supported single selection. This release of Nimbus includes a completely re-written tree control with expanded capabilities, such as search, filtering, and, crucially, multi-selection.

  • The help project properties page and Tools -> Options pages now include a Browse button for locating a certificate for signing Help Viewer content.

  • Double-clicking an item in the Driver Designer now navigates to the definition or declaration of the item.

  • Keyboard navigation within the Driver Designer has been improved to facilitate more efficient editing of driver designs.

    See the section Keyboard Navigation for details.

  • Nimbus now validates that the minimum IVI and IVI.NET Shared Components are installed.

  • The required Introduction.rtf is now generated and integrated with newly created setup projects.

  • Renaming of IVI.NET drivers is now supported.

  • When a driver solution is upgraded, the Nimbus converter automatically updates the global.json to refer to the appropriate version of the Nimbus Build Tools NuGet package.

  • Scrolling through tree nodes in the Driver Designer is notably faster.

Issues fixed in Nimbus 5.1.0

  • Fix IntelliSense in the embedded HTML help editor in Visual Studio 2019.

  • Sort overloaded IVI.NET method nodes with lower-parameter-count methods first.

  • Rename IVI-C repcap identifier parameters when a repcap is renamed.

  • Create IVI-C repcap identifier parameters according to the convention <repcapName>Name.

  • Auto-correct IVI-C parameter label editing to ensure Pascal casing rather than reporting an error.

  • Don't throw an exception in the IVI-C options editor if IVI-C is not enabled on an IVI-COM or IVI-NET driver project.

  • Sort enum members by value in the Driver Designer, the header file (for IVI-C), and the generated help content.

  • Don't throw an exception when renaming an IVI-C attribute to an attribute name that already exists.

  • Update the IVI-COM and IVI-C parameter info panels when a new parameter is added.

  • Don't show delete and rename commands for IVI-C container nodes in the Driver Designer.

  • Newly created drivers can now be re-opened without having to delete the .vs folder.

  • Sign IVI.NET drivers with a strong name by default.

  • Refresh Driver Designer tree node labels when an enum is renamed.

  • Allow IVI-C-only enum members to be added to enums in an IVI-COM driver with an IVI-C wrapper.

  • Remove #pragma once from .cpp files in IVI-COM and IVI-C drivers.

  • Change casing of include files in IVI-COM and IVI-C drivers to match actual casing of file on disk.

  • Fix bug in Nrt.h where some statically declared local variables incorrectly established the value for all subsequent calls.

  • Show the driver "Source" folder in the 64-bit hierarchy within the setup designer.

  • Fix issue where property pages windows persisted via the .suo file would sometimes display an error when initially opened.

  • Qualify the setup editor document window title with "IVI.NET" or "IVI-C" for IVI.NET drivers with a linked IVI-C driver.

  • Enable adding a linked IVI-C driver to an IVI.NET driver after initial creation of the solution.

  • Initialize linked IVI-C driver in new project wizard with IVI.NET or IVI-COM instrument class.

  • Don't throw an exception when changing an indexer type.

  • Allow changing the access (read-only, write-only, read-write) of indexers.

  • Create linked IVI-C attributes when pasting IVI.NET and IVI-COM properties.

Nimbus 5.0.4

Issues fixed in Nimbus 5.0.4

  • Fixed project converter deadlock.

Nimbus 5.0.3

Issues fixed in Nimbus 5.0.3

  • Extended time limit for licensing to 6/1/2020.

  • Fixed bug where duplicate IVI.NET assemby references could get added to a project leading to methods and properties with unresolvable types.

  • Updated assembly version for IVI-defined assemblies to 1.4.0.0.

Nimbus 5.0.3

Issues fixed in Nimbus 5.0.3

  • Extended time limit for licensing to 6/2/2020.

  • Fixed bug where duplicate IVI.NET assemby references could get added to a project leading to methods and properties with unresolvable types.

  • Updated assembly version for IVI-defined assemblies to 1.4.0.0.

Nimbus 5.0.2

Issues fixed in Nimbus 5.0.2

  • Use a 3-digit version number for the VSIX version in public releases.

  • Fix some bugs in IVI-C enum member editing.

  • Don't throw an exception when a help project is added to an existing driver..

  • Fix a broken link on the IVI-C driver help page for "inherent capabilities"..

  • Fix some minor spacing issues in the standardized help summaries.

  • Fix a broken link to the IVI Shared Components page on the IVI Foundation web site.

  • Don't allow collection-style repcaps in the "Add Repeated Capability" dialog in IVI-C-only drivers.

  • Change the help summary of IVI-C session parameters so that they use the actual IVI-C prefix in the name of the init and InitWithOptions functions.

  • Don't throw an exception when renaming IVI.NET enums from the tree view.

  • Don't throw an exception when re-naming an IVI.NET free-standing interface with a unit test project is in the solution.

  • Don't show "IVI-C: None" in the info panel when there is no IVI-C driver or wrapper linked to the IVI.NET and IVI-COM driver.

  • Don't throw an exception if a struct is deleted and there is no unit test for it.

  • Don't generate unit tests for structs.

  • Don't show a warning for incompatible IVI-C types when adding an IVI.NET method if there is no linked IVI-C driver.

  • Fix bug in IVI.NET paste where some operations would leave the source and target members sharing the same implementation data.

  • Show IVI.NET parameters as grayed out if the parent method has a read-only signature.

  • Introduce a text box style for instrument commands and responses so that they are more legible when an error is shown.

  • Update the driver help page on building source to say that .NET 4.7.2 is installed.

  • Fix a bug in the help editor focus handling that would cause the wrong tree node content to get updated on edit.

  • Make help content validation tasks display interface name instead of class name.

  • Make IVI.NET "Instrument Command Reference" page use interface name and not class name.

  • Fix a bug whereby changing the help editor tab does not always preserve the content entered in the previous tab.

  • Ensure that at least one help editor tab is selected when changing selection in the Driver Designer tree view.

Nimbus 5.0.1

Issues fixed in Nimbus 5.0.1

  • Don't throw an exception when adding parameters that are arrays or pointers of generic types.

  • Don't throw exceptions when adding IVI.NET driver constructors.

  • Allow constructors to be deleted.

  • Refresh the Driver Designer when IVI.NET constructors are deleted.

  • Refresh IVI.NET method and parameter labels in the Driver Designer when a generic parameter is renamed.

  • Rename IVI.NET unit test file and class when a generic type parameter is renamed.

  • Refresh Driver Designer class, exception, interface, and struct container nodes when a type is added or removed.

  • Don't allow circular base interface references in IVI.NET Driver Designer.

  • Don't throw an exception when adding a base interface after a previous add base interface operation was cancelled.

  • Don't throw an exception when adding a base interface to an IVI.NET struct.

  • Remove the base types node when the last base interface of a type is removed.

  • Don't throw an exception when a generic base interface was removed and then re-added to another generic interface.

  • Don't throw an exception when adding unit tests for new base interface methods that are overloaded.

  • Show expansion arrow for indexers in the Driver Designer.

  • Sort IVI.NET interface reference property child nodes using the same logic as other type member containers (e.g. the Hierarchy node).

  • Don't allow copying inherent capabilities in the Driver Designer.

  • Don't allow duplicate repcap management methods and properties to be pasted.

Nimbus 5.0.0

Issues fixed in Nimbus 5.0.0

  • Extended time-limit license to expire on 2/1/2020.

  • Updated NCL to use some of the newer C# language features.

    Note Note

    This change may require a change to your IVI.NET driver project properties to set the C# language version used by the compiler. If the <LangVersion> property has not be directly set in the driver project file, then the Nimbus build tools will specify a value of latest. IVI.NET drivers currently require C# 7.2 or greater to build.

  • Disable IVI-C state caching, range checking, and simulation editors when the IVI-C attribute or function is linked to IVI.NET.

  • Update IVI.NET editor so that IVI-C attribute display names have spaces.

  • Update enabled state of IVI.NET enum member editor Response field whenever Command field changes.

  • Update NCL so that the default model is used in simulation mode if no Model option is specified.

Nimbus Preview 5.0.0.631

Issues fixed in Nimbus 5.0.0.631

  • Help and setup project property pages fail to load if opened before the Driver Designer or settings editor.

Nimbus Preview 5.0.0.628

Issues fixed in Nimbus 5.0.0.628

  • Nimbus fails to load on non-English versions of Windows.

  • Help project fails to build after switching help templates.

  • Driver conversion fails of .sln file is not in the same folder as the .design file.

  • Arrays are displayed with an extra set of brackets in the info panel.

  • Output and reference parameters are not persisted properly when typed into the Driver Designer as a single line in the tree view.

  • Instrument models that start with numerics are not allowed.

  • Roundtripping operations fail if the Driver Designer or settings editor is opened, closed, and then re-opened within a single Visual Studio session.

Nimbus Preview 5.0.0.603

What's new in Nimbus 5.0.0.603

  • Nimbus can now convert driver solutions created with Nimbus version 2.0.10 and later.

Issues fixed in Nimbus 5.0.0.603

  • Driver settings designer window appears blank when opening some projects.

  • Driver converter fails if the .design file is not located in the same folder as the driver solution file.

  • Help project crashes if it contains an item with a None MSBuild item type.

  • Converted setup project references Help Viewer manifest file without the .msha file extension.

  • Setup project converter does not remove policy files, which are now included via the file globs in the setup targets file.

  • Update the ToolsVersion in the IVI-C unit tests to be 15.0.

  • Settings editor crashes if an instrument family or model is edited and a non-valid C# identifier is used.

  • Refresh the capabilities group editor when adding/removing instrument classes or changing LXI settings.

  • Updating the help template in the help project properties is slow.

  • Applying a new IVI.NET help template mistakenly copies over the IVI-COM help template.

  • Nimbus throws exceptions for IVI.NET solutions where the linked IVI-C driver project appears before the IVI.NET driver project in the solution file.

  • Adding new IVI.NET enum members sometimes throws an exception.

  • Setup project converter does not update occurrences of HelpContentSetup.msha in the Common.wxs file.

  • Remove usage of undefined VCUnitTestDir MSBuild property in the IVI-C unit test project file.

  • Fix bug in the setup targets that would case IVI-C wrapper files to not be deployed.

  • Adding an IVI.NET method with out or ref parameters does not retain the parameter direction.

Nimbus Preview 5.0.0.549

Issues fixed in Nimbus 5.0.0.549

  • Don't show "Add Constructor" command on reference properties.

  • Update the DriverVersion MSBuild property when changing the driver version in the driver settings editor.

  • Refresh the IVI.NET info panel when linked IVI-C items are deleted.

  • An incorrect data type is used in the LXI GetNextEventLogEntry IVI-C unit test.

  • Nimbus crashes when using whitespace in an instrument family or model name.

  • Don't add the .design file as a project item to the IVI-C driver project when the IVI-C driver is linked to IVI.NET.

  • Converting Nimbus 4 IVI.NET drivers that don't have a linked IVI-C driver throws an exception.

  • Adding an instrument class to an IVI-COM solution with a unit test fails.

  • The TargetFramework of IVI.NET help and setup projects does not match the value in the driver project.

  • Don't require the .design file to be located in the same folder as the .sln file.

  • Specify the -restore flag for msbuild.exe in the driver boilerplate help when explaining how to build driver source code in end-user systems.

  • The setup designer opens when any file in the setup project is double-clicked.

Nimbus Preview 5.0.0.530

Issues fixed in Nimbus 5.0.0.530

  • The help project would sometimes fail to build due to the .msha file being missing from the obj folder.

  • The return value field does not appear in the help editor.

  • Some custom fields do not appear in the help editor.

  • Linked IVI-C functions and attributes do not display the correct implementation style in the Implementation Style combo box.

  • IVI-C files in a linked IVI-C driver are not regenerated when the Regenerate Files command is executed on the master IVI.NET driver.

  • IVI-C enum command maps do not include both the SCPI long and short form of the associated commands.

  • Changing an IVI.NET method response can result in the associated command being updated instead.

  • Don't delete the implementation of IEnumerable.GetEnumerator in NCL when removing the instrument-specific clone of a class-compliant repeated capability.

Nimbus Preview 5.0.0.520

Issues fixed in Nimbus 5.0.0.520

  • Don't show the Remarks tab in the help editor for items to which it does not apply.

  • Linked IVI-C attributes are not created for IVI.NET properties when a project is initially created.

  • Renaming an IVI.NET property from the item editor does not work.

  • Exception is thrown in "Go To Unit Test" command if a unit test project is not present in the solution.

  • Warning dialog claiming the implementation code has changed is mistakenly shown when changing the implementation type.

  • Don't show Create IVI-C property commands on IVI-COM and IVI.NET properties when no IVI-C driver is present.

  • Adding or removing a repeated capability physical name throws an error when an IVI.NET unit test is present in the solution.

Nimbus Preview 5.0.0.510
Important note Important

This release delivers a single VSIX package that provides support for both Visual Studio 2017 and Visual Studio 2019. To accomplish that, the VSIX ID was necessarily changed and the name of the package appears as simply Nimbus Driver Studio in both Visual Studio 2017 and Visual Studio 2019. Consequently, the previous VSIX extension must be explicitly uninstalled before installing this version.

What's new in Nimbus 5.0.0.510

  • Support for Visual Studio 2019 has been added.

  • Nimbus now appears in the Project Type combo box in the Visual Studio 2019 New Project Dialog.

  • The number of prerequisite Visual Studio components has been reduced.

  • Updated Setup Designer to offer context menu commands from the tree view or the list view.

Issues fixed in Nimbus 5.0.0.510

  • The ItemDefinitionGroups defined in IVI-COM and IVI-C targets could not be overridden as easily as in previous Nimbus versions.

  • Linked IVI-C enums do not show up in the IVI.NET enum info panel.

  • Source files should not automatically be opened when a new driver solution is created.

  • Disable the Paste menu command when the clipboard contains data from a different Nimbus project.

  • Incorrect TargetFrameworkVersion is stored in the .design file when creating new driver solutions.

  • View Help command does not work when changing between different solution configurations.

  • IVI-C help and setup output files overwrite IVI.NET output files if linked and the project name matches the IVI-C prefix.

  • The Go To IVI.NET commands do not work when executed from the IVI-C designer.

  • Don't add the {value} tag to the instrumment response of a method if the return type is not compatible with automatic command formatting.

  • Help editor displays summary information for the previously selected item.

  • Renaming an IVI.NET property with a linked IVI-C attribute fails.

  • Changing an IVI.NET property access does not always round-trip the implementation code properly.

  • Don't attempt to add a unit test when adding a property to a free-standing interface.

  • All unit test classes associated with an instrument class are not removed when removing support from an instrument class.

  • Rename repeated capability fails if the ActiveXXX property is displayed when the rename is performed.

  • Renaming the IVI-C prefix in an IVI.NET or IVI-COM driver project does not rename all functions in the <prefix>.cpp file.

  • IVI-COM indexers do not display the Name parameter.


Converting Driver Projects From Earlier Versions of Nimbus

Before You Convert

  1. Be sure to make a backup copy of your entire driver solution if it is not maintained in source control.

  2. If the conversion fails at any point, the process must be started again using the original version. Attempting to close and re-open a partially-converted driver will produce unexpected results.

  3. Delete the following items, as they easily become invalid between Visual Studio Versions, and they are automatically re-generated by Visual Studio upon opening a solution.

    • .vs folder

    • .VC.db file

Project Changes to Expect

Nimbus performs a number of required transforms to your driver solution in order to fully migrate it to the latest version. While this topic does not provide an exhaustive listing of all of these modifications, there are some that are helpful to be aware of, as they can influence how, and if, the project builds successfully immediately after conversion, or whether some manual conversion tasks are required.

  1. IVI-COM and IVI.NET unit tests will get updated to target .NET Framework 4.5, if they are not already targeting at least that version. This is required by the MSTest framework used for these projects.

    To achieve this, Nimbus removes the existing unit test project reference to Microsoft.VisualStudio.QualityTools.UnitTestFramework and adds the requisite PackageReference entries for the MSTest framework.

  2. Nimbus converts driver projects, unit test projects (C# and C++), help projects, and setup projects. No conversion is performed on console application projects in the solution, even if they were originally created using the Nimbus wizard.

  3. All of the following projects will be converted to SDK-style projects:

    • IVI.NET driver projects

    • IVI.NET and IVI-COM unit test projects

    • IVI.NET, IVI-COM, and IVI-C help projects

    • IVI.NET, IVI-COM, and IVI-C setup projects

    One important (and useful) feature of SDK-style projects is that several of the common assembly attributes that would previously exist in the AssemblyInfo.cs file are managed as MSBuild project properties. This is a much more effective approach for managing important assembly-level metadata, such as the AssemblyVersion and the AssemblyFileVersion.

    As part of the conversion to SDK-style projects, Nimbus will remove the following assembly attributes from the AssemblyInfo.cs file:

    Note Note

    These assembly attribute modifications are only done for IVI.NET driver projects, IVI.NET unit test projects and IVI-COM unit test projects, since those are the three C# project types that are automatically converted to SDK-style.

    • AssemblyCompanyAttribute

    • AssemblyCopyrightAttribute

    • AssemblyDescriptionAttribute

    • AssemblyFileVersionAttribute

    • AssemblyProductAttribute

    • AssemblyTitleAttribute

    • AssemblyVersionAttribute

    For IVI.NET and IVI-COM unit tests, any of the above that appeared in the project's AssemblyInfo.cs file are injected directly into the project file.

    For IVI.NET driver projects, the values of some of these attributes is defined very precisely by the IVI specifications. Consequently, Nimbus maintains these values automatically in the Nimbus.Driver.IviNet.props file within the Nimbus Build Tools NuGet package.

    The following properties are defined in the IVI.NET .props file to provide the same functionality as the corresponding assembly attributes:

    • <FileVersion>

    • <Product>

    • <Title>

    • <Version>

    Important note Important

    With regards to the above four assembly attributes, any values discovered in the AssemblyInfo.cs file are ignored. Because IVI prescribes these values precisely, Nimbus is able to compute and maintain these values automatically in the Nimbus.Driver.IviNet.props file. This could result in a change in the values compiled into the resulting driver assembly, relative to what was compiled into the assembly prior to conversion. However, any difference would be the result of the driver having been manually modified after initial generation to use a non-compliant value.

    For IVI.NET drivers, if any of the following appeared in the AssemblyInfo.cs file, then their values are injected directly into the corresponding MSBuild properties in the driver project file.

    • AssemblyCompanyAttribute

    • AssemblyCopyrightAttribute

    • AssemblyDescriptionAttribute

  4. Nimbus injects MSBuild properties into the driver, help, setup, and C# unit test projects to unify the intermediate and output path locations under a single build folder. This greatly simplifies management of build artifacts, installer build operations, and facilitates better incremental build behavior.

    To achieve this, Nimbus removes all of the following MSBuild properties from the driver, help, setup, and C# unit test projects:

    • <BaseIntermediateOutputPath>

      <BaseOutputPath>

      <IntDir>

      <IntermediateOutputPath>

      <OutDir>

      <OutputPath>

      <TargetBaseName>

      <TargetName>

    Important note Important

    Nimbus only performs the output and intermediate folder unification for driver, help, setup, and C# unit test projects. It specifically does NOT, due to Visual Studio limitations, perform automatic output folder transformation for IVI-C wrapper unit test projects or any of the C#, Visual Basic, or C# console application projects. See the section below on manual conversion tasks for details on the simple changes to unify the output of these projects as well.

  5. The Nimbus Build Tools are now used directly by end users building installed drivers. As such, the build tools no longer ship with Nimbus-created drivers. The Nimbus conversion process removes NTL from IVI-COM setup projects, NCL from IVI.NET setup projects, and NRT from IVI-C setup projects.

    Additionally, because there are no build tools included with the IVI.NET driver installer, the Nimbus migration process removes NimbusExpressEULA page that would appear as part of IVI.NET driver installation.

Performing the Conversion

To convert your driver to Nimbus 5:

  1. Ensure you have a backup copy or that the previous version of the driver is in source control.

  2. Remove the .vs folder from disk.

  3. Important note Important

    Remove all bin and obj folders from the solution. You may need to navigate to multiple subfolders in the various project solutions to properly clean the solution of binaries that could impact the conversion.

  4. Open the solution in Visual Studio. If there are any C++ projects in the solution, then you will be prompted by Visual Studio to retarget to use a newer platform toolset. It is typically best to choose the latest.

  5. Once the retargeting has completed, you will see that several of the projects fail to load. This is expected. You will also see a Nimbus node at the top that says Nimbus upgrade required....

    Right-click on that node and choose Upgrade driver...

  6. A dialog box will appear indicating success or failure.

  7. Often all projects in the solution will not be immediately buildable without some simple manual modifications. This is expected and does not indicate a failure of the conversion process. See the section below on manual conversion tasks for details.

Manual Conversion Tasks

  1. After conversion, the obj folder will likely appear in Solution Explorer as a member of some projects. This folder can safely be deleted from Solution Explorer, and from disk.

  2. For native IVI-C unit tests, Visual Studio 2019 pre-defines the template specialization for ViInt64 This specialization is not defined in earlier versions of Visual Studio, so Nimbus generated it automatically. A build error occurs if this redundant definition remains in the native IVI-C unit tests for Visual Studio 2019. Simply delete the following template specialization at the top of the IVI-C unit test.

    C++
    Copy
    template<> static std::wstring ToString<ViInt64>(const ViInt64& t) { RETURN_WIDE_STRING(t); }

  3. Nimbus converts help projects to SDK-style projets. The large number of items that were previously managed directly in each help .nhproj file are now managed with file globs defined in the Nimbus.Help.targets file within the Nimbus Build Tools.

    XML
    Copy
    <!-- These file globs define the items included in the project. -->
<ItemGroup>
  <Content Include="Template\**\*.js" />
  <Content Include="Template\**\*.html" />
  <Content Include="Template\**\*.htm" />
  <Content Include="Template\**\*.jpg" />
  <Content Include="Template\**\*.gif" />
  <Content Include="Template\**\*.png" />
  <Content Include="Template\**\*.css" />
  <Content Include="Template\Manifest.xml" />
</ItemGroup>

    If you added items to your help project folder that are included in your help project content, then ensure they are included in the list of file extensions above. If not, simply add the appropriate glob for your file extension directly to your .nhproj file.

    Conversely, if the file globs above would include content that you explicitly wish to be exluded, then a file glob can be added to the project file with an Exclude attribute. Please consult the Microsoft online documentation for details in the syntax of file globs.

  4. Nimbus automatically unifies the output of driver, help, setup, and C# unit test projects. IVI-COM C# and Visual Basic console applications are not automatically updated by the conversion process.

    To update IVI-COM C# and Visual Basic console applications to use the unified output folder:

    1. Use the $(OutputPath) in the <HintPath> element associated with the driver project reference.

      Important note Important

      Without properly adjusting the <HintPath> element, the driver reference will not resolve and the console application project will not build.

    2. Paste the following code in the project file just above the <Import> element for Microsoft.Common.props.

      XML
      Copy
      <PropertyGroup>
  <BaseOutputPath Condition=" '$(BaseOutputPath)' == '' ">..\build\</BaseOutputPath>
  <BaseIntermediateOutputPath Condition=" '$(BaseIntermediateOutputPath)' == '' ">$(BaseOutputPath)obj\$(MSBuildProjectName)\</BaseIntermediateOutputPath>
  <OutputPath>$(BaseOutputPath)$(Configuration)\$(Platform)\</OutputPath>
  <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
  <AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
</PropertyGroup>

  5. Nimbus automatically unifies the output of driver, help, setup, and C# unit test projects. IVI-COM C++ console applications and IVI-C wrapper C++/CLI unit tests are not automatically updated by the conversion process.

    To update IVI-COM C++ console applications and IVI-C wrapper C++/CLI unit tests to use the unified output folder:

    1. Paste the following code in the project file just below the <Import> element for Microsoft.Cpp.props.

      XML
      Copy
      <PropertyGroup>
  <NormalizedPlatform Condition=" '$(Platform)' == 'x86' OR '$(Platform)' == 'Win32' OR '$(Platform)' == 'AnyCPU' ">x86</NormalizedPlatform>
  <NormalizedPlatform Condition=" '$(Platform)' == 'x64' ">$(Platform)</NormalizedPlatform>
  <OutDir>..\build\$(Configuration)\$(NormalizedPlatform)\</OutDir>
  <IntDir>..\build\obj\$(MSBuildProjectName)\$(Configuration)\$(NormalizedPlatform)\</IntDir>
</PropertyGroup>

    2. For the IVI-C wrapper unit test only, change the <DriverId> element to <DriverName> and change the value to match that of the driver name.

    3. Remove any <OutDir> and <IntDir> elements.

    4. Add the $(OutputPath) to each <AdditionalLibraryDirectories> element.


IVI Backgrounder

The IVI Foundation is an open consortium founded in 1998 to promote standards for programming test instruments. Composed primarily of instrument manufacturers, end-users, software vendors, and system integrators, the Foundation strives to create specifications that govern the development of instrument drivers.

IVI-compliant drivers offer a number of benefits, such as a consistent programming interface, better performance, seamless integration into a wide variety of development environments, and interchangeability. Interchangeability refers to the ability of an end user to replace one IVI driver in an application program with another IVI driver from a different vendor, without modifying or even recompiling the application program. To achieve interchangeability, IVI driver developers must carefully follow all of the requirements laid out in the IVI Foundation specifications.

The following sections present an overview of some of the most important IVI topics for driver developers. This document does not attempt to reproduce all of the details contained in the IVI specifications. For complete information on IVI and for the most up-to-date versions of all IVI specifications and components, visit the IVI Foundation web site

In This Section

What All IVI Drivers Do -- Inherent Capabilities

Explains the basic functionality that all IVI drivers support.

How IVI Drivers Provide Interchangeability

Describes the basics of how interchangeability works with IVI.NET.

Instrument-Specific Capabilities

Provides a brief explanation of non-interchangeable device-specific functionality in IVI drivers.

IVI Shared Components

Provides an introduction to the shared software components required for an IVI-based system.

Repeated Capabilities

Explains IVI repeated capabilities along with the notions of physical and virtual names.


What All IVI Drivers Do -- Inherent Capabilities

The IVI Foundation has established a set of functions and attributes that all IVI drivers must support -- irrespective of which IVI instrument class the driver supports. These common functions and attributes are called IVI inherent capabilities and they are documented in IVI-3.2: Inherent Capabilities Specification. Importantly, drivers that do not support any IVI instrument class must still support the IVI inherent capabilities.

Having a common set of basic functionality that all IVI drivers must support ensures that end users have a standard, recognizable way to perform basic operations with the IVI driver. If an end user has programmed with an IVI driver of any type before, they will immediately know how to perform at least basic tasks with any new IVI driver they encounter. Some of the tasks that fall under the inherent capabilities specification are:

  • Initializing the driver.

  • Querying errors from the driver.

  • Enabling standard driver features, such as simulation, state caching, and range checking.

  • Identifying the capabilities of the driver, such as the supported instrument classes, capability groups.

  • Reading driver and instrument identification information.

  • Performing instrument self-test and reset operations.

Standard Driver Features

IVI drivers may offer several different features whose behavior has been standardized by the IVI Foundation. Although these are referred to as standard driver features, they are not all required to be supported by an IVI driver, as shown in the table below:

Feature | Required
State caching | No
Range checking | No
Coercion and coercion recording | No
Interchangeability checking | No
Simulation | Yes

State Caching -- Optional

As a means to offer better performance in customer test applications, IVI drivers often support a feature known as state caching. The principle of state caching is quite simple, although in practice it can be extraordinarily difficult to implement properly.

When a end user enables state caching for an IVI driver, the driver attempts to determine if new settings passed into the driver are different from the actual instrument state. In this way, I/O traffic between the driver and the instrument is reduced, as fewer I/O calls are performed.

In the simplest example of when state caching improves performance, consider what happens when a user passes identical values several times in a row for the frequency property on a function generator driver. Without state caching, each call into the driver would result in an I/O function call to the instrument, whereas a driver performing state caching would detect that subsequent calls to the frequency property were redundant and should not result in any communication with the instrument. Correspondingly, the driver can "remember" the last known value for instrument properties so that queries can be performed by retrieving data from computer memory, rather than by performing instrument I/O.

As with caching schemes in other types of software systems, IVI driver state caching is frought with potential pitfalls. The chief challenge in properly implementing state caching is maintaining cache coherency. Complex instruments often have complex couplings between instrument settings, making it difficult for the driver to track whether or not settings stored in the driver cache are valid. Consequently, many instrument vendors choose not to implement state caching in the driver.

For more information on state caching, see IVI-3.1: Driver Architecture Specification.

Range Checking -- Optional

Range checking in IVI drivers simply refers to the ability for the driver to test whether or not input values passed to the driver are within an acceptable range. End users typically use range checking during debugging and, after validation is complete, disable it to maximize performance.

For more information on range checking, see IVI-3.1: Driver Architecture Specification.

Coercion and Coercion Recording -- Optional

Instruments often accept only a discrete set of values for certain properties. For example, a DMM might only accept values such as 10 V, 100 V, 300 V for the voltage range setting. These discrete value sets will necessarily be different for different vendor's instruments. A Keysight DMM may accept 10 V, 100 V, 300 V while a Fluke DMM accepts 20 V, 200 V, and 400 V. As a result, IVI class specifications are forced to define such real-valued properties as accepting a continuous range of values, even though the underlying instrument only accepts a discrete set of values.

Following along with the DMM voltage range example, if a user sends a value of 150 V for the voltage range, the instrument will internally coerce the value to one of the accepted values, such as 300 V. To maximize interchangeability, the IVI class specifications provide guidance on how IVI drivers should coerce user requested values for specific properties.

To aid end users in building interchangeable applications, IVI drivers may implement a feature called coercion recording. If a user enables coercion recording, the IVI driver retains a log of each user value that it coerces. Standard functions in the IVI inherent capabilities provide the user with access to the driver's coercion log.

For more information on coercion, see IVI-3.1: Driver Architecture Specification.

Interchangeability checking -- Optional

A program written using an IVI driver will not be interchangeable if the program relies upon default settings within the instrument. This is because different instruments will have different default values for many important settings. Repeatable results can only be obtained if all of the instrument settings on which an operation depends are in a user-specified state.

IVI drivers may implement a feature called interchangeability checking to ensure that driver attributes relevant to a particular operation are in a user-specified state whenever that operation is performed. The IVI instrument class specifications all include class-specific sections detailing which driver attributes need to be in a known state for particular operations. The driver can then track these attributes and report a warning if one or more are not set explicitly by the client program before an important operation is performed.

Standard functions in the IVI inherent capabilities provide the user with the ability to enable interchangeability checking in the driver and to retrieve any warnings that occur. Typically, this feature is only used during development and debug of an application and disabled during normal operation, so as not to adversely impact performance.

For more information on interchangeability checking, see IVI-3.1: Driver Architecture Specification.

Simulation -- Required

IVI drivers are often constructed for complex instruments that are difficult to procure or that are in high demand at the end user facility. Consequently, it may be the case that end users need to be able to test their application programs without being physically connected to an instrument. IVI driver simulation is a feature that allows end users to use IVI drivers without a physical connection to the instrument.

When an end user enables simulation in an IVI driver, the driver performs no I/O communication whatsoever. IVI drivers are free in their choice of mechanisms for returning meaningful output values to the end user, but the intent is that the user program should be able to proceed normally when calling functions on the driver. This allows the end user to exercise their test application before the actual hardware is available.

For more information on simulation, see IVI-3.1: Driver Architecture Specification.


How IVI Drivers Provide Interchangeability

What is an IVI Instrument Class?

The IVI Foundation uses the term instrument class to refer to a distinct set of functionality for a canonical instrument type. Although there are many different types of instruments used in test and measurement and their functionality varies considerably, many of these instruments naturally fall into distinct categories, or types. Often these instruments are categorized based upon the type of measurements they can perform or the type of output they can produce.

For each instrument class, the IVI Foundation publishes a specification, known as the class specification. Each class specification lays out the requirements for compliance with that class specification. An IVI driver that complies with a class specification is said to be a class-compliant IVI driver. The primary purpose of an IVI class specification is to detail the set of functions and attributes that an IVI driver must support in order to be class-compliant. The class specification carefully prescribes the exact name of each function, along with the parameter list and the API hierarchy, as well as other behavior details.

Currently, the IVI Foundation has defined and approved specifications for twelve instrument classes. These specifications are available from the IVI Foundation.

  • IVI-4.1: IviScope Class Specification

  • IVI-4.2: IviDmm Class Specification

  • IVI-4.3: IviFgen Class Specification

  • IVI-4.4: IviDCPwr Class Specification

  • IVI-4.5: IviACPwr Class Specification

  • IVI-4.6: IviSwtch Class Specification

  • IVI-4.7: IviPwrMeter Class Specification

  • IVI-4.8: IviSpecAn Class Specification

  • IVI-4.10: IviRFSigGen Class Specification

  • IVI-4.12: IviCounter Class Specification

  • IVI-4.13: IviDownconverter Class Specification

  • IVI-4.14: IviUpconverter Class Specification

  • IVI-4.15: IviDigitizer Class Specification

Interchangeability and IVI

The term interchangeability in IVI refers to the ability to exchange an instrument of one class in a system with a different instrument from that same class. IVI interchangeability does not generally refer to the case of exchanging instruments from different instrument classes.

Client applications achieve interchangeability by writing their code such that it meets at least the following two conditions:

  1. It uses only functions and attributes from the IVI class specification.

  2. It has no references to a specific IVI instrument driver.

Since IVI drivers can contain functionality beyond the class specification (known as instrument-specific functionality), the client programmer must take care to only use functionality from the IVI specification if their program is to be interchangeable. Only the IVI-defined functionality is guaranteed to be supported by a class-compliant driver.

The second condition (excluding references to a specific driver) is a bit trickier to meet, and requires the use of extra software components. The mechanism by which this is achieved is different for IVI-COM drivers and IVI-C drivers.

IVI.NET Interchangeability

Interchangeability with IVI.NET relies upon special components shipped as part of the IVI Shared Components. The first component required for IVI.NET interchangeability is the .NET factory classes. These classes component allows users to instantiate a specific IVI.NET driver by name rather than by a hard-coded program reference. The IVI Shared Components supply one factory class per IVI instrument class.

The name used to instantiate the driver is termed the logical name. The IVI Configuration Store holds all of the user-assigned logical names, and maps them to specific IVI drivers. When a different instrument is introduced into the system, the user need only change the specific driver referenced by their logical name in the IVI Configuration Store. No user code is modified, so the application will run without re-compiling or re-linking. The factory class will lookup the logical name in the IVI Configuration Store and instantiate the new driver.

The second component required for IVI.NET interchangeability is the class assembly associated with the IVI instrument class in use. The IVI.NET class assemblies are also part of the IVI Shared Components. These DLLs contain the interface definitions (method signatures, property and parameter types, etc.) for a particular instrument class. Class-compliant IVI.NET drivers reference these type libraries to implement the functionality they define. Client applications reference these type libraries to access driver functionality in a driver-independent fashion.

The .NET factory classes and the class assemblies are the basic machinery that enables interchangeability with IVI.NET drivers.

Capability Groups -- Base and Extension

An instrument class capability group is a logical grouping of related methods and properties. Capability groups might accurately be thought of as coarse-grained instrument class "features". Dividing the functionality of an instrument class into capability groups allows class-compliant drivers to advertise the subset of instrument class features they support. When a class-compliant driver is installed, the IVI specifications require the driver installer to publish in the IVI Configuration Store not only the name of the instrument class with which it complies, but also the set of class-defined capability groups it supports.

Each IVI class specification partitions IVI-defined functionality a into two kinds of capability groups -- the required base capabilities and the optional extension groups.

Base Capabilities Group

The Base Capabilities group contains functionality that all IVI drivers must implement if they wish to claim conformance with the instrument class in question. Typically, the Base Capabilities group represents the "least common denominator" of functionality for an instrument class, so most commercial instruments can be expected to support this level of capability.

As an example, the IviDmm Base Capabilities group contains functions for range, resolution, and triggering. Most commercial DMMs possess at least these capabilities, so any IVI driver that wishes to claim IviDmm-compliance must support this group of functionality.

Extension Groups

IVI uses Extension Groups to define functionality that is found in many instruments of a particular class but may not be as common as the functionality expressed in the Base Capabilities. One may think of Extension Groups as being standard definitions for "optional" functionality in an IVI driver.

Extension Groups provide a means for more advanced intruments to expose functionality in an interchangeable fashion, while still allowing simpler instruments to be class-compliant. For instance, not all DMMs have the ability to perform temperature measurements. Thus, the IviDmm class specification uses the IviDmmTemperature Extension Group to define temperature measurement capabilities.

Simply put, an Extension Group is making the statement to the driver developer, "You do not have to provide these capabilities in your IVI driver, but if you do, you must do it according to the IVI definition." An IVI driver can be class-compliant without supporting any of the extension groups in its instrument class. All IVI drivers expose a GroupCapabilities attribute that returns a comma-separated list of the extension groups supported by the driver. Using this attribute, client applications and tools can programmatically determine what optional functionality is present in an IVI driver.


Instrument-Specific Capabilities

Modern instruments typically possess much more functionality than is represented in the IVI instrument class specifications. End users must have a way to access the full capability of the instrument they have purchased. Thus, the driver must expose interfaces that are specific to that instrument alone. These are known as instrument-specific capabilities.

Instrument-specific capabilities are obviously not interchangeable. End users programming against a driver's instrument-specific interfaces typically do so to access functionality that is not available in the class-compliant interfaces . Nevertheless, for complex instruments such as spectrum analyzers, there will often be far more functionality in the IVI driver's instrument-specific hierarchy than in the class-compliant hierarchy.

Although, by definition, IVI does not dictate the syntax and semantics of instrument-specific interfaces, there are still guidelines that must be followed in the design of the interfaces if the driver is to be IVI compliant. Most of these rules are laid out in IVI-3.4: API Style Guide.


IVI Shared Components

In order to facilitate IVI driver development and to ensure a consistent experience for end users building IVI-based test systems, the IVI Foundation develops and maintains a series of freely available software components. These components are collectively referred to as the IVI Shared Components, and they must be installed on any computer that will use IVI drivers. In fact, IVI driver installation programs are required to check for the presence of the IVI Shared Components before installing.

The following sections provide a brief overview of some of the most important IVI Shared Components.

IVI Shared Component Installer

The IVI Foundation provides an installer for the IVI Shared Components. Moreover, the Foundation's Shared Component installer is the only IVI-compliant way to install the IVI Shared Components. Third parties are not allowed to develop custom installation programs for the IVI Shared Components.

The IVI Shared Component installer creates a directory structure to house the IVI Shared Components as well as IVI drivers themselves. The root of this directory structure is referred to as the IVI install directory (<IviInstallDir>) and is typically <ProgramFilesDir>\IVI Foundation\IVI.

The IVI Shared Component installer is available for download from the IVI Foundation web site.

IVI.NET Shared Component Installer

The IVI Shared Component installer described above installs the required components for IVI-COM and IVI-C drivers. For IVI.NET drivers, addtional components are required and these are supplied by the IVI.NET Shared Component installer. The IVI Shared Components must be installed before installing the IVI.NET Shared Components.

The IVI.NET Shared Component installer creates a directory structure to house the IVI Shared Components as well as IVI.NET drivers themselves. The root of this directory structure is referred to as the IVI.NET install directory (<IviInstallDir>) and is typically <ProgramFilesDir>\IVI Foundation\IVI\Microsoft.NET.

The IVI.NET Shared Component installer is available for download from the IVI Foundation web site.

IVI Configuration Store

When the IVI Shared Components are installed, a special XML file named IviConfigurationStore.xml is placed in the <IviInstallDir>\Data folder. This file is known as the IVI Configuration Store and serves as a central repository for IVI driver configuration information.

IVI driver installers are required to populate the Configuration Store with information such as the instrument classes supported, the instrument models for which the driver is designed, and the physical channel names understood by the driver. End users add information to the Configuration Store to describe how they intend to use IVI drivers in their system. End users can specify logical names for IVI drivers and virtual names for channels.

For more information on the structure of the IVI Configuration Store, see IVI-3.5: Configuration Server Specification.

IVI Configuration Server

The IVI Foundation discourages users and driver developers from directly manipulating the Configuration Store XML file (IviConfigurationStore.xml). The Configuration Store is highly self-referential and easily corrupted if modified directly. Thus, the Foundation provides a COM component known as the IVI Configuration Server for programmatically reading and writing information to the Configuration Store.

The IVI Configuration Server is installed automatically by the IVI Shared Component installer. For more information on how to use the IVI Configuration Server, see IVI-3.5: Configuration Server Specification.


Repeated Capabilities

Instruments often contain multiple instances of the same kind of functionality or capability. For instance, modern oscilloscopes may have multiple channels, each with independent settings for such things as vertical scale and input attenuation. IVI refers to funtionality that is duplicated in an instrument as a repeated capability.

Physical Repeated Capability Names

Instances of repeated capabilities are identified by name. These names are passed as parameters to standard repeated capability accessor functions in order to change settings and execute methods on a driver's repeated capabilities. There are two types of repeated capability names -- physical names and virtual names. Physical repeated capability names are those that the driver writer specifies during driver development. These are the names that the driver natively understands and, as such, they cannot be modified by an end user. They can only be read by an end user. Virtual repeated capability names are explained below.

The physical repeated capability names (or simply physical names) understood by a particular driver can be discovered interactively or programmatically. Each IVI driver is required to register the set of physical names it understands with the IVI Configuration Store. This means an end user can use whatever IVI Configuration Store browser they have to look up the physical names supported by the driver.

Physical names can also be discovered programmatically using standard repeated capability functions. Example code for doing this is given below in the section on Parameter-Style Repeated Capabilities.

Virtual Repeated Capability Names

Virtual names allow end users to specify their own names for repeated capability instances and map those names to the physical names that the driver natively understands. The user establishes the virtual-to-physical name mappings in the IVI Configuration Store. At runtime, the user can supply a virtual channel name to the appropriate function the driver will use the mappings in the IVI Configuration Store to translate the virtual name into a physical name that the driver understands.

The purpose of virtual names is to faciliate driver interchangeability. If a user writes application code using virtual names, then no modifications to the application code are necessary when an existing driver is replaced with one that natively understands different physical names. The user need only modify the appropriate settings in the IVI Configuration Store to map their virtual names to the new driver's physical names.

Types of Repeated Capabilities

The IVI specifications define three different types of repeated capabilities -- parameter-style repeated capabilities, selector-style repeated capabilities, and collection-style repeated capabilities. Each type of repeated capability is often more appropriate depending upon such factors as how common the repeated capability is in a particular instrument class and whether one repeated capability instance is controlled at a time or multiple instances are commonly controlled at a time. Since IVI instrument classes use all three types of repeated capabilities in various instrument classes, it is important to understand the basics of each type of repeated capability.

Parameter-Style Repeated Capabilities

The simplest type of repeated capability is the parameter style. Parameter-style repeated capabilities are used most commonly in IVI-C drivers, though they can also appear in IVI-COM drivers. As the name implies, parameter-style repeated capabilities are supported by simply adding an extra string parameter to any function that applies to a repeated capability (as opposed to a function that applies to the driver as a whole). The client application passes in either a valid physical or virtual repeated capability name for this parameter to identify the particular repeated capability instance to access.

The code below shows an IVI.NET driver client using the SetOperationMode function from the IviFGen class specification:

C#
Copy
var fgen = IviFgen.Create("MyLogicalName");
// ...
fgen.SetOperationMode("Output1", OperationMode.Burst);

In the code above, the second parameter is the repeated capability name. The repeated capability name almost always appears as the second parameter to a function that applies to a repeated capability. The example is setting the operation mode to burst for only the output channel identified by Output1. The name Output1 could be a physical name or a virtual name.

Drivers that expose a parameter-style repeated capability always expose a couple of additional functions and attributes that allow you to programmatically determine the number of repeated capabilities instances (e.g. "channels") and the physical names supported (e.g. channel names). The names of these support functions are also standardized, so that they can easily be identified when the name of the capability is know. IVI-COM drivers and IVI-C drivers differ slightly in the repeated capability support functions they expose for parameter-style repeated capabilities.

For IVI.NET drivers exposing parameter-style repeated capabilities, the following are required to be present:

  • Count property

  • Get<Capability>Name property (Ex: GetChannelName)

The client code simply reads the value of the Count property and then uses this value to iterate through the repeated capability instances. The GetName method accepts a zero-based index parameter to identify which repeated capability instance name is desired. The code below shows how to iterate through all of the physical names supported by an IVI.NET FGen driver that exposes a "Channel" repeated capability.

C#
Copy
var fgen = IviFgen.Create("MyLogicalName");
// ...
for (int i = 0; i &lt; fgen.Output.Count; i++)
{
  Console.WriteLine(fgen.GetChannelName(i));
}

Selector-Style Repeated Capabilities

Selector-style repeated capabilities use a special selector function to set the "active" repeated capability. Subsequent function calls that apply to a repeated capability are understood to apply to the active instance. The active instance remains active until the client code sets the active instance to another repeated capability name. Selector-style repeated capabilities have the advantage of not requiring a repeated capability name to be passed to every function that applies to the repeated capability.

As with parameter-style repeated capabilities, drivers that expose a selector-style repeated capability always expose additional functions for managing the repeated capability instances. Indeed, the selector-style repeated capability uses the same functions and attributes as the parameter style, with the addition of one property and one function for setting and getting the active instance.

For IVI.NET drivers, the following are required to be present:

  • Count property

  • Get<Capability>Name method (Ex: GetChannelName)

  • Active<Capability> property (Ex: ActiveChannel)

Since the selector-style repeated capability uses the same Count attribute and GetName function as the parameter style, the code required to iterate through the instance names for a selector-style repeated capability is identical to that shown above for the parameter style.

Collection-Style Repeated Capabilities

The most common type of repeated capability for IVI.NET drivers is the collection-style repeated capability.

As with the parameter and collection style, collection-style repeated capabilities always expose a Count and Name attribute for iterating through the list of available repeated capability names. Unique to collection-style repeated capabilities is the Item property, which provides access to individual repeated capability instances. The Item property accepts a repeated capability name (physical name or virtual name) and returns an interface pointer to the desired repeated capability instance. All method and property calls on the returned interface pointer implicitly apply to the repeated capability instance chosen with the Item property.

The C# code below demonstrates how to use the Item property to access a channel called CH1 and enable it.

C#
Copy
var scope = IviScope.Create("MyLogicalName");
// ...
var channel = scope.Channels["CH1"];
channel.Enabled = true;

Note that declaring the intermediate variable for the IIviScopeChannel interface returned by indexer is not necessary. Depending upon the client application, it may be more convenient to write the code as follows:

C#
Copy
var scope = IviScope.Create("MyLogicalName");
// ...
scope.Channels["CH1"].Enabled = true;
Static and Dynamic Repeated Capabilities

Many instruments have a fixed number of repeated capabilities. For instance, a function generator typically has a fixed number of output channels. However, some instruments can have a variable number of repeated capabilities, depending upon end-user configuration. For instance, a switching mainframe might have any of a number of combinations of multiplexer cards installed on a particular end-user system. Thus, the number of channels is not fixed and can only be determined at runtime. Such instruments possess what are termed dynamic repeated capabilities. Conversely, instruments that always have a fixed number of repeated capabilities use the term static repeated capabilities.

A driver that exposes dynamic repeated capabilities cannot register the supported repeated capability names during driver installation. Instead, during the driver Initialize call, the driver typically queries the instrument to determine its exact configuration. The mechanism by which a driver determines the name and number of the supported repeated capabilities is always instrument specific, but the net result is that the end user must use the Count and Name attributes to programmatically determine what repeated capability instances are available. An IVI Configuration Store browser is useless in determining what dynamic repeated capabilities a driver supports. It relies only upon static information in the IVI Configuration Store, so it can only report details on static repeated capabilities.

Finally, it is worth noting that a driver can contain both static and dynamic repeated capabilities.


Understanding the Nimbus User Interface

Nimbus integrates with the Visual Studio IDE by providing a series of custom editors and windows for manipulating various aspects of the IVI driver project. The topics in this section introduce the terminology used in discussing Nimbus UI features and explains in detail each of the editors available.

In This Section

Using the Nimbus Driver Designer

Using Per-User Preferences


Using the Nimbus Driver Designer

The Nimbus user interface is completely integrated with the Visual Studio IDE. Nimbus offers a variety of tool windows, document windows, menus, and commands for manipulating every aspect of the driver project. Driver developers can quickly navigate between Nimbus-supplied commands and windows and native Visual Studio windows with which they are already familiar, such as code editors and Solution Explorer. This topic presents an overview of the Nimbus user interface within Visual Studio and introduces UI terminology used throughout the Nimbus documentation.

Note Note

The images presented in this topic show the user interface elements for an IVI.NET driver with a linked IVI-C driver. However, the same user interface elements exist for IVI-COM and stand-alone IVI-C drivers. The IVI.NET user interface is presented here for illustration purposes.

The image below shows an example of a Nimbus IVI.NET driver project in Visual Studio. Each of the Nimbus-supplied items are labeled and discussed in the sections below.

Figure 1: The Nimbus User Interface
A 228862B-17 C 3-4 E 41-9459-C 2 F 094 F 27990
Solution Explorer and the Nimbus Project

A Nimbus driver solution is simply a container for the Nimbus driver project and all of its supporting projects -- such as the unit test project, the help project, and the setup project. As with any Visual Studio solution, a Nimbus driver solution is managed from the Solution Explorer window shown on the right side of Figure 1. The node that appears at the top of Solution Explorer is the referred to as the Nimbus node -- (the node with the Nimbus icon). It is used to access project-wide features. For instance, the Driver Designer and the Driver Settings Editor are accessed by right-clicking the Nimbus node and choosing from the context menu, or by expanding the Nimbus node and double-clicking one of its child nodes.

The projects that appear in Solution Explorer beneath the Nimbus node are Nimbus Driver Help, Nimbus Driver Setup, and standard unit test project types. Though Nimbus automatically generates and manages much of the code in these projects, they can be accessed just as typical Visual Studio projects.

The Driver Designer

Most of the tasks involved in IVI driver developer are performed within a special document window -- the Driver Designer. The image in Figure 1 shows how the Driver Designer appears as a tabbed document window alongside other Visual Studio document windows -- such as code editor windows and project property pages. This makes it easy to move between the Driver Designer and other areas within the IDE.

The Driver Designer can be accessed from Solution Explorer by double-clicking the Driver Designer node. The designer is divided into three regions -- a tree view that occupies the left portion of the window, an Item Editor in the right portion of the window, and a yellow Info Panel appearing along the bottom of the window.

The Tree View

The tree view is used to navigate the hierarchy of types, methods and properties in the driver. Right-clicking the various nodes in the tree, reveals context menu commands for performing the most common Nimbus tasks, such as adding methods, properties, and parameters. The tree fully supports standard copy/paste functionality as well as drag and drop for quickly arranging the driver hierarchy as desired.

The Item Editors

The right portion of the Driver Designer window is occupied by a series of Item Editors. The Item editors are used to manipulate various aspects of the method, property, parameter or other item selected in the tree view. In Figure 1, a property is selected -- making five different Item Editors available via the row of five buttons along the bottom. These are labeled "General", "Help", "Simulation", "Range Checking", and "State Caching".

The Info Panel

The bottom portion of the Driver Designer window is occupied by a yellow window called the Info Panel. This read-only window provides useful "at-a-glance" summary information about the item selected in the tree view. For instance, when a method is selected in the tree view, the Info Panel displays the full signature of the method or property. In addition, the help summary information for the method or property is display.

If a method or property uses a type that also exists in the tree view, such as enums or interfaces defiend by the driver itself, then the Info Panel displays that type as a hyperlink. Clicking the hyperlink navigates to the type where details about the specific type can be reviewed.

Searching and Filtering

The Driver Designer window provides a standard Visual Studio search box for searching and filtering the items displayed in the tree view. This search box works similarly to the standard search box integrated into Solution Explorer.

You can quickly navigate to the search box by typing CTRL+E. The image below shows the results of typing a few characters into the search box.

Driver Designer Search Box
Driver Designer Search

Quick Navigation

Visual Studio includes a feature called Go To All that allows quick navigation to specific elements in a solution. By typing CTRL+, or CTRL+t, users have access to the Go To All dialog from which they can very quickly navigate to specifci files, methods, classes, and more.

Nimbus integrates directly with this feature of Visual Studio to extend the set of items users can quickly access. Within the Go To All dialog, typing part of driver method or property name, for example, presents options for navigating directly to the item in the Nimbus Driver Designer.

"Go To All" Integration

Keyboard Navigation and Tabbing

When keyboard focus in on an item in the Driver Designer tree view, tabbing proceeds as follows:

  1. Grid splitter

    The first tab operation places focus on the grid splitter. When focus is on the grid splitter, the left and right arrow keys can be used to move the splitter left and right -- effectively changing the amount of space allocated to the tree view relative to the item editors.

  2. Item Editor Tab

    The next tab operation places focus on the item editor tab, usually the General tab. The focus visual (a dotted rectangle) appears around the tab that has keyboard focus. Use the left and right arrow keys to select different item editor tabs, such as moving to the Help or State Caching tabs.

  3. Item Editor Controls

    The next tab operation places focus on the first control within a specific item editor. This is often then Name text box, such as the name of a method or property. Successive tab operations move to the next control in the item editor.

    Tip Tip

    At any point after tabbing away from the tree control, use CTRL+SHIFT+LEFT ARROW to navigate directly back to the associated tree item. This makes it very convenient to edit one control in the item editor and then return to the tree view and move to another tree view item.


Using Per-User Preferences

Visual Studio offers a variety of per-user settings that can be accessed via the Options Dialog under the Tools menu. Nimbus adds a series of settings that are convenient for configuring commonly used defaults in IVI driver projects. Rather than storing these preferences on a per-project basis as with the Driver Settings Editor, the settings under the Options dialog are associated with the current user.

To configure per-user IVI Driver Settings

  1. From the Tools menu, choose Options.

  2. The standard Visual Studio Options Dialog appears.

  3. In the tree view on the left, expand the Nimbus Driver Studio node.

  4. Select one of the preference categories listed below.

In This Section

Common Per-User Preferences for all Driver Types

IVI.NET Per-User Preferences

IVI-COM Per-User Preferences

IVI-C Per-User Preferences


Common Per-User Preferences for all Driver Types

The topics in this section present per-user settings that are common to IVI-COM, IVI.NET, and IVI-C driver types.

In This Section

General Page, All Drivers Per-User Preferences

Help Page, All Drivers Per-User Preferences


General Page, All Drivers Per-User Preferences

The options on this page control some of the default settings that appear on the General page of the New Project Wizard for IVI-COM, IVI.NET, and IVI-C drivers.

Instrument manufacturer

The instrument manufacturer is used to identify the manufacturer of the instrument for which the driver is being written. This entry is used in the IVI Configuration Store registration as well as in the implementation of the Instrument Manufacturer attribute.

Driver vender

The driver vendor identifies the company responsible for development and support of the driver. This entry is used in the IVI Configuration Store registration as well as in the implementation of the Vendor attribute.


Help Page, All Drivers Per-User Preferences

This options on this page control some of the default settings used when creating help projects for IVI-COM, IVI.NET, and IVI-C drivers.

Help formats
Help 1.x (chm)

This setting controls whether or not a self-contained .chm file will be generated. When enabled, the associated driver installer (if any) will deploy this file to the end-user machine.

Help Viewer

This setting controls whether or not driver help content will be generated for the Microsoft Help Viewer , which is used by Visual Studio. When enabled, the associated driver installer (if any) will integrate the driver help content into the Microsoft Help Viewer on the end-user's machine.

Register content with Help Viewer on build

This setting controls whether or not the driver help content will be automatically registered with the Microsoft Help Viewer on your machine whenever the driver help project is built. This setting has no effect on the end-user's machine.

To preview the generated help content from within Visual Studio, right click on the help project node in the Solution Explorer and selecting View in Help Viewer.

Sign content with a code-signing certificate

Enables signing sign of the help content to be integrated with the Microsoft Help Viewer. Signed help content can be silently installed without the Microsoft Help Viewer without displaying a security warning to the end-user. Refer here for more information on signing Microsoft Help Viewer content.

Certificate thumbprint

The certificate thumbprint of the code-signing certificate to use for signing the help content.

Use the Browse button to bring up a dialog that can be used to conveniently select the thumbprint from certificates installed on the local machine.

See Also

Other Resources

Signing Microsoft Help Viewer Content
Microsoft Help Viewer


IVI.NET Per-User Preferences

The topics in this section present per-user settings for IVI.NET drivers.

In This Section

General Page, IVI.NET Driver Per-User Preferences

I/O Page, IVI.NET Driver Per-User Preferences


General Page, IVI.NET Driver Per-User Preferences

The options on this page control some of the default settings that appear on the General page of the New Project Wizard for IVI.NET drivers.

General information
Assembly name prefix

This entry controls the name of the .NET assembly. The IVI specifications require that this prefix represent the driver vendor.

Projects
Create IVI.NET unit test project

Causes the IVI.NET Driver Wizard to default to including a unit test project in new IVI.NET driver solutions.

Create IVI.NET help project

Causes the IVI.NET Driver Wizard to default to including a driver help project in new IVI.NET driver solutions.

Create IVI.NET setup project

Causes the IVI.NET Driver Wizard to default to including a driver setup project in new IVI.NET driver solutions.

Create IVI.NET C# application

Causes the IVI.NET Driver Wizard to default to including a sample C# console application in new IVI.NET driver solutions.

Create IVI.NET Visual Basic application

Causes the IVI.NET Driver Wizard to default to including a sample Visual Basic .NET application in new IVI.NET driver solutions.

Create IVI-C driver

Causes the IVI.NET Driver Wizard to default to including an IVI-C driver project that is linked to the IVI.NET driver in new IVI.NET driver solutions.

Create IVI-C driver help

Causes the IVI.NET Driver Wizard to default to including an IVI-C driver help project in new IVI.NET driver solutions.

Create IVI-C driver setup

Causes the IVI.NET Driver Wizard to default to including an IVI-C driver setup project in new IVI.NET driver solutions.

Create IVI-C driver unit test

Causes the IVI.NET Driver Wizard to default to including an IVI-C driver unit test project in new IVI.NET driver solutions.

Create IVI-C driver C++ application

Causes the IVI.NET Driver Wizard to default to including an IVI-C driver C++ appliction in new IVI.NET driver solutions.

Note Note

These settings just control the initial configuration of the New IVI.NET Driver Wizard. You will have the chance to make different choices when the wizard is actually run.

See Also

Other Resources

Using The IVI.NET Driver Wizard


I/O Page, IVI.NET Driver Per-User Preferences

The settings on this page are identical to those found on the I/O Property Page for an IVI.NET driver project. The selections made here control how the driver is intially created. These settings can be changed on a specific driver project at any time using the I/O Property Page. Refer to that topic for more information.

See Also

Other Resources

I/O Page, IVI.NET Driver Settings


IVI-COM Per-User Preferences

The topics in this section present per-user settings for IVI-COM drivers.

In This Section

General Page, IVI-COM Driver Per-User Preferences

I/O Page, IVI-COM Driver Per-User Preferences


General Page, IVI-COM Driver Per-User Preferences

The options on this page control some of the default settings that appear on the General page of the New Project Wizard for IVI-COM drivers.

General information
.NET assembly name prefix

This entry controls the name of the .NET interop assembly as well as that of any .NET policy files shipped with the driver. The IVI specifications require that this prefix represent the driver vendor. The full name of the .NET assemblies based on this prefix is displayed in the .NET assembly name text box just below this entry.

For more information on .NET interop assemblies, see the topic Supporting .NET Client Applications.

For more information on .NET policy files, see the topic Understanding .NET Versioning.

IVI-C prefix 2-letter abbreviation

Specifies the first two letters of the IVI-C wrapper prefix. This is generally a prefix associated with the driver vendor.

Projects
Create IVI-COM unit test

Specifies whether a Visual C# unit test project for the IVI-COM driver should be created and added to the driver solution.

Nimbus provides advanced IVI-COM driver unit testing features that integrate directly with the Visual Studio IDE. For more information, see the topic Testing an IVI-COM Driver.

Create help project

Specifies whether an IVI-COM driver help project for the IVI-COM driver should be created and added to the driver solution. The project is generated based on your per-user preferences for help projects.

Create setup project

Specifies whether an IVI-COM driver setup project for the IVI.NET driver should be created and added to the driver solution.

Create IVI-COM C++ application

This option creates a starter Visual C++ project for exercising the IVI-COM driver. The project is generated with the appropriate references, declarations, initialization and shutdown calls as well as basic error checking code. This project is a good starting point for building more involved C++ client applications or for simply testing driver operation in C++.

Create IVI-COM C# application

This option creates a starter Visual C# project for exercising the IVI-COM driver. The project is generated with the appropriate references, declarations, initialization and shutdown calls as well as basic error checking code. This project is a good starting point for building more involved C# client applications or for simply testing driver operation in C#.

Create IVI-COM Visual Basic application

This option creates a starter Visual Basic.NET project for exercising the IVI-COM driver. The project is generated with the appropriate references, declarations, initialization and shutdown calls as well as basic error checking code. This project is a good starting point for building more involved Visual Basic client applications or for simply testing driver operation in Visual Basic.

Create IVI-C wrapper

Specifies whether IVI-C wrapper generation should be enabled..

Create IVI-C unit test

Specifies whether a Visual C++ unit test project for the IVI-C wrapper should be created and added to the driver solution.

Nimbus provides advanced IVI-C driver unit testing features that integrate directly with the Visual Studio IDE. For more information, see the topic Testing an IVI-C Wrapper.

Create IVI-C C++ application

This option creates a starter Visual C++ project for exercising the IVI-C driver. The project is generated with the appropriate references, declarations, initialization and shutdown calls as well as basic error checking code. This project is a good starting point for building more involved IVI-C client applications or for simply testing the IVI-C wrapper operation.

Create MATLAB wrapper

This setting controls whether Nimbus will generate a MATLAB wrapper for the driver.

For more information on MATLAB wrappers, see the topic Developing a MATLAB Driver.

Note Note

These settings just control the initial configuration of the New IVI-COM Driver Wizard. You will have the chance to make different choices when the wizard is actually run.

See Also

Other Resources

Using the IVI-COM Driver Wizard


I/O Page, IVI-COM Driver Per-User Preferences

The settings on this page are identical to those found on the I/O Property Page for an IVI-COM driver project. The selections made here control how the driver is intially created. These settings can be changed on a specific driver project at any time using the I/O Property Page. Refer to that topic for more information.

See Also

Other Resources

I/O Page, IVI-COM Driver Settings


IVI-C Per-User Preferences

The topics in this section present per-user settings for IVI-C drivers.

In This Section

General Page, IVI-C Driver Per-User Preferences

I/O Page, IVI-C Driver Per-User Preferences


General Page, IVI-C Driver Per-User Preferences

The options on this page control some of the default settings that appear on the General page of the New Project Wizard for IVI-C drivers.

General options for IVI-C drivers
Create unit test

Causes the IVI-C Driver Wizard to default to including a unit test project in new IVI-C Driver solutions.

Create help project

Causes the IVI-C Driver Wizard to default to including a driver help project in new IVI-C Driver solutions.

Create setup project

Causes the IVI-C Driver Wizard to default to including a driver setup project in new IVI-C Driver solutions.

Create C++ application

Causes the IVI-C Driver Wizard to default to including a sample C++ console application in new IVI-C Driver solutions.

Note Note

These settings just control the initial configuration of the New IVI-C Driver Wizard. You will have the chance to make different choices when the wizard is actually run.

Code generation
Automatically generate getter functions for IVI-C attributes

This setting controls whether getter functions are automatically generated when an IVI-C attribute is added to the driver.

Getter function prefix

This setting controls the name of automatically generated IVI-C attribute getter functions. For example, if an attribute named OUTPUT_VOLTAGE is created, and this setting is chosen to be Get, Nimbus will automatically generate an IVI-C getter function named GetOutputVoltage.

The name resulting from selections made here represent the initial name given to the getter function. Individual getter functions can be renamed as desired.

Automatically generate setter functions for IVI-C attributes

This setting controls whether setter functions are automatically generated when an IVI-C attribute is added to the driver.

Setter function prefix

This setting controls the name of automatically generated IVI-C attribute setter functions. For example, if an attribute named OUTPUT_VOLTAGE is created, and this setting is chosen to be Set, Nimbus will automatically generate an IVI-C setter function named SetOutputVoltage.

The name resulting from selections made here represent the initial name given to the setter function. Individual setter functions can be renamed as desired.

See Also

Other Resources

Using The IVI-C Driver Wizard
Adding Attribute Getter and Setter Functions


I/O Page, IVI-C Driver Per-User Preferences

The settings on this page are identical to those found on the I/O Property Page for an IVI-C driver project. The selections made here control how the driver is intially created. These settings can be changed on a specific driver project at any time using the I/O Property Page. Refer to that topic for more information.

See Also

Other Resources

I/O Page, IVI-C Driver Settings


Understanding IVI-C Driver Development Options

Nimbus provides three options for creating an IVI-C driver -- a standalone IVI-C driver, an IVI-C wrapper on top of an IVI-COM driver, and a linked IVI-C driver developed as part of an IVI.NET driver solution. Standalone IVI-C drivers and IVI-C drivers linked to IVI.NET are new with Nimbus 4, while IVI-C wrappers on IVI-COM drivers work the same in Nimbus 4 as they have for years in prior versions of Nimbus. This topic discusses all three options for IVI-C driver development.

Standalone IVI-C Drivers

Standalone IVI-C drivers are created by running the New Project Wizard and selecting IVI-C Driver. Standalone IVI-C drivers are developed using native C++ code without any reliance on an underlying IVI-COM driver. These drivers have easy-to-read source code that uses the C++ Standard Library, instead of COM and the Active Template Library (ATL), as is used with IVI-C wrappers on IVI-COM drivers. This has a number of important advantages, including making it much easier for the end user to browse the source code and potentially understand more about how the instrument works. It also makes the debugging experience (for developers and end users) much more intuitive.

Standalone IVI-C drivers will often use the VISA library for instrument communication and Nimbus can be instructed to automatically implement message-based IVI-C drivers using standard VISA library functions such as viPrintf, viScanf, and viQueryf.

Important note Important

When choosing to develop a standalone IVI-C driver, it is important to realize that the standalone IVI-C driver cannot be linked to an IVI-COM driver or IVI.NET driver in the future. Once created, standalone IVI-C drivers must always be developed, implemented, and maintained independently of any other driver (IVI-COM or IVI.NET), even all of the drivers are being developed for the same instrument. For this reason, it is advisable to consider the benefits of creating an IVI-C driver linked to IVI-COM or IVI.NET if one of those driver types may be desired for the same instrument.

IVI-C Wrappers on IVI-COM Drivers

IVI-C wrappers on IVI-COM drivers are created by running the New Project Wizard and selecting IVI-COM Driver and then enabling IVI-C wrapper support on the Features page of the New IVI-COM Driver Wizard.

IVI-C wrappers on IVI-COM drivers expose both the IVI-C and IVI-COM driver interfaces from a single DLL. All of the functionality of the driver is typically implemented in the IVI-COM methods and properties and Nimbus automatically generates IVI-C entry points that simply delegate to the underlying IVI-COM implementation.

IVI-C wrappers can be developed very rapidly as part of an IVI-COM driver because Nimbus automatically adds functionality to the IVI-C wrapper as the driver developer adds functionality to the IVI-COM driver. Moreover, Nimbus keeps the IVI-C wrapper functions synchronized with the IVI-COM methods. For instance, changing a method name or removing a parameter in the IVI-COM Driver Designer causes Nimbus to automatically effect the corresponding change to the IVI-C function or parameter.

The primary advantage that IVI-C wrappers on IVI-COM have is that in nearly all cases, only a single implementation is required. For non-messaged-based drivers that cannot leverage the auto-generated VISA-based features of Nimbus, manual implementation of methods and properties is required. This manual implementation code need only be implemented once -- in the IVI-COM driver, and the IVI-C wrapper code simply delegates to the single IVI-COM implementation.

Similarly, any customizations to the driver initialization and shutdown sequence need only be implemented once in the IVI-COM driver and the IVI-C wrapper can leveraged all of that implementation.

The primary disadvantage of IVI-C wrappers on IVI-COM is that the source code is dizzingly complex. Since all of the implementation code is implemented in the IVI-COM driver, both the driver developer and the end user must contend with all of the complexities of COM and ATL, both of which are very unfamiliar to most developers and end users.

In addition to the inherent complexities of COM itself are the mechanics of delegating from IVI-C functions to IVI-COM methods. This involves translating from COM data types to and from IVI-C data types. These translations also come with a performance penalty which is not always insignificant. For instance, the memory models of IVI-COM and IVI-C are "opposite" of one another in that memory for output parameters is allocated by the caller in IVI-C (the client program) and by the callee (the driver method) in IVI-COM. Bridging those two memory models often requires performing extra buffer copies, which can become considerable when passing large amounts of data into and out of drivers.

In spite of its shortcomings, building IVI-C wrappers on IVI-COM drivers has been a very popular and successful feature for many driver developers using Nimbus for many years. It remains a very viable option worthy of consideration.

IVI-C Drivers Linked to IVI.NET

IVI-C drivers can also be linked to an IVI.NET driver and developed simultaneously with the IVI.NET driver in an analagous fashion to IVI-C wrappers being developed simultaneously with an IVI-COM driver. IVI-C drivers linked to IVI.NET are structurally identical to standalone IVI-C drivers -- the internals of the driver project, the unit test project, the help project, and the setup project are exactly the same as if the IVI-C driver was being developed on its own.

IVI-C drivers are linked to IVI.NET in the sense that adding methods and properties to an IVI.NET driver automatically creates a corresponding function or attribute in the linked IVI-C driver, just as with IVI-C wrappers on IVI-COM. This gives IVI-C drivers linked to IVI.NET much of the same productivity gains as IVI-C wrappers on IVI-COM -- design data is entered in one place and rendered in both drivers.

The key difference between developing IVI-C drivers linked to IVI.NET and IVI-C wrappers on top of IVI-COM is that the implementation code is completely indepedent between IVI-C drivers linked to IVI.NET and their IVI.NET driver counterpart. Unlike IVI-C wrappers on IVI-COM where Nimbus would generate implementation code in the IVI-COM driver and have the IVI-C wrapper delegate, Nimbus generates two completely independent implementations for linked IVI-C and IVI.NET drivers. For message-based devices, the IVI.NET implementation is realized using VISA.NET functions and an independent implementation is realized using VISA-C functions in the linked IVI-C driver.

Since IVI-C drivers linked to IVI.NET are structurally identical to standalone IVI-C drivers, this option has the advantages of both approaches -- the source code simplicity of standalone IVI-C along with the design-time productivity of IVI-C wrappers on IVI-COM.

Also like their standalone counterparts, IVI-C drivers linked to IVI.NET inherit some of the same disadvantages. The key disadvantage is that manually implemented functionality must be manually implemented in both the IVI.NET driver and IVI-C driver -- no code is shared between the two implementations. This manual implementation code might simply be a few methods and properties, or, for non-message-based devices, it might be all of the methods and properties in the driver. Even for message-based devices which leverage the auto-implementation features of Nimbus, any customizations to the initialization and shutdown sequence must be duplicated in both the IVI.NET and IVI-C drivers.

Comparing IVI-C Driver Development Options

The table below summarizes many of the important differences between the three options for build IVI-C drivers with Nimbus.

Feature | Standalone IVI-C Driver | IVI-C Wrapper on IVI-COM | IVI-C Linked to IVI.NET
Functionality management | Independent | Auto-synchronized with IVI-COM | Auto-synchronized with IVI.NET
Installer | Standalone | Always installed with IVI-COM | Standalone
Help file | Standalone | Integrated with IVI-COM help | Standalone
Versioning | Independent | Always versioned with IVI-COM | Independent
Source code technology | C++ Standard Library | COM with ATL | C++ Standard Library
Source code complexity | Straightforward | Complex | Straightforward
Message-based implementation | Auto-generated using VISA-C | Delegates to IVI-COM | Auto-generated using VISA-C
Non-message-based implementation | Manually implemented | Delegates to IVI-COM | Manually implemented (independent of IVI.NET)
Initialization and shutdown customization | Manually implemented | Delegates to IVI-COM | Manually implemented (independent of IVI.NET)
Performance | Fast | Impacted by data type conversions | Fast


Developing an IVI.NET Driver

Developing an IVI driver involves a number of tasks. The New IVI.NET Wizard is used to create the driver project. Various Nimbus features integrated into the Visual Studio IDE allow functionality to be added to the driver, while the Nimbus Class Library provides a rich set of support functions for implementing these features.

In This Section

Understanding Nimbus Code Weaving

Creating an IVI.NET Driver Project

Visual Studio Projects for an IVI.NET Driver

Accessing Driver Settings

Adding Functionality to an IVI.NET Driver

IVI.NET Item Editors

Implementing Driver Methods and Properties

Implementing Dynamic Repeated Capabilities

State Caching Overview

Customizing Config Store Registration

Testing an IVI.NET Driver

Nimbus Class Library


Understanding Nimbus Code Weaving

Nimbus-based IVI.NET drivers utilize a powerful technology referred to as code weaving. In Nimbus, code weaving is characterized by the following.

  • Attributes defined in the Nimbus Class Library are applied to method, property and event declarations. These attributes express one or more desired behaviors that the driver developer would like the Nimbus code weaver to supply automatically. Examples of code weaver supplied behaviors include, but are not limited to, simulation (SimulationAttribute), caching (CacheAttribute), and range checking (RangeCheckMinMaxAttribute, RangeCheckDiscreteAttribute).

  • As you use the Nimbus driver designer to enable, disable and configure various options (simulation, range checking, etc), the designer adds, removes and updates code weaver attributes in the source code automatically.

  • When the driver project is built, the compiler produces a driver assembly (for example, Acme.Acme4321.Fx20.dll). The desired behaviors expressed as attributes in the source code are encoded by the compiler as-is in the resulting binary, and are available for use by the Nimbus code weaver.

  • After the compiler builds the driver assembly, the Nimbus code weaver runs, analyzing all of the attributes applied to driver methods, properties and events. Based on the desired behaviors expressed by attributes, the code weaver rewrites the implementations of driver methods, properties and events so that each is augmented with the additional behaviors expressed by the attributes that were applied.

    Note Note

    Nimbus code weaving does not use reflection to provide the requested behaviors at runtime. Instead, the compiler-produced implementation of each driver method, property and event is rewritten at build time so that it includes the original developer implementation as well as the code weaver-supplied behaviors. This means that driver methods, properties and events have the identical performance characteristics as methods, properties and events that are not processed by the code weaver and instead perform the same operations (simulation, range checking, etc) manually using developer-supplied code.

  • Code weaver attributes can only be applied to instance (not static) properties, methods and events defined on the following:

    • Classes that derive from the DriverNode class, or that implement the IDriverNode interface.

    • Structures that implement the IDriverNode interface.

    The Nimbus driver designer handles this automatically for any code it adds to your driver.

  • Nimbus code weaving is enabled by default for the driver project, and any method, property or event created by the designer. However, code weaving may be disabled for the entire driver project, or disabled selectively for individual methods, properties or events.

Consider the simple driver property shown below.

C#
Copy
[DriverProperty]
public double Frequency
{
    get
    {
        this.IO.FormattedIO.PrintfAndFlush("FREQ:RANG\n");
        double value;
        this.IO.FormattedIO.Scanf("%g", out value);

        return value;
    }
    set
    {
        this.IO.FormattedIO.PrintfAndFlush("FREQ:RANG %0.15g\n", value);
    }
}

If code weaving is disabled for the driver, then viewing the disassembled code in the driver assembly using a tool such as .NET Reflector would look as shown below in Figure 1.

Figure 1: A Driver Property with Code Weaving Disabled

Note that the disassembled view of the property's binary implementation looks nearly identical to the original source code. However, if code weaving is enabled (which is the default), then the disassembled code as viewed using .NET Reflector would look as shown below in Figure 2.

Figure 2: A Driver Property with Code Weaving Enabled

Note that in addition to the recognizable developer-supplied code, the Nimbus code weaver has injected a call to an AcquireLock method, which is a Nimbus Class Library method that provides standard IVI.NET-defined thread synchronization. The lock acquired by that method is automatically released at the conclusion of the using construct shown in Figure 2, where its implementation of IDisposable.Dispose is called.

Note that in addition to providing IVI.NET-standard thread synchronization, the code weaver has also injected a call to CheckDisposed, which implements the .NET standard idiom of checking to see if the driver object is being used after its own IDisposable.Dispose method has been called.

If the Nimbus driver designer is now used to enable simulation for this property (specifying a default value in simulation mode equal to 50), the source code would automatically be updated by the designer to look like this:

C#
Copy
[DriverProperty]
[Simulation(SimulationMode.LastValue, Default = "5.000000E+001")]
public double Frequency
{
    get
    {
        this.IO.FormattedIO.PrintfAndFlush("FREQ:RANG\n");
        double value;
        this.IO.FormattedIO.Scanf("%g", out value);

        return value;
    }
    set
    {
        this.IO.FormattedIO.PrintfAndFlush("FREQ:RANG %0.15g\n", value);
    }
}

When the driver is rebuilt, .NET Reflector would reveal the implementation of the property to be similar to what's shown in Figure 3.

Figure 3: A Driver Property with Simulation Enabled

Note that in addition to the standard driver property preamble, the code weaver injected a call to the this.Session.InitOptions.SimulationEnabled property (to see if simulation has been enabled via the driver's setup option) into both the property getter and setter. If simulation is enabled, and because the simulation style requested via the attribute is SimulationMode.LastValue, the code weaver modified the getter to return the previously cached value (if any) or the requested default value of 50. Likewise, the property setter was modified to cache any new property values passed to the setter.

Finally, if the Nimbus driver designer is now used to enable range checking of values being passed to the setter to enforce that values must be between 0 (exclusive) and 300 (inclusive), the source code would automatically be updated by the designer to look like this:

C#
Copy
[DriverProperty]
[Simulation(SimulationMode.LastValue, Default = "5.000000E+001")]
[RangeCheckMinMax(0, 300, MaxInclusive = true)]
public double Frequency
{
    get
    {
        this.IO.FormattedIO.PrintfAndFlush("FREQ:RANG\n");
        double value;
        this.IO.FormattedIO.Scanf("%g", out value);

        return value;
    }
    set
    {
        this.IO.FormattedIO.PrintfAndFlush("FREQ:RANG %0.15g\n", value);
    }
}

When the driver is rebuilt, .NET Reflector would reveal the implementation of the property to be similar to what's shown in Figure 4.

Figure 4: A Driver Property with Simulation and Range Checking Enabled

With this modification in place, the Nimbus code weaver has now also modified the property setter to check whether range checking has been enabled (this.Session.InitOptions.RangeCheckingEnabled) and, if so, use the ErrorService class to throw an IVI.NET standard exception if the value passed into the setter was out of range.

Note Note

In this case, note that the Nimbus code weaver used the minimum and maximum values indicated by the RangeCheckMinMaxAttribute attribute to directly inject the requested range checking behavior without the need for additional method calls.

The topics listed below provide additional information on working with the Nimbus code weaver.

In This Section

Controlling Locking

Suppressing Code Weaving

Stepping Into or Over Injected Calls to NCL Code

See Also

Other Resources

Using the Nimbus Driver Designer
Nimbus Class Library
Nimbus Class Library Code Weaver Attributes
Building the IVI.NET Driver
Attributes (MSDN)
.NET Reflector


Controlling Locking

By default, the Nimbus code weaver will ensure that driver methods, properties and events have the following thread synchronization characteristics:

  1. Access to the driver method, property or event will be serialized such that only one thread at a time may enter the body of the method, property or event for the same instance of a driver object.

  2. An infinite timeout will be used to wait for ownership of the underlying lock.

The code weaver accomplishes this by injecting a call to the AcquireLock method defined within the Nimbus Class Library, which in turn uses the IVI.NET standard LockManager class.

For example, consider the driver property shown below, which shows a common use of the DriverProperty attribute.

C#
Copy
[DriverProperty]
public TriggerSource Source
{
    get
    {
        this.IO.FormattedIO.PrintfAndFlush("TRIG:SOUR?\n");
        Acme.Acme4321.TriggerSource value;
        this.IO.FormattedIO.Scanf("%s", out value);

        return value;
    }
    set
    {
        this.IO.FormattedIO.PrintfAndFlush("TRIG:SOUR %s\n", value);
    }
}

When built and viewed in .NET Reflector, that property would be implemented as shown in Figure 1.

Figure 1: Default Locking with the DriverProperty Attribute (as seen in .NET Reflector)

Notice that, as seen in the disassembled code, the Nimbus code weaver has injected a call to AcquireLock without any parameters, which implies a willingness to wait for an unbounded period of time for entry into the body of the property.

This default behavior can be modified in two ways, depending on your needs:

  • A non-infinite timeout may be specified. The procedure for making this customization is described here.

  • Locking may be disabled altogether. The procedure for making this customization is described here.

Specify a non-infinite lock timeout

  1. From the driver designer, right click on the property, method or event for which you wish to customize locking and select Go to Implementation.

  2. Locate the DriverProperty, DriverMethod or DriverEvent attribute that appears above the implementation.

  3. Update the attribute declaration to set the named parameter LockTimeoutMilliseconds to a non-zero value that expresses the maximum amount of time, in milliseconds, that blocked threads should wait before entering the associated method, property or event body. The following example illustrates setting the maximum lock timeout for a driver property to 5000 milliseconds.

    C#
    Copy
    [DriverProperty(LockTimeoutMilliseconds = 5000)] // Non-infinite lock timeout specified.
public TriggerSource Source
{
    get
    {
        this.IO.FormattedIO.PrintfAndFlush("TRIG:SOUR?\n");
        Acme.Acme4321.TriggerSource value;
        this.IO.FormattedIO.Scanf("%s", out value);

        return value;
    }
    set
    {
        this.IO.FormattedIO.PrintfAndFlush("TRIG:SOUR %s\n", value);
    }
}

  4. Rebuild the driver.

    When built and viewed in .NET Reflector, that property would be implemented as shown in Figure 2.

    Figure 2: Specifying a non-Infinite Lock Timeout (as seen in .NET Reflector)

    Notice that, as seen in the disassembled code, the Nimbus code weaver has injected a call to AcquireLock(PrecisionTimeSpan), using the timeout value expressed in the DriverProperty attribute.

    Note Note

    If this technique is used, the underlying IVI.NET LockManager will raise an exception if the calling thread cannot acquire the requested lock within the user-defined timeout period.

Disable locking completely

  1. From the driver designer, right click on the property, method or event for which you wish to customize locking and select Go to Implementation.

  2. Locate the DriverProperty, DriverMethod or DriverEvent attribute that appears above the implementation.

  3. Update the attribute declaration to set the named parameter Lock to false, as shown below.

    C#
    Copy
    [DriverProperty(Lock = false)] // Locking disabled.
public TriggerSource Source
{
    get
    {
        this.IO.FormattedIO.PrintfAndFlush("TRIG:SOUR?\n");
        Acme.Acme4321.TriggerSource value;
        this.IO.FormattedIO.Scanf("%s", out value);

        return value;
    }
    set
    {
        this.IO.FormattedIO.PrintfAndFlush("TRIG:SOUR %s\n", value);
    }
}

  4. Rebuild the driver.

    Figure 3 shows the corresponding disassembled view in .NET Reflector.

    Figure 3: Disable Locking (as seen in .NET Reflector)

    Notice that the code weaver no longer performs any sort of thread synchronization.

    Caution note Caution

    Disabling lock acquisition completely is an advanced technique, and should only be used in cases where the developer is certain that the code being invoked does not need any thread synchronization (for example, a property that simply returns a constant value), or if the developer wants to use a different thread synchronization technique (for example, using the standard .NET Framework Class Library ReaderWriterLock).

See Also

Reference

DriverMemberAttribute
AcquireLock
AcquireLock(PrecisionTimeSpan)

Other Resources

Understanding Nimbus Code Weaving
Stepping Into or Over Injected Calls to NCL Code
Suppressing Code Weaving
Using the Nimbus Driver Designer
Nimbus Class Library
Attributes (MSDN)
.NET Reflector


Suppressing Code Weaving

Should the need arise, the Nimbus code weaver can be disabled in two different ways:

  • On a per-method, per-property or per-event basis. This approach allows you to exempt specific code members from code weaving without disabling code weaving for your entire driver. The procedure for this is described here.

  • On a project-wide basis. This approach allows you to disable (and later reinstate) code weaving for the entire driver. The procedure for this is described here.

Both approaches allow you to enable and disable code weaving as needed without requiring any changes to code you've written or designer-driven changes you may have made.

Disable code weaving for an individual method, property or event

  1. From the driver designer, right click on the property, method or event for which you wish to disable code weaving and select Go to Implementation.

  2. Locate the DriverProperty, DriverMethod or DriverEvent attribute that appears above the implementation.

  3. Update the attribute declaration to set the named parameter SuppressAll to true, as shown below for a Frequency property.

    C#
    Copy
    [DriverProperty(SuppressAll = true)] // Code weaving disabled for this property.
[Cache]
[InvalidateCacheEntries("Bandwidth")]
[RangeCheckMinMax(0, 300, MaxInclusive = true)]
public double Frequency
{
    get
    {
        this.IO.FormattedIO.PrintfAndFlush("FREQ:RANG\n");
        double value;
        this.IO.FormattedIO.Scanf("%g", out value);

        return value;
    }
    set
    {
        this.IO.FormattedIO.PrintfAndFlush("FREQ:RANG %0.15g\n", value);
    }
}

  4. Rebuild the driver.

    Note Note

    With this technique, other attributes that may have been added to your method, property or event by the driver designer are not modified and will remain in the source code. However, the Nimbus code weaver will ignore those attributes at build time as long as SuppressAll is set to true. To reinstate code weaving for the selected method, property or event, change the value of SuppressAll to false, or remove the use of the SuppressAll named parameter altogether.

Disable code weaving for the entire driver

  1. From Solution Explorer, right click on the driver project node (the C# assembly, not the Nimbus node) and choose Properties. This will display the standard project properties page for a C# class library assembly.

  2. Select the Build properties tab.

  3. Locate the Conditional compilation symbols field.

  4. If the Conditional compilation symbols field is empty, enter DisableNimbusCodeWeaving. If the Conditional compilation symbols field is not empty, enter a semicolon after the existing value(s), followed by DisableNimbusCodeWeaving. This is illutrated in Figure 2.

    Figure 2: Code Weaving Disabled for the Entire Driver

  5. Rebuild the driver.

    Note Note

    With this technique, code weaving can be enabled and disabled for the entire driver project without affecting the driver designer or any of your source code. To reinstate code weaving for your driver, simply remove the DisableNimbusCodeWeaving conditional compilation symbol.

See Also

Reference

DriverMemberAttribute

Other Resources

Understanding Nimbus Code Weaving
Stepping Into or Over Injected Calls to NCL Code
Controlling Locking
Using the Nimbus Driver Designer
Nimbus Class Library
Attributes (MSDN)


Stepping Into or Over Injected Calls to NCL Code

The steps outlined below explain how to step into or over the code that the Nimbus code weaver injects into driver methods, properties and events during code weaving.

Note Note

By default, Visual Studio steps over calls to property getters and setters. If you're trying to step into properties, follow the instructions here to configure Visual Studio to step into properties before proceeding.

The procedures below show the behavior of the Visual Studio debugger for the Configure method shown below.

C#
Copy
[DriverMethod]
[InvalidateCacheEntries("Frequency")]
public void Configure(double resBW, double videoBW, double sweepTime)
{
    if (this.Session.InitOptions.SimulationEnabled)
    {
        return;
    }

    this.IO.FormattedIO.PrintfAndFlush("SENS:BAND%0.15g; SWE:TIME%d; BAND:VID%3.2f;\n", resBW, sweepTime, videoBW);
}

Figure 1 illustrates what that method would look like after being built, when viewed using .NET Reflector.

Figure 1: A Configure Method (as seen in .NET Reflector)

Note that, based on the attributes applied to this method, the Nimbus code weaver has injected the standard thread synchronization preamble and object disposed check, as well as a call to the InvalidateCacheEntry(String) method, which is defined on the DriverNode base class that Nimbus-generated classes derive from.

Figure 2 shows a debugging session that's currently poised to call to that Configure method from within the standard Nimbus-generated unit test method.

Figure 2: Configure Method Unit Test

At this point, if you were to use the Visual Studio Step Over command (F10 typically), the Configure method would be invoked in its entirety, and then the debugger would stop on the closing curly brace at the end of the unit test method. However, if you were to use the Visual Studio Step Into command (F11 typically), the debugger would take you to the opening curly brace of the Configure method, as shown in Figure 3.

Figure 3: Stepping Into the Configure Method

Depending on what you do next, you can either step over the injected calls to Nimbus Class Library code, or step into the injected calls to Nimbus Class Library code.

Stepping Over Code Weaver-Injected Code

  • With execution positioned at the opening curly brace of a driver method, property accessor, event accessor, simply use the Step Over command (F10) to run until you reach the first line of code within your method, property or event body.

Stepping Into Code Weaver-Injected Code

  1. With execution positioned at the opening curly brace of a driver method, property accessor, event accessor, simply use the Step Into command (F11) to run until you reach the first line of code within your method, property or event body.

    For example, using the Step Into command (F11) when execution is positioned on the opening curly brace of the of the Configure method shown above will take you to the start of the AcquireLock method, as show in Figure 4.

    Figure 4: Stepping Into Nimbus Class Library Code

  2. Step through the Nimbus Class Library code as desired.

    Tip Tip

    To facilitate quickly getting back to the first line of code within the body of your driver method, property or event, set a breakpoint on the first line of code after the opening curly brace for your driver method, property or event before using the Step Into command (F11) to begin stepping through injected calls to Nimbus Class Library code. When you're ready to quickly proceed to the start of your driver method, property or event, use the debugger Continue command (F5 typically) to execute until your breakpoint is reached.

Configuring Visual Studio to Step Into Properties

  1. Click on Tools then Options to bring up the Visual Studio preference dialog.

  2. Expand the Debugging node in the tree view on the left and click on General. This will display several checkbox options on the right.

  3. Clear the checkbox labeled Step over properties and operators (Managed only). This is illustrated by Figure 5.

    Figure 5: Configuring Visual Studio to Step Into Properties
See Also

Other Resources

Understanding Nimbus Code Weaving
Controlling Locking
Suppressing Code Weaving
Nimbus Class Library
Testing an IVI.NET Driver
.NET Reflector


Creating an IVI.NET Driver Project

The first step in developing an IVI.NET driver is to create the IVI driver project. Nimbus supplies a custom project type to the Visual Studio project system just for this purpose. The topics in this section explain how to run the New IVI.NET Driver Wizard as well as the Visual Studio projects that are created in the process. Also, certain the topics in this section explain the Visual Studio settings that must be properly configured to build the IVI.NET driver project.

In This Section

Using the IVI.NET Driver Wizard

Required Visual Studio Configuration Changes

Building the IVI.NET Driver


Using The IVI.NET Driver Wizard

The first step in creating an IVI.NET driver is running the IVI.NET Driver Wizard. The wizard is launched from within the Visual Studio IDE, just as native Visual Studio project types.

To launch the New IVI.NET Driver Wizard

  1. From within Visual Studio, click on the File menu, select New and then choose Project.

  2. The standard Visual Studio New Project Dialog appears.

  3. Under Installed Templates on the left, choose IVI.NET Projects and then select IVI.NET Driver from the list of templates displayed.

  4. Review the Name suggested for the new IVI.NET driver project at the bottom of the dialog, changing it if desired.

  5. Review the directory Location suggested for the new IVI.NET driver project, changing it if desired.

  6. Review the Solution name and other settings suggested for the new IVI.NET driver project, changing them if desired.

  7. Press the OK button.

  8. The IVI.NET Driver Project Wizard appears.

  9. The New IVI.NET Driver Wizard appears.

Tip Tip

When filling out the wizard pages, keep in mind that any of the options selected can be changed later using the Driver Settings Editor, IVI.NET Driver Help Project Properties, and IVI.NET Driver Setup Project Properties.

The remaining topics in this section discuss each wizard page separately.

In This Section

General Page, New IVI.NET Driver Wizard

Instrument Class Page, New IVI.NET Driver Wizard

LXI Compliance Page, New IVI.NET Driver Wizard

Projects Page, New IVI.NET Driver Wizard

See Also

Other Resources

Visual Studio Projects for an IVI.NET Driver


General Page, New IVI.NET Driver Wizard

The General Page of the New IVI.NET Driver Wizard presents basic information about the IVI.NET driver project.

Driver name

The driver name is the primary identifier for the entire IVI.NET driver project. Virtually all names associated with the driver will be based on the driver name. The driver DLL, the IVI Configuration Store entries, the driver interfaces, the main driver class, and many other items are based on this entry.

Instrument manufacturer

The instrument manufacturer is used to identify the manufacturer of the instrument for which the driver is being written. This entry is used in the IVI Configuration Store registration as well as in the implementation of the IIviDriver.InstrumentManufactuer property.

Driver vendor

The driver vendor identifies the company responsible for development and support of the driver. This entry is used in the IVI Configuration Store registration as well as in the implementation of the IIviDriverComponentIdentity.Vendor property.

Assembly name prefix

This entry controls the name of the .NET assembly. The IVI specifications require that this prefix represent the driver vendor. The full name of the .NET assembly based on this prefix is displayed in the Assembly name text box just below this entry.

Assembly name

This is a read-only field that displays the .NET assembly name resulting from the choice entered in the Assembly name prefix field

Instrument model

The name of the instrument model for which the driver is being written. The driver must be able to use this string to identify the actual connected instrument during driver initialization, such as through the use of a "*IDN?" query. See the topic Understanding the Initialization Sequence for information on identifying the connected model.

If the driver is to support multiple instrument models, enter one of the most common models here. The Models Page of the Driver Settings Editor can be used to add models to the driver. See the topic Adding Support for Multiple Instrument Models for more information on multi-model drivers.


I/O Page, New IVI.NET Driver Wizard

Enable VISA-based I/O

This setting controls whether the driver uses the VISA.NET for instrument communication.

Integer format

Specifies the default format code to use for integer values in instrument command strings. Explicit format codes used in the instrument command override this setting.

See the topics under Working With Instrument Commands for more information.

Floating-point format

Specifies the default format code to use for floating-point values in instrument command strings. Explicit format codes used in the instrument command override this setting.

See the topics under Working With Instrument Commands for more information.

String format

Specifies the default format code to use for string values in instrument response strings. Explicit format codes used in the instrument command override this setting. This setting is only used for reading values from the instrument -- not for formatting values sent to the instrument.

See the topics under Working With Instrument Commands for more information.

Boolean True

Specifies a comma-separated list of instrument responses that should be interpreted as a boolean true. For instrument commands, the first string in the list will be used to send a boolean true to the device.

Boolean False

Specifies a comma-separated list of instrument responses that should be interpreted as a boolean false. For instrument commands, the first string in the list will be used to send a boolean false to the device.

SCPI compliant

Indicates whether the instrument uses SCPI-compliant instrument commands. Nimbus provides specialized support for SCPI-compliant instruments. See the topic Special Features For SCPI Commands for detailed information.

Generate direct I/O functions and attributes

This setting controls whether the wizard will generate the IVI-defined methods and properties for directly communicating with the instrument using the underlying I/O mechanism. For a driver using VISA.NET as its underlying I/O library, Nimbus will generate a working implementation of these methods and properties. For a non-VISA-based driver, Nimbus will generate stub implementations that the driver developer must then fill in with an implementation appropriate for their specific I/O library.

The exact syntax and behavior of these functions is prescribed in IVI-3.4: API Sytle Guide.

Important note Important

In order to comply with the IVI Generation IVI-2014, drivers must implement these direct I/O methods and properties. These methods and properties can be created after the wizard runs, but it is typically easier to let the wizard create them upfront.

Enable simulation code generation

Determines whether or not Nimbus ever generates automatic simulation handling code. When true, Nimbus enables the Simulation Editor for properties so that the developer can choose on a property-by-property basis whether or not to instruct Nimbus to generate simulation handling code. Nimbus also generates "stub" simulation code blocks for methods so that the developer has a convenient place to insert their manual method simulation code.

When this setting is false, all properties are set to Manual simulation mode, and the Simulation Editor is disabled. Nimbus also does not generate "stub" simulation code blocks for methods in this case.

This setting is useful in situations where a lower-level software component is handling all of the simulation logic, and the Nimbus driver is simply delegating to that lower-level component. In such cases, it's inconveninet for the developer to explicitly set all properties to Manual simulation mode and to delete all residual and unneeded simulation code generated for methods and properties. With this setting, the developer can simply disable simulation code generation "globally".

See Also

Other Resources

Communicating With Instruments
Working With Instrument Commands
Special Features for SCPI Commands


Instrument Class Page, New IVI.NET Driver Wizard

The IVI Instrument Classes Page of the New IVI.net Driver Wizard allows you to select which IVI instrument classes the driver supports. Check the box next to each instrument class you wish to support. Nimbus automatically adds the appropriate references to the driver project and creates code for implementing and testing the IVI-defined methods and properties in the selected instrument classes.

Note Note

It is not necessary to decide which instrument classes will be supported when running the wizard. Support for specific instrument classes can be added and removed at any stage of development using commands available within the IDE. See the topic Adding Support for an Instrument Class for more information.

See Also

Other Resources

How IVI Drivers Provide Interchangeability
Adding Support for an Instrument Class


LXI Compliance Page, New IVI.NET Driver Wizard

The LXI Compliance Page of the New IVI.NET Driver Wizard allows you to select whether the instruments support LXI and which LXI extension groups are supported. Based upon the selections made here, Nimbus automatically creates a project with the appropriate LXI repeated capabilities and repeated capability names and the required IviLxiSync functions and attributes.

Note Note

It is not necessary to decide upon the degress of LXI compliance when running the wizard. Support for LXI can be added and removed at any stage of development using commands available within the IDE. See the topic Adding Support for LXI for more information.

Conformance

Indicates whether the driver supports any level of LXI conformance. No modifications are performed based on this selection alone, but by selecting LXI Core 2016, the checkboxes for the various LXI-defined extension groups become enabled and selecting those extension groups does cause Nimbus to modify the driver code.

LXI Extension Groups

Selecting any of the LXI-defined extension groups adds the IviLxiSync functions, attributes, and repeated capabilities to the driver.

For the added repeated capabilities, Nimbus adds the LXI-defined repeated capability names for LAN triggers (LAN0...7).

If LXI Wired Trigger Bus is selected, Nimbus adds LXI-defined repeated capability names for the LXI hardware trigger lines (LXI0...7).

See Also

Other Resources

Adding Support for LXI


Features Page, New IVI.NET Driver Wizard

The Features Page of the New IVI.NET Driver Wizard allows you to select various IVI driver features, such as adding a linked IVI-C driver.

Create an IVI-C driver linked to this IVI.NET driver

This setting controls whether Nimbus will generate an IVI-C driver linked to this IVI.NET driver.

For more information on IVI-C drivers, see the topic Developing an IVI-C Driver.

Prefix

If IVI-C drivergeneration is enabled, this setting controls the IVI-C prefix for the driver. This prefix is very important as it controls the name of many items associated with the driver. The driver DLL itself will be named using this prefix. The names of all IVI-C functions and attributes begin with this prefix. Additionally, the driver install location is governed by the prefix chosen here.

Important note Important

The IVI specifications require that the first two letters of this prefix match the official two-letter abbreviation assigned to the driver vendor by the IVI Foundation in the specification "VPP-9: Instrument Vendor Abbreviations" . If the driver vendor does not have an assigned two-letter prefix, one can be obtained from the IVI Foundation. Visit the IVI Foundation website for details.

Instrument class

Unlike IVI.NET drivers, IVI-C drivers can only support a single instrument class. This is a fundamental limitation of all IVI-C drivers and stems from the fact that IVI-C attributes are defined with numeric identifiers that are not unique across the various instrument classes. See the IVI Backgrounder section on Interchangeability for more information on this IVI-C limitation.

This setting selects which of the supported IVI.NET driver instrument classes should be supported by the IVI-C driver.

Automatically generate getter functions for IVI-C attributes

This setting controls whether getter functions are automatically generated when an IVI-C attribute is added to the driver.

Getter function prefix

This setting controls the name of automatically generated IVI-C attribute getter functions. For example, if an attribute named OUTPUT_VOLTAGE is created, and this setting is chosen to be Get, Nimbus will automatically generate an IVI-C getter function named GetOutputVoltage.

The name resulting from selections made here represent the initial name given to the getter function. Individual getter functions can be renamed as desired.

Automatically generate setter functions for IVI-C attributes

This setting controls whether setter functions are automatically generated when an IVI-C attribute is added to the driver.

Setter function prefix

This setting controls the name of automatically generated IVI-C attribute setter functions. For example, if an attribute named OUTPUT_VOLTAGE is created, and this setting is chosen to be Set, Nimbus will automatically generate an IVI-C setter function named SetOutputVoltage.

The name resulting from selections made here represent the initial name given to the setter function. Individual setter functions can be renamed as desired.

See Also

Other Resources

Developing an IVI-C Driver
Adding Attribute Getter and Setter Functions


Projects Page, New IVI.NET Driver Wizard

The Projects Page of the New IVI.NET Driver Wizard allows you to select which additional Nimbus-generated Visual Studio projects should be created and added to the driver solution.

Note Note

Any of the projects available via the wizard can be added later by right-clicking on the Solution node in Solution Explorer and choosing Add and then selecting New Project.

Create IVI.NET unit test project

Specifies whether a Visual C# unit test project for the IVI.NET driver should be created and added to the driver solution.

Nimbus provides advanced IVI.NET driver unit testing features that integrate directly with the Visual Studio IDE. For more information, see the topic Testing an IVI.NET Driver.

Create IVI.NET help project

Specifies whether an IVI.NET driver help project for the IVI.NET driver should be created and added to the driver solution. The project is generated based on your per-user preferences for help projects.

Create IVI.NET setup project

Specifies whether an IVI.NET driver setup project for the IVI.NET driver should be created and added to the driver solution.

Create IVI.NET C# console application

This option creates a starter Visual C# project for exercising the IVI.NET driver. The project is generated with the appropriate references, declarations, initialization and shutdown calls as well as basic error checking code. This project is a good starting point for building more involved C# client applications or for simply testing driver operation in C#.

Create IVI.NET Visual Basic console application

This option creates a starter VB.NET project for exercising the IVI.NET driver. The project is generated with the appropriate references, declarations, initialization and shutdown calls as well as basic error checking code. This project is a good starting point for building more involved VB.NET client applications or for simply testing driver operation in VB.NET.

See Also

Other Resources

Visual Studio Projects for an IVI.NET Driver
Testing an IVI.NET Driver
Using Per-User Preferences


Required Visual Studio Configuration Changes

Before building an IVI.NET driver project, some configuration settings must be manually changed. The Visual Studio project system does not expose this functionality in a way that allows Nimbus to automatically perform these configuration changes, so this topic explains each step the driver developer must perform.

To configure the appropriate solution platforms

  1. From Solution Explorer, right click on the solution and choose Configuration Manager. The Configuration Manager Dialog Box appears.

  2. From the Active solution platform combo box, choose <Edit...>. The Edit Solution Platforms dialog box appears.

  3. The exact list of platforms listed depends upon which projects are present in your solution. The following shows the list of platforms that would appear if you selected all of the projects to be included when you ran the New IVI.NET Driver Wizard:

    • Any CPU

    • Mixed Platforms

    • x64

    • x86

  4. For most developers, only one or two solution platforms are needed. The recommended solution platforms to keep depend upon whether you are creating a linked IVI-C driver as part of the solution or simply creating an IVI.NET driver without a linked IVI-C driver.

    For solutions that have only an IVI.NET driver, typically only Mixed Platforms will be needed. Other solution platforms can be safely deleted.

    For solutions that have an IVI.NET driver and a linked IVI-C driver, both Mixed Platforms and x64 will typically be needed. Other solution platforms can be safely deleted.

  5. Close the Edit Solution Platforms dialog.

  6. From the Configuration Manager dialog, choose the Mixed Platforms platform from the Action solution platform combo box.

  7. Make sure that the Platform column setting and Build column setting for each project is set according to the table below. (Note the list of projects that appears depends upon the driver options chosen.)

    Important note Important

    It is important to make these setting changes for both Debug and Release configurations.

    Project

    Platform

    Build

    <driverName>CsConsoleApplication

    x86

    Checked

    <driverName>Driver

    Any CPU

    Checked

    <driverName>Help

    Any CPU

    Unchecked

    <driverName>Setup

    x86

    Unchecked

    <driverName>UnitTest

    Any CPU

    Checked

    <driverName>VbConsoleApplication

    x86

    Checked

  8. Use the Active solution configuration combo box to repeat the above settings for both Debug and Release configurations. The only difference between the Debug and Release configurations is that the Build column should be checked for the help and setup projects in the Release configuration. This makes it convenient in that these projects don't need to be built in the Debug configuration but will be built in Release mode.

  9. If the solution contains a linked IVI-C driver, then the above process should be repeated for the x64 solution platform. See the IVI-C driver topic Required Visual Studio Configuration Changes for the recommended IVI-C settings for the x64 solution platform.


Building the IVI.NET Driver

Project Dependencies

A Nimbus driver solution consists a several Visual Studio projects. The topic Visual Studio Projects for an IVI.NET Driver discusses each of these projects. When these projects are created and added to the driver solution, Nimbus adds the appropriate build dependencies so that the projects are built in the proper order when the entire driver solution is built.

For example, the unit test project obviously relies upon the driver project, so Nimbus adds to the unit test project a dependency on the driver project. This ensures the driver project is built before the unit test project is built. Similarly, the driver setup project requires the driver and the help project to be built before it can be built, so it has dependencies on both of those projects.

To view the project dependencies

  1. From Solution Explorer, right click on the solution node (not the Nimbus node), and choose Properties.

  2. The Solution Property Pages Dialog appears.

  3. Choose Project Dependencies from the tree view on the left.

  4. Use the Project combo box on the right to view the project dependencies for the various Visual Studio projects in the driver solution.

Building the Driver

If you have properly set up the solution build configurations as explained in the topic topic Required Visual Studio Configuration Changes, then building the driver solution in the Debug configuation will result in all of the projects except for the help and setup projects being built. to be built. The build step for compiling the help file and the driver installer is intentionally separate from the build step for compiling other projects in the driver solution because the help and installer projects are typically built less often than the driver project and the unit test projects.

Important note Important

Before building the driver, it is important to properly set up the Visual Studio solution build configurations. Visual Studio does not provide programmatic access to these settings, so Nimbus is unable to automatically configure them. The topic Required Visual Studio Configuration Changes provides details on what exactly must be done before building.

When the build is performed, the output files will be placed in the appropriate bin\Debug or bin\Release subfolder of each project in the solution.

See Also

Other Resources

Required Visual Studio Configuration Changes


Visual Studio Projects for an IVI.NET Driver

Nimbus supplies two custom project types to the Visual Studio project system that enable IVI.NET driver development, documentation, and installation.

  • IVI.NET Driver Help Project

    This project type is used to build the IVI.NET driver help file(s) for an associated IVI.NET driver. Each help project is associated with a single IVI.NET driver project, and includes the help template files used to control the look and feel of the driver documentation being produced. A driver help project may be created by the IVI.NET Driver Wizard based on your selections, or added to the driver solution later.

  • IVI.NET Driver Setup Project

    This project type is used to build the IVI.NET driver installer for an associated IVI.NET driver. Each setup project is associated with a single IVI.NET driver project, and includes the WiX source files used to produce the driver installer (MSI). A driver setup project may be created by the IVI.NET Driver Wizard based on your selections, or added to the driver solution later.

In addition to the above custom project types, Nimbus also supports adding three standard Visual Studio project types to a driver solution.

  • Unit Test Project

    This is a standard Visual Studio project type that enables unit testing of IVI.NET drivers. Although Nimbus leverages the standard Visual Studio unit testing framework, the Nimbus driver automatically adds and removes unit test methods from this project as you interact with the Nimbus driver designer.

  • C# Console Application

    This is a standard Visual Studio project type for building a console application using C#. After adding this type of project to a driver solution, Nimbus performs no further modifications. This provides a convenient way to create a starter application associated with your driver that can be used for additional testing or as sample code.

  • Visual Basic Console Application

    This is a standard Visual Studio project type for building a console application using Visual Basic. After adding this type of project to a driver solution, Nimbus performs no further modifications. This provides a convenient way to create a starter application associated with your driver that can be used for additional testing or as sample code.

Managing Multiple Drivers in a Solution

In some situations, it may be desirable to manage multiple IVI drivers in a single solution. Since a Nimbus IVI driver project is simply another type of Visual Studio project, this can be supported using standard Visual Studio techniques.

To add a Nimbus driver project to an existing solution

  1. From Solution Explorer, right-click on the Solution node.

  2. Choose Add and then either New Project... or Existing Project....

  3. For a new Nimbus IVI driver project, choose Nimbus Projects from the New Project Wizard and proceed as usual with the New IVI.NET Driver Wizard. For an existing Nimbus IVI driver project, browse to the .csproj file for the desired driver.

  4. The added Nimbus IVI driver project will be loaded into Visual Studio with all of its associated projects -- setup, installer, unit test, etc. A separate Nimbus node with its subnodes will appear in Solution Explorer.

See Also

Other Resources

Using The IVI.NET Driver Wizard
Using the Nimbus Driver Designer
Required Visual Studio Configuration Changes
Building the IVI.NET Driver


Accessing Driver Settings

Nimbus supplies a number of project-wide settings that are used to control important driver features. These are collectively referred to as the Driver Settings Editor. Note that unlike the per-user options which are applied across driver projects, the Driver Settings Editor pertain only to a specific driver project.

To access the IVI.NET driver settings

  1. From Solution Explorer, double-click the Driver Settings Editor node.

  2. A tabbed document window appears with various settings on each tab.

    The remaining topics in this section provide a detailed explanation of the properties available on each tab.

In This Section

General Page, IVI.NET Driver Settings

Capability Groups Page, IVI.NET Driver Settings

LXI Page, IVI.NET Driver Settings

I/O Page, IVI.NET Driver Settings

Models Page, IVI.NET Driver Settings


General Page, IVI.NET Driver Settings

Instrument manufacturer

The instrument manufacturer is used to identify the manufacturer of the instrument for which the driver is being written. This entry is used in the IVI Configuration Store registration as well as in the implementation of the IIviDriver.InstrumentManufactuer property.

Driver vendor

The driver vendor identifies the company responsible for development and support of the driver. This entry is used in the IVI Configuration Store registration as well as in the implementation of the IIviDriverComponentIdentity.Vendor property.

Description

A description of your driver. This value is used in the driver help and .NET assembly metadata (AssemblyDescription assembly-level attribute).

Copyright

The copyright statement to use for your driver. This value is used in the .NET assembly metadata (AssemblyCopyright assembly-level attribute).

Version

The 3-digit version number to use for this driver. The value expressed here controls a variety of things, such as .NET assembly resolution and IVI.NET driver installer generation. Nimbus will always use a value of 0 for the 4th digit making up the assembly version number.

Assembly name prefix

This entry controls the name of the .NET assembly. The IVI specifications require that this prefix represent the driver vendor. The full name of the .NET assembly based on this prefix is displayed in the Assembly name text box just below this entry.

Assembly name

This is a read-only field that displays the .NET assembly name resulting from the choice entered in the Assembly name prefix field

See Also

Other Resources

.NET Assembly Versioning (MSDN)
General Page, Driver Installer Project Properties


I/O Page, IVI.NET Driver Settings

Instrument command formatting
Enable VISA-based I/O

This setting controls whether the driver uses the VISA.NET for instrument communication.

Integer format

Specifies the default format code to use for integer values in instrument command strings. Explicit format codes used in the instrument command override this setting.

See the topics under Working With Instrument Commands for more information.

Floating-point format

Specifies the default format code to use for floating-point values in instrument command strings. Explicit format codes used in the instrument command override this setting.

See the topics under Working With Instrument Commands for more information.

String format

Specifies the default format code to use for string values in instrument response strings. Explicit format codes used in the instrument command override this setting. This setting is only used for reading values from the instrument -- not for formatting values sent to the instrument.

See the topics under Working With Instrument Commands for more information.

Boolean True

Specifies a comma-separated list of instrument responses that should be interpreted as a boolean true. For instrument commands, the first string in the list will be used to send a boolean true to the device.

Boolean False

Specifies a comma-separated list of instrument responses that should be interpreted as a boolean false. For instrument commands, the first string in the list will be used to send a boolean false to the device.

SCPI compliant

Indicates whether the instrument uses SCPI-compliant instrument commands. Nimbus provides specialized support for SCPI-compliant instruments. See the topic Special Features For SCPI Commands for detailed information.

Enable simulation code generation

Determines whether or not Nimbus ever generates automatic simulation handling code. When true, Nimbus enables the Simulation Editor for properties so that the developer can choose on a property-by-property basis whether or not to instruct Nimbus to generate simulation handling code. Nimbus also generates "stub" simulation code blocks for methods so that the developer has a convenient place to insert their manual method simulation code.

When this setting is false, all properties are set to Manual simulation mode, and the Simulation Editor is disabled. Nimbus also does not generate "stub" simulation code blocks for methods in this case.

This setting is useful in situations where a lower-level software component is handling all of the simulation logic, and the Nimbus driver is simply delegating to that lower-level component. In such cases, it's inconveninet for the developer to explicitly set all properties to Manual simulation mode and to delete all residual and unneeded simulation code generated for methods and properties. With this setting, the developer can simply disable simulation code generation "globally".

See Also

Other Resources

Communicating With Instruments
Working With Instrument Commands
Special Features for SCPI Commands


Instrument Classes Page, IVI.NET Driver Settings

The Instrument Classes Page of the Driver Settings Editors allows you to select which instrument classes will be supported by the driver. Nimbus performs a number of roundtripping operations based upon the selected instrument classes. Adding instrument classes by clicking the Add button in the list of Available instrument classes instructs Nimbus to add numerous items to the driver project.

Important note Important

By default, all of the class capability groups defined by a selected instrument class are marked as being supported by the driver. After adding an instrument class to the driver, it is important to visit the Capability Groups Page of the Driver Settings Editor to select the appropriate capability groups.

Available instrument classes

List of installed instrument classes that are available to be implemented by the driver. This list appearing here corresponds to the set of instrument class project files (.iviproj) installed in the NimbusInstallDir\IviInstrumentClasses folder.

Important note Important

Unlike IVI.NET drivers, IVI-C drivers can only support a single instrument class. This is a fundamental limitation of all IVI-C drivers and stems from the fact that IVI-C attributes are defined with numeric identifiers that are not unique across the various instrument classes. See the IVI Backgrounder section on Interchangeability for more information on this IVI-C limitation.

If more than one instrument class is implemented by the IVI.NET driver, then the one that you wish to support in the linked IVI-C driver must be selected via the IVI-C Page of the Driver Settings Editor.

Implemented instrument classes

Displays the list of instrument classes already implemented by the driver. The classes listed here do not appear in the list of Available instrument classes.

See Also

Other Resources

How IVI Drivers Provide Interchangeability


Capability Groups Page, IVI.NET Driver Settings

The Group Capabilities page is used to specify which instrument class capability groups a driver supports. All extension groups for each instrument class supported by the driver are listed in the Capability Groups listbox. If the driver does not support any instrument classes, the listbox will be empty.

To specify that the driver supports a particular extension group, check the box next to the supported capability group. Nimbus uses the information specified here for the following purposes:

  • The list of supported groups is registered in the IVI Configuration Store.

  • The list of supported groups is used to implement the IIviDriver.GroupCapabilities property.

  • The list of supported groups is used in the generation of the IVI compliance information in the driver help file.

See Also

Other Resources

How IVI Drivers Provide Interchangeability


Models Page, IVI.NET Driver Settings

The Models Page is used to define the list of instrument models supported by the driver. Nimbus allows the driver's method and property behavior to vary based on model or family. The topic Adding Support for Multiple Instrument Models explains many of the multi-model Nimbus concepts.

To add a supported instrument model

  1. Right-click a model or family node.

  2. Choose Add Model.

  3. Enter the desired model name.

    Important note Important

    The name chosen here is NOT an arbitrary identifier. This name must exactly match the model string read from the device during initialization, such as the response to the "*IDN?" string. See the topic Adding Support for Multiple Instrument Models for an explanation of how Nimbus determines the connected instrument model.

Nimbus allows a driver to organize its supported list of models into related groups called families. Only a single level of hierarchy is supported -- in other words, you cannot have families of families. Unlike the instrument model names, the instrument family names are not used directly in any externally visible way. They are only used within Nimbus to group and organize models.

To add an instrument family

  1. Right-click an existing family.

  2. Choose Add Family.

  3. Enter the desired family name.

    Note Note

    The name chosen here is treated as an arbitrary identifier as does not need to match any actual identifier read from the instrument.

Nimbus supports the notion of a default model to handle the situation where the driver is operating in simulation mode and thus cannot determine what instrument model to use when executing driver-specific implementation code. The default model is used only for simulated driver sessions and only if no Model parameter is passed to Initialize.

See the topic Adding Support for Multiple Instrument Models for a discussion of the default instrument model.

To specify the default model for simulation

  1. Right-click an existing model.

  2. Choose Make default model.

  3. The selected model is shown in bold font.

See Also

Other Resources

Adding Support for Multiple Instrument Models
Retrieving the Instrument Model


LXI Page, IVI.NET Driver Settings

This page allows you to change the level of LXI support offered by your driver. Refer to this page for a complete description of these options.

Note Note

Changing the level of LXI support is a fairly major operation. As a result, you may be prompted to confirm that you wish to proceed before the requested changes are applied to your driver project.

See Also

Other Resources

LXI Compliance Page, New IVI.NET Driver Wizard


IVI-C Page, IVI.NET Driver Settings

The IVI-C Page is used to create a new IVI-C driver linked to the IVI.NET driver, or to unlink a linked IVI-C driver from the IVI.NET driver, thereby creating a standalone IVI-C driver .

IVI-C support
Link/Unlink button

Use this button to create a new linked IVI-C driver or to unlink an existing IVI-C driver.

When an existing IVI-C driver is not linked to the IVI.NET driver, then clicking this button will create a new IVI-C driver and link it to the IVI.NET driver. A special version of the New IVI-C Driver wizard will be presented where the driver developer can select the IVI-C prefix, instrument I/O, and the associated projects, such as help and setup.

Note Note

Clicking the Link button always creates a new IVI-C driver. It is not possible to link an existing IVI.NET driver with an existing IVI-C driver.

When an existing IVI-C driver is already linked to the IVI.NET driver, then clicking this button will unlink the IVI-C driver from IVI.NET. This does not delete the IVI-C driver or alter it in any way. Rather, the IVI-C driver is now a standalone Nimbus project that will be managed completely independently of the IVI.NET driver. Nimbus creates a new Nimbus project and displays it in Solution Exlorer. Though both the IVI.NET and IVI-C drivers remain in the same Visual Studio solution, there is no need to maintain them in the same solution.s

Caution note Caution

Unlinking an IVI-C driver from IVI.NET is an irreversible process. Once separated, the IVI.NET driver and IVI-C driver cannot be re-linked.

IVI-C prefix

This setting controls the IVI-C prefix for the driver. This prefix is very important as it controls the name of many items associated with the driver. The driver DLL itself will be named using this prefix. The names of all IVI-C functions and attributes begin with this prefix as do defined constants (enumerations). Additionally, the driver install location is governed by the prefix chosen here.

Important note Important

The IVI specifications require that the first two letters of this prefix match the official two-letter abbreviation assigned to the driver vendor by the IVI Foundation in the specification "VPP-9: Instrument Vendor Abbreviations" . If the driver vendor does not have an assigned two-letter prefix, one can be obtained from the IVI Foundation. Visit the IVI Foundation website for details.

Description

A description of your driver. This value is used in the implementation of the SPECIFIC_DRIVER_DESCRIPTION attribute.

Version

The 3-digit version number to use for this driver. The value expressed here controls a variety of things, such as the driver DLL version info resource and the driver installer generation. Nimbus will always use a value of 0 for the 4th digit making up the assembly version number.

IVI-C instrument class

IVI-C drivers can only support a single instrument class. This is a fundamental limitation of all IVI-C drivers and stems from the fact that IVI-C attributes are defined with numeric identifiers that are not unique across the various instrument classes. See the IVI Backgrounder section on Interchangeability for more information on this IVI-C limitation.

This setting selects which of the supported IVI.NET driver instrument classes should be supported by the IVI-C driver.

Enable VISA-based I/O

This setting controls whether the driver uses the VISA library for instrument communication. When true, Nimbus will link against VISA so that the driver implementation can use any of the standard VISA functions. In addition, Nimbus will automatically open a VISA session upon driver initialization (and close it when the driver's close function is executed. Nimbus will also implement the following functions automatically using standard instrument commands when this setting is true:

SCPI compliant

Indicates whether the instrument uses SCPI-compliant instrument commands. Nimbus provides specialized support for SCPI-compliant instruments. See the topic Special Features For SCPI Commands for detailed information.

Code generation
Automatically generate getter functions for IVI-C attributes

This setting controls whether getter functions are automatically generated when an IVI-C attribute is added to the driver.

Getter function prefix

This setting controls the name of automatically generated IVI-C attribute getter functions. For example, if an attribute named OUTPUT_VOLTAGE is created, and this setting is chosen to be Get, Nimbus will automatically generate an IVI-C getter function named GetOutputVoltage.

The name resulting from selections made here represent the initial name given to the getter function. Individual getter functions can be renamed as desired.

Automatically generate setter functions for IVI-C attributes

This setting controls whether setter functions are automatically generated when an IVI-C attribute is added to the driver.

Setter function prefix

This setting controls the name of automatically generated IVI-C attribute setter functions. For example, if an attribute named OUTPUT_VOLTAGE is created, and this setting is chosen to be Set, Nimbus will automatically generate an IVI-C setter function named SetOutputVoltage.

The name resulting from selections made here represent the initial name given to the setter function. Individual setter functions can be renamed as desired.

Synchronize Code

Use this button to bring up a dialog that allows you to update all getter and setter functions with the current selections made on this page.

See Also

Other Resources

Adding Attribute Getter and Setter Functions


Adding Functionality to an IVI.NET Driver

One of the principal tasks in creating an IVI.NET driver is using the IVI.NET Driver Designer to add functionality, such as methods, properties and enumerations. IVI.NET drivers also often support one or more IVI.NET instrument classes, and may include repeated capabilities.

The topics in this section explain how Nimbus is used to added various pieces of driver functionality.

In This Section

Managing IVI-C Driver Functionality

Defining New Data Types Inline

Adding a Method

Adding a Parameter

Adding a Property

Adding an Indexer

Adding an Event

Adding an Enumeration

Adding a Struct

Adding a Class

Adding an Interface

Adding an Exception

Adding a Child Interface

Adding a Repeated Capability

Merging Repeated Capabilities

Linking IVI.NET and IVI-C Methods and Properties

Adding Help Information

Adding State Caching to a Property

Adding Range Checking and Coercion to a Property

Adding Simulation to a Property

Adding Support for an Instrument Class

Adding Support for LXI

Understanding Type Name Resolution in Nimbus


Managing IVI-C Driver Functionality

When an IVI-C driver is linked to an IVI.NET driver via the IVI-C Page of the Driver Settings Editor, Nimbus creates a complete IVI-C driver that is based on the functionality defined in the IVI.NET driver. This topic introduces important concepts in understanding how the IVI-C driver functionality is defined and managed.

Important note Important

This topic only applies to IVI.NET driver projects that have a linked IVI-C driver on the IVI-C Page of the Driver Settings Editor.

Visual Studio Projects for Linked IVI-C Drivers

The first important thing to understand about IVI-C drivers linked to IVI.NET is that they are structurally identical to standalone IVI-C drivers (those created by choosing IVI-C Driver directly from the New Project Wizard). Unlike the IVI-C wrappers built upon IVI-COM drivers, the driver code for the IVI.NET driver and a linked IVI-C driver are completely separate -- housed in separate DLLs. The IVI-C driver is composed of purely native C++ code, while the IVI.NET driver is (typically) composed of purely managed C# code. There are no inherent compile-time, runtime, or versioning dependencies between an IVI.NET driver and a linked IVI-C driver. Additionally, each driver maintains its own help and setup project.

A linked IVI-C driver may be added to an IVI.NET driver at any stage during the IVI.NET driver development process. Nimbus will create the IVI-C driver C++ project and optionally create the IVI-C unit test, help, and setup projects. The IVI-C driver will include as many of the IVI.NET driver methods and properties as could be translated to IVI-C. The topic Linking IVI.NET and IVI-C Methods and Properties discusses how Nimbus creates and manages associations between IVI.NET methods and properties and their IVI-C function and attribute counterparts.

Although a new linked IVI-C driver can be added to an IVI.NET driver solution at any stage during development, an existing IVI-C driver cannot be linked to an IVI.NET driver solution. Linked IVI-C drivers must always be created based upon an IVI.NET driver -- either at IVI.NET project creation time with the New Project Wizard runs or later via the IVI-C Page of the Driver Settings Editor. However a standalone IVI-C driver cannot be linked to an existing IVI.NET driver. This hold true even if the IVI-C driver was initially created with the IVI.NET driver and later unlinked from it (via the IVI.NET Driver Settings Editor). Unlinking an IVI-C driver from an IVI.NET driver makes that IVI-C driver a standalone IVI-C driver, just as if it had never been linked to IVI.NET at all.

Important note Important

IVI-C drivers linked to IVI.NET must always be created from the IVI.NET driver project -- either when the IVI.NET New Project Wizard runs or when the driver developer explicitly enables it via the IVI-C Page of the Driver Settings Editor. Existing IVI-C drivers cannot be linked to IVI.NET.

The IVI.NET and IVI-C Designers

The Nimbus user interface allows you to view the IVI.NET and IVI-C hierarchies in a single Driver Designer. window. Both designers are accessed by double-clicking the Driver Designer node under the Nimbus project node in Solution Explorer. The Driver Designer that appears as a tabbed document window displays separate tabs for the IVI.NET Designer and the IVI-C Designer.

Tip Tip

The terminology used to describe IVI-C driver functionality is slightly different than that used to describe IVI.NET functionality. A method in IVI.NET is referred to as a function when speaking in the context of IVI-C. Similarly, a property in IVI.NET corresponds to an attribute in IVI-C. This terminology is used throughout the IVI specifications and is followed in this documentation as much as possible.

The IVI.NET Designer is referred to as the master view because it "pushes" changes made in it to the IVI-C hierarchy. For instance, when a method is added to the IVI.NET driver, a corresponding IVI-C function is also added to the driver project. Nimbus maintains the association between the IVI.NET method and the IVI-C function so that it can keep the function names, parameter names, and parameter types synchronized between the two. Additionally, Nimbus can often automatically generate and maintain the appropriate code to implement both the IVI-C function using design data entered in the IVI.NET designer.

When Nimbus automatically creates IVI-C items, such as IVI-C functions, attributes, and parameters, based on changes made in the IVI.NET Designer, various "transforms" may be required, such as translating IVI.NET data types like long and double to IVI-C data types like ViInt32 and ViReal64. The topic Linking IVI.NET and IVI-C Methods and Properties provides details on these automatic transforms.

Using the IVI-C Designer

It is critical to understand the difference in behavior when working from the IVI-COM Designer versus the IVI-C Designer. Since the IVI.NET Designer is the master view, changes made there typically affect both the IVI.NET and IVI-C hierarchies. By contrast, editing the IVI-C driver via the IVI-C Designer only affects the IVI-C hierarchy.

Important note Important

The IVI-C Designer does not push changes to the IVI.NET hierarchy.

As an example, using the IVI-C Designer, renaming an IVI-C function from Configure to ConfigureTrigger will only rename the IVI-C function. The IVI.NET method will still be named Configure and the IVI.NET method and IVI-C function will still be linked with one another. Similarly, adding a function using the IVI-C Designer only adds the function to the IVI-C hierarchy -- a corresponding method is NOT added to the IVI.NET hierarchy. In fact, this is how IVI-C-only functions are created. IVI-C-only functions are discussed below.

Navigating Between the IVI.NET and IVI-C Hierarchies

Nimbus offers two convenient ways to navigate between items in the IVI.NET hierarchy and their linked items in the IVI-C hierarchy:

  • From the tree view, right-click the desired item, such as an IVI.NET method, and choose Go to IVI-C .... The IVI-C Designer is immediately opened and linked item is selected. Correspondingly, a Go to IVI.NET... context menu command is available when working in the IVI-C Designer.

  • The Info Panel shows the linked IVI.NET or IVI-C item name as a hyperlink. Clicking it navigates to the linked item in the alternate view.

IVI.NET-only and IVI-C-only Methods and Properties

As discussed above, IVI.NET methods are initially created with an linked IVI-C function. Changes made to the IVI.NET method in the IVI.NET Designer, such as adding parameters, are "pushed" to the IVI-C function so that the two items stay in sync. Most of the time, this is the desired behavior. However, there are some instances where it is not possible or desirable to expose an IVI.NET method in the IVI-C driver. Such an IVI.NET method has no linked IVI-C function and is termed an IVI.NET-only method. Correspondingly, there are occaisions where an IVI-C function serves no useful purpose in the IVI.NET hierarchy. This requires IVI-C functions that have no IVI.NET counterpart -- these are termed IVI-C-only functions.

Nimbus fully supports the ability to create IVI.NET-only methods and IVI-C-only functions. In addition, other items, such as properties, function parameters, and enums can all be exposed in one of the hierarchies and not exposed in the others. The topic Linking IVI.NET and IVI-C Methods and Properties discusses how IVI.NET-only and IVI-C-only items are created and managed.


Defining New Data Types Inline

When adding methods and properties to a driver, it can be convenient to create the data types needed at the same time the method or property itself is being defined. Nimbus allows enums to be created and defined when entering new parameters, method return types, or property types. This is simpler than defining an enum ahead of time in one portion of the Driver Designer and then returning to where the desired method or property is to be created and using that newly defined enum.

Creating an enum when defining a method or property

As an example of creating a new enum when defining a method, after executing the Add Method command, and while still in edit mode, the following text can be used to create a ConfigureTrigger method that returns a newly created TriggerSource enum. enum.

ConfigureTrigger : new enum TriggerSource

In addition to creating the enum, the enum members can be defined at the same time as the enum, as in the following:

ConfigureTrigger : new enum TriggerSource; Internal = 2, External = 0x15, Software = 47

The above example creates a new TriggerSource enum with three member, each with member numeric values specified.

See the Shorthand section of the Adding an Enumeration topic for details on enum creation shorthand.

Tip Tip

The syntax for creating new enums inline can be used in the driver designer tree view for method return types, parameter types, and property types. It can also be used in the Type text boxes in the item editors for those items.

See Also

Other Resources

Adding an Enumeration


Adding a Method

To add a method to a driver

  1. From Solution Explorer, double-click the Driver Designer node under the Nimbus node.

  2. The IVI.NET Driver Designer tree view opens.

  3. Expand the root node, which will be named after the driver assembly (e.g.: Acme.Acme4321).

  4. Locate and then select the desired class, struct, or interface where the new method is desired.

  5. Right-click on the selected node and choose Add Method.

  6. A new method is added with a default name and the tree node enters edit mode. By default the method return type is Void, meaning that the method has no return type.

  7. With the method node still in edit mode, type the desired name of the method followed by a colon (:) followed by the name of the return type, and hit the Enter key. The colon and return type can be excluded if the method has no return type (e.g. the Void return type is implied).

    Note Note

    Refer to the help topic Understanding Type Name Resolution in Nimbus for more information regarding how Nimbus resolves type names entered into the designer.

    When choosing a method name, the following naming rules apply:

    • The name must be unique within its containing type. It need not be unique across the entire driver.

    • The name must contain only alphanumeric characters.

    • Spaces are not allowed.

    • The name must begin with an alphabetic character.

  8. After the method is added, the IVI.NET Method General Editor appears in the right portion of the IVI.NET Driver Designer. See the help topic for that Item Editor for details on defining the method further.

  9. Once a method has been added, parameters can be added to the method. See the topic Adding a Parameter for details on adding parameters.

  10. If an IVI-C driver is currently linked to the IVI.NET driver via the IVI-C Page of the Driver Settings Editor, then an IVI-C function is automatically created at this time and linked to the IVI.NET method.

    To view the linked IVI-C function, right-click the IVI.NET method, and choose Go to IVI-C Function.

    To remove the linked IVI-C function, thereby creating an IVI.NET-only method, right-click the IVI.NET method, and choose Delete IVI-C Function.

    For a detailed discussion of the associations between IVI.NET methods and IVI-C functions, see the topics Managing IVI-C Driver Functionality and Linking IVI.NET and IVI-C Methods and Properties.

See Also

Other Resources

Understanding Type Name Resolution in Nimbus
Adding a Property
Adding an Event
Adding a Child Interface


Adding a Parameter

To add a parameter to a method

  1. From Solution Explorer, double-click the Driver Designer node under the Nimbus node.

  2. The IVI.NET Driver Designer tree view opens.

  3. Expand the root node, which will be named after the driver assembly (e.g.: Acme.Acme4321).

  4. Locate and then select the desired method from the tree view.

  5. A new parameter is added with a default name and the tree node enters edit mode. By default the parameter type is Double.

  6. With the parameter node still in edit mode, type the desired name of the parameter followed by a colon (:) followed by the name of the desired type, and hit the Enter key. The colon and type can be excluded if the desired type is Double.

    Note Note

    Refer to the help topic Understanding Type Name Resolution in Nimbus for more information regarding how Nimbus resolves type names entered into the designer.

    When choosing a parameter name, the following naming rules apply:

    • The name must be unique within its parent method.

    • The name must contain only alphanumeric characters.

    • Spaces are not allowed.

    • The name must begin with an alphabetic character.

  7. After the parameter is added, the IVI.NET Parameter General Editor appears in the right portion of the IVI.NET Driver Designer. See the help topic for that Item Editor for details on defining the method further.

  8. If an IVI-C driver is currently linked to the IVI.NET driver via the IVI-C Page of the Driver Settings Editor, then an IVI-C parameter is automatically created at this time and linked to the IVI.NET parameter. For array parameters, Nimbus automatically generates an extra IVI-C buffer size parameter to indicate the size of the array on input. If the array is an Output or Input/Output, Nimbus also generates an IVI-C actual size parameter to indicate the size of the array returned from the driver method.

    To view the linked IVI-C parameter, navigate to the parent method or property, right-click the IVI.NET method, and choose Go to IVI-C Function.

    For a detailed discussion of the associations between IVI.NET methods and IVI-C functions, see the topics Managing IVI-C Driver Functionality and Linking IVI.NET and IVI-C Methods and Properties.

See Also

Other Resources

Understanding Type Name Resolution in Nimbus
Adding a Method
Adding a Property


Adding a Property

To add a property to a driver

  1. From Solution Explorer, double-click the Driver Designer node under the Nimbus node.

  2. The IVI.NET Driver Designer tree view opens.

  3. Expand the root node, which will be named after the driver assembly (e.g.: Acme.Acme4321).

  4. Locate and then select the desired class, struct, or interface where the new property is desired.

  5. Right-click on the selected node and choose Add Property.

  6. A new property is added with a default name and the tree node enters edit mode. By default the property type is Double.

  7. With the property node still in edit mode, type the desired name of the property followed by a colon (:) followed by the name of the return type, and hit the Enter key. The colon and type can be excluded if the desired property type is Double.

    Note Note

    Refer to the help topic Understanding Type Name Resolution in Nimbus for more information regarding how Nimbus resolves type names entered into the designer.

    When choosing a property name, the following naming rules apply:

    • The name must be unique within its containing type. It need not be unique across the entire driver.

    • The name must contain only alphanumeric characters.

    • Spaces are not allowed.

    • The name must begin with an alphabetic character.

  8. After the property is added, the IVI.NET Property General Editor appears in the right portion of the IVI.NET Driver Designer. See the help topic for that Item Editor for details on defining the property further.

  9. If an IVI-C driver is currently linked to the IVI.NET driver via the IVI-C Page of the Driver Settings Editor, then an IVI-C attribute is automatically created at this time and linked to the IVI.NET property.

    To view the linked IVI-C attribute, right-click the IVI.NET property, and choose Go to IVI-C Attribute.

    To remove the linked IVI-C attribute, thereby creating an IVI.NET-only property, right-click the IVI.NET property, and choose Delete IVI-C Attribute.

    For a detailed discussion of the associations between IVI.NET methods and IVI-C functions, see the topics Managing IVI-C Driver Functionality and Linking IVI.NET and IVI-C Methods and Properties.

See Also

Other Resources

Understanding Type Name Resolution in Nimbus
Adding a Method
Adding an Event
Adding a Child Interface


Adding an Indexer

Indexers may be added to free standing classes, structs and interfaces. They cannot be added to the main driver hierarchy.

To add an indexer to a driver

  1. From Solution Explorer, double-click the Driver Designer node under the Nimbus node.

  2. The IVI.NET Driver Designer tree view opens.

  3. Expand the root node, which will be named after the driver assembly (e.g.: Acme.Acme4321).

  4. Locate and then select the desired class, struct, or interface where the new indexer is desired.

  5. Right-click on the selected node and choose Add Indexer.

  6. A new indexer is added with the required name and the tree node enters edit mode. By default the indexer type is Double, and it will have a single String parameter (name).

  7. With the indexer node still in edit mode, change the indexer type (after the colon) or parameter list as desired, and hit the Enter key. The colon and indexer type can be excluded if the desired indexer type is Double.

    Note Note

    Indexers must have at least one parameter, and can be overloaded just like methods based on differences in the parameter list.

    Indexers must be named Item, and cannot be renamed. Attempting to do so will result in an error message.

    Refer to the help topic Understanding Type Name Resolution in Nimbus for more information regarding how Nimbus resolves type names entered into the designer.

  8. After the indexer is added, the IVI.NET Indexer General Editor appears in the right portion of the IVI.NET Driver Designer. See the help topic for that Item Editor for details on defining the indexer further.

See Also

Other Resources

Understanding Type Name Resolution in Nimbus
Adding a Property
Adding a Method
Adding a Child Interface


Adding an Event

To add an event to a driver

  1. From Solution Explorer, double-click the Driver Designer node under the Nimbus node.

  2. The IVI.NET Driver Designer tree view opens.

  3. Expand the root node, which will be named after the driver assembly (e.g.: Acme.Acme4321).

  4. Locate and then select the desired class, struct, or interface where the new event is desired.

  5. Right-click on the selected node and choose Add Event.

  6. A new event is added with a default name and the tree node enters edit mode. By default the event type is EventHandler. See the section below on Understanding Event Types to learn more about events and delegate types in Nimbus.

  7. With the event node still in edit mode, type the desired name of the event followed by a colon (:) followed by the name of the event type, and hit the Enter key. The colon and event type can be excluded if the default EventHandler delegate type.

    Note Note

    Refer to the help topic Understanding Type Name Resolution in Nimbus for more information regarding how Nimbus resolves type names entered into the designer.

    When choosing an event name, the following naming rules apply:

    • The name must be unique within its containing type. It need not be unique across the entire driver.

    • The name must contain only alphanumeric characters.

    • Spaces are not allowed.

    • The name must begin with an alphabetic character.

  8. After the event is added, the IVI.NET Event General Editor appears in the right portion of the IVI.NET Driver Designer. See the help topic for that Item Editor for details on defining the event further.

Understanding Event Types

.NET events must always be of type delegate. By default, Nimbus creates new events with the existing EventHandler delegate type from the .NET Framework. This type has been around since .NET 1.1, so it is a reasonable default choice for IVI.NET drivers targeting .NET Framework 2.0. However, many events in IVI.NET drivers will need to communicate driver-specific data to the client when firing the event. The EventHandler delegate is quite limited in this regard, so typically driver developers will need to change the event type to something with richer semantics.

There are a few basic approaches to designing event types in .NET components. In early versions of .NET, the typical solution would be to create an entirely new delegate type for each unique event. However, current .NET design guidelines strongly favor using existing delegate types from the .NET Framework and customizing the signature of that delegate type. Because the creation of custom delegates is discouraged, Nimbus does not support the creation of these types from the Driver Designer.

The approach taken for designing events depends upon the .NET Framework version the IVI.NET driver is targeting:

  • For IVI.NET drivers targeting .NET Framework 2.0, the recommended approach is to use the EventHandler<T> generic delegate type along with a driver-defined EventArgs class. This is accomplished by adding a class to the driver using the Driver Designer, taking care that the class derives from EventArgs. The newly created EventArgs-derived class can be augmented with whatever properties are desired.

  • For IVI.NET drivers targeting .NET Framework 3.5 or greater, the recommended approach is to use either the Action<T> or Func<T> generic delegate types. This approach supports the ability to use delegates that take up to 16 parameters of any type. Thus, there is no need to create a special EventArgs-derived class to carry event data. This simplifies the code that clients need to write when fielding such events.

See Also

Other Resources

Understanding Type Name Resolution in Nimbus
Adding a Method
Adding a Property
Adding a Child Interface


Adding an Enumeration

To add an enum to a driver

  1. From Solution Explorer, double-click the Driver Designer node under the Nimbus node.

  2. The IVI.NET Driver Designer tree view opens.

  3. Expand the root node, which will be named after the driver assembly (e.g.: Acme.Acme4321).

  4. Right-click on the Enums node and select Add Enum.

  5. A new enum is added with a default name and the tree node enters edit mode.

  6. With the enum node still in edit mode, type the desired name of the enum and hit the Enter key.

    When choosing an enum name, the following naming rules apply:

    • The name must be unique within the driver.

    • The name must contain only alphanumeric characters, and must start with an alphabetic character.

    • Spaces are not allowed.

  7. The new enum will be defined in Enums.cs.

    After the enum is added, the Enum General Editor appears in the right portion of the IVI.NET Driver Designer.

  8. If an IVI-C driver is currently linked to the IVI.NET driver via the IVI-C Page of the Driver Settings Editor, time and linked to the IVI.NET enum.

    To view the linked IVI-C enum, right-click the IVI.NET enum, and choose Go to IVI-C Enum.

    To remove the linked IVI-C enum, thereby creating an IVI.NET-only enum, right-click the IVI.NET enum, and choose Delete IVI-C Enum.

Tip Tip

Use the Info Panel in the lower portion of the IVI.NET Driver Designer to view and navigate to methods and properties that use the enum.

To add an enum member to an enum

  1. Locate the enum to be modified under the Enums node in the IVI.NET Driver Designer

  2. Right click on the enum name and select Add Enum Member.

  3. A new enum member is added with a default name and the tree node enters edit mode.

  4. With the enum member node still in edit mode, type the desired name of the enum member and hit the Enter key.

    When choosing an enum member name, the following naming rules apply:

    • The member name must be unique within the enum being modified.

    • The name must contain only alphanumeric characters, and must start with an alphabetic character.

    • Spaces are not allowed.

    Tip Tip

    The enum member value can be entered in either hexadecimal or decimal format. It will be converted to the format configured for that enum. Right-click on the parent enum to see a context menu which enables or disables hexadecimal display mode.

  5. After the enum member is added, the Enum Member Editor appears in the right portion of the IVI.NET Driver Designer.

  6. If an IVI-C driver is currently linked to the IVI.NET driver via the IVI-C Page of the Driver Settings Editor, then an IVI-C enum member is automatically created at this time and linked to the IVI.NET member.

    To view the linked IVI-C enum member, right-click the IVI.NET method, and choose Go to IVI-C Enum Member.

    To remove the linked IVI-C enum member, thereby creating an IVI.NET-only enum member, right-click the IVI.NET enum member, and choose Delete IVI-C Enum Member.

    For a detailed discussion of the associations between IVI.NET methods and IVI-C functions, see the topics Managing IVI-C Driver Functionality and Linking IVI.NET and IVI-C Methods and Properties.

Shorthand notation for defining enums

Nimbus supports a convenient shorthand notation for defining enums. The enum and its members can be defined all at once when the enum is initially added.

After executing the Add Enum command, and while still in edit mode, the following text can be used to define a TriggerSource enum with members Internal, External, and Software.

TriggerSource; Internal, External, Software

In the above, the enum name TriggerSource is specified first, followed by a semicolon to delineate it from the enum member specifications. Enum members follow and are separated by commas.

This shorthand notation can also be used to define the enum member values, as in the following:

TriggerSource; Internal = 2, External = 0x15, Software = 47

Note that when assigning enum member values, either hex format or decimal format may be used.

Once an enum is defined, additional enum members can be added using this same shorthand notation, except that the enum name is excluded. After executing the Add Enum Member command, and while still in edit mode, the following text can be used to add a series of TTL trigger source lines to the existing TriggerSource enum from the above example:

TTL0, TTL1 = 5, TTL2 = 6, TTL3, TTL4, TTL5 = 0x14, TTL6, TTL7


Adding a Struct

To add a new struct to the driver

  1. From Solution Explorer, double-click the Driver Designer node under the Nimbus node.

  2. The IVI.NET Driver Designer tree view opens.

  3. Expand the root node, which will be named after the driver assembly (e.g.: Acme.Acme4321).

  4. Right-click on the Structs node and select Add Struct.

  5. A new struct is added with a default name and the tree node enters edit mode. Type the desired name for the new struct and hit the Enter key.

    When choosing a struct name, the following naming rules apply:

    • The name must be unique within the driver.

    • The name must contain only alphanumeric characters, and must start with an alphabetic character.

    • Spaces are not allowed.

    Note Note

    To define a generic struct, specify the generic type parameter(s) as part of the struct name, for example Acme4321Tuple<T, U>.

    Refer to Understanding Type Name Resolution in Nimbus for more information about type name resolution and generics in Nimbus.

  6. The new struct will be defined in a file named <structName>.cs that Nimbus will automatically add to the driver project.

    After the struct is added, the Struct General Editor appears in the right portion of the IVI.NET Driver Designer.

See Also

Other Resources

Understanding Type Name Resolution in Nimbus
Struct General Editor


Adding a Class

To add a new class to the driver

  1. From Solution Explorer, double-click the Driver Designer node under the Nimbus node.

  2. The IVI.NET Driver Designer tree view opens.

  3. Expand the root node, which will be named after the driver assembly (e.g.: Acme.Acme4321).

  4. Right-click on the Classes node and select Add Class.

  5. A new class is added with a default name and the tree node enters edit mode. Type the desired name for the new class and hit the Enter key.

    When choosing a class name, the following naming rules apply:

    • The name must be unique within the driver.

    • The name must contain only alphanumeric characters, and must start with an alphabetic character.

    • Spaces are not allowed.

    Note Note

    To define a generic class, specify the generic type parameter(s) as part of the class name, for example Acme4321DataSet<T, U>.

    Refer to Understanding Type Name Resolution in Nimbus for more information about type name resolution and generics in Nimbus.

  6. The new class will be defined in a file named <className>.cs that Nimbus will automatically add to the driver project.

    After the class is added, the Class General Editor appears in the right portion of the IVI.NET Driver Designer.

See Also

Other Resources

Understanding Type Name Resolution in Nimbus
Class General Editor


Adding an Interface

To add a new interface to the driver

  1. From Solution Explorer, double-click the Driver Designer node under the Nimbus node.

  2. The IVI.NET Driver Designer tree view opens.

  3. Expand the root node, which will be named after the driver assembly (e.g.: Acme.Acme4321).

  4. Right-click on the Interfaces node and select Add Interface.

  5. A new interface is added with a default name and the tree node enters edit mode. Type the desired name for the new interface and hit the Enter key.

    When choosing an interface name, the following naming rules apply:

    • The name must be unique within the driver.

    • The name must contain only alphanumeric characters, and must start with an alphabetic character.

    • Spaces are not allowed.

    Note Note

    To define a generic interface, specify the generic type parameter(s) as part of the interface name, for example IAcme4321DataSet<T, U>.

    Refer to Understanding Type Name Resolution in Nimbus for more information about type name resolution and generics in Nimbus.

  6. The new interface definition will be added to Interfaces.cs.

    After the interface is added, the Interface General Editor appears in the right portion of the IVI.NET Driver Designer.

See Also

Other Resources

Understanding Type Name Resolution in Nimbus
Interface General Editor


Adding a Child Interface

To add a child interface to a driver

  1. From Solution Explorer, double-click the Driver Designer node under the Nimbus node.

  2. The IVI.NET Driver Designer tree view opens.

  3. Expand the root node, which will be named after the driver assembly (e.g.: Acme.Acme4321).

  4. Expand the Hierarchy node.

  5. Right-click on the desired location within the hierarchy and choose Add Child Interface. You can add a new child interface directly below the Hierarchy node, or any user-defined interface reference property defined within the Hierarchy.

  6. A new interface reference property is added with a default name and the tree node enters edit mode. Type the desired name for the reference property and hit the Enter key.

    An interface will be added to the driver with a name based on the chosen property name, as follows:

    I<driverName><propName>

    This new interface will be defined in Interfaces.cs.

    Note Note

    If the child interface is added at a level beneath a collection-style repeated capability Item property, then it is inherently part of the repeated capability. The interface will be a base interface of the repeated capability class and implemented on that class. Otherwise, the child interface is added as a base of the main driver class and implemented on that class.

See Also

Other Resources

Understanding Type Name Resolution in Nimbus
Adding a Method
Adding a Property


Adding an Exception

To add a new exception class to the driver

  1. From Solution Explorer, double-click the Driver Designer node under the Nimbus node.

  2. The IVI.NET Driver Designer tree view opens.

  3. Expand the root node, which will be named after the driver assembly (e.g.: Acme.Acme4321).

  4. Right-click on the Exceptions node and select Add Exception.

  5. A new exception class is added with a default name and the tree node enters edit mode. Type the desired name for the new exception class and hit the Enter key.

    When choosing the name for a new exception class, the following naming rules apply:

    • The name must be unique within the driver.

    • The name must contain only alphanumeric characters, and must start with an alphabetic character.

    • Spaces are not allowed.

    Note Note

    To define a generic exception class, specify the generic type parameter(s) as part of the exception class name, for example Acme4321Exception<T, U>.

    Refer to Understanding Type Name Resolution in Nimbus for more information about type name resolution and generics in Nimbus.

  6. The new exception class will be defined in a file named <exceptionName>.cs that Nimbus will automatically add to the driver project.

    After the exception class is added, the Exception General Editor appears in the right portion of the IVI.NET Driver Designer.

See Also

Other Resources

Understanding Type Name Resolution in Nimbus
Exception General Editor


Adding a Repeated Capability

Repeated capabilities allow the driver to expose duplicate functionality in an instrument using IVI-defined functions and conventions. For instance, a single set of methods and properties can be defined for operating on a series of channels in an oscillscope. IVI terms this duplicate functionality a repeated capability.

For a complete discussion of repeated capabilities, see the IVI Backgrounder topic entitled Repeated Capabilities.

Nimbus provides two ways to initiate the process of adding a new repeated capability to a driver, each of which is described in detail below.

  • Add a repeated capability to the main driver interface

  • Add a repeated capability at an arbitrary location within the driver's interface hierarchy

To add a repeated capability to the main driver interface

  1. From Solution Explorer, expand the Nimbus node.

  2. Right-click on the Repeated Capabilities node.

  3. Choose Add Repeated Capability...

  4. The Add Repeated Capability Wizard appears.

  5. Follow the steps outlined below for using the Add Repeated Capability Wizard.

To add a repeated capability at an arbitrary location within the driver's interface hierarchy

  1. From Solution Explorer, double-click the Driver Designer node under the Nimbus node.

  2. The IVI.NET Driver Designer tree view opens.

  3. Expand the root node, which will be named after the driver assembly (e.g.: Acme.Acme4321).

  4. Expand the Hierarchy node.

  5. Locate the interface reference property where you would like to add the new repeated capability.

  6. Right-click on the selected interface reference property and choose the Add Child Repeated Capability....

  7. The Add Repeated Capability Dialog appears.

  8. Follow the steps outlined below for using the Add Repeated Capability Dialog.

The remaining topics in this section discuss each wizard page separately.

Tip Tip

After adding a repeated capability using the dialog, you can bring up the Repeated Capabilities Editor by double-clicking the Driver Settings Editor node in Solution Explorer and choosing the Repeated Capabilities tab. The Repeated Capabilities Editor allows you to view and edit characteristics of all driver repeated capabilities, such as the physical names defined for each repeated capability.

In This Section

Add Repeated Capability Dialog

See Also

Other Resources

Repeated Capabilities


Add Repeated Capability Dialog

For a complete discussion of repeated capabilities, see the IVI Backgrounder topic entitled Repeated Capabilities.

Name

Specifies the repeated capability name. This name serves as a unique identifier for the repeated capability. The name chosen here is used registered by the driver installer in the IVI Configuration Store. In addition, the name chosen here is used as a base name for the following items:

  • I<driverName><repCapName> interface - the repeated capability interface on which the repeated capability methods and properties will be defined.

  • I<driverName><repCapName>Collection interface - (collection-style only) - collection interface on which the Count, Item, and Name properties will be defined.

  • repCapName>s property- (collection-style only) - reference property pointing to the repeated capability collection interface.

  • <driverName>repCapName> class - (collection-style only) - class added to the driver source code for implementing the repeated capability methods and properties.

  • <driverName>repCapName>Collection class - (collection-style only) - class added to the driver source code for implementing the repeated capability collection interface.

  • repCapName> property - (selector and parameter-style only) - reference property pointing to the repeated capability interface.

For example, if the name Channel is chosen for a collection-style repeated capability on a driver named Acme4321, then the following items would be created:

  • An IAcme4321Channel interface (defined in Interfaces.cs).

  • An IAcme4321ChannelCollection interface (defined in Interfaces.cs).

  • A property Channels that points to the IAcme4321ChannelCollection interface.

  • An IAcme4321Channels.Item property that returns an IAcme4321Channel interface.

  • An Acme4321Channel implementation class (defined in Acme4321Channel.cs).

  • An Acme4321ChannelCollection implementation class (defined in Acme4321ChannelCollection.cs).

Parent

The parent repeated capability, if this is a nested repeated capability, or (none) otherwise. This is a read-only field, as the parent is determined by where the repeated capability was added in the driver hierarchy or by the parent repeated capability that was selected when the dialog was initiated.

Style

The type of repeated capability to be added to the driver.

A discussion of the three types of IVI repeated capabilities can be found in the topic Repeated Capabilities.

Physical names are dynamically added at initialization time

Indicates if the driver supports dynamic repeated capability names. Dynamic repeated capabilities allow the driver to decide at runtime what repeated capability names the driver supports, often based on information it reads from the instrument during the driver's initialization sequence.

If checked, an override of the function GetDynamicRepCapNames(String, IListString) must be manually added to the appropriate class in the driver project. See the topic Implementing Dynamic Repeated Capabilities for detailed information on using this function.

Use qualified physical names

Repeated capabilities can be configured to use either qualified or unqualified physical names when registering names in the IVI Configuration Store and when returning physical name strings from the driver functions.

Typically this can be left unchecked. It is intended for scenarios where the physical names defined for this repeated capability collide with physical names used in other repeated capabilities in the driver.

Physical names

Use the Add, Remove, and Edit buttons to manage the list of physical names to associate with the repeated capability. The names entered here represent the static repeated capability instances -- that is, they will be available irrespective of what is discovered about the connected instrument at runtime. The names added here will be registered with the IVI Configuration Store by the driver installer.

Tip Tip

Use '-' to specify a range of physical names. For example, entering Channel(1-3) is equivalent to creating three separate entries: Channel1, Channel2, and Channel3. The range must follow the base name and be enclosed in parentheses. The beginning value in the range must be smaller than the end value.

Tip Tip

To modify the list of physical names after running the wizard, double-click the Driver Settings Editor node in Solution Explorer and choose the Repeated Capabilities tab from Driver Settings Editor, editor that appears.

See Also

Other Resources

Repeated Capabilities


Linking IVI.NET and IVI-C Methods and Properties

When IVI.NET items, such as methods, properties, parameters, and enums, are added to the driver hierarchy using the IVI.NET Designer, corresponding items are automatically added to the IVI-C hierarchy. For instance, adding an IVI.NET method automatically adds a corresponding IVI-C function. Since IVI.NET and IVI-C represent data types, repeated capabilities, and other driver characteristics differently, Nimbus must perform various transformations when mapping between IVI.NET and IVI-C. In situations where an IVI.NETitem cannot or should not be represented in IVI-C, or vice versa, Nimbus provides a means to implement IVI.NET-only and IVI-C-only items. This topic explains important aspects of managing the relationship between the IVI.NET driver and its linked IVI-C driver.

Important note Important

This topic only applies to IVI.NET driver projects that have enabled IVI-C wrapper generation on the IVI-C Page of the Driver Settings Editor.

The IVI-C ViSession Parameter

Every IVI-C function accepts a ViSession as its first parameter. The ViSession parameter identifies the instrument I/O session. Nimbus automatically adds a ViSession parameter to every IVI-C function it associates with an IVI.NET method. Inside the implementation of the IVI-C function, the Nimbus-generated code uses the ViSession parameter to locate the correct IVI.NET driver instance to call. The ViSession parameter cannot be deleted from an IVI-C driver function.

IVI.NET and IVI-C Return Types

IVI.NET methods may have a non-void return type. By contrast, IVI-C functions always return a ViStatus result. This means that if an IVI.NET method specifies anything other than void as its return type, an [out] parameter of the specified type must be added to the corresponding IVI-C function function signature. Nimbus adds such an [out] parameter automatically when needed.

Mapping IVI.NET and IVI-C Data Types

When an IVI.NET method is associated with an IVI-C function, the method return type as well as the data type of each parameter must be mapped to an appropriate IVI-C data type. Similarly, an IVI.NET property type must be mapped to its corresponding IVI-C attribute type. Nimbus performs these transformations automatically when an IVI.NETmethod or property is created and when parameters are added. Most of these mappings are straightforward and are given in the table below:

IVI.NET Data Type | IVI-C Data Type
Boolean | ViBoolean
String | ViConstString (for [in] parameters) ViString, plus a BufferSize parameter (for [out] and [in,out] parameters) (See discussion below.)
Byte | ViChar
Int16 | ViInt16
Int32 | ViInt32
Int64 | ViInt64
Single | ViReal32
Double | ViReal64
TimeSpan | ViReal64
PrecisionTimeSpan | ViReal64

Mapping Array Parameters

IVI.NET drivers use standard .NET arrays where the number and type of elements present in the array is maintained within the System.Array class itself. IVI-C drivers, however, use C-style arrays. Since C-style arrays are simply pointers, extra parameters must be used with an IVI-C array to indicate the number of elements present. The IVI specifications prescribe specific naming and ordering conventions for these extra "array size" parameters. Nimbus automatically manages these extra IVI-C parameters as follows:

When an array parameter is added to an IVI.NET method

  1. An [in] parameter of type ViInt32 is added to the IVI-C function and placed just before the IVI-C array parameter. The parameter name is based upon the array parameter name, as follows:

    <arrayParamName>BufferSize

    This buffer size parameter is used to indicate how many elements (not bytes) have been allocated in the array by the caller. This helps ensure the function implementation does not try to access more elements than are available.

  2. A C-style array is added to the IVI-C function to represent the SAFEARRAY data itself.

  3. If the arrayparameter is an [in,out] parameter, then an [out] parameter of type ViInt32 is added to the IVI-C function and placed just after the IVI-C array parameter. The parameter name is based upon the array parameter name, as follows:

    <arrayParamName>ActualSize

    This actual size parameter is used to indicate how many elements (not bytes) were filled in by the function implementation. This indicates to the caller how much of the allocated space, as indicated by the buffer size parameter, was actually used.

Mapping String Parameters

Unlike IVI.NET drivers which use self-describing System.String types for string parameters, IVI-C drivers use character arrays (arrays of ViChar typedef'd to the ViString data type). When used as input parameters IVI-C strings do not need additional length parameters because the string is NULL-terminated and the length is easily determined by the function implementation. However, when strings are used as [out] parameters in IVI-C drivers, an additional buffer size parameter must be used to indicate to the function implementation how many characters have been allocated by the caller. The IVI specifications prescribe specific naming and ordering conventions for this extra "buffer size" parameter. Nimbus automatically manages this extra IVI-C parameter as follows:

When a string [out] parameter is added to an IVI.NET method

  1. An [in] parameter of type ViInt32 is added to the IVI-C function and placed just before the IVI-C ViString parameter. The parameter name is based upon the ViString parameter name, as follows:

    <stringParamName>BufferSize

    This buffer size parameter is used to indicate how many characters have been allocated in the string by the caller. This helps ensure the function implementation does not try to access more characters than are available.

  2. A ViString parameter is added to the IVI-C function to represent the System.String data itself.

Mapping TimeSpan and PrecisionTimeSpan Parameters

Because time-based values are quite common in IVI driver APIs the IVI Foundation introduced the PrecisionTimeSpan data type. This data type provides much of the convenience as the standard TimeSpan data type available in the .NET Framework, but it offers higher timekeeping accuracy.

Nimbus provides special support for TimeSpan and PrecisionTimeSpan parameters. Whenever a parameter or property of either of those types is created in an IVI.NET driver, a ViReal64 parameter or attribute is created in the linked IVI-C driver.

Mapping IVI.NET and IVI-C Repeated Capabilities

IVI.NET and IVI-C have a few important differences in the way they represent repeated capabilities. The first difference of note is that IVI-C drivers do not support collection-style repeated capabilities. IVI.NET and IVI-C drivers also use a different set of IVI-defined standard methods and properties to manage the repeated capability instances.

The table below presents the required repeated capability methods and properties for IVI.NET and IVI-C drivers based upon the type of repeated capability. For a discussion of the different types of repeated capabilities see the IVI Backgrounder topic on Repeated Capabilities.

Repeated Capability Style

IVI.NET

IVI-C

Collection-Style

  • Count property

  • Item property

  • Name property

  • Not supported.

Parameter-Style

  • <Capability>Count property (Ex: ChannelCount)

  • <CAPABILITY>_COUNT attribute (Ex: CHANNEL_COUNT)

  • Get<Capability>Name function (Ex: GetChannelName)

Selector-Style

  • <Capability>Count property (Ex: ChannelCount)

  • Active<Capability> property (Ex: ActiveChannel)

  • Get<Capability>Name method (Ex: GetChannelName)

  • <CAPABILITY>_COUNT attribute (Ex: CHANNEL_COUNT)

  • Get<Capability>Name function (Ex: GetChannelName)

  • ACTIVE_<CAPABILITY> attribute (Ex: ACTIVE_CHANNEL)

  • SetActive<Capability> function (Ex: SetActiveChannel)

As the table shows, different methods and properties must be maintained in the IVI.NET and IVI-C hierarchies based upon the type of repeated capability. Nimbus automatically handles each case by creating the appropriate IVI-C functions and attributes.

Collection-Style Repeated Capabilities and IVI-C

The case of collection-style repeated capabilities requires special handling since this type of repeated capability is not supported by IVI-C drivers. Whenever a collection-style repeated capability is added to a driver, Nimbus treats the repeated capability as a parameter-style repeated capability in the IVI-C hierarchy. This means Nimbus automatically creates the <CAPABILITY>_COUNT attribute and the Get<Capability>Name function.

Important note Important

Collection-style repeated capabilities in an IVI.NET driver are always treated as parameter-style repeated capabilities in the IVI-C hierarchy.

Creating IVI.NET-only and IVI-C-only Methods and Properties

There are some instances where it is not possible or desirable to expose an IVI.NET method in the IVI-C driver. Such an IVI.NET method has no associated IVI-C function and is termed an IVI.NET-only method. Correspondingly, there are occaisions where an IVI-C function serves no useful purpose in the IVI.NET hierarchy. This requires IVI-C functions that have no IVI.NET counterpart -- these are termed IVI-C-only functions.

IVI.NET-only methods and properties are established by deleting the linked IVI-C function or attribute.

To create an IVI.NET-only method or property

  1. From the IVI.NET Designer, select the desired method or property.

  2. For a method, right-click and choose Delete IVI-C Function.

    For a property, right-click and choose Delete IVI-C Attribute.

  3. The Info Panel should display None for the associated IVI-C items.

IVI-C-only functions and attributes are created by simply adding an IVI-C function or attribute directly using the IVI-C Designer. Recall that the IVI-C Designer does not push changes to the IVI.NET hierarchy, so anything created directly from the IVI-C Designer is inherently IVI-C-only.

To create an IVI-C-only function or attribute

  1. From the IVI-C Designer, select the desired location within the IVI-C tree view.

  2. Right-click and choose Add Function or Add Attribute.

  3. The Info Panel shows that no IVI.NET method or property is linked with the item.

See Also

Other Resources

Managing IVI-C Driver Functionality


Adding Help Information

Most of the items in an IVI.NET driver (methods, properties, parameters, etc.) have help information associated with them. The help content is used to generate HTML help files as well as other help-based artifacts, such as the XML IntelliSense file. The topics under Creating a Driver Help File provide detailed information on how driver help content is used.

Irrespective of where Nimbus uses the help information for an item, the content for each item is managed from a single location -- the Help Editor.

To add help information to an item

  1. From Solution Explorer, double-click the Driver Designer node under the Nimbus node.

  2. The IVI.NET Driver Designer tree view opens.

  3. Expand the root node, which will be named after the driver assembly (e.g.: Acme.Acme4321).

  4. Locate the desired item beneath the main Hierarchy node, the Enums node, or any of the other nodes corresponding to entities defined within the driver.

  5. Select the desired item in the tree view.

  6. On the right-side of the IVI.NET Driver Designer, click the Help tab along the lower section of the designer.

    Note Note

    The Help tab will only be enabled if there is a help project in the active solution that is associated with the driver being modified. If the Help tab is disabled, simply add a new help project to the solution and then return to the IVI.NET Driver Designer in order to enter the desired help information.

  7. The Help Editor appears. Select the desired tab (Summary, Remarks, etc.) and enter the desired help information. See the Help Editor topic for details.

See Also

Other Resources

Using the Nimbus Driver Designer
Creating a Driver Help File


Adding State Caching to a Property

To add state caching to a property

  1. From Solution Explorer, double-click the Driver Designer node under the Nimbus node.

  2. The IVI.NET Driver Designer tree view opens.

  3. Expand the root node, which will be named after the driver assembly (e.g.: Acme.Acme4321).

  4. On the right-side of the IVI.NET Driver Designer, click the State Caching button along the lower section of the designer.

  5. The State Caching Editor appears. See the State Caching Editor topic for details.

    Important note Important

    Refer to the State Caching Overview help topic for important details on state caching in Nimbus.

See Also

Other Resources

What All IVI Drivers Do -- Inherent Capabilities
State Caching Overview
Understanding Nimbus Code Weaving


Adding Range Checking and Coercion to a Property

To add range checking to a property

  1. From Solution Explorer, double-click the Driver Designer node under the Nimbus node.

  2. The IVI.NET Driver Designer tree view opens.

  3. Expand the root node, which will be named after the driver assembly (e.g.: Acme.Acme4321).

  4. Locate and then select the desired property from the tree view.

  5. On the right-side of the IVI.NET Driver Designer, click the Range Checking tab along the lower section of the designer.

  6. The Range Checking Editor appears. See the Range Checking Editor topic for details.

See Also

Other Resources

What All IVI Drivers Do -- Inherent Capabilities
Understanding Nimbus Code Weaving


Adding Simulation to a Property

To add simulation to a property

  1. From Solution Explorer, double-click the Driver Designer node under the Nimbus node.

  2. The IVI.NET Driver Designer tree view opens.

  3. Expand the root node, which will be named after the driver assembly (e.g.: Acme.Acme4321).

  4. Locate and then select the desired property from the tree view.

  5. On the right-side of the IVI.NET Driver Designer, click the Simulation button along the lower section of the designer.

  6. The Simulation Editor appears. See the Simulation Editor topic for details.

See Also

Other Resources

What All IVI Drivers Do -- Inherent Capabilities
Understanding Nimbus Code Weaving


Adding Support for an Instrument Class

To add support for an instrument class

  1. From Solution Explorer, double-click the Driver Settings Editor node under the Nimbus node.

  2. The Driver Settings Editor appears.

  3. Select the Instrument Classes tab.

  4. From the list of Available instrument classes, select the instrument class you wish to add to the driver, and select Add.

    Caution note Caution

    Adding support for an instrument class is a major operation and injects a large amount of code into the driver project and unit test project. Do not perform this operation until you are certain you wish to include support for the instrument class.

  5. When the operation completes, the newly added instrument classes will appear in the IVI.NET Driver Designer tree view. In addition, Nimbus performs a variety of tasks to add support for the selected instrument classes:

    • A reference to the IVI instrument class assembly is added to the driver project.

    • Any repeated capabilities defined by the instrument class are added to the driver and any supporting interfaces, methods, properties, and classes are added to the driver hierarchy.

    • Implementation code for the methods and properties defined on the instrument class are added to the driver project.

    • Unit test code for exercising the instrument class methods and properties is added to the unit test project.

    • The driver installer is updated to register the driver with the IVI Configuration Store as supporting the selected instrument classes.

Important note Important

By default, all of the class capability groups defined by a selected instrument class are marked as being supported by the driver. After adding an instrument class to the driver, it is important to visit the Capability Groups Page of the Driver Settings Editor to select the appropriate capability groups.

Tip Tip

If the new instrument class contains a repeated capability that represents the same physical repeated capability as one already defined in the driver, then you may want to merge the repeated capabilities.

The remaining topics in this section discuss each wizard page separately.

In This Section

Instrument Classes Page, IVI.NET Driver Settings

See Also

Other Resources

How IVI Drivers Provide Interchangeability
Repeated Capabilities
Merging Repeated Capabilities


Adding Support for LXI

The level of LXI compliance supported by the driver can be changed at any stage of development. Nimbus performs a number of roundtripping operations based upon the specific level of LXI compliance chosen. For example, changing the conformance from None to LXI Core 2016 and adding support for LXI Event Messaging adds several repeated capabilities to the driver as well as a host of methods, properties, and interfaces. Correspondingly, decreasing the level of compliance will cause Nimbus to remove code from the project.

Caution note Caution

When decreasing the level of LXI compliance, Nimbus removes implementation and test code from the project. It is important to ensure that no code of interest exists in the LXI-related implementation and test files before changing the driver to support a lower level of LXI compliance.

To adjust the LXI support level

  1. From Solution Explorer, double-click the Driver Settings Editor node to bring up the Driver Settings Editor.

  2. Click on the LXI tab of the Driver Settings Editor that is displayed.

    This page allows you to change the level of LXI support offered by your driver. Refer to this page for a complete description of these options.

    Note Note

    Changing the level of LXI support is a fairly major operation. As a result, you may be prompted to confirm that you wish to proceed before the requested changes are applied to your driver project.

Tip Tip

If the IviLxiSync interfaces contain a repeated capability that represents the same physical repeated capability as one already defined in the driver, then you may want to merge the repeated capabilities.

See Also

Other Resources

LXI Compliance Page, New IVI.NET Driver Wizard


Understanding Type Name Resolution in Nimbus

Whenever you enter the name of a type into the Nimbus driver designer or any of its associated item editors, Nimbus needs to locate the assembly in which the type you're referring to is defined. To do this, Nimbus uses the same mechanism as Visual Studio itself. Specifically, it resolves type names based upon the driver project's set of assembly refererences, project references, and NuGet package references.

If the type name resolution operation fails, Nimbus will display an error message indicating the type you've entered is unknown. The most common reasons for this error message are:

  • The type name is misspelled (i.e., there is a typo in the name you entered).

  • The namespace has not been included in the type name. For most types used by an IVI.NET driver, the type can be specified without including the parent namespace. The namespace need not be specfied in the following cases:

    1. The type is in the main driver assembly.

    2. The type is defined in an IVI assembly. For example, IWaveform<double> can be specified instead of Ivi.Driver.IWaveform<double>.

    3. The type is in mscorlib. For example, IList can be specified instead of System.Collections.IList.

  • The type is defined in an assembly that the driver project is not currently referencing. Nimbus cannot infer which assembly that might be, so you'll need to add a reference to the assembly that contains the type you're trying to use.

If Nimbus determines that the type you entered exists in more than one assembly referenced by the driver project, then Nimbus will display a dialog box asking you to clarify which type you intended to use.

Nimbus type name resolution is characterized in more detail below.

Type Parameters

In addition to recognizing standard type names, Nimbus also recognizes generic type parameter names, so long as the type parameter you're referring to is in scope relative to the item you're editing.

In order to further explain, consider the following simple generic type definition:

C#
Copy
// A generic type.
public class Acme4321DataSet<T> : DriverNode
{
    private T[] DataSet { get; set; }

  [DriverMethod]
  public void Transform<U>(U[] data)
    {
      // Transformation each element of "DataSet" according to the values passed in
        // via the "data" parameter.
    }
}

In the above code, the Acme4321DataSet class has been defined as a generic type, and includes a single type parameter (T). This type parameter is used to define a private property within the Acme4321DataSet class that will hold a reference to an "array of T" (DataSet).

This class also defines a generic method named Transform. The Transform method defines a different type parameter (U), and accepts an "array of U" as a parameter (data).

In this example, T and U are different type names, and may be used when entering type names in the driver designer's tree view or item editors. Exactly when type parameters such as T and U used above may be entered depends on exactly what you are trying to add or modify using the designer.

For example, if you are adding a new property to the Acme4321DataSet class, or using an item editor to change the type of a property already defined on that class, you may enter T as the type of that property. Likewise, you may enter T as the return type for a method defined on that class.

Similarly, if you are adding or changing a parameter of the Transform method, then the set of type names you may use to indicate the type of that parameter includes both T and U. The type parameter T is available because it is defined on the class that contains the Transform method. The type parameter U is also available to be used as a parameter type because U is defined on the method that contains the parameter you're adding or updating.

For a more in-depth explanation of generic types, generic methods and working with type parameters, refer to the C# Programming Guide in MSDN.

See Also

Other Resources

Generics (C# Programming Guide)
Generic Type Parameters (C# Programming Guide)


IVI.NET Item Editors

When the IVI.NET Driver Designer is open, a tree view of the driver methods, properties, and types appears on the left, while a set of tabbed controls for the selected tree view item appears on the right. As the tree view selection changes, these controls are updated with the details of the selected item. Developers manipulate the selected item by working with these controls. Such an arrangement is often referred to in user interface design as a master-details view. Nimbus uses the term Item Editor to refer to the various tabbed controls available when working with the IVI.NET Driver Designer tree view.

The topics in this section explain each of the IVI.NET Item Editors in detail.

In This Section

Interface General Editor

Class General Editor

Struct General Editor

Exception General Editor

Enum General Editor

Enum Member Editor

Delegate General Editor

Event General Editor

Method General Editor

Method State Caching Editor

Parameter General Editor

Property General Editor

Property Simulation Editor

Property Range Checking Editor

Property State Caching Editor

Using the Help Editor

See Also

Other Resources

Adding Functionality to an IVI.NET Driver


Interface General Editor

Name

Specifies the name of the interface. If this interface is a generic interface, its type arguments are specified as part of the name. For information on how to use generic types, refer to Generics (C# Programming Guide)

The following naming rules apply to the interface name:

  • The name must begin with an alphabetic character, and consist entirely of alphanumeric characters.

  • The name must be unique within the driver.

See Also

Other Resources

Adding Functionality to an IVI.NET Driver
Understanding Type Name Resolution in Nimbus
Interfaces (C# Programming Guide)
Generics (C# Programming Guide)


Class General Editor

Name

Specifies the name of the class. If this class is a generic class, its type arguments are specified as part of the name. For information on how to use generic types, refer to Generics (C# Programming Guide)

The following naming rules apply to the class name:

  • The name must begin with an alphabetic character, and consist entirely of alphanumeric characters.

  • The name must be unique within the driver.

Base class

Specifies the name of the base class, if any.

See Also

Other Resources

Adding Functionality to an IVI.NET Driver
Understanding Type Name Resolution in Nimbus
Classes and Structs (C# Programming Guide)
Classes (C# Programming Guide)
Generics (C# Programming Guide)


Struct General Editor

Name

Specifies the name of the struct. If this struct is a generic struct, its type arguments are specified as part of the name. For information on how to use generic types, refer to Generics (C# Programming Guide)

The following naming rules apply to the struct name:

  • The name must begin with an alphabetic character, and consist entirely of alphanumeric characters.

  • The name must be unique within the driver.

See Also

Other Resources

Adding Functionality to an IVI.NET Driver
Understanding Type Name Resolution in Nimbus
Classes and Structs (C# Programming Guide)
Structs (C# Programming Guide)
Generics (C# Programming Guide)


Exception General Editor

Name

Specifies the name of the exception class. If this exception class is a generic class, its type arguments are specified as part of the name. For information on how to use generic types, refer to Generics (C# Programming Guide)

The following naming rules apply to the exception class name:

  • The name must begin with an alphabetic character, and consist entirely of alphanumeric characters.

  • The name must be unique within the driver.

Base class

Specifies the name of the base exception class.

See Also

Other Resources

Adding Functionality to an IVI.NET Driver
Understanding Type Name Resolution in Nimbus
Exceptions and Exception Handling (C# Programming Guide)
Generics (C# Programming Guide)


Enum General Editor

Name

Specifies the name of the enum. The following naming rules apply to the enum name:

  • The name must begin with an alphabetic character, and consist entirely of alphanumeric characters.

  • The name must be unique within the driver.

See Also

Other Resources

Adding Functionality to an IVI.NET Driver
Enumeration Types (C# Programming Guide)


Enum Member Editor

Name

Specifies the name of the enum member. The following naming rules apply to the enum member name:

  • The name must begin with an alphabetic character, and consist entirely of alphanumeric characters.

  • The name must be unique relative to other enum members defined on the parent enum.

Value

Specifies the numeric value of the enum member. The value should be unique within the parent enum.

See Also

Other Resources

Adding Functionality to an IVI.NET Driver
Enum General Editor


Delegate General Editor

Signature

Specifies the signature of the delegate. If this delegate is a generic type, its type arguments are specified as part of the signature. For information on how to use generic types, refer to Generics (C# Programming Guide)

The following naming rules apply to the delegate signature:

  • The name must begin with an alphabetic character, and consist entirely of alphanumeric characters.

  • The name must be unique within the driver.

See Also

Other Resources

Adding Functionality to an IVI.NET Driver
Understanding Type Name Resolution in Nimbus
Delegates (C# Programming Guide)
Generics (C# Programming Guide)


Event General Editor

Name

Name of the event. Event names must start with a capital letter and can contain only alphanumeric characters.

Delegate type

The delegate type of the event.

Generic delegate types are supported. For information on how to use generic types, refer to Generics (C# Programming Guide)

Tip Tip

For additional information on delegate types in IVI.NET drivers, see the section Understanding Event Types in the topic Adding an Event.

See Also

Other Resources

Adding Functionality to an IVI.NET Driver
Understanding Type Name Resolution in Nimbus
Events (C# Programming Guide)
Delegates (C# Programming Guide)
Generics (C# Programming Guide)


Method General Editor

Name

Name of the method. Method names must start with a capital letter and can contain only alphanumeric characters.

Return type

Return type of the method.

Generic types are supported. For information on how to use generic types, refer to Generics (C# Programming Guide)

If an array is desired, append opening and closing square brakets ([]) to the type name. For example, to have the method return an array of double, enter Double[].

Tip Tip

The following syntax can be used in the Return type text box to create a new enum type and use that enum as the return type all in one operation:

new enum TriggerSource; Internal = 2, External = 0x15, Software = 47

See the topic Defining New Data Types Inline for more information on this feature.

Repeated capability

The repeated capability with which the method is associated.

Note Note

Not all repeated capabilites defined for the driver may appear in the Repeated capability combo box. This is because not all repeated capability transitions may be valid for the selected method. For instance, a method located on a collection-style repeated capability is inherently associated with that repeated capability based on its location within the driver hierarchy. Thus, it cannot be associated with a completely different repeated capability by using the Repeated capability combo box.

Implementation

Choosing the Manual option requires the driver developer to provide the method implementation. This choice is often used for methods that rely upon non-message-based device communications, such as register-based devices or drivers that rely upon a support DLL.

Choosing the Instrument command option instructs Nimbus to automatically generate all of the implementation code needed to send the specified command and to read a response if the Response text box is non-empty.

Choosing the Manual with instrument command option is the same as Manual except that the Command and Response textboxes are enabled and used to populate the Instrument Command section of the driver help page for the method. This is useful for methods that require manual implementation but that ultimately rely upon an instrument command in their manually added code.

Command

Specifies the command to send to the device. Nimbus supports a rich command and responseformatting syntax, which can include the parameters, repeated capabilities, and more. Please see the topic Working With Instrument Commands for a detailed discussion of automatic command formatting.

Response

Specifies the format of the response to read back from the device. Nimbus supports a rich command formatting syntax, which can include the parameters, repeated capabilities, and more. Please see the topic Working With Instrument Commands for a detailed discussion of automatic command formatting.

If no response is specified, Nimbus will only send the command specified in the Command text box -- no response will be read from the device.

Allow null for any reference-type parameter

By default, the Nimbus Code Weaver will automatically generate parameter validation code that raises a NullReferenceException if null is passed for any reference-type parameters to this method. Checking this box causes Nimbus to decorate this method with a NullAllowed attribute, which suppresses the standard null reference check for all reference-type parameters to this method.

Model-Specific Programming with the Models Window

The Method General Editor contains a collapsible Models Window in the right portion of the editor. This window is used for two purposes:

  • Specifying that a model or group of models does not support the method.

  • Customizing settings on a per-model or per-family basis.

Note Note

The Models Window cannot be used to define new models for the driver. The list of models supported by the driver is specified on the Models Page of the Driver Settings Editor.

The root node of the Models Window is labeled "All Models". This node can be thought of as the "default behavior" for the method. By default, all instrument models are supported for the method and all share the same command and response. Thus, the editor controls are initially only enabled when "All Models" is selected in the Models Window. This changes when model-specific behavior is specified, as explained below.

When you use the Models Window to specify that a method is not supported for a model, Nimbus will generate the necessary code to raise the IVI-defined OperationNotSupportedException exception.

To specify that a particular model is not supported

  1. From the Models Window, right-click on the desired model or family.

  2. Choose Remove model support.

  3. The selected model name appears with a strikethrough font.

    Note that if a family was selected, all models in the family appear with a strikethrough font, indicating that the OperationNotSupportedException exception will be raised for those models as well.

  4. To re-enable support for a model, right-click the model and choose Add model support.

When customizing behavior on a per-model or per-family basis, Nimbus generates code that will send a different command and/or read a differently formatted response, based upon the actual model detected at runtime. See the discussion of the InitializeIdentification function to understand how Nimbus determines the connected model at runtime.

Only the instrument command and instrument response can be customized on a per-model basis. The return data type, repeated capability, and implementation style are all static characteristics of the method and cannot be changed dynamically based on the connected instrument model.

To customize the command or response for a model

  1. From the Models Window, right-click on the desired model or family.

  2. Choose Customize settings

  3. The Command and Reponse text boxes are enabled for the selected model, allowing model-specific values to be set. The model appears in bold font for the customized model.

    Note that if a family was selected, all models in the family appear in bold font, indicating that they will all share a custom command and/or resposne.

  4. To have a method return to using the default command and response for a model, right-click the model and choose Remove custom settings. The model appears in normal font and the editor controls are once again disabled when the model is selected, indicating that the model is controlled via the default settings specified when the "All Models" node is selected.

See Also

Reference

NullAllowedAttribute

Other Resources

Adding Functionality to an IVI.NET Driver
Understanding Type Name Resolution in Nimbus
Understanding Nimbus Code Weaving
Defining New Data Types Inline
Methods (C# Programming Guide)
Generics (C# Programming Guide)


Method State Caching Editor

Nimbus allows state caching to be enabled on a property-by-property basis. The Method State Caching Editor allows the driver developer to specify cache couplings. See the topic Understanding Nimbus State Caching for more information.

Properties invalidated when this property is set

This list contains the cache keys for any cached properties that will be invalidated whenever this method is invoked. Invoking this method will cause any previously cached values corresponding to the specified keys to be discarded.

To add a cache entry key to the invalidation list

  1. Click the "+" button to add a new entry.

  2. Enter a cache entry key. Cache keys are expressed in one of the following three formats:

    • PropertyName

      Use this format to invalidate a property defined on the same interface as the method being configured.

      For example, if the method being configured is defined on the IAcme4301Trigger interface, entering Frequency indicates that whenever this method is invoked, any value previously cached by the implementation of IAcme4301Trigger.Frequency should be discarded.

    • InterfaceName.PropertyName

      Use this format to invalidate a property defined on the same class as the method being configured, where the property satisfies the implementation of the specified interface.

      For example, if the class containing the method being configured implements both the IIviDownconverterIFOutput and IIviDownconverterRFInput interfaces (both of which define a Frequency property), specifying IIviDownconverterIFOutput.Frequency indicates that whenever this method is invoked, any value previously cached by the implementation of IIviDownconverterIFOutput.Frequency should be discarded. Any value previously cached by the implementation of IIviDownconverterRFInput.Frequency will not be affected.

    • CollectionStyleRepCapItemPath.InterfaceName.PropertyName

      Use this format to invalidate a property defined on a collection-style repeated capability interface.

      In this case, a combination of repeated capability names and repeated capability selectors are specified in addition to the appropriate interface and property name. Examples include:

      • Channel[CHANNEL1].Trace[TRACE2].IAcme4321Acquisition.Frequency

      • Channel[*].Trace[TRACE2].IAcme4321Acquisition.Frequency

      • Channel[CHANNEL1].Trace[*].IAcme4321Acquisition.Frequency

      • Channel[CHANNEL1-CHANNEL3].Trace[*].IAcme4321Acquisition.Frequency

      • Channel[*].Trace[TRACE2,TRACE4].IAcme4321Acquisition.Frequency

      • Channel[CHANNEL1,CHANNEL3-CHANNEL5].Trace[*].IAcme4321Acquisition.Frequency

  3. Press the enter key.

See Also

Reference

InvalidateCacheEntriesAttribute

Other Resources

Adding Functionality to an IVI.NET Driver
State Caching Overview
Understanding Nimbus Code Weaving


Parameter General Editor

Name

Name of the parameter. Parameter names must start with a capital letter and can contain only alphanumeric characters.

Type

Data type of the method.

Generic types are supported. For information on how to use generic types, refer to Generics (C# Programming Guide)

If an array is desired, append opening and closing square brakets ([]) to the type name. For example, to specify an array of double, enter Double[].

Tip Tip

The following syntax can be used in the Type text box to create a new enum type and use that enum as the type all in one operation:

new enum TriggerSource; Internal = 2, External = 0x15, Software = 47

See the topic Defining New Data Types Inline for more information on this feature.

Direction

Choose Input to specify an input parameter.

Choose Output to specify an output parameter.

Choose Input/Output to specify an input/output parameter.

Choose VarArgs (params) to specify a variable-length list of parameters.

Allow null

By default, the Nimbus Code Weaver will automatically generate parameter validation code that raises a NullReferenceException if null is passed for any reference-type parameters to this method. Checking this box causes Nimbus to decorate this parameter with a NullAllowed attribute, which suppresses the standard null reference check for this parameter without affecting null reference checking that may be performed for other parameters to this method.

See Also

Reference

NullAllowedAttribute

Other Resources

Adding Functionality to an IVI.NET Driver
Understanding Type Name Resolution in Nimbus
Understanding Nimbus Code Weaving
Defining New Data Types Inline
Generics (C# Programming Guide)


Property General Editor

Name

Name of the property. Property names must start with a capital letter and can contain only alphanumeric characters.

Type

Data type of the property.

Generic types are supported. For information on how to use generic types, refer to Generics (C# Programming Guide)

If an array is desired, append opening and closing square brakets ([]) to the type name. For example, to have the property return an array of double, enter Double[].

Tip Tip

The following syntax can be used in the Type text box to create a new enum type and use that enum as the type all in one operation:

new enum TriggerSource; Internal = 2, External = 0x15, Software = 47

See the topic Defining New Data Types Inline for more information on this feature.

Access

Indicates if the property is read-write, read-only, or write-only.

Repeated capability

The repeated capability with which the property is associated.

Note Note

Not all repeated capabilites defined for the driver may appear in the Repeated capability combo box. This is because not all repeated capability transitions may be valid for the selected property. For instance, a property located on a collection-style repeated capability is inherently associated with that repeated capability based on its location within the driver hierarchy. Thus, it cannot be associated with a completely different repeated capability by using the Repeated capability combo box.

Implementation

Choosing the Manual option requires the driver developer to provide the implementation for the property getter and setter. This choice is often used for properties that rely upon non-message-based device communications, such as register-based devices or drivers that rely upon a support DLL.

Choosing the Instrument command option instructs Nimbus to automatically generate all of the implementation code needed to send the specified commands and to read a response for the property getter, if the Response text box is non-empty.

Choosing the Manual with instrument command option is the same as Manual except that the command and response textboxes are enabled and used to populate the Instrument Command section of the driver help page for the property. This is useful for properties that require manual implementation but that ultimately rely upon an instrument command in their manually added code.

Setter command

Specifies the command to send to the device when the value of the property is set (i.e. the property setter executes). This control is not enabled for read-only properties. Nimbus supports a rich command and response formatting syntax, which can include the parameters, repeated capabilities, and more. Please see the topic Working With Instrument Commands for a detailed discussion of automatic command formatting.

Getter command

Specifies the query to send to the device when the value of the property value is read (i.e. the property getter executes). This control is not enabled for write-only properties. Nimbus supports a rich command and response formatting syntax, which can include the parameters, repeated capabilities, and more. Please see the topic Working With Instrument Commands for a detailed discussion of automatic command formatting.

Getter response

Specifies the format of the response to read back from the device when the property value is read. This control is not enabled for write-only properties.

Allow null

By default, the Nimbus Code Weaver will automatically validation code that raises a NullReferenceException if a reference-type property is set to null. Checking this box causes Nimbus to decorate this property with a NullAllowed attribute, which suppresses the standard null reference check for this property.

Model-Specific Programming with the Models Window

The Property General Editor contains a collapsible Models Window in the right portion of the editor. This window is used for two purposes:

  • Specifying that a model or group of models does not support the method.

  • Customizing settings on a per-model or per-family basis.

Note Note

The Models Window cannot be used to define new models for the driver. The list of models supported by the driver is specified on the Models Page of the Driver Settings Editor.

The root node of the Models Window is labeled "All Models". This node can be thought of as the "default behavior" for the property. By default, all instrument models are supported for the property and all share the same command and response. Thus, the editor controls are initially only enabled when "All Models" is selected in the Models Window. This changes when model-specific behavior is specified, as explained below.

When you use the Models Window to specify that a property is not supported for a model, Nimbus will generate the necessary code to raise the IVI-defined OperationNotSupportedException exception.

To specify that a particular model is not supported

  1. From the Models Window, right-click on the desired model or family.

  2. Choose Remove model support.

  3. The selected model name appears with a strikethrough font.

    Note that if a family was selected, all models in the family appear with a strikethrough font, indicating that the OperationNotSupportedException exception will be raised for those models as well.

  4. To re-enable support for a model, right-click the model and choose Add model support.

When customizing behavior on a per-model or per-family basis, Nimbus generates code that will send different setter commands, getter commands, and/or read a differently formatted getter response, based upon the actual model detected at runtime. See the discussion of the InitializeIdentification method to understand how Nimbus determines the connected model at runtime.

Only the getter and setter commands and getter response can be customized on a per-model basis. The return data type, property access, repeated capability, and implementation style are all static characteristics of the property and cannot be changed dynamically based on the connected instrument model.

To customize the command or response for a model

  1. From the Models Window, right-click on the desired model or family.

  2. Choose Customize settings

  3. The Setter command, Getter command, and Getter reponse text boxes are enabled for the selected model, allowing model-specific values to be set. The model appears in bold font for the customized model.

    Note that if a family was selected, all models in the family appear in bold font, indicating that they will all share a custom command and/or resposne.

  4. To have a property return to using the default commands and response for a model, right-click the model and choose Remove custom settings. The model appears in normal font and the editor controls are once again disabled when the model is selected, indicating that the model is controlled via the default settings specified when the "All Models" node is selected.

See Also

Reference

NullAllowedAttribute

Other Resources

Adding Functionality to an IVI.NET Driver
Understanding Type Name Resolution in Nimbus
Defining New Data Types Inline
Properties (C# Programming Guide)
Indexers (C# Programming Guide)
Generics (C# Programming Guide)


Property Simulation Editor

Nimbus offers two different styles of automatic simulation support -- returning a fixed value for the property and returning the last value to which the property was set.

Important note Important

The simulation logic for either option is only executed when simulation is enabled by the end user. This can be done by passing Simulate=True as part of the OptionString parameter to the driver's Initialize method, or it can be done after driver initialization via the IIviDriverOperation.Simulate property.

Manual

Specifies that no automatic simulated value should be returned for the property. Selecting this option indicates that the driver developer will manually implement simulation logic in the property implementation.

Fixed value

Instructs Nimbus to simply return the value specified in the Value text box when the property is read in simulation mode. Setting the property to a different value has no effect on the driver behavior.

Last Value Set

Specifies that the driver should cache the value of the property when it is set and return the most recent value set when the property is read. If the property is read without having been set, then the value specified in the Default text box is returned.

Model-Specific Programming with the Models Window

The Property Simulation Editor contains a collapsible Models Window in the right portion of the editor. This window is used to customize simulation settings on a per-model or per-family basis.

Note Note

The Models Window cannot be used to define new models for the driver. The list of models supported by the driver is specified on the Models Page of the Driver Settings Editor.

The root node of the Models Window is labeled "All Models". This node can be thought of as the "default behavior" for the property. By default, all instrument models share the same simulation settings. Thus, the editor controls are initially only enabled when "All Models" is selected in the Models Window. This changes when model-specific behavior is specified, as explained below.

When simulation behavior on a per-model or per-family basis, Nimbus generates code that will use different simulated values based upon the actual model detected at runtime. See the discussion of the InitializeIdentification method to understand how Nimbus determines the connected model at runtime.

The only simulation settings that can be customized on a per-model basis are the constant returned when the Fixed Value option is chosen and the default value used when the Last Value Set option is chosen. The simulation style (manual, last value set, fixed) must be the same for all models.

To customize the simulation settings for a model

  1. From the Models Window, right-click on the desired model or family.

  2. Choose Customize settings

  3. The Value text boxes or the Default text box is enabled for the selected model, allowing a model-specific value to be set. The model appears in bold font for the customized model.

    Note that if a family was selected, all models in the family appear in bold font, indicating that they will all the same simulation values.

  4. To have a property return to using the simulation settings, right-click the model and choose Remove custom settings. The model appears in normal font and the editor controls are once again disabled when the model is selected, indicating that the model is controlled via the default settings specified when the "All Models" node is selected.

See Also

Reference

SimulationAttribute

Other Resources

Adding Functionality to an IVI.NET Driver
Understanding Nimbus Code Weaving


Property Range Checking Editor

Nimbus offers two different styles of automatic range checking -- validation against a continous range of values, or checking against a list of discrete values. In both cases, Nimbus generates code that raises the IVI-defined OutOfRangeException exception if the range check condition fails.

Important note Important

The range-checking logic for any option is only executed when range-checking is enabled by the end user. This can be done by passing RangeCheck=True as part of the OptionString parameter to the driver's Initialize method, or it can be done after driver initialization via the IIviDriverOperation.RangeCheck property.

None

Specifies that no automatic range checking should be performed on the property.

Continuous range

Enables range checking for the selected property against a continuous range of values between the specified Minimum and Maximum. The two Inclusive check boxes are used to specify if the Minimum and Maximum values are included in the list of valid values for the property.

Discrete values

Enables range checking for the selected property against a discrete set of values specifed as a comma-separated list.

Using this option also enables coercion of the property value. If the property value falls between two values in the list of Allowed values, then the Coercion combo box indicates whether the property value should rounded to the next higher value in the list (coerce Up), to the next lower value in the list (coerce Down), or should generate an error (coercion set to None).

Model-Specific Programming with the Models Window

The Property Range Checking Editor contains a collapsible Models Window in the right portion of the editor. This window is used to customize range-checking settings on a per-model or per-family basis.

Note Note

The Models Window cannot be used to define new models for the driver. The list of models supported by the driver is specified on the Models Page of the Driver Settings Editor.

The root node of the Models Window is labeled "All Models". This node can be thought of as the "default behavior" for the property. By default, all instrument models share the same range-checking settings. Thus, the editor controls are initially only enabled when "All Models" is selected in the Models Window. This changes when model-specific behavior is specified, as explained below.

When customizing range-checking behavior on a per-model or per-family basis, Nimbus generates code that will use different allowed values based upon the actual model detected at runtime. See the discussion of the InitializeIdentification method to understand how Nimbus determines the connected model at runtime.

The only range checking settings that can be customized on a per-model basis are the Minimum and Maximum values for continuous range checking and the Allowed values list for discrete range checking. The range checking style (none, continuous, discrete) must be the same for all models.

To customize the range checking settings for a model

  1. From the Models Window, right-click on the desired model or family.

  2. Choose Customize settings

  3. The Minimum and Maximum text boxes or the Allowed values text box are enabled for the selected model, allowing model-specific values to be set. The model appears in bold font for the customized model.

    Note that if a family was selected, all models in the family appear in bold font, indicating that they will all the same custom range checking values.

  4. To have a property return to using the default range checking settings, right-click the model and choose Remove custom settings. The model appears in normal font and the editor controls are once again disabled when the model is selected, indicating that the model is controlled via the default settings specified when the "All Models" node is selected.

See Also

Reference

RangeCheckMinMaxAttribute
RangeCheckDiscreteAttribute
RangeCheckStringAttribute

Other Resources

Adding Functionality to an IVI.NET Driver
Adding Range Checking and Coercion to a Property
Understanding Nimbus Code Weaving


Property State Caching Editor

Nimbus allows state caching to be enabled on a property-by-property basis. The Property State Caching Editor allows the driver developer to enable or disable state caching for the selected property and to specify cache couplings. See the topic Understanding Nimbus State Caching for more information.

Important note Important

The state caching logic specified here is only executed when state caching is enabled by the end user. This can be done by passing Cache=True as part of the OptionString parameter to the driver's Initialize method, or it can be done after driver initialization via the IIviDriverOperation.Cache property.

Enable caching of this property

When checked, Nimbus will apply the Cache attribute to this property, which instructs the Nimbus Code Weaver to generate implementation code that caches the property value between calls. This can reduce I/O traffic if redundant calls to the property occur, but it can also lead to cache coherency issues (data in memory out-of-sync with the actual instrument settings) if the property couplings are not thorougly understood and properly specified.

Properties invalidated when this property is set

This list contains the cache keys for any cached properties that will be invalidated whenever this property's value is modified. Changing the value of this property will cause any previously cached values corresponding to the specified keys to be discarded.

To add a cache entry key to the invalidation list

  1. Click the "+" button to add a new entry.

  2. Enter a cache entry key. Cache keys are expressed in one of the following three formats:

    • PropertyName

      Use this format to invalidate a property defined on the same interface as the property being configured.

      For example, if the property being configured is defined on the IAcme4301Trigger interface, entering Frequency indicates that whenever this property's value is changed, any value previously cached by the implementation of IAcme4301Trigger.Frequency should be discarded.

    • InterfaceName.PropertyName

      Use this format to invalidate a property defined on the same class as the property being configured, where the property satisfies the implementation of the specified interface.

      For example, if the class containing the property being configured implements both the IIviDownconverterIFOutput and IIviDownconverterRFInput interfaces (both of which define a Frequency property), specifying IIviDownconverterIFOutput.Frequency indicates that whenever this property's value is changed, any value previously cached by the implementation of IIviDownconverterIFOutput.Frequency should be discarded. Any value previously cached by the implementation of IIviDownconverterRFInput.Frequency will not be affected.

    • CollectionStyleRepCapItemPath.InterfaceName.PropertyName

      Use this format to invalidate a property defined on a collection-style repeated capability interface.

      In this case, a combination of repeated capability names and repeated capability selectors are specified in addition to the appropriate interface and property name. Examples include:

      • Channel[CHANNEL1].Trace[TRACE2].IAcme4321Acquisition.Frequency

      • Channel[*].Trace[TRACE2].IAcme4321Acquisition.Frequency

      • Channel[CHANNEL1].Trace[*].IAcme4321Acquisition.Frequency

      • Channel[CHANNEL1-CHANNEL3].Trace[*].IAcme4321Acquisition.Frequency

      • Channel[*].Trace[TRACE2,TRACE4].IAcme4321Acquisition.Frequency

      • Channel[CHANNEL1,CHANNEL3-CHANNEL5].Trace[*].IAcme4321Acquisition.Frequency

  3. Press the enter key.

See Also

Reference

CacheAttribute
InvalidateCacheEntriesAttribute

Other Resources

Adding Functionality to an IVI.NET Driver
State Caching Overview
Understanding Nimbus Code Weaving


Indexer General Editor

Name

Name of the indexer. Indexer names are fixed according to the programming language, and cannot be renamed.

Type

Data type of the indexer.

Generic types are supported. For information on how to use generic types, refer to Generics (C# Programming Guide)

If an array is desired, append opening and closing square brakets ([]) to the type name. For example, to have the indexer return an array of double, enter Double[].

Access

Indicates if the indexer is read-write, read-only, or write-only.

Repeated capability

The repeated capability with which the indexer is associated.

Implementation

Choosing the Manual option requires the driver developer to provide the implementation for the indexer getter and setter. This choice is often used for indexers that rely upon non-message-based device communications, such as register-based devices or drivers that rely upon a support DLL.

Choosing the Instrument command option instructs Nimbus to automatically generate all of the implementation code needed to send the specified commands and to read a response for the indexer getter, if the Response text box is non-empty.

Choosing the Manual with instrument command option is the same as Manual except that the command and response textboxes are enabled and used to populate the Instrument Command section of the driver help page for the indexer. This is useful for indexers that require manual implementation but that ultimately rely upon an instrument command in their manually added code.

Setter command

Specifies the command to send to the device when the value of the indexer is set (i.e. the indexer setter executes). This control is not enabled for read-only indexers. Nimbus supports a rich command and response formatting syntax, which can include the parameters, repeated capabilities, and more. Please see the topic Working With Instrument Commands for a detailed discussion of automatic command formatting.

Getter command

Specifies the query to send to the device when the value of the indexer value is read (i.e. the indexer getter executes). This control is not enabled for write-only indexers. Nimbus supports a rich command and response formatting syntax, which can include the parameters, repeated capabilities, and more. Please see the topic Working With Instrument Commands for a detailed discussion of automatic command formatting.

Getter response

Specifies the format of the response to read back from the device when the indexer value is read. This control is not enabled for write-only indexers.

Allow null

By default, the Nimbus Code Weaver will automatically validation code that raises a NullReferenceException if a reference-type indexer is set to null. Checking this box causes Nimbus to decorate this indexer with a NullAllowed attribute, which suppresses the standard null reference check for this indexer.

Model-Specific Programming with the Models Window

The Indexer General Editor contains a collapsible Models Window in the right portion of the editor. This window is used for two purposes:

  • Specifying that a model or group of models does not support the method.

  • Customizing settings on a per-model or per-family basis.

Note Note

The Models Window cannot be used to define new models for the driver. The list of models supported by the driver is specified on the Models Page of the Driver Settings Editor.

The root node of the Models Window is labeled "All Models". This node can be thought of as the "default behavior" for the indexer. By default, all instrument models are supported for the indexer and all share the same command and response. Thus, the editor controls are initially only enabled when "All Models" is selected in the Models Window. This changes when model-specific behavior is specified, as explained below.

When you use the Models Window to specify that a indexer is not supported for a model, Nimbus will generate the necessary code to raise the IVI-defined OperationNotSupportedException exception.

To specify that a particular model is not supported

  1. From the Models Window, right-click on the desired model or family.

  2. Choose Remove model support.

  3. The selected model name appears with a strikethrough font.

    Note that if a family was selected, all models in the family appear with a strikethrough font, indicating that the OperationNotSupportedException exception will be raised for those models as well.

  4. To re-enable support for a model, right-click the model and choose Add model support.

When customizing behavior on a per-model or per-family basis, Nimbus generates code that will send different setter commands, getter commands, and/or read a differently formatted getter response, based upon the actual model detected at runtime. See the discussion of the InitializeIdentification method to understand how Nimbus determines the connected model at runtime.

Only the getter and setter commands and getter response can be customized on a per-model basis. The return data type, indexer access, repeated capability, and implementation style are all static characteristics of the indexer and cannot be changed dynamically based on the connected instrument model.

To customize the command or response for a model

  1. From the Models Window, right-click on the desired model or family.

  2. Choose Customize settings

  3. The Setter command, Getter command, and Getter reponse text boxes are enabled for the selected model, allowing model-specific values to be set. The model appears in bold font for the customized model.

    Note that if a family was selected, all models in the family appear in bold font, indicating that they will all share a custom command and/or resposne.

  4. To have a indexer return to using the default commands and response for a model, right-click the model and choose Remove custom settings. The model appears in normal font and the editor controls are once again disabled when the model is selected, indicating that the model is controlled via the default settings specified when the "All Models" node is selected.

See Also

Reference

NullAllowedAttribute

Other Resources

Adding Functionality to an IVI.NET Driver
Understanding Type Name Resolution in Nimbus
Properties (C# Programming Guide)
Indexers (C# Programming Guide)
Generics (C# Programming Guide)


Implementing Driver Methods and Properties

The topics in this section explain the basics of IVI.NET driver method implementation.

In This Section

Working With Instrument Commands

Communicating With Instruments

Retrieving the Instrument Model

Retrieving Initialization Options

See Also

Other Resources

Working With Instrument Commands
Communicating With Instruments
Retrieving the Instrument Model
Retrieving Initialization Options


Communicating With Instruments

Nimbus can be used to build IVI.NET drivers for instruments that have use virtually any I/O protocol. Many instruments are accessed via standard protocols, such as TCP/IP, USB, GPIB, or serial. For these kinds of instruments, Nimbus leverages the VISA.NET library to perform I/O operations. The current implementation of VISA.NET provided by Pacific MindWorks uses the underlying VISA-C library to perform the low-level device communication.

Important note Important

Even though Nimbus provides built-in, easy-to-access support for instruments that communicate using VISA-supported protocols, there is no intrinsic dependence that Nimbus has on VISA. Fully compliant IVI.NET drivers can be built with Nimbus using a custom DLL that implements any private I/O protocol required.

Using Automatic Command Formatting

To use automatic command formatting, you must first associate an instrument command with the method or property by choosing the Instrument Command implementation type in the Method General Editor or the Property General Editor . Within the method implementation, Nimbus will generate a call to a standard VISA.NET method -- typically either PrintfAndFlush or Scanf. The code below is an example of the complete implementation of a method that uses the automatic command formatting features of the Method General Editor and the Property General Editor.

C#
Copy
// Acme4321.cs
void Configure(double frequency, double bandwidth)
{
   if (this.Session.InitOptions.SimulationEnabled)
   {
      throw new NotImplementedException();  // TODO
   }

   this.IO.FormattedIO.PrintfAndFlush("SENS:FREQ %0.15g; SENS:BAND %0.15g");
}


Working With Instrument Commands

By far, the most common way to implement Nimbus IVI.NET driver methods and properites is by specifying an instrument command and relying upon Nimbus to generate all of the necessary code to send the command and, optionally, to read back a response. Nimbus provides a powerful instrument command syntax that allows method parameters and other information to be automatically formatted into the command.

In This Section

Instrument Command Syntax

Special Features for SCPI Commands


Instrument Command Syntax

Nimbus provides a very flexible syntax for specifying instrument commands and responses that are associated with methods and properties. The command syntax described here applies to commands and responses entered in the Method General Editor or the Property General Editor.

When the user associates an instrument command or response with a method or property, Nimbus generates code to automatically format the command using the values of parameters passed to the method. Correspondingly, when responses are read back from an instrument, the results are parsed and assigned to out-parameters according to the response string specified by the user. Commands and responses can contain parameter replacement tags to control how each parameter is associated with the command or response. Additionally, commands (not responses) may include repeated capability replacement tags for inserting the repeated capability instance name or index into the command string.

Parameter Replacement Tags

Parameter replacement tags are enclosed in curly braces { } and can appear anywhere within an instrument command. They have the following general form:

{<paramName> | value[:<formatSpec>]}

The paramName is the name of the parameter in the method signature.

The value keyword is used to refer to the property value itself when defining property setter commands and property getter responses. The value keyword is also used to refer to a method return value. Use of the {value} keyword is discussed further in the sections below.

The formatSpec is an optional format specification for the parameter. This format specification is similar to that supported by the C Run-Time Library's familiar sprintf function. More precisely, this format specification can be any of those supported by VISA.NET. For a complete list of format specifications, see the documentation for your VISA.NET supplier.

Tip Tip

In general, the format specifications supported by VISA.NET match those supported by the viPrintf and viScanf methods that are part of the long-standing VISA-C specification. The IVI Foundation has made a concerted effort to follow these format specifications from VISA-C whereever possible, so that users already familiar with viPrintf and viScanf can use VISA.NET easily and effectively.

If no formatSpec is provided, then the default format specification is used. The default format specification only applies to integers, floating-point, and boolean parameters. These defaults are configured on the I/O Page of the Driver Settings Editor.

Special support is provided for formatting boolean and enum parameters.

Example: Basic Parameter Replacement

This example shows a Configure method that takes three parameters -- resolution bandwidth (ResBW), video bandwidth (VideoBW), and sweep time (SweepTime). Assume a method defined as follows

C#
Copy
void Configure([double resBW, double videoBW, double sweepTime);

The following instrument command is associated with the Configure method:

SENS:BAND{resBW}; SWE:TIME{sweepTime:%d}; BAND:VID{videoBW:%3.2f};

Given this method definition and the replacement tags shown, the instrument command would be formatted as follows:

  • The replacement tag {resBW} would be replaced with the run-time value of the resBW parameter. Since no format specification is provided, the default format for floating-point values would be applied.

  • The replacement tag {sweepTime:%d} would be replaced with the run-time value of the sweepTime parameter and formatted as a decimal as dictated by the %d format specification.

  • The replacement tag {videoBW} would be replaced with the run-time value of the videoBW parameter and formatted as a floating point number as dictated by the %3.2f format specification.

Formatting Property Setters

Property setters support a special {value} replacement tag to represent the value of the property itself. This special tag allows you to insert the runtime value of the property into the command string.

The following instrument command applied to a property setter would append the value of the property to the SENS:BAND string:

SENS:BAND {value}

Since most functionality in IVI.NET drivers is provided by properties, Nimbus simplifies the instrument command syntax by not requiring a replacement tag to be provided explicitly for property setters. Rather, the formatted property value will simply be appended to the command string. If the formatted parameter should appear elsewhere in the command string, then an explicit parameter replacement tag must be specified.

Given this shorthand notation, the following two instrument commands applied to a property setter produce identical results:

  • SENS:BAND

  • SENS:BAND {value}

Both command strings will append the formatted value of the property to the SENSE:BAND string. Note that in both cases the default parameter formatting for the property type will be applied, since no format specification is provided. If an alternate format specification is desired, then the {value} replacement tag must be specified.

The following example shows an instrument command using the {value} tag with a format specification:

SENS:BAND {value:%3.2e}

The above example will append the value of the property in exponentional form with a minimum length of 3 characters and 2 digits following the decimal point.

Properties may have parameters. Thus, the associated instrument command may include parameter replacement tags, just as with methods. The following example demonstrates use of the {value} tag in conjunction with a normal parameter replacement tag.

:CURRent:AC:BANDwidth {value}, {channelList}

The above example would be valid for a property setter that accepted a parameter named channelList.

Formatting Property Getters

Property getters utilize the {value} tag in precisely the same way as methods use the tag for responses. Only the getter response string may use the {value} tag -- the getter command may only use input and input/output (ref) parameter tags and repeated capability tags, not the {value}. See the discussion in the following section on how to use the {value} tag in method responses.

Formatting Method Return Values

Methods often have a return value associated with them. Since there is no parameter name to reference, the {value} tag is used to represent the method return value. A method return value is effectively an output parameter, so the {value} tag can only be used in the method response. The {value} tag cannot be used in the method command.

Consider a method defined as follows in the IVI.NET Driver Designer:

C#
Copy
double[] Fetch(long start, long numPoints)

The method command might be the following:

CALC:DATA? {start}, {numPoints}

The above command uses parameter replacement tags for the two input parameters Start and NumPoints. After issuing the above command, the driver needs to read data from the instrument and assign the resulting array of double-precision floating point numbers to the return value of the method. This can be done with the following method response string.

{value:%,e}

The response string above uses the {value} tag with a format specification of %,e. This format specification indicates that the instrument response is a comma-separated list of floating-point numbers in ASCII format.

Formatting Boolean And Enum Parameters

When an instrument command parameter tag refers to a boolean or enum parameter, Nimbus must generate code that converts the boolean or enum value to a string. Correspondingly, when an instrument response uses a parameter tag that references a boolean or enum, the instrument response string must be parsed and converted to the appropriate boolean or enum value.

The string-to-enum mappings are created using the Enum Member Editor. These mappings will apply to every property and method in which that enum is used as a parameter or return value. If a particular method or property using that enum needs unique string-to-enum mappings, then that method or property must be manually implemented.

The string-to-boolean mappings are managed differently -- by simply changing the settings in the I/O Page of the Driver Settings Editor.

As an example, consider the definition of a simple Source property:

C#
Copy
Acme.Acme4301.TriggerSource Source { get; set; }

The Source property is a read-write property of type TriggerSource. The command for the setter is defined as:

TRIG:SOUR {value}

The command for the getter is defined as:

TRIG:SOUR?

Finally, the response for the getter is defined simply as:

{value}

When the setter is executed, the specified value for the Source parameter needs to be converted to a string and inserted into the setter command where the {value} tag appears. For instance, if the property were set to the value TriggerSource.External, the enum value might need to be converted to EXT to produce the following command:

TRIG:SOUR EXT

Similarly, when the TRIG:SOUR? query is issued upon executing the property getter, the instrument might respond with a string such as INT (to represent an internal trigger source). This string needs to be converted to a valid TriggerSource enum value, such as TriggerSource.Internal.

Formatting TimeSpan and PrecisionTimeSpan Parameters

Because the TimeSpan and PrecisionTimeSpan data types are common in IVI.NET driver APIs, Nimbus provides special support for converting parameters of these types to and from instrument commands. When a parameter of type TimeSpan or PrecisionTimeSpan is used in an instrument command, Nimbus internally accesses the TotalSeconds member of the data type and formats the result as a string. Similarly, when an instrument response is received, it is parsed as a double and that value is used to create a TimeSpan or PrecisionTimeSpan object via the FromSeconds member.

Repeated Capability Replacement Tags

Instrument commands sent from methods implemented on repeated capability classes often need to incorporate runtime information about the specific repeated capability instance issuing the command. For example, a spectrum analyzer driver might define a repeated capability class to represent multiple traces stored in the instrument. A command that would read data from a specific trace might look something like the following:

DATA:TRACE4:READ?

Note that the 4 included in the command refers to a specific trace within the instrument.

Note Note

Repeated capability tags cannot appear in instrument response strings.

Repeated capability replacement tags are used to insert into command strings runtime information about the repeated capability instance sending the command. These special tags can be replaced by either the name or the index of the repeated capability.

For more information on repeated capabilities, see Repeated Capabilities.

Repeated capability replacement tags are enclosed in curly braces { } and can appear anywhere within an instrument command. They have the following general form:

{ [<parentRepCap>.]rcindex[+|-<offset>] | rcname }

The rcindex keyword is used to insert into the command string the runtime value of the index of the repeated capability instance issuing the command. The rcindex keyword can optionally be followed by an offset, such as +1 or -3, to account for differences between how repeated capabilities are indexed by the driver and how the instrument expects them to appear in the command string.

The rcname keyword is used to insert into the command string the runtime value of the name of the repeated capability instance issuing the command.

The parentRepCap is an optional parameter used to designate a parent (or any ancestor) repeated capability.

Example: Using the repeated capability index in instrument commands

This example shows a Resolution property that is defined on a repeated capability that represents multiple markers. In order to set the resolution for the correct marker, the index of the current repeated capability instance must be included in the command string. Assume a property definition as follows:

C#
Copy
double Resolution { get; set; }

The following instrument command is assigned to the Resolution property:

CALC:MARK{rcindex}:RES

If the Resolution property was executed from the fourth instance of the marker repeated capability, then the formatted string sent to the instrument would be as follows:

CALC:MARK3:RES

Example: Using the repeated capability index with an offset

In this example, the Resolution property of a marker repeated capability uses an instrument command with a positive offset of 1 for the repeated capability index. Assume a property definition as follows:

C#
Copy
double Resolution { get; set; }

The following instrument command is assigned to the Resolution property:

CALC:MARK{rcindex+1}:RES

If the Resolution property was executed from the fourth instance of the marker repeated capability, then the formatted string sent to the instrument would be as follows:

CALC:MARK4:RES

Example: Using the repeated capability name in an instrument command

This example demonstrates the use of the rcname keyword to insert the name of the current repeated capability instance into the instrument command. Assume a property definition as follows:

C#
Copy
double Amplitude { get; set; }

The following instrument command is assigned to the Amplitude property:

TRAC:DAT? {rcname}

Example: Building instrument commands with nested repeated capabilities

This example demonstrates the use of repeated capability replacement tags when nested repeated capabilities are involved.

Here, the command string includes two repeated capability replacement tags. One tag does not specify a parent repeated capability and, hence, implicitly refers to the repeated capability on which the method is defined (as in the previous examples). The other replacement tag refers to the Display repeated capability, which is a parent repeated capability of the class on which the method is defined. Assume the following method definition:

C#
Copy
void StoreReferenceTrace();

The following instrument command is assigned to the StoreReferenceTrace method:

CALC:DISP{Display.rcindex}:SRTR{rcindex}:REF

Assuming this method was invoked from the second instance of the trace repeated capability on the third instance of the display repeated capability, the following formatted command would be sent to the instrument:

CALC:DISP2:SRTR1:REF


Special Features for SCPI Commands

Many instruments today follow the SCPI (Standard Commands for Programmable Instruments) standard supported command set. Nimbus offers special convenience features for SCPI-based instruments. By checking the SCPI compliant check box on the I/O Page of the Driver Settings Editor, you are telling Nimbus that the instrument commands associated with methods and properties are SCPI compliant.

When a driver project is SCPI-compliant, Nimbus automatically strips the optional characters from the SCPI command string. This allows the developer to enter the full verbose form of the SCPI command in the Method General Editor (as well as the Property General Editor and the Enum Member Editor) and have the full text appear in the help page for the method. However, the Nimbus-generated code that sends the command to the instrument will use the minimal form of the command.

Consider the SCPI command below:

[SENSe:]FREQuency[:VOLTage]:RANGe[:UPPer]

If this command is associated with a method or property via the item editor, the command that will ultimately be sent to the instrument as follows:

FREQ:RANG

Note that all of the optional characters enclosed in square brackets have been removed, as have all of the lowercase characters.

Tip Tip

It is best to always enter the full SCPI command when associating instrument commands with methods and properties so that the full text shows up in the driver help file. Nimbus automatically adds the instrument commands to the driver help file index and builds a special page that maps instrument commands to driver methods and properties. Most users will expect to see the full form of the SCPI command in such contexts.

See Also

Other Resources

I/O Page, IVI.NET Driver Settings


Retrieving the Instrument Model

When a client application instantiates a driver, the standard Nimbus implementation of the constructor executes the InitializeIdentification function to query the instrument for identification information, such as the manufacturer, the firmware revision, and the specific instrument model. Nimbus caches the results of this process so that the driver developer (and the Nimbus-generated code) can use functions within the Nimbus Class Library to retrieve the identification information at any time during the driver session.

The InstrumentIsModel(String) is provided to allow driver code to compose conditional logical based upon the specific instrument model with which the driver is currently communicating. For instance, in the code example below, the InstrumentIsModel method is used to determine the exact SCPI command that should be sent to the instrument to program the voltage range.

Important note Important

Note the use of the Models class in the code below. This class is defined in the Models.cs file in the driver project and should always be used when referencing specific instrument models. Do not use the string literal for a particular model, else the Nimbus code roundtripping engine may not be able to roundtrip those model names if a model is added, deleted, or renamed. Using the Models class for all instrument model references also reduces the liklihood of errors in your driver implementation.

C#
Copy
void ConfigureRange(double range)
{
   // ....
     if (this.InstrumentIsModel(Models.ModelA))
   {
      this.IO.FormattedIO.PrintfAndFlush("SENS:FREQ:VOLT:RANGE %.15g", range);
     }
     else if (this.InstrumentIsModel(Models.ModelB))
     {
      this.IO.FormattedIO.PrintfAndFlush("FREQ:RANGE %.15g", range);
     }
     else if (this.InstrumentInFamily(Families.Family1)
     {
      this.IO.FormattedIO.PrintfAndFlush("FREQ:VOLT:RANGE %.15g", range);
     }
     else
     {
      this.IO.FormattedIO.PrintfAndFlush("FREQ:VOLT:RANGE %.15g", range);
     }
}

Note how the above example also makes use of InstrumentInFamily(String) method and the Families class (also defined in the Models.cs file) to incorporate logic that is common to muliple models within an instrument family. The definition of instrument models and families is managed from the Models Page of the Driver Settings Editor.

Important note Important

When using the InstrumentIsModel(String) method in conjunction with the InstrumentInFamily(String) method in an if-else construct such as the one in the above ConfigureRange example, it is important that the InstrumentIsModel checks be performed before the InstrumentInFamily checks.

Retrieving the Instrument Model in Simulation Mode

When a driver is initialized in simulation mode, the driver constructor obviously cannot use the InitializeIdentification method to query the instrument for its identification information, such as the instrument model. Rather, the instrument model must be provided to the driver so that all of the model-based logic will operate properly. The model that is provided during simulation is referred to as the simulated model. When the driver is running in simulation mode, the InstrumentIsModel(String) method, InstrumentInFamily(String) method, and the InstrumentModel property can all be used in exactly the same fashion as with a live session.

The simulated model can be specified in one of two ways:

  • By using the Models Page of the Driver Settings Editor to specify a default model. The default model is stored by the driver installer in the IVI Configuration Store and is automatically retrieved by the Nimbus implementation of the driver constructor.

  • By passing in a DriverSetup string to the driver constructor. The client application includes in the DriverSetup string a name-value pair of the form "Model=<model>". A simulated model provided in this way overrides the default model specified by the driver developer in the Driver Settings Editor.

The code below demonsrates how a client application can specify a simulated model when calling the driver's Initialize method.

C#
Copy
// Client.cs
var driver = new Acme43XX("GPIB::14", false, false, "Simulate=true, DriverSetup=Model=4302");
See Also

Reference

InstrumentModel
InstrumentIsModel(String)
InstrumentInFamily(String)

Other Resources

Adding Support for Multiple Instrument Models


Retrieving Initialization Options

When client applications instantiates an IVI.NET driver, the client may provide a series of initialization options in the form of name-value pairs. Two types of initialization options may be passed to a driver's constructor - inherent options and driver setup options.

The inherent options are specific name-value pairs defined by the IVI Foundation. These include options such as Cache to turn on/off state caching and Simulation to indicate whether simulation should be enabled or not. The driver setup options are custom name-value pairs defined by the driver developer. Driver setup options may be used to control driver-specific features or to perform any custom setup. They are delineated from the inherent options by the IVI-defined DriverSetup keyword.

The example below shows a typical client application instantiating and a driver.

C#
Copy
// Client.cs
var driver = new Acme4321(GPIB::10", true, true, "InterchangeCheck=False, Simulate=True, DriverSetup=OptionA=Foo,OptionB=True");

InterchangeCheck option is an inherent option being passed in with a value of False. Simulation is also an inherent option specified with a value of True in the code above. Two driver setup options, OptionA and OptionB are being passed in with values of Foo and True, respectively.

The Nimbus implementation of the driver constructor automatically saves the values of all inherent and driver setup options. If some of the IVI-defined inherent options are not specified, Nimbus caches IVI-defined default values for those options.

Nimbus provides several functions for retrieving the values of the IVI-defined inherent options. The table below shows each inherent option and the Nimbus function available to retrieve its value. The IVI-defined default value of each option is also shown.

Inherent Options | Accessor property | Default Value
Cache | CachingEnabled | True
InterchangeCheck | InterchangeCheckingEnabled | False
QueryInstrStatus | QueryInstrumentStatusEnabled | False
RangeCheck | RangeCheckingEnabled | True
RecordCoercions | CoercionRecordingEnabled | False
Simulate | SimulationEnabled | False

In addition to providing access to the IVI-defined intialization options, the Nimbus Class Library provides a means to retrieve the DriverSetup options. The InitOptions.DriverSetup property exposes a map of key-value pairs, where the key is the name of the option and the value is the string value supplied. If the DriverSetup string does not take on the form of name-value pairs for a particular driver, then the raw value can be retrieved using the InitOptions.DriverSetupString property. The example below demonstrates how to retrieve the value of a custom DriverSetup option called OptionA.

C#
Copy
// Acme4321.cs
Configure(double frequency, double span)
{
   // The line of code below assumes the constructor was invoked with a call such as:
     //
     //   var driver = new Acme4321("MyLogicalName", false, false, "DriverSetup= OptionA=Foo");
     //
   var myOptionValue = this.Session.DriverSetup["OptionA"];

     if (myOptionValue == "Foo")
     {
       // ....
     }
}


Implementing Dynamic Repeated Capabilities

Nimbus supports two types of repeated capabilities -- static repeated capabilities and dynamic repeated capabilities. Static repeated capabilities represent the fixed functionality of the instrument -- such as physical channels on an oscilloscope. These repeated capabilities must be configured at driver development time using the Properties Window for the repeated capability in question.

Dynamic repeated capabilities are those that cannot be determined at driver development time. Rather, the driver must "discover" by communicating with the instrument what repeated capabilities are present. For example, a driver for a multi-slot digital I/O mainframe has no way to know at driver development time what type and number of digital I/O cards will be plugged into the available mainframe slots.

In order to support dynamic repeated capabilities, Nimbus provides the GetDynamicRepCapNames(String, IListString) method. One may accurately think of GetDynamicRepCapNames(String, IListString) method as the programmatic equivalent of the repeated capabilities Properties Window. The driver developer overrides this function in the appropriate class and provides whatever logic necessary to return a list of repeated capability names. Nimbus automatically invokes the overridden GetDynamicRepCapNames function during driver execution of the driver constructor.

The signature of the GetDynamicRepCapNames function is as follows:

C#
Copy
protected virtual void GetDynamicRepCapNames(string repCapName, IList<string> physicalNames)

The repCapName parameter is passed to the function by Nimbus and represents the repeated capability name for which you should return the associated physical names for the repeated capability instances that Nimbus should created.

The physicalNames parameter is a list that the method implementation should use to return the dynamic repeated capability names to Nimbus. Nimbus will create one instance of the repeated capability class associated with the identified by the repCapName parameter for each element added to the physicalNames list.

The class on which GetDynamicRepCapNames function is implemented depends upon the repeated capability style (collection-style, parameter-style, or selector-style) and whether or not the repeated capability is nested. For a collection-style repeated capability, the GetDynamicRepCapNames function must be overridden on the corresponding collection class (e.g. Acme4321ChannelCollection). This is true irrespective of whether or not the collection-style repeated capability is nested (i.e. has a parent repeated capability). For parameter-style and selector-style repeated capabilities, the GetDynamicRepCapNames function must be overridden on the parent class. For non-nested parameter-style or selector-style repeated capabilities, the parent class will be the main driver class (e.g. Acme4321). If a parameter-style repeated capability has any parent collection-style repeated capability, then the override of GetDynamicRepCapNames function for that parameter style repeated capability must appear on the parent repeated capability class (e.g. Acme4321Channel).

Nimbus invokes the GetDynamicRepCapNames function only once for each non-nested repeated capability. For nested repeated capabilities, Nimbus first invokes the GetDynamicRepCapNames function for the parent repeated capability, thereby gathering and creating all instances of that parent repeated capability. Then, for each parent repeated capability instance, Nimbus invokes the GetDynamicRepCapNames function for the child repeated capability. For example, consider a collection-style "Channel" repeated capability with a child "Trace" parameter-style repeated capability. The three driver classes are Acme4321 (the main driver class), Acme4321ChannelCollection (the channel collection class), and Acme4321Channel (the channel repeated capability class). During initialization of the driver, Nimbus will invoke the GetDynamicRepCapNames function on the Acme4321ChannelCollection class (passing in "Channel" as the repeated capability name). Assume the implementation returns the names "Channel1", "Channel2", and "Channel3". This results in the construction of three instances of the Acme4321Channel class. Next, Nimbus will invoke the GetDynamicRepCapNames function (passing in "Trace" as the repeated capability name) on the Acme4321Channel class three times -- once for each of the three instances of the parent Acme4321Channel.

The code below demonstrates how to implement GetDynamicRepCapNames in the main driver class.

C#
Copy
// Acme4321InputChannelCollection.cs
public sealed class class Acme4321InputChannelCollection : RepCapCollection<Acme4321InputChannel>,
        IAcme4321InputChannelCollection
   // ...
{
   // ...

   protected override void GetDynamicRepCapNames(string repCapName, IList<string> physicalNames)
   {
      if (repCapName == _T("InputChannel"))
      {
         // Query the instrument for the number of digital input cards plugged into the mainframe
         this.IO.FormattedIO.WriteLine("SYST:CTYP:COUN?");
         var cardCount = this.IO.FormattedIO.ReadLineInt64();

         // Each card has 32 input channels
         for (int slot = 0; slot < cardCount; slot++)
         {
            for (int channel = 0; channel < 32; channel++)
            {
               // Each channel name will be of the form: "Channel-[slot]-[channel]"
               var name = String.Format("Channel-{0}-{1}"), slot, channel);

               // Add the name to the collection of repeated capability names
               physicalNames.Add(name);
            }
         }
      }
   }

   // ...
}
See Also

Other Resources

Repeated Capabilities
Adding a Repeated Capability


State Caching Overview

Nimbus provides powerful state caching features that allow driver developers to maximize the performance of their driver by minimizing the number of expensive instrument I/O operations. A special State Caching Editor provides a simple declarative mechanism for expressing couplings between instrument properties.

In This Section

Understanding Nimbus State Caching

Property Identifiers

See Also

Other Resources

Property State Caching Editor
Method State Caching Editor
Understanding Nimbus Code Weaving


Understanding State Caching

State caching is a feature of IVI drivers that can improve performance by minimizing the number of I/O calls to an instrument. For instance, if a driver property value is set and the driver sends the programmed value to the instrument, subsequent calls to the same property need not communicate with the instrument if the value being set is the same as the previous value. Correspondingly, reading a driver property need not result in instrument communication if the driver can somehow "remember" the last value that was sent to the instrument. When a client application invokes a driver property, the driver caches the value specified in memory so that subsequently the driver can simply retrieve the value from the driver's cache when the property is read or avoid making a redundant call to the instrument when the property is written. In this way, the instrument I/O traffic is minimized and the overall client application performance can be improved.

Understanding Cache Couplings

When a driver caches the value of a property, it should ideally return the cached value when the property is later read, rather than incurring the performance hit of querying the instrument for the property value. This will work so long as nothing takes place within the instrument that would invalidate the value cached in the driver. If, after caching the value of a property, the driver performs a different instrument operation that directly or indirectly changes the value of the property within the instrument, then the driver's cache and the "real" setting in the instrument are inconsistent. This is one form of what is termed a cache coherency problem.

If setting some driver property or executing a driver method produces a change in an instrument setting represented by another property, the properties or methods are said to be coupled. For state caching to work properly, these cache couplings must be programmed into the driver, so that the driver knows when to invalidate specific cached values. For instance, if the driver is caching a Frequency property, then setting the Bandwidth property may also change the frequency setting within the instrument. This means that the driver must know to invalidate the cached value for the Frequency property whenever the Bandwidth is set.

State Caching Features in Nimbus

The automatic state caching feature of Nimbus is the simplest to use and will suffice in most circumstances. With this technique, Nimbus automatically creates and manages a cache entry for every driver property for which state caching has been enabled. The State Caching Editor is used to turn state caching on and off on a property-by-property basis. The other bit of information that the driver developer must provide via the State Caching Editor is the list of properties to which the cached property is coupled. In other words, the driver developer must specify which driver properties are invalidated when the current property's value is changed.

When To Enable State Caching

State caching is a feature that certainly must be used with care. Cache coherency problems can easily arise if the driver developer is not keenly aware of the details of the instrument behavior and/or does not accurately and thorougly represent instrument couplings in the driver. Thus, in general, it is advisable to consider enabling state caching for those properties that have the following characteristics:

  1. They require considerable time to execute (and, hence, stand to improve performance the most when cached).

  2. They have a modest and easily expressed set of couplings to other properties.

Enabling state caching broadly across all properties in a driver is almost never feasible, as correctly implementing the driver code would involve effectively replicating much of the instrument firmware logic itself. Consequently, Nimbus disables state caching by default for all properties.


Property Identifiers

Nimbus state caching relies upon the the ability to reference a driver property by name from the driver implemenation code itself. Nimbus state caching allows couplings between properties to be expressed using string identifiers via the Property State Caching Editor and the Method State Caching Editor. These identifiers are known as property identifiers.

Property Identifiers Used in State Cachine

There are three kinds of property identifiers used as cache keys in the Nimbus state caching engine:

  1. Property name only.

    Example: Bandwidth

    When only the property name is supplied, it is implied that the referenced property exists on the same interface and the same class as the method or property referring to the property. When Nimbus attempts to resolve this kind of property identifier, it will only look on the IAcme4301 interface on the same class as the calling method or property.

  2. Interface and property name only.

    Example: IAcm4301.Bandwidth

    When only the interface and property name are supplied, it is implied that the referenced property exists on the specified interface and the same class as the method or property referring to the property. The specified interface may be the same interface or a different interface on the same class. When Nimbus attempts to resolve this kind of property identifier, it will only look on the the same class as the calling method or property.

  3. Parent repcap collection property with the interface and property name

    Example: Traces[3,4,5].IAcme4300Trace.Bandwidth

    Nimbus property identifiers also allow you to reference properties on different repeated capability classes. In the above example, the Bandwidth property on three different instances of the class implementing the Trace repeated capability are being referenced. This allows complex cache couplings to be established between methods and properties without having to write procedural code.

    Nested repeated capabilities are supported by allowing the property identifier to include multiple parent repeated capabilities, as in the following:

    Example: Traces[TRACE1].Channels[CH2].IAcme4300Trace.Bandwidth

    Finally, wildcard characters can be used to reference all repeated capability instances on a particular repeated capability, as in the following:

    Example: Traces[*].Channels[CH1,CH4,CH5-CH9].IAcme4300Trace.Frequency

See Also

Other Resources

Understanding State Caching
Property State Caching Editor
Method State Caching Editor


Customizing Config Store Registration

When an IVI driver is installed on an end user system, a number of entries for the driver must be created in the IVI Configuration Store. Information such as the driver's repeated capability physical names, and supported IVI instrument classes is all required by the IVI specifications to be placed in the IVI Configuration Store by the IVI driver installer.

During the build process of the driver project, Nimbus automatically emits a special XML file based on declarations and attributes within the driver source code itself. This file is named located in the intermediate output folder and is named ConfigStore.g.xml. This file does not appear as a project item in Solution Explorer. It contains all of the information that the Nimbus driver installer will use when the IVI driver is deployed on the end user system. This ConfigStore.g.xml is actually a complete "mini" IVI Configuration Store, with all of the requisite formatting and entries. The driver installer merges the contents of this file with the end-user's IVI Configuration Store file.

There are two ways to customize the Configuration Store entries for a specific driver:

  1. Adding attributes to the ConfigStore.cs file in the driver project.

  2. Adding a custom ConfigStore.xml file to the driver project.

The first technique should be preferred when the requisite control is available via the special Configuration Store attributes available in the Nimbus Class Library. The attributes that can be added to the ConfigStore.cs file include the following:

  • LogicalNameAttribute

  • DriverSessionAttribute

  • HardwareAssetAttribute

  • ConfigurableInitialSettingAttribute

Example usage of these attributes is available directly in the ConfigStore.g.cs file for any Nimbus-generated IVI.NET driver.

When greater control is required than can be achieved with the Nimbus Class Library Configuration Store attributes, a custom ConfigStore.xml file can be added directly to the driver project. If a ConfigStore.xml is added to the driver project as a project item, Nimbus will not generate the ConfigStore.g.cs file and the driver developer's custom ConfigStore.xml file will be used instead.

Caution note Caution

If you add a custom ConfigStore.xml file by directly editing it, you must take great care to produce a valid XML file, else the driver installer will fail on the end user system (often with a non-intuitive error message).

One effective technique for producing a valid ConfigStore.xml file is to start with the ConfigStore.g.xml produced from the normal Nimbus build process. Then, edit the resulting file in one of two ways:

  1. Directly editing the file with a text editor.

  2. Using a 3rd-party IVI Configuration Store editor.

    One of the chief benefits of the Nimbus ConfigStore.g.xml file being a complete IVI Configuration Store is that it can be edited using any available IVI Configuration Store editor, such as NI-MAX® from National Instruments®. The advantages of this approach are that there is far less danger of corrupting the format of the ConfigStore.g.xml file and that the customization can be performed without having to understand the details of the IVI Configuration Store file format.

See Also

Other Resources

IVI Shared Components


Testing an IVI.NET Driver

One of the most important aspects of IVI driver development is authoring and maintaining a suite of driver tests. Nimbus provides integrated unit testing support for IVI.NET drivers.

Important note Important

When testing an IVI-COM driver using the Visual Studio debugger, whether it be inside a unit test or in a standalone application, there is a debugger setting that should be changed from its default value. From the Tools menu, choose Options to bring up the Options Dialog.

From the tree view on the left, choose Debugging. Uncheck the box labeled Enable property evaluation and other implicit function calls.

If this option is left at its default enabled setting, then the Visual Studio debugger will sporadically execute properties on the driver as you are debugging. This will trigger unexpected and undesired instrument communication and produce confusing results.

Creating an IVI.NET Driver Unit Test

All of the unit test code for an IVI.NET driver is housed in a single Visual C# project created by Nimbus. Typically, this project is created upfront with the other driver projects after the New IVI.NET Driver Wizard runs. This is controlled by the Create unit test project check box on the Projects page of the New IVI.NET Driver Wizard.

If the unit test project is not created by the wizard, then it can always be generated at any stage of driver development by right-clicking on the solution node in Solution Explorer and choosing Add New Project....

Structure of an IVI.NET Driver Unit Test

The IVI.NET driver unit tests are contained within the unit test project, named as follows:

<driverName>UnitTest

This Visual C# project contains one source file per IVI.NET driver interface. Each source file contains one test class for the interface, and the test class contains one test method per driver method or property in that interface.

In addition, one unit test class and file is created for each additional class or struct that is used as a parameter type or return value type. Nimbus refers to these types as free-standing types.

The code below shows an example of a test class.

C#
Copy
// IIviScopeTriggerEdgeTest.cs
[TestClass]
public class IIviScopeTriggerEdgeTest : BaseTest
{
    protected IIviDriverIdentity Interface { get; private set; }

    public override void _Init()
    {
        base._Init();

        this.Interface = (this.Driver as IIviScopeTrigger);
    }

    [TestMethod]
    public void Configure()
    {
        string source = "Internal";
        double level = 0.1;
        Ivi.Scope.Slope slope = Ivi.Scope.Slope.Positive;
        this.Interface.Configure(source, level, slope);
    }

    [TestMethod]
    public void Slope()
    {`
        Ivi.Scope.Slope inVal;
        Ivi.Scope.Slope outVal;

        inVal = Ivi.Scope.Slope.Positive;
        this.Interface.Slope = inVal;
        outVal = this.Interface.Slope;
        Assert.AreEqual(inVal, outVal);

        inVal = Ivi.Scope.Slope.Negative;
        this.Interface.Slope = inVal;
        outVal = this.Interface.Slope;
        Assert.AreEqual(inVal, outVal);
    }
}

The above test shows the IIviScopeTriggerEdgeTest class that is used to test the methods and properties in the IIviScopeTriggerEdge interface. The class is adorned with a [TestClass] attribute to indicate that the class contains unit test methods. Similarly, each test method within the class is adorned with a [TestMethod] attribute to indicate that it is a test method.

The Slope test method in the example above is used to exercise the IIviScopeTriggerEdge.Slope property in the driver. Note that a single test method is used to test both the property getter and the property setter. In this example, the test method sets the Slope property to the enum value Positive and then immediately reads back the value of the property. The Interface property is used to access driver methods and properties on the IIviScopeTriggerEdge interface. The Assert class is used to compare the value written with the value read back. If the comparison fails, then an exception is thrown and a test failure is reported in the Driver Test Results window. The process is repeated for the Negative enum value.

Test Initialization and Shutdown

Each test class in a unit test project derives from a BaseTest class. The BaseTest class is defined in the BaseTest.cs file of the unit test project. It serves two purposes in driver unit testing:

  • It provides a place to define common member variables that many test classes might need, such as the Driver property that can be used by any test method to access any driver method or property.

  • It defines the _Init and _Close methods that are executed before and after each test method in the unit test project.

The key methods of interest in the BaseTest class are the _Init and _Close. and is marked with the [Setup] attribute. This method is executed before each test method. The _Init method is responsible for instantiating the driver performing any other driver-specific setup the test methods may require. Since every test class derives from the BaseTest class, they all share the same _Init method. If a particular set of unit tests need interface-specific initialization, then the test class can override the definition of _Init in the BaseTest class.

The code below demonstrates how a test class overrides _Init in order to initialize the Driver property and to call the ConfigureWaveform methodh.

Important note Important

It is critical that any override of _Init call the base class _Init function, as shown in the example below. The driver will not be properly initialized if the base class implementation is not called.

C#
Copy
// IIviScopeTriggerEdgeTest.cs
[TestClass]
public class IIviScopeTriggerEdgeTest : BaseTest
{
    protected IIviScopeTriggerEdge Interface { get; private set; }

    public override void _Init()
    {
        base._Init();

        this.Interface = (this.Driver as IIviScopeTriggerEdge);

    this.Driver.Waveform.ConfigureWaveform(Waveform.Sine, 1000, 0.1);
    }

  // ... test methods
}

The _Close method on the BaseTest class is executed after each test method. As with the _Init function, the _Close method can also be customized on a per-test-class basis by overriding it in the test class.

Running Unit Tests

The unit tests generated by Nimbus integrate directly with Visual Studio's native unit testing features. The starting point for executing tests is to bring up the Visual Studio Test View, which is typically docked as a tab within Solution Explorer. To bring up Test View for executing unit tests, click on the Test menu, then choose Windows and select Test View.

Once the Test View window is shown, executing tests proceeds in the exact same fashion as any other Visual Studio unit test. For details on working with the Visual Studio unit testing features, see the MSDN topic Verifying Code by Using Unit Tests.

Tip Tip

Nimbus drivers typically contain a large number of unit tests. To work with the Test View effectively, use the Group By combo box, which offers a variety of choices for organizing the display of unit tests in the Test View. For Nimbus drivers, setting the Group By combo box to Class Name is often the most effective presentation of the unit test methods.

See Also

Other Resources

Verifying Code by Using Unit Tests


Nimbus Class Library

The Nimbus Class Library is a set of classes, interfaces, and other types that enable IVI.NET driver development. The source code generated by the Nimbus Driver Designer relies on the types defined in the Nimbus Class Library to implement the IVI.NET driver's properties, methods and events. Likewise, the Nimbus Code Weaver leverages implicit knowledge of the Nimbus Class Library in order to perform code weaving of an IVI.NET driver's properties, methods and events.

However, unlike traditional class libraries, which are distributed in separate .NET assemblies that other projects reference, the source code for the Nimbus Class Library is compiled directly into each IVI.NET driver assembly. This is accomplished using Visual Studio's standard linked files mechanism within each IVI.NET driver project, making the source code for the Nimbus Class Library appear in the Solution Explorer below the NCL folder within the IVI.NET driver project. This approach has the following important benefits:

  • The Nimbus Class Library does not introduce additional assembly dependencies that complicate IVI.NET driver deployment.

  • After being tested and deployed to the field, Nimbus IVI.NET drivers are isolated from any future changes to the Nimbus Class Library that may be installed on a driver developer's machine by a subsequent Nimbus upgrade.

In This Section

Nimbus Class Library Attributes

MindWorks.Nimbus

See Also

Other Resources

Understanding Nimbus Code Weaving
Using the Nimbus Driver Designer


Nimbus Class Library Attributes

The Nimbus Class Library contains several attributes that provide important metadata that Nimbus uses to facilitate driver development and runtime operations. Some of these attributes influence how the Nimbus Code Weaver modifies the driver assembly when the driver is built, while others influence various aspects of driver configuration, initialization, or runtime operations.

Code Weaver Attributes

The following attributes influence how the Nimbus Code Weaver modifies the IL for a driver assembly at the conclusion of each build.

DriverMethodAttribute

DriverPropertyAttribute

DriverEventAttribute

CacheAttribute

InvalidateCacheEntriesAttribute

NotSupportedAttribute

NullAllowedAttribute

RangeCheckMinMaxAttribute

RangeCheckDiscreteAttribute

RangeCheckStringAttribute

SimulationAttribute

Configuration and Other Attributes

The following attributes control driver configuration (in the IVI Config Store), enum mappings, and other aspects of driver operations.

BooleanCommandAttribute

CommandAttribute

ConfigurableInitialSettingAttribute

DriverCapabilitiesAttribute

DriverSessionAttribute

EnumCommandAttribute

HardwareAssetAttribute

InstrumentFamiliesAttribute

InstrumentModelsAttribute

LogicalNameAttribute

PhysicalNamesAttribute

RepeatedCapabilityAttribute

SupportedInstrumentClassAttribute

See Also

Reference

MindWorks.Nimbus

Other Resources

Understanding Nimbus Code Weaving
Customizing Config Store Registration


MindWorks.Nimbus Namespace

Classes
 | Class | Description
Protected class | BooleanCommandAttribute |
Protected class | CacheAttribute |
Protected class | CommandAttribute |
Protected class | ConfigurableInitialSettingAttribute |
Public class | Driver |
Protected class | DriverCapabilitiesAttribute |
Protected class | DriverDescriptionAttribute |
Protected class | DriverEventAttribute |
Public class | DriverInfo |
Protected class | DriverMemberAttribute |
Protected class | DriverMethodAttribute |
Public class | DriverNode |
Protected class | DriverNodeHelper |
Protected class | DriverPropertyAttribute |
Protected class | DriverSessionAttribute |
Protected class | EnumCommandAttribute |
Protected class | ErrorService |
Protected class | HardwareAssetAttribute |
Protected class | InitOptions |
Protected class | InstrumentFamiliesAttribute |
Protected class | InstrumentModelsAttribute |
Protected class | InvalidateCacheEntriesAttribute |
Public class | IOConstants |
Protected class | LogicalNameAttribute |
Protected class | ModelSpecificNimbusAttribute |
Protected class | ModelSpecificNimbusCodeWeaverAttribute |
Protected class | NclStrings |
Protected class | NimbusAttribute |
Protected class | NimbusCodeWeaverAttribute |
Protected class | NotSupportedAttribute |
Protected class | NullAllowedAttribute |
Public class | ParameterStyleRepCapManager |
Protected class | PhysicalName |
Protected class | PhysicalNamesAttribute |
Protected class | RangeCheckDiscreteAttribute |
Protected class | RangeCheckMinMaxAttribute |
Protected class | RangeCheckStringAttribute |
Protected class | RepCap |
Public class | RepCapCollection |
Protected class | RepCapCollectionTRepCap |
Public class | RepCapManager |
Protected class | RepCapSelector |
Protected class | RepeatedCapabilityAttribute |
Protected class | SCPICompliantAttribute |
Public class | SelectorStyleRepCapManager |
Public class | SessionInfo |
Protected class | SimulationAttribute |
Protected class | SupportedInstrumentClassAttribute |
Protected class | TextUtility |
Protected class | Utility |
Protected class | VisaTimeoutManager |
Interfaces
 | Interface | Description
Protected interface | ICacheEquatable |
Enumerations
 | Enumeration | Description
Protected enumeration | Capabilities |
Public enumeration | CoercionStyle |
Protected enumeration | RepeatedCapabilityStyle |
Protected enumeration | SimulationMode |
Protected enumeration | UsedInSession |


BooleanCommandAttribute Class

Inheritance Hierarchy
SystemObject
SystemAttribute
MindWorks.NimbusNimbusAttribute
MindWorks.NimbusBooleanCommandAttribute

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal sealed class BooleanCommandAttribute : NimbusAttribute
internal ref class BooleanCommandAttribute sealed : public NimbusAttribute

The BooleanCommandAttribute type exposes the following members.

Constructors
 | Name | Description
Protected method | BooleanCommandAttribute | Initializes a new instance of the BooleanCommandAttribute class
Top
Properties
 | Name | Description
Public property | IgnoreCase |
Top
See Also

Reference

MindWorks.Nimbus Namespace


BooleanCommandAttribute Constructor

Initializes a new instance of the BooleanCommandAttribute class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal BooleanCommandAttribute(
    string trueCommands,
    string falseCommands
)
internal:
BooleanCommandAttribute(
    String^ trueCommands,
    String^ falseCommands
)

Parameters

trueCommands
Type: SystemString
falseCommands
Type: SystemString
See Also

Reference

BooleanCommandAttribute Class
MindWorks.Nimbus Namespace


BooleanCommandAttribute Properties

The BooleanCommandAttribute type exposes the following members.

Properties
 | Name | Description
Public property | IgnoreCase |
Top
See Also

Reference

BooleanCommandAttribute Class
MindWorks.Nimbus Namespace


BooleanCommandAttribute.IgnoreCase Property

Pacific MindWorks Nimbus Driver Studio

BooleanCommandAttributeIgnoreCase Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public bool IgnoreCase { get; set; }
public:
property bool IgnoreCase {
    bool get ();
    void set (bool value);
}

Property Value

Type: Boolean
See Also

Reference

BooleanCommandAttribute Class
MindWorks.Nimbus Namespace


CacheAttribute Class

Inheritance Hierarchy
SystemObject
SystemAttribute
MindWorks.NimbusNimbusAttribute
MindWorks.NimbusNimbusCodeWeaverAttribute
MindWorks.NimbusCacheAttribute

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal sealed class CacheAttribute : NimbusCodeWeaverAttribute
internal ref class CacheAttribute sealed : public NimbusCodeWeaverAttribute

The CacheAttribute type exposes the following members.

Constructors
 | Name | Description
Public method | CacheAttribute | Initializes a new instance of the CacheAttribute class
Top
Properties
 | Name | Description
Public property | SuppressAll | (Inherited from NimbusCodeWeaverAttribute.)
Top
See Also

Reference

MindWorks.Nimbus Namespace


CacheAttribute Constructor

Initializes a new instance of the CacheAttribute class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public CacheAttribute()
public:
CacheAttribute()
See Also

Reference

CacheAttribute Class
MindWorks.Nimbus Namespace


CacheAttribute Properties

The CacheAttribute type exposes the following members.

Properties
 | Name | Description
Public property | SuppressAll | (Inherited from NimbusCodeWeaverAttribute.)
Top
See Also

Reference

CacheAttribute Class
MindWorks.Nimbus Namespace


Capabilities Enumeration

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
[FlagsAttribute]
internal enum Capabilities
[FlagsAttribute]
internal enum class Capabilities
Members
Member name | Value | Description
None | 0 |
IdQuery | 1 |
InterchangeCheck | 2 |
Reset | 4 |
RevisionQuery | 8 |
SelfTest | 16 |
AllExceptInterchangeCheck | 29 |
All | 31 |
See Also

Reference

MindWorks.Nimbus Namespace


CoercionStyle Enumeration

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public enum CoercionStyle
public enum class CoercionStyle
Members
Member name | Value | Description
None | 0 |
Up | 1 |
Down | 2 |
See Also

Reference

MindWorks.Nimbus Namespace


CommandAttribute Class

Inheritance Hierarchy
SystemObject
SystemAttribute
MindWorks.NimbusNimbusAttribute
MindWorks.NimbusModelSpecificNimbusAttribute
MindWorks.NimbusCommandAttribute

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal sealed class CommandAttribute : ModelSpecificNimbusAttribute
internal ref class CommandAttribute sealed : public ModelSpecificNimbusAttribute

The CommandAttribute type exposes the following members.

Constructors
 | Name | Description
Protected method | CommandAttribute | Initializes a new instance of the CommandAttribute class
Top
Properties
 | Name | Description
Public property | AdditionalResponses |
Public property | Command |
Public property | Models | (Inherited from ModelSpecificNimbusAttribute.)
Top
See Also

Reference

MindWorks.Nimbus Namespace


CommandAttribute Constructor

Initializes a new instance of the CommandAttribute class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal CommandAttribute(
    string command,
    params string[] models
)
internal:
CommandAttribute(
    String^ command,
    ... array<String^>^ models
)

Parameters

command
Type: SystemString
models
Type: SystemString
See Also

Reference

CommandAttribute Class
MindWorks.Nimbus Namespace


CommandAttribute Properties

The CommandAttribute type exposes the following members.

Properties
 | Name | Description
Public property | AdditionalResponses |
Public property | Command |
Public property | Models | (Inherited from ModelSpecificNimbusAttribute.)
Top
See Also

Reference

CommandAttribute Class
MindWorks.Nimbus Namespace


CommandAttribute.AdditionalResponses Property

Pacific MindWorks Nimbus Driver Studio

CommandAttributeAdditionalResponses Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public string AdditionalResponses { get; set; }
public:
property String^ AdditionalResponses {
    String^ get ();
    void set (String^ value);
}

Property Value

Type: String
See Also

Reference

CommandAttribute Class
MindWorks.Nimbus Namespace


CommandAttribute.Command Property

Pacific MindWorks Nimbus Driver Studio

CommandAttributeCommand Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public string Command { get; }
public:
property String^ Command {
    String^ get ();
}

Property Value

Type: String
See Also

Reference

CommandAttribute Class
MindWorks.Nimbus Namespace


ConfigurableInitialSettingAttribute Class

Inheritance Hierarchy
SystemObject
SystemAttribute
MindWorks.NimbusNimbusAttribute
MindWorks.NimbusConfigurableInitialSettingAttribute

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal sealed class ConfigurableInitialSettingAttribute : NimbusAttribute
internal ref class ConfigurableInitialSettingAttribute sealed : public NimbusAttribute

The ConfigurableInitialSettingAttribute type exposes the following members.

Constructors
 | Name | Description
Protected method | ConfigurableInitialSettingAttribute | Initializes a new instance of the ConfigurableInitialSettingAttribute class
Top
Properties
 | Name | Description
Protected property | Description |
Protected property | HelpContextId |
Protected property | HelpFilePath |
Protected property | KeyName |
Protected property | UsedInSession |
Protected property | Value |
Top
See Also

Reference

MindWorks.Nimbus Namespace


ConfigurableInitialSettingAttribute Constructor

Initializes a new instance of the ConfigurableInitialSettingAttribute class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal ConfigurableInitialSettingAttribute(
    string keyName,
    Object value,
    UsedInSession usedInSession,
    string description
)
internal:
ConfigurableInitialSettingAttribute(
    String^ keyName,
    Object^ value,
    UsedInSession usedInSession,
    String^ description
)

Parameters

keyName
Type: SystemString
value
Type: SystemObject
usedInSession
Type: MindWorks.NimbusUsedInSession
description
Type: SystemString
See Also

Reference

ConfigurableInitialSettingAttribute Class
MindWorks.Nimbus Namespace


ConfigurableInitialSettingAttribute Properties

The ConfigurableInitialSettingAttribute type exposes the following members.

Properties
 | Name | Description
Protected property | Description |
Protected property | HelpContextId |
Protected property | HelpFilePath |
Protected property | KeyName |
Protected property | UsedInSession |
Protected property | Value |
Top
See Also

Reference

ConfigurableInitialSettingAttribute Class
MindWorks.Nimbus Namespace


ConfigurableInitialSettingAttribute.Description Property

Pacific MindWorks Nimbus Driver Studio

ConfigurableInitialSettingAttributeDescription Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal string Description { get; }
internal:
property String^ Description {
    String^ get ();
}

Property Value

Type: String
See Also

Reference

ConfigurableInitialSettingAttribute Class
MindWorks.Nimbus Namespace


ConfigurableInitialSettingAttribute.HelpContextId Property

Pacific MindWorks Nimbus Driver Studio

ConfigurableInitialSettingAttributeHelpContextId Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal int HelpContextId { get; }
internal:
property int HelpContextId {
    int get ();
}

Property Value

Type: Int32
See Also

Reference

ConfigurableInitialSettingAttribute Class
MindWorks.Nimbus Namespace


ConfigurableInitialSettingAttribute.HelpFilePath Property

Pacific MindWorks Nimbus Driver Studio

ConfigurableInitialSettingAttributeHelpFilePath Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal string HelpFilePath { get; }
internal:
property String^ HelpFilePath {
    String^ get ();
}

Property Value

Type: String
See Also

Reference

ConfigurableInitialSettingAttribute Class
MindWorks.Nimbus Namespace


ConfigurableInitialSettingAttribute.KeyName Property

Pacific MindWorks Nimbus Driver Studio

ConfigurableInitialSettingAttributeKeyName Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal string KeyName { get; }
internal:
property String^ KeyName {
    String^ get ();
}

Property Value

Type: String
See Also

Reference

ConfigurableInitialSettingAttribute Class
MindWorks.Nimbus Namespace


ConfigurableInitialSettingAttribute.UsedInSession Property

Pacific MindWorks Nimbus Driver Studio

ConfigurableInitialSettingAttributeUsedInSession Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal UsedInSession UsedInSession { get; }
internal:
property UsedInSession UsedInSession {
    UsedInSession get ();
}

Property Value

Type: UsedInSession
See Also

Reference

ConfigurableInitialSettingAttribute Class
MindWorks.Nimbus Namespace


ConfigurableInitialSettingAttribute.Value Property

Pacific MindWorks Nimbus Driver Studio

ConfigurableInitialSettingAttributeValue Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal Object Value { get; }
internal:
property Object^ Value {
    Object^ get ();
}

Property Value

Type: Object
See Also

Reference

ConfigurableInitialSettingAttribute Class
MindWorks.Nimbus Namespace


Driver Class

Inheritance Hierarchy
SystemObject
MindWorks.NimbusDriverNode
MindWorks.NimbusDriver

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public abstract class Driver : DriverNode,
    IServiceProvider, IDisposable
public ref class Driver abstract : public DriverNode,
    IServiceProvider, IDisposable

The Driver type exposes the following members.

Constructors
 | Name | Description
Protected method | Driver | Initializes a new instance of the Driver class
Top
Properties
 | Name | Description
Protected property | CacheKeyPrefix | (Overrides DriverNode.CacheKeyPrefix.)
Protected property | CollectionStyleRepCaps | (Inherited from DriverNode.)
Protected property | DefaultImplementation |
Protected property | DriverInfo | (Overrides DriverNodeDriverInfo.)
Protected property | IO | (Overrides DriverNodeIO.)
Protected property | IsMessageBasedIOSession | (Inherited from DriverNode.)
Protected property | IsRegisterBasedIOSession | (Inherited from DriverNode.)
Protected property | ParameterStyleRepCaps | (Inherited from DriverNode.)
Protected property | Parent | (Inherited from DriverNode.)
Protected property | RegisterIO | (Overrides DriverNodeRegisterIO.)
Protected property | Root | (Inherited from DriverNode.)
Protected property | SelectorStyleRepCaps | (Inherited from DriverNode.)
Protected property | Session | (Overrides DriverNodeSession.)
Protected property | VisaSession | (Overrides DriverNodeVisaSession.)
Top
Methods
 | Name | Description
Protected method | AcquireLock | (Overrides DriverNodeAcquireLock.)
Protected method | AcquireLock(PrecisionTimeSpan) | (Overrides DriverNodeAcquireLock(PrecisionTimeSpan).)
Protected method | AddPhysicalName | (Inherited from DriverNode.)
Protected method | AddService |
Protected method | CacheContainsValue(Object) | (Overrides DriverNodeCacheContainsValue(Object).)
Protected method | CacheContainsValue(MethodInfo, DriverNode, Object) |
Protected method | CheckDisposed | (Overrides DriverNodeCheckDisposed.)
Protected method | CheckInstrumentSupported |
Protected method | CleanupUnmanagedResources |
Protected method | ClearIO |
Protected method | CloseIO |
Protected method | ConvertEnumToString | (Overrides DriverNodeConvertEnumToString(Enum).)
Protected method | ConvertStringToEnumTEnum | (Overrides DriverNodeConvertStringToEnumTEnum(String).)
Public method | Dispose | Releases all resources used by the Driver
Protected method | Dispose(Boolean) | Releases the unmanaged resources used by the Driver and optionally releases the managed resources
Protected method | ExpandSelector | (Inherited from DriverNode.)
Protected method | ExpandSingleSelector | (Inherited from DriverNode.)
Protected method | Finalize | (Overrides ObjectFinalize.)
Protected method | GetActivePhysicalName | (Inherited from DriverNode.)
Protected method | GetActivePhysicalNames | (Inherited from DriverNode.)
Protected method | GetCacheValue(Object) | (Overrides DriverNodeGetCacheValue(Object).)
Protected method | GetCacheValue(MethodInfo, DriverNode, Object) |
Protected method | GetCacheValueT(T) | (Overrides DriverNodeGetCacheValueT(T).)
Protected method | GetCacheValueT(T) | (Inherited from DriverNode.)
Protected method | GetCacheValueT(String, T) | (Overrides DriverNodeGetCacheValueT(String, T).)
Protected method | GetCacheValueT(String, T) | (Inherited from DriverNode.)
Protected method | GetCacheValueT(MethodInfo, DriverNode, T) |
Protected method | GetCacheValueT(String, MethodInfo, DriverNode, T) |
Protected method | GetDefaultValueForSimulation | (Overrides DriverNodeGetDefaultValueForSimulation(Type, String).)
Protected method | GetDynamicRepCapNames | (Inherited from DriverNode.)
Protected method | GetRepCapManager(String) | (Inherited from DriverNode.)
Public method | GetService |
Protected method | Initialize |
Protected method | InitializeIdentification |
Protected method | InitializeIO |
Protected method | InitNode | (Inherited from DriverNode.)
Protected method | InstrumentInFamily | (Overrides DriverNodeInstrumentInFamily(String).)
Protected method | InstrumentIsModel | (Overrides DriverNodeInstrumentIsModel(String).)
Protected method | InvalidateAllCacheEntries | (Overrides DriverNodeInvalidateAllCacheEntries.)
Protected method | InvalidateCacheEntry(String) | (Overrides DriverNodeInvalidateCacheEntry(String).)
Protected method | InvalidateCacheEntry(MethodInfo, DriverNode, String) |
Protected method | PollInstrumentErrors | (Overrides DriverNodePollInstrumentErrors.)
Protected method | ProcessCustomDriverSetupOption |
Protected method | RemovePhysicalName | (Inherited from DriverNode.)
Protected method | ResetObjectState | (Inherited from DriverNode.)
Protected method | SendCoercionEvent | (Overrides DriverNodeSendCoercionEvent(Object, Object).)
Protected method | SendInterchangeEvent | (Overrides DriverNodeSendInterchangeEvent(InterchangeCheckWarningEventArgs).)
Protected method | SendWarningEvent | (Overrides DriverNodeSendWarningEvent(WarningEventArgs).)
Protected method | TryConvertEnumToString | (Inherited from DriverNode.)
Protected method | TryConvertStringToEnumTEnum | (Inherited from DriverNode.)
Protected method | UpdateCacheValue(Object) | (Overrides DriverNodeUpdateCacheValue(Object).)
Protected method | UpdateCacheValue(String, Object) | (Overrides DriverNodeUpdateCacheValue(String, Object).)
Protected method | UpdateCacheValue(MethodInfo, DriverNode, Object) |
Protected method | UpdateCacheValue(String, MethodInfo, DriverNode, Object) |
Protected method | ValidateSessionInformation |
Top
Events
 | Name | Description
Protected event | Coercion |
Protected event | InterchangeCheckWarning |
Protected event | Warning |
Top
See Also

Reference

MindWorks.Nimbus Namespace


Driver Constructor

Initializes a new instance of the Driver class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected Driver()
protected:
Driver()
See Also

Reference

Driver Class
MindWorks.Nimbus Namespace


Driver Properties

The Driver type exposes the following members.

Properties
 | Name | Description
Protected property | CacheKeyPrefix | (Overrides DriverNode.CacheKeyPrefix.)
Protected property | CollectionStyleRepCaps | (Inherited from DriverNode.)
Protected property | DefaultImplementation |
Protected property | DriverInfo | (Overrides DriverNodeDriverInfo.)
Protected property | IO | (Overrides DriverNodeIO.)
Protected property | IsMessageBasedIOSession | (Inherited from DriverNode.)
Protected property | IsRegisterBasedIOSession | (Inherited from DriverNode.)
Protected property | ParameterStyleRepCaps | (Inherited from DriverNode.)
Protected property | Parent | (Inherited from DriverNode.)
Protected property | RegisterIO | (Overrides DriverNodeRegisterIO.)
Protected property | Root | (Inherited from DriverNode.)
Protected property | SelectorStyleRepCaps | (Inherited from DriverNode.)
Protected property | Session | (Overrides DriverNodeSession.)
Protected property | VisaSession | (Overrides DriverNodeVisaSession.)
Top
See Also

Reference

Driver Class
MindWorks.Nimbus Namespace


Driver.CacheKeyPrefix Property

Pacific MindWorks Nimbus Driver Studio

DriverCacheKeyPrefix Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected override string CacheKeyPrefix { get; }
protected:
virtual property String^ CacheKeyPrefix {
    String^ get () override;
}

Property Value

Type: String
See Also

Reference

Driver Class
MindWorks.Nimbus Namespace


Driver.DefaultImplementation Property

Pacific MindWorks Nimbus Driver Studio

DriverDefaultImplementation Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected DefaultImplementations DefaultImplementation { get; }
protected:
property DefaultImplementations^ DefaultImplementation {
    DefaultImplementations^ get ();
}

Property Value

Type: DefaultImplementations
See Also

Reference

Driver Class
MindWorks.Nimbus Namespace


Driver.DriverInfo Property

Pacific MindWorks Nimbus Driver Studio

DriverDriverInfo Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected override sealed DriverInfo DriverInfo { get; }
protected:
virtual property DriverInfo^ DriverInfo {
    DriverInfo^ get () override sealed;
}

Property Value

Type: DriverInfo
See Also

Reference

Driver Class
MindWorks.Nimbus Namespace


Driver.IO Property

Pacific MindWorks Nimbus Driver Studio

DriverIO Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected override sealed IMessageBasedSession IO { get; }
protected:
virtual property IMessageBasedSession^ IO {
    IMessageBasedSession^ get () override sealed;
}

Property Value

Type: IMessageBasedSession
See Also

Reference

Driver Class
MindWorks.Nimbus Namespace


Driver.RegisterIO Property

Pacific MindWorks Nimbus Driver Studio

DriverRegisterIO Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected override sealed IRegisterBasedSession RegisterIO { get; }
protected:
virtual property IRegisterBasedSession^ RegisterIO {
    IRegisterBasedSession^ get () override sealed;
}

Property Value

Type: IRegisterBasedSession
See Also

Reference

Driver Class
MindWorks.Nimbus Namespace


Driver.Session Property

Pacific MindWorks Nimbus Driver Studio

DriverSession Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal override sealed SessionInfo Session { get; }
internal:
virtual property SessionInfo^ Session {
    SessionInfo^ get () override sealed;
}

Property Value

Type: SessionInfo
See Also

Reference

Driver Class
MindWorks.Nimbus Namespace


Driver.VisaSession Property

Pacific MindWorks Nimbus Driver Studio

DriverVisaSession Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected override sealed IVisaSession VisaSession { get; }
protected:
virtual property IVisaSession^ VisaSession {
    IVisaSession^ get () override sealed;
}

Property Value

Type: IVisaSession
See Also

Reference

Driver Class
MindWorks.Nimbus Namespace


Driver Methods

The Driver type exposes the following members.

Methods
 | Name | Description
Protected method | AcquireLock | (Overrides DriverNodeAcquireLock.)
Protected method | AcquireLock(PrecisionTimeSpan) | (Overrides DriverNodeAcquireLock(PrecisionTimeSpan).)
Protected method | AddPhysicalName | (Inherited from DriverNode.)
Protected method | AddService |
Protected method | CacheContainsValue(Object) | (Overrides DriverNodeCacheContainsValue(Object).)
Protected method | CacheContainsValue(MethodInfo, DriverNode, Object) |
Protected method | CheckDisposed | (Overrides DriverNodeCheckDisposed.)
Protected method | CheckInstrumentSupported |
Protected method | CleanupUnmanagedResources |
Protected method | ClearIO |
Protected method | CloseIO |
Protected method | ConvertEnumToString | (Overrides DriverNodeConvertEnumToString(Enum).)
Protected method | ConvertStringToEnumTEnum | (Overrides DriverNodeConvertStringToEnumTEnum(String).)
Public method | Dispose |
Protected method | Dispose(Boolean) |
Protected method | ExpandSelector | (Inherited from DriverNode.)
Protected method | ExpandSingleSelector | (Inherited from DriverNode.)
Protected method | Finalize | (Overrides ObjectFinalize.)
Protected method | GetActivePhysicalName | (Inherited from DriverNode.)
Protected method | GetActivePhysicalNames | (Inherited from DriverNode.)
Protected method | GetCacheValue(Object) | (Overrides DriverNodeGetCacheValue(Object).)
Protected method | GetCacheValue(MethodInfo, DriverNode, Object) |
Protected method | GetCacheValueT(T) | (Overrides DriverNodeGetCacheValueT(T).)
Protected method | GetCacheValueT(T) | (Inherited from DriverNode.)
Protected method | GetCacheValueT(String, T) | (Overrides DriverNodeGetCacheValueT(String, T).)
Protected method | GetCacheValueT(String, T) | (Inherited from DriverNode.)
Protected method | GetCacheValueT(MethodInfo, DriverNode, T) |
Protected method | GetCacheValueT(String, MethodInfo, DriverNode, T) |
Protected method | GetDefaultValueForSimulation | (Overrides DriverNodeGetDefaultValueForSimulation(Type, String).)
Protected method | GetDynamicRepCapNames | (Inherited from DriverNode.)
Protected method | GetRepCapManager(String) | (Inherited from DriverNode.)
Public method | GetService |
Protected method | Initialize |
Protected method | InitializeIdentification |
Protected method | InitializeIO |
Protected method | InitNode | (Inherited from DriverNode.)
Protected method | InstrumentInFamily | (Overrides DriverNodeInstrumentInFamily(String).)
Protected method | InstrumentIsModel | (Overrides DriverNodeInstrumentIsModel(String).)
Protected method | InvalidateAllCacheEntries | (Overrides DriverNodeInvalidateAllCacheEntries.)
Protected method | InvalidateCacheEntry(String) | (Overrides DriverNodeInvalidateCacheEntry(String).)
Protected method | InvalidateCacheEntry(MethodInfo, DriverNode, String) |
Protected method | PollInstrumentErrors | (Overrides DriverNodePollInstrumentErrors.)
Protected method | ProcessCustomDriverSetupOption |
Protected method | RemovePhysicalName | (Inherited from DriverNode.)
Protected method | ResetObjectState | (Inherited from DriverNode.)
Protected method | SendCoercionEvent | (Overrides DriverNodeSendCoercionEvent(Object, Object).)
Protected method | SendInterchangeEvent | (Overrides DriverNodeSendInterchangeEvent(InterchangeCheckWarningEventArgs).)
Protected method | SendWarningEvent | (Overrides DriverNodeSendWarningEvent(WarningEventArgs).)
Protected method | TryConvertEnumToString | (Inherited from DriverNode.)
Protected method | TryConvertStringToEnumTEnum | (Inherited from DriverNode.)
Protected method | UpdateCacheValue(Object) | (Overrides DriverNodeUpdateCacheValue(Object).)
Protected method | UpdateCacheValue(String, Object) | (Overrides DriverNodeUpdateCacheValue(String, Object).)
Protected method | UpdateCacheValue(MethodInfo, DriverNode, Object) |
Protected method | UpdateCacheValue(String, MethodInfo, DriverNode, Object) |
Protected method | ValidateSessionInformation |
Top
See Also

Reference

Driver Class
MindWorks.Nimbus Namespace


Driver.AcquireLock Method

Pacific MindWorks Nimbus Driver Studio

DriverAcquireLock Method

Overload List
 | Name | Description
Protected method | AcquireLock | (Overrides DriverNodeAcquireLock.)
Protected method | AcquireLock(PrecisionTimeSpan) | (Overrides DriverNodeAcquireLock(PrecisionTimeSpan).)
Top
See Also

Reference

Driver Class
MindWorks.Nimbus Namespace


Driver.AcquireLock Method

Pacific MindWorks Nimbus Driver Studio

DriverAcquireLock Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected override sealed IIviDriverLock AcquireLock()
protected:
virtual IIviDriverLock^ AcquireLock() override sealed

Return Value

Type: IIviDriverLock
See Also

Reference

Driver Class
AcquireLock Overload
MindWorks.Nimbus Namespace


Driver.AcquireLock Method (PrecisionTimeSpan)

Pacific MindWorks Nimbus Driver Studio

DriverAcquireLock Method (PrecisionTimeSpan)

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected override sealed IIviDriverLock AcquireLock(
    PrecisionTimeSpan maxTime
)
protected:
virtual IIviDriverLock^ AcquireLock(
    PrecisionTimeSpan maxTime
) override sealed

Parameters

maxTime
Type: PrecisionTimeSpan

Return Value

Type: IIviDriverLock
See Also

Reference

Driver Class
AcquireLock Overload
MindWorks.Nimbus Namespace


Driver.AddService Method

Pacific MindWorks Nimbus Driver Studio

DriverAddService Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal void AddService(
    Type serviceIdentifier,
    Object serviceProvider
)
internal:
void AddService(
    Type^ serviceIdentifier,
    Object^ serviceProvider
)

Parameters

serviceIdentifier
Type: SystemType
serviceProvider
Type: SystemObject
See Also

Reference

Driver Class
MindWorks.Nimbus Namespace


Driver.CacheContainsValue Method

Pacific MindWorks Nimbus Driver Studio

DriverCacheContainsValue Method

Overload List
 | Name | Description
Protected method | CacheContainsValue(Object) | (Overrides DriverNodeCacheContainsValue(Object).)
Protected method | CacheContainsValue(MethodInfo, DriverNode, Object) |
Top
See Also

Reference

Driver Class
MindWorks.Nimbus Namespace


Driver.CacheContainsValue Method (Object)

Pacific MindWorks Nimbus Driver Studio

DriverCacheContainsValue Method (Object)

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected override sealed bool CacheContainsValue(
    Object value
)
protected:
virtual bool CacheContainsValue(
    Object^ value
) override sealed

Parameters

value
Type: SystemObject

Return Value

Type: Boolean
See Also

Reference

Driver Class
CacheContainsValue Overload
MindWorks.Nimbus Namespace


Driver.CacheContainsValue Method (MethodInfo, DriverNode, Object)

Pacific MindWorks Nimbus Driver Studio

DriverCacheContainsValue Method (MethodInfo, DriverNode, Object)

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal bool CacheContainsValue(
    MethodInfo meth,
    DriverNode node,
    Object value
)
internal:
bool CacheContainsValue(
    MethodInfo^ meth,
    DriverNode^ node,
    Object^ value
)

Parameters

meth
Type: System.ReflectionMethodInfo
node
Type: MindWorks.NimbusDriverNode
value
Type: SystemObject

Return Value

Type: Boolean
See Also

Reference

Driver Class
CacheContainsValue Overload
MindWorks.Nimbus Namespace


Driver.CheckDisposed Method

Pacific MindWorks Nimbus Driver Studio

DriverCheckDisposed Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected override void CheckDisposed()
protected:
virtual void CheckDisposed() override
See Also

Reference

Driver Class
MindWorks.Nimbus Namespace


Driver.CheckInstrumentSupported Method

Pacific MindWorks Nimbus Driver Studio

DriverCheckInstrumentSupported Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal virtual void CheckInstrumentSupported()
internal:
virtual void CheckInstrumentSupported()
See Also

Reference

Driver Class
MindWorks.Nimbus Namespace


Driver.CleanupUnmanagedResources Method

Pacific MindWorks Nimbus Driver Studio

DriverCleanupUnmanagedResources Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected virtual void CleanupUnmanagedResources()
protected:
virtual void CleanupUnmanagedResources()
See Also

Reference

Driver Class
MindWorks.Nimbus Namespace


Driver.ClearIO Method

Pacific MindWorks Nimbus Driver Studio

DriverClearIO Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected virtual void ClearIO()
protected:
virtual void ClearIO()
See Also

Reference

Driver Class
MindWorks.Nimbus Namespace


Driver.CloseIO Method

Pacific MindWorks Nimbus Driver Studio

DriverCloseIO Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal virtual void CloseIO()
internal:
virtual void CloseIO()
See Also

Reference

Driver Class
MindWorks.Nimbus Namespace


Driver.ConvertEnumToString Method

Pacific MindWorks Nimbus Driver Studio

DriverConvertEnumToString Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal override sealed string ConvertEnumToString(
    Enum member
)
internal:
virtual String^ ConvertEnumToString(
    Enum^ member
) override sealed

Parameters

member
Type: SystemEnum

Return Value

Type: String
See Also

Reference

Driver Class
MindWorks.Nimbus Namespace


Driver.ConvertStringToEnum(TEnum) Method

Pacific MindWorks Nimbus Driver Studio

DriverConvertStringToEnumTEnum Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal override sealed Enum ConvertStringToEnum<TEnum>(
    string data
)

internal:
generic<typename TEnum>
virtual Enum^ ConvertStringToEnum(
    String^ data
) override sealed

Parameters

data
Type: SystemString

Type Parameters

TEnum

Return Value

Type: Enum
See Also

Reference

Driver Class
MindWorks.Nimbus Namespace


Driver.Dispose Method

Pacific MindWorks Nimbus Driver Studio

DriverDispose Method

Overload List
 | Name | Description
Public method | Dispose | Releases all resources used by the Driver
Protected method | Dispose(Boolean) | Releases the unmanaged resources used by the Driver and optionally releases the managed resources
Top
See Also

Reference

Driver Class
MindWorks.Nimbus Namespace


Driver.Dispose Method

Pacific MindWorks Nimbus Driver Studio

DriverDispose Method

Releases all resources used by the Driver

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public void Dispose()
public:
virtual void Dispose() sealed

Implements

IDisposableDispose
See Also

Reference

Driver Class
Dispose Overload
MindWorks.Nimbus Namespace


Driver.Dispose Method (Boolean)

Pacific MindWorks Nimbus Driver Studio

DriverDispose Method (Boolean)

Releases the unmanaged resources used by the Driver and optionally releases the managed resources

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected void Dispose(
    bool disposing
)
protected:
void Dispose(
    bool disposing
)

Parameters

disposing
Type: SystemBoolean
True to release both managed and unmanaged resources; false to release only unmanaged resources
See Also

Reference

Driver Class
Dispose Overload
MindWorks.Nimbus Namespace


Driver.Finalize Method

Pacific MindWorks Nimbus Driver Studio

DriverFinalize Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected override void Finalize()
protected:
virtual void Finalize() override

Implements

ObjectFinalize
See Also

Reference

Driver Class
MindWorks.Nimbus Namespace


Driver.GetCacheValue Method

Pacific MindWorks Nimbus Driver Studio

DriverGetCacheValue Method

Overload List
 | Name | Description
Protected method | GetCacheValueT(T) | (Overrides DriverNodeGetCacheValueT(T).)
Protected method | GetCacheValueT(T) | (Inherited from DriverNode.)
Protected method | GetCacheValue(Object) | (Overrides DriverNodeGetCacheValue(Object).)
Protected method | GetCacheValueT(String, T) | (Overrides DriverNodeGetCacheValueT(String, T).)
Protected method | GetCacheValueT(String, T) | (Inherited from DriverNode.)
Protected method | GetCacheValue(MethodInfo, DriverNode, Object) |
Protected method | GetCacheValueT(MethodInfo, DriverNode, T) |
Protected method | GetCacheValueT(String, MethodInfo, DriverNode, T) |
Top
See Also

Reference

Driver Class
MindWorks.Nimbus Namespace


Driver.GetCacheValue(T) Method (T)

Pacific MindWorks Nimbus Driver Studio

DriverGetCacheValueT Method (T)

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected override sealed bool GetCacheValue<T>(
    out T value
)

protected:
generic<typename T>
virtual bool GetCacheValue(
    [OutAttribute] T% value
) override sealed

Parameters

value
Type: T

Type Parameters

T

Return Value

Type: Boolean
See Also

Reference

Driver Class
GetCacheValue Overload
MindWorks.Nimbus Namespace


Driver.GetCacheValue Method (Object)

Pacific MindWorks Nimbus Driver Studio

DriverGetCacheValue Method (Object)

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected override sealed bool GetCacheValue(
    out Object value
)
protected:
virtual bool GetCacheValue(
    [OutAttribute] Object^% value
) override sealed

Parameters

value
Type: SystemObject

Return Value

Type: Boolean
See Also

Reference

Driver Class
GetCacheValue Overload
MindWorks.Nimbus Namespace


Driver.GetCacheValue(T) Method (String, T)

Pacific MindWorks Nimbus Driver Studio

DriverGetCacheValueT Method (String, T)

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected override sealed bool GetCacheValue<T>(
    string key,
    out T value
)

protected:
generic<typename T>
virtual bool GetCacheValue(
    String^ key,
    [OutAttribute] T% value
) override sealed

Parameters

key
Type: SystemString
value
Type: T

Type Parameters

T

Return Value

Type: Boolean
See Also

Reference

Driver Class
GetCacheValue Overload
MindWorks.Nimbus Namespace


Driver.GetCacheValue Method (MethodInfo, DriverNode, Object)

Pacific MindWorks Nimbus Driver Studio

DriverGetCacheValue Method (MethodInfo, DriverNode, Object)

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal bool GetCacheValue(
    MethodInfo meth,
    DriverNode node,
    out Object value
)
internal:
bool GetCacheValue(
    MethodInfo^ meth,
    DriverNode^ node,
    [OutAttribute] Object^% value
)

Parameters

meth
Type: System.ReflectionMethodInfo
node
Type: MindWorks.NimbusDriverNode
value
Type: SystemObject

Return Value

Type: Boolean
See Also

Reference

Driver Class
GetCacheValue Overload
MindWorks.Nimbus Namespace


Driver.GetCacheValue(T) Method (MethodInfo, DriverNode, T)

Pacific MindWorks Nimbus Driver Studio

DriverGetCacheValueT Method (MethodInfo, DriverNode, T)

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal bool GetCacheValue<T>(
    MethodInfo meth,
    DriverNode node,
    out T value
)

internal:
generic<typename T>
bool GetCacheValue(
    MethodInfo^ meth,
    DriverNode^ node,
    [OutAttribute] T% value
)

Parameters

meth
Type: System.ReflectionMethodInfo
node
Type: MindWorks.NimbusDriverNode
value
Type: T

Type Parameters

T

Return Value

Type: Boolean
See Also

Reference

Driver Class
GetCacheValue Overload
MindWorks.Nimbus Namespace


Driver.GetCacheValue(T) Method (String, MethodInfo, DriverNode, T)

Pacific MindWorks Nimbus Driver Studio

DriverGetCacheValueT Method (String, MethodInfo, DriverNode, T)

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal bool GetCacheValue<T>(
    string key,
    MethodInfo meth,
    DriverNode node,
    out T value
)

internal:
generic<typename T>
bool GetCacheValue(
    String^ key,
    MethodInfo^ meth,
    DriverNode^ node,
    [OutAttribute] T% value
)

Parameters

key
Type: SystemString
meth
Type: System.ReflectionMethodInfo
node
Type: MindWorks.NimbusDriverNode
value
Type: T

Type Parameters

T

Return Value

Type: Boolean
See Also

Reference

Driver Class
GetCacheValue Overload
MindWorks.Nimbus Namespace


Driver.GetDefaultValueForSimulation Method

Pacific MindWorks Nimbus Driver Studio

DriverGetDefaultValueForSimulation Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected override Object GetDefaultValueForSimulation(
    Type targetType,
    string defaultValue
)
protected:
virtual Object^ GetDefaultValueForSimulation(
    Type^ targetType,
    String^ defaultValue
) override

Parameters

targetType
Type: SystemType
defaultValue
Type: SystemString

Return Value

Type: Object
See Also

Reference

Driver Class
MindWorks.Nimbus Namespace


Driver.GetService Method

Pacific MindWorks Nimbus Driver Studio

DriverGetService Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public Object GetService(
    Type serviceType
)
public:
virtual Object^ GetService(
    Type^ serviceType
) sealed

Parameters

serviceType
Type: SystemType

Return Value

Type: Object

Implements

IServiceProviderGetService(Type)
See Also

Reference

Driver Class
MindWorks.Nimbus Namespace


Driver.Initialize Method

Pacific MindWorks Nimbus Driver Studio

DriverInitialize Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected void Initialize(
    string resourceName,
    bool idQuery,
    bool reset,
    string options,
    LockType lockType,
    string accessKey,
    int ioTimeoutMilliseconds,
    int resetTimeoutMilliseconds,
    int selfTestTimeoutMilliseconds
)
protected:
void Initialize(
    String^ resourceName,
    bool idQuery,
    bool reset,
    String^ options,
    LockType lockType,
    String^ accessKey,
    int ioTimeoutMilliseconds,
    int resetTimeoutMilliseconds,
    int selfTestTimeoutMilliseconds
)

Parameters

resourceName
Type: SystemString
idQuery
Type: SystemBoolean
reset
Type: SystemBoolean
options
Type: SystemString
lockType
Type: LockType
accessKey
Type: SystemString
ioTimeoutMilliseconds
Type: SystemInt32
resetTimeoutMilliseconds
Type: SystemInt32
selfTestTimeoutMilliseconds
Type: SystemInt32
See Also

Reference

Driver Class
MindWorks.Nimbus Namespace


Driver.InitializeIdentification Method

Pacific MindWorks Nimbus Driver Studio

DriverInitializeIdentification Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected virtual void InitializeIdentification()
protected:
virtual void InitializeIdentification()
See Also

Reference

Driver Class
MindWorks.Nimbus Namespace


Driver.InitializeIO Method

Pacific MindWorks Nimbus Driver Studio

DriverInitializeIO Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected virtual void InitializeIO()
protected:
virtual void InitializeIO()
See Also

Reference

Driver Class
MindWorks.Nimbus Namespace


Driver.InstrumentInFamily Method

Pacific MindWorks Nimbus Driver Studio

DriverInstrumentInFamily Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected override bool InstrumentInFamily(
    string family
)
protected:
virtual bool InstrumentInFamily(
    String^ family
) override

Parameters

family
Type: SystemString

Return Value

Type: Boolean
See Also

Reference

Driver Class
MindWorks.Nimbus Namespace


Driver.InstrumentIsModel Method

Pacific MindWorks Nimbus Driver Studio

DriverInstrumentIsModel Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected override bool InstrumentIsModel(
    string model
)
protected:
virtual bool InstrumentIsModel(
    String^ model
) override

Parameters

model
Type: SystemString

Return Value

Type: Boolean
See Also

Reference

Driver Class
MindWorks.Nimbus Namespace


Driver.InvalidateAllCacheEntries Method

Pacific MindWorks Nimbus Driver Studio

DriverInvalidateAllCacheEntries Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected override sealed void InvalidateAllCacheEntries()
protected:
virtual void InvalidateAllCacheEntries() override sealed
See Also

Reference

Driver Class
MindWorks.Nimbus Namespace


Driver.InvalidateCacheEntry Method

Pacific MindWorks Nimbus Driver Studio

DriverInvalidateCacheEntry Method

Overload List
 | Name | Description
Protected method | InvalidateCacheEntry(String) | (Overrides DriverNodeInvalidateCacheEntry(String).)
Protected method | InvalidateCacheEntry(MethodInfo, DriverNode, String) |
Top
See Also

Reference

Driver Class
MindWorks.Nimbus Namespace


Driver.InvalidateCacheEntry Method (String)

Pacific MindWorks Nimbus Driver Studio

DriverInvalidateCacheEntry Method (String)

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected override sealed void InvalidateCacheEntry(
    string key
)
protected:
virtual void InvalidateCacheEntry(
    String^ key
) override sealed

Parameters

key
Type: SystemString
See Also

Reference

Driver Class
InvalidateCacheEntry Overload
MindWorks.Nimbus Namespace


Driver.InvalidateCacheEntry Method (MethodInfo, DriverNode, String)

Pacific MindWorks Nimbus Driver Studio

DriverInvalidateCacheEntry Method (MethodInfo, DriverNode, String)

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal void InvalidateCacheEntry(
    MethodInfo meth,
    DriverNode node,
    string key
)
internal:
void InvalidateCacheEntry(
    MethodInfo^ meth,
    DriverNode^ node,
    String^ key
)

Parameters

meth
Type: System.ReflectionMethodInfo
node
Type: MindWorks.NimbusDriverNode
key
Type: SystemString
See Also

Reference

Driver Class
InvalidateCacheEntry Overload
MindWorks.Nimbus Namespace


Driver.PollInstrumentErrors Method

Pacific MindWorks Nimbus Driver Studio

DriverPollInstrumentErrors Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected override void PollInstrumentErrors()
protected:
virtual void PollInstrumentErrors() override
See Also

Reference

Driver Class
MindWorks.Nimbus Namespace


Driver.ProcessCustomDriverSetupOption Method

Pacific MindWorks Nimbus Driver Studio

DriverProcessCustomDriverSetupOption Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal virtual void ProcessCustomDriverSetupOption(
    string name,
    string value
)
internal:
virtual void ProcessCustomDriverSetupOption(
    String^ name,
    String^ value
)

Parameters

name
Type: SystemString
value
Type: SystemString
See Also

Reference

Driver Class
MindWorks.Nimbus Namespace


Driver.SendCoercionEvent Method

Pacific MindWorks Nimbus Driver Studio

DriverSendCoercionEvent Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected override sealed void SendCoercionEvent(
    Object originalValue,
    Object coercedValue
)
protected:
virtual void SendCoercionEvent(
    Object^ originalValue,
    Object^ coercedValue
) override sealed

Parameters

originalValue
Type: SystemObject
coercedValue
Type: SystemObject
See Also

Reference

Driver Class
MindWorks.Nimbus Namespace


Driver.SendInterchangeEvent Method

Pacific MindWorks Nimbus Driver Studio

DriverSendInterchangeEvent Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected override sealed void SendInterchangeEvent(
    InterchangeCheckWarningEventArgs args
)
protected:
virtual void SendInterchangeEvent(
    InterchangeCheckWarningEventArgs^ args
) override sealed

Parameters

args
Type: InterchangeCheckWarningEventArgs
See Also

Reference

Driver Class
MindWorks.Nimbus Namespace


Driver.SendWarningEvent Method

Pacific MindWorks Nimbus Driver Studio

DriverSendWarningEvent Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected override sealed void SendWarningEvent(
    WarningEventArgs args
)
protected:
virtual void SendWarningEvent(
    WarningEventArgs^ args
) override sealed

Parameters

args
Type: WarningEventArgs
See Also

Reference

Driver Class
MindWorks.Nimbus Namespace


Driver.UpdateCacheValue Method

Pacific MindWorks Nimbus Driver Studio

DriverUpdateCacheValue Method

Overload List
 | Name | Description
Protected method | UpdateCacheValue(Object) | (Overrides DriverNodeUpdateCacheValue(Object).)
Protected method | UpdateCacheValue(String, Object) | (Overrides DriverNodeUpdateCacheValue(String, Object).)
Protected method | UpdateCacheValue(MethodInfo, DriverNode, Object) |
Protected method | UpdateCacheValue(String, MethodInfo, DriverNode, Object) |
Top
See Also

Reference

Driver Class
MindWorks.Nimbus Namespace


Driver.UpdateCacheValue Method (Object)

Pacific MindWorks Nimbus Driver Studio

DriverUpdateCacheValue Method (Object)

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected override sealed void UpdateCacheValue(
    Object value
)
protected:
virtual void UpdateCacheValue(
    Object^ value
) override sealed

Parameters

value
Type: SystemObject
See Also

Reference

Driver Class
UpdateCacheValue Overload
MindWorks.Nimbus Namespace


Driver.UpdateCacheValue Method (String, Object)

Pacific MindWorks Nimbus Driver Studio

DriverUpdateCacheValue Method (String, Object)

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected override sealed void UpdateCacheValue(
    string key,
    Object value
)
protected:
virtual void UpdateCacheValue(
    String^ key,
    Object^ value
) override sealed

Parameters

key
Type: SystemString
value
Type: SystemObject
See Also

Reference

Driver Class
UpdateCacheValue Overload
MindWorks.Nimbus Namespace


Driver.UpdateCacheValue Method (MethodInfo, DriverNode, Object)

Pacific MindWorks Nimbus Driver Studio

DriverUpdateCacheValue Method (MethodInfo, DriverNode, Object)

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal void UpdateCacheValue(
    MethodInfo meth,
    DriverNode node,
    Object value
)
internal:
void UpdateCacheValue(
    MethodInfo^ meth,
    DriverNode^ node,
    Object^ value
)

Parameters

meth
Type: System.ReflectionMethodInfo
node
Type: MindWorks.NimbusDriverNode
value
Type: SystemObject
See Also

Reference

Driver Class
UpdateCacheValue Overload
MindWorks.Nimbus Namespace


Driver.UpdateCacheValue Method (String, MethodInfo, DriverNode, Object)

Pacific MindWorks Nimbus Driver Studio

DriverUpdateCacheValue Method (String, MethodInfo, DriverNode, Object)

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal void UpdateCacheValue(
    string key,
    MethodInfo meth,
    DriverNode node,
    Object value
)
internal:
void UpdateCacheValue(
    String^ key,
    MethodInfo^ meth,
    DriverNode^ node,
    Object^ value
)

Parameters

key
Type: SystemString
meth
Type: System.ReflectionMethodInfo
node
Type: MindWorks.NimbusDriverNode
value
Type: SystemObject
See Also

Reference

Driver Class
UpdateCacheValue Overload
MindWorks.Nimbus Namespace


Driver.ValidateSessionInformation Method

Pacific MindWorks Nimbus Driver Studio

DriverValidateSessionInformation Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected virtual void ValidateSessionInformation()
protected:
virtual void ValidateSessionInformation()
See Also

Reference

Driver Class
MindWorks.Nimbus Namespace


Driver Events

The Driver type exposes the following members.

Events
 | Name | Description
Protected event | Coercion |
Protected event | InterchangeCheckWarning |
Protected event | Warning |
Top
See Also

Reference

Driver Class
MindWorks.Nimbus Namespace


Driver.Coercion Event

Pacific MindWorks Nimbus Driver Studio

DriverCoercion Event

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected event EventHandler<CoercionEventArgs> Coercion
protected:
 event EventHandler<CoercionEventArgs^>^ Coercion {
    void add (EventHandler<CoercionEventArgs^>^ value);
    void remove (EventHandler<CoercionEventArgs^>^ value);
}

Value

Type: SystemEventHandler CoercionEventArgs
See Also

Reference

Driver Class
MindWorks.Nimbus Namespace


Driver.InterchangeCheckWarning Event

Pacific MindWorks Nimbus Driver Studio

DriverInterchangeCheckWarning Event

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected event EventHandler<InterchangeCheckWarningEventArgs> InterchangeCheckWarning
protected:
 event EventHandler<InterchangeCheckWarningEventArgs^>^ InterchangeCheckWarning {
    void add (EventHandler<InterchangeCheckWarningEventArgs^>^ value);
    void remove (EventHandler<InterchangeCheckWarningEventArgs^>^ value);
}

Value

Type: SystemEventHandler InterchangeCheckWarningEventArgs
See Also

Reference

Driver Class
MindWorks.Nimbus Namespace


Driver.Warning Event

Pacific MindWorks Nimbus Driver Studio

DriverWarning Event

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected event EventHandler<WarningEventArgs> Warning
protected:
 event EventHandler<WarningEventArgs^>^ Warning {
    void add (EventHandler<WarningEventArgs^>^ value);
    void remove (EventHandler<WarningEventArgs^>^ value);
}

Value

Type: SystemEventHandler WarningEventArgs
See Also

Reference

Driver Class
MindWorks.Nimbus Namespace


DriverCapabilitiesAttribute Class

Inheritance Hierarchy
SystemObject
SystemAttribute
MindWorks.NimbusNimbusAttribute
MindWorks.NimbusDriverCapabilitiesAttribute

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal sealed class DriverCapabilitiesAttribute : NimbusAttribute
internal ref class DriverCapabilitiesAttribute sealed : public NimbusAttribute

The DriverCapabilitiesAttribute type exposes the following members.

Constructors
 | Name | Description
Protected method | DriverCapabilitiesAttribute | Initializes a new instance of the DriverCapabilitiesAttribute class
Top
Properties
 | Name | Description
Protected property | DriverCapabilities |
Top
See Also

Reference

MindWorks.Nimbus Namespace


DriverCapabilitiesAttribute Constructor

Initializes a new instance of the DriverCapabilitiesAttribute class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal DriverCapabilitiesAttribute(
    Capabilities capabilities
)
internal:
DriverCapabilitiesAttribute(
    Capabilities capabilities
)

Parameters

capabilities
Type: MindWorks.NimbusCapabilities
See Also

Reference

DriverCapabilitiesAttribute Class
MindWorks.Nimbus Namespace


DriverCapabilitiesAttribute Properties

The DriverCapabilitiesAttribute type exposes the following members.

Properties
 | Name | Description
Protected property | DriverCapabilities |
Top
See Also

Reference

DriverCapabilitiesAttribute Class
MindWorks.Nimbus Namespace


DriverCapabilitiesAttribute.DriverCapabilities Property

Pacific MindWorks Nimbus Driver Studio

DriverCapabilitiesAttributeDriverCapabilities Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal Capabilities DriverCapabilities { get; }
internal:
property Capabilities DriverCapabilities {
    Capabilities get ();
}

Property Value

Type: Capabilities
See Also

Reference

DriverCapabilitiesAttribute Class
MindWorks.Nimbus Namespace


DriverDescriptionAttribute Class

Inheritance Hierarchy
SystemObject
SystemAttribute
MindWorks.NimbusNimbusAttribute
MindWorks.NimbusDriverDescriptionAttribute

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal sealed class DriverDescriptionAttribute : NimbusAttribute
internal ref class DriverDescriptionAttribute sealed : public NimbusAttribute

The DriverDescriptionAttribute type exposes the following members.

Constructors
 | Name | Description
Protected method | DriverDescriptionAttribute | Initializes a new instance of the DriverDescriptionAttribute class
Top
Properties
 | Name | Description
Public property | Description |
Top
See Also

Reference

MindWorks.Nimbus Namespace


DriverDescriptionAttribute Constructor

Initializes a new instance of the DriverDescriptionAttribute class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal DriverDescriptionAttribute(
    string description
)
internal:
DriverDescriptionAttribute(
    String^ description
)

Parameters

description
Type: SystemString
See Also

Reference

DriverDescriptionAttribute Class
MindWorks.Nimbus Namespace


DriverDescriptionAttribute Properties

The DriverDescriptionAttribute type exposes the following members.

Properties
 | Name | Description
Public property | Description |
Top
See Also

Reference

DriverDescriptionAttribute Class
MindWorks.Nimbus Namespace


DriverDescriptionAttribute.Description Property

Pacific MindWorks Nimbus Driver Studio

DriverDescriptionAttributeDescription Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public string Description { get; set; }
public:
property String^ Description {
    String^ get ();
    void set (String^ value);
}

Property Value

Type: String
See Also

Reference

DriverDescriptionAttribute Class
MindWorks.Nimbus Namespace


DriverEventAttribute Class

Inheritance Hierarchy
SystemObject
SystemAttribute
MindWorks.NimbusNimbusAttribute
MindWorks.NimbusNimbusCodeWeaverAttribute
MindWorks.NimbusDriverMemberAttribute
MindWorks.NimbusDriverEventAttribute

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal sealed class DriverEventAttribute : DriverMemberAttribute
internal ref class DriverEventAttribute sealed : public DriverMemberAttribute

The DriverEventAttribute type exposes the following members.

Constructors
 | Name | Description
Protected method | DriverEventAttribute | Initializes a new instance of the DriverEventAttribute class
Top
Properties
 | Name | Description
Public property | Lock | (Inherited from DriverMemberAttribute.)
Public property | LockTimeoutMilliseconds | (Inherited from DriverMemberAttribute.)
Public property | SuppressAll | (Inherited from NimbusCodeWeaverAttribute.)
Public property | SuppressObjectDisposedCheck | (Inherited from DriverMemberAttribute.)
Public property | SuppressPollInstrumentErrors | (Inherited from DriverMemberAttribute.)
Top
See Also

Reference

MindWorks.Nimbus Namespace


DriverEventAttribute Constructor

Initializes a new instance of the DriverEventAttribute class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal DriverEventAttribute()
internal:
DriverEventAttribute()
See Also

Reference

DriverEventAttribute Class
MindWorks.Nimbus Namespace


DriverEventAttribute Properties

The DriverEventAttribute type exposes the following members.

Properties
 | Name | Description
Public property | Lock | (Inherited from DriverMemberAttribute.)
Public property | LockTimeoutMilliseconds | (Inherited from DriverMemberAttribute.)
Public property | SuppressAll | (Inherited from NimbusCodeWeaverAttribute.)
Public property | SuppressObjectDisposedCheck | (Inherited from DriverMemberAttribute.)
Public property | SuppressPollInstrumentErrors | (Inherited from DriverMemberAttribute.)
Top
See Also

Reference

DriverEventAttribute Class
MindWorks.Nimbus Namespace


DriverInfo Class

Inheritance Hierarchy
SystemObject
MindWorks.NimbusDriverInfo

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public class DriverInfo
public ref class DriverInfo

The DriverInfo type exposes the following members.

Properties
 | Name | Description
Protected property | CapabilityGroups |
Protected property | DefaultModelForSimulation |
Protected property | DriverDescription |
Protected property | DriverIdentifier |
Protected property | DriverRevision |
Protected property | DriverVendor |
Protected property | IdQuerySupported |
Protected property | InterchangeCheckSupported |
Protected property | ResetSupported |
Protected property | RevisionQuerySupported |
Protected property | SelfTestSupported |
Protected property | SoftwareModuleName |
Protected property | SpecificationMajorVersion |
Protected property | SpecificationMinorVersion |
Top
Methods
 | Name | Description
Protected method | GetAllSupportedModels |
Protected method | IsModelInFamily |
Protected method | IsModelSupported |
 | Load |
Top
See Also

Reference

MindWorks.Nimbus Namespace


DriverInfo Properties

The DriverInfo type exposes the following members.

Properties
 | Name | Description
Protected property | CapabilityGroups |
Protected property | DefaultModelForSimulation |
Protected property | DriverDescription |
Protected property | DriverIdentifier |
Protected property | DriverRevision |
Protected property | DriverVendor |
Protected property | IdQuerySupported |
Protected property | InterchangeCheckSupported |
Protected property | ResetSupported |
Protected property | RevisionQuerySupported |
Protected property | SelfTestSupported |
Protected property | SoftwareModuleName |
Protected property | SpecificationMajorVersion |
Protected property | SpecificationMinorVersion |
Top
See Also

Reference

DriverInfo Class
MindWorks.Nimbus Namespace


DriverInfo.CapabilityGroups Property

Pacific MindWorks Nimbus Driver Studio

DriverInfoCapabilityGroups Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal IEnumerable<string> CapabilityGroups { get; }
internal:
property IEnumerable<String^>^ CapabilityGroups {
    IEnumerable<String^>^ get ();
}

Property Value

Type: IEnumerable String
See Also

Reference

DriverInfo Class
MindWorks.Nimbus Namespace


DriverInfo.DefaultModelForSimulation Property

Pacific MindWorks Nimbus Driver Studio

DriverInfoDefaultModelForSimulation Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal string DefaultModelForSimulation { get; }
internal:
property String^ DefaultModelForSimulation {
    String^ get ();
}

Property Value

Type: String
See Also

Reference

DriverInfo Class
MindWorks.Nimbus Namespace


DriverInfo.DriverDescription Property

Pacific MindWorks Nimbus Driver Studio

DriverInfoDriverDescription Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal string DriverDescription { get; }
internal:
property String^ DriverDescription {
    String^ get ();
}

Property Value

Type: String
See Also

Reference

DriverInfo Class
MindWorks.Nimbus Namespace


DriverInfo.DriverIdentifier Property

Pacific MindWorks Nimbus Driver Studio

DriverInfoDriverIdentifier Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal string DriverIdentifier { get; }
internal:
property String^ DriverIdentifier {
    String^ get ();
}

Property Value

Type: String
See Also

Reference

DriverInfo Class
MindWorks.Nimbus Namespace


DriverInfo.DriverRevision Property

Pacific MindWorks Nimbus Driver Studio

DriverInfoDriverRevision Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal string DriverRevision { get; }
internal:
property String^ DriverRevision {
    String^ get ();
}

Property Value

Type: String
See Also

Reference

DriverInfo Class
MindWorks.Nimbus Namespace


DriverInfo.DriverVendor Property

Pacific MindWorks Nimbus Driver Studio

DriverInfoDriverVendor Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal string DriverVendor { get; }
internal:
property String^ DriverVendor {
    String^ get ();
}

Property Value

Type: String
See Also

Reference

DriverInfo Class
MindWorks.Nimbus Namespace


DriverInfo.IdQuerySupported Property

Pacific MindWorks Nimbus Driver Studio

DriverInfoIdQuerySupported Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal bool IdQuerySupported { get; }
internal:
property bool IdQuerySupported {
    bool get ();
}

Property Value

Type: Boolean
See Also

Reference

DriverInfo Class
MindWorks.Nimbus Namespace


DriverInfo.InterchangeCheckSupported Property

Pacific MindWorks Nimbus Driver Studio

DriverInfoInterchangeCheckSupported Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal bool InterchangeCheckSupported { get; }
internal:
property bool InterchangeCheckSupported {
    bool get ();
}

Property Value

Type: Boolean
See Also

Reference

DriverInfo Class
MindWorks.Nimbus Namespace


DriverInfo.ResetSupported Property

Pacific MindWorks Nimbus Driver Studio

DriverInfoResetSupported Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal bool ResetSupported { get; }
internal:
property bool ResetSupported {
    bool get ();
}

Property Value

Type: Boolean
See Also

Reference

DriverInfo Class
MindWorks.Nimbus Namespace


DriverInfo.RevisionQuerySupported Property

Pacific MindWorks Nimbus Driver Studio

DriverInfoRevisionQuerySupported Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal bool RevisionQuerySupported { get; }
internal:
property bool RevisionQuerySupported {
    bool get ();
}

Property Value

Type: Boolean
See Also

Reference

DriverInfo Class
MindWorks.Nimbus Namespace


DriverInfo.SelfTestSupported Property

Pacific MindWorks Nimbus Driver Studio

DriverInfoSelfTestSupported Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal bool SelfTestSupported { get; }
internal:
property bool SelfTestSupported {
    bool get ();
}

Property Value

Type: Boolean
See Also

Reference

DriverInfo Class
MindWorks.Nimbus Namespace


DriverInfo.SoftwareModuleName Property

Pacific MindWorks Nimbus Driver Studio

DriverInfoSoftwareModuleName Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal string SoftwareModuleName { get; }
internal:
property String^ SoftwareModuleName {
    String^ get ();
}

Property Value

Type: String
See Also

Reference

DriverInfo Class
MindWorks.Nimbus Namespace


DriverInfo.SpecificationMajorVersion Property

Pacific MindWorks Nimbus Driver Studio

DriverInfoSpecificationMajorVersion Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal int SpecificationMajorVersion { get; }
internal:
property int SpecificationMajorVersion {
    int get ();
}

Property Value

Type: Int32
See Also

Reference

DriverInfo Class
MindWorks.Nimbus Namespace


DriverInfo.SpecificationMinorVersion Property

Pacific MindWorks Nimbus Driver Studio

DriverInfoSpecificationMinorVersion Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal int SpecificationMinorVersion { get; }
internal:
property int SpecificationMinorVersion {
    int get ();
}

Property Value

Type: Int32
See Also

Reference

DriverInfo Class
MindWorks.Nimbus Namespace


DriverInfo Methods

The DriverInfo type exposes the following members.

Methods
 | Name | Description
Protected method | GetAllSupportedModels |
Protected method | IsModelInFamily |
Protected method | IsModelSupported |
 | Load |
Top
See Also

Reference

DriverInfo Class
MindWorks.Nimbus Namespace


DriverInfo.GetAllSupportedModels Method

Pacific MindWorks Nimbus Driver Studio

DriverInfoGetAllSupportedModels Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal IEnumerable<string> GetAllSupportedModels()
internal:
IEnumerable<String^>^ GetAllSupportedModels()

Return Value

Type: IEnumerable String
See Also

Reference

DriverInfo Class
MindWorks.Nimbus Namespace


DriverInfo.IsModelInFamily Method

Pacific MindWorks Nimbus Driver Studio

DriverInfoIsModelInFamily Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal bool IsModelInFamily(
    string model,
    string family
)
internal:
bool IsModelInFamily(
    String^ model,
    String^ family
)

Parameters

model
Type: SystemString
family
Type: SystemString

Return Value

Type: Boolean
See Also

Reference

DriverInfo Class
MindWorks.Nimbus Namespace


DriverInfo.IsModelSupported Method

Pacific MindWorks Nimbus Driver Studio

DriverInfoIsModelSupported Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal bool IsModelSupported(
    string model
)
internal:
bool IsModelSupported(
    String^ model
)

Parameters

model
Type: SystemString

Return Value

Type: Boolean
See Also

Reference

DriverInfo Class
MindWorks.Nimbus Namespace


DriverInfo.Load Method

Pacific MindWorks Nimbus Driver Studio

DriverInfoLoad Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static DriverInfo Load(
    Driver mainDriverClass
)
internal:
static DriverInfo^ Load(
    Driver^ mainDriverClass
)

Parameters

mainDriverClass
Type: MindWorks.NimbusDriver

Return Value

Type: DriverInfo
See Also

Reference

DriverInfo Class
MindWorks.Nimbus Namespace


DriverMemberAttribute Class

Inheritance Hierarchy
SystemObject
SystemAttribute
MindWorks.NimbusNimbusAttribute
MindWorks.NimbusNimbusCodeWeaverAttribute
MindWorks.NimbusDriverMemberAttribute
MindWorks.NimbusDriverEventAttribute
MindWorks.NimbusDriverMethodAttribute
MindWorks.NimbusDriverPropertyAttribute

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal abstract class DriverMemberAttribute : NimbusCodeWeaverAttribute
internal ref class DriverMemberAttribute abstract : public NimbusCodeWeaverAttribute

The DriverMemberAttribute type exposes the following members.

Constructors
 | Name | Description
Protected method | DriverMemberAttribute | Initializes a new instance of the DriverMemberAttribute class
Top
Properties
 | Name | Description
Public property | Lock |
Public property | LockTimeoutMilliseconds |
Public property | SuppressAll | (Inherited from NimbusCodeWeaverAttribute.)
Public property | SuppressObjectDisposedCheck |
Public property | SuppressPollInstrumentErrors |
Top
See Also

Reference

MindWorks.Nimbus Namespace


DriverMemberAttribute Constructor

Initializes a new instance of the DriverMemberAttribute class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected DriverMemberAttribute()
protected:
DriverMemberAttribute()
See Also

Reference

DriverMemberAttribute Class
MindWorks.Nimbus Namespace


DriverMemberAttribute Properties

The DriverMemberAttribute type exposes the following members.

Properties
 | Name | Description
Public property | Lock |
Public property | LockTimeoutMilliseconds |
Public property | SuppressAll | (Inherited from NimbusCodeWeaverAttribute.)
Public property | SuppressObjectDisposedCheck |
Public property | SuppressPollInstrumentErrors |
Top
See Also

Reference

DriverMemberAttribute Class
MindWorks.Nimbus Namespace


DriverMemberAttribute.Lock Property

Pacific MindWorks Nimbus Driver Studio

DriverMemberAttributeLock Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public bool Lock { get; set; }
public:
property bool Lock {
    bool get ();
    void set (bool value);
}

Property Value

Type: Boolean
See Also

Reference

DriverMemberAttribute Class
MindWorks.Nimbus Namespace


DriverMemberAttribute.LockTimeoutMilliseconds Property

Pacific MindWorks Nimbus Driver Studio

DriverMemberAttributeLockTimeoutMilliseconds Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public uint LockTimeoutMilliseconds { get; set; }
public:
property unsigned int LockTimeoutMilliseconds {
    unsigned int get ();
    void set (unsigned int value);
}

Property Value

Type: UInt32
See Also

Reference

DriverMemberAttribute Class
MindWorks.Nimbus Namespace


DriverMemberAttribute.SuppressObjectDisposedCheck Property

Pacific MindWorks Nimbus Driver Studio

DriverMemberAttributeSuppressObjectDisposedCheck Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public bool SuppressObjectDisposedCheck { get; set; }
public:
property bool SuppressObjectDisposedCheck {
    bool get ();
    void set (bool value);
}

Property Value

Type: Boolean
See Also

Reference

DriverMemberAttribute Class
MindWorks.Nimbus Namespace


DriverMemberAttribute.SuppressPollInstrumentErrors Property

Pacific MindWorks Nimbus Driver Studio

DriverMemberAttributeSuppressPollInstrumentErrors Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public bool SuppressPollInstrumentErrors { get; set; }
public:
property bool SuppressPollInstrumentErrors {
    bool get ();
    void set (bool value);
}

Property Value

Type: Boolean
See Also

Reference

DriverMemberAttribute Class
MindWorks.Nimbus Namespace


DriverMethodAttribute Class

Inheritance Hierarchy
SystemObject
SystemAttribute
MindWorks.NimbusNimbusAttribute
MindWorks.NimbusNimbusCodeWeaverAttribute
MindWorks.NimbusDriverMemberAttribute
MindWorks.NimbusDriverMethodAttribute

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal sealed class DriverMethodAttribute : DriverMemberAttribute
internal ref class DriverMethodAttribute sealed : public DriverMemberAttribute

The DriverMethodAttribute type exposes the following members.

Constructors
 | Name | Description
Protected method | DriverMethodAttribute | Initializes a new instance of the DriverMethodAttribute class
Top
Properties
 | Name | Description
Public property | Lock | (Inherited from DriverMemberAttribute.)
Public property | LockTimeoutMilliseconds | (Inherited from DriverMemberAttribute.)
Public property | SuppressAll | (Inherited from NimbusCodeWeaverAttribute.)
Public property | SuppressObjectDisposedCheck | (Inherited from DriverMemberAttribute.)
Public property | SuppressPollInstrumentErrors | (Inherited from DriverMemberAttribute.)
Top
See Also

Reference

MindWorks.Nimbus Namespace


DriverMethodAttribute Constructor

Initializes a new instance of the DriverMethodAttribute class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal DriverMethodAttribute()
internal:
DriverMethodAttribute()
See Also

Reference

DriverMethodAttribute Class
MindWorks.Nimbus Namespace


DriverMethodAttribute Properties

The DriverMethodAttribute type exposes the following members.

Properties
 | Name | Description
Public property | Lock | (Inherited from DriverMemberAttribute.)
Public property | LockTimeoutMilliseconds | (Inherited from DriverMemberAttribute.)
Public property | SuppressAll | (Inherited from NimbusCodeWeaverAttribute.)
Public property | SuppressObjectDisposedCheck | (Inherited from DriverMemberAttribute.)
Public property | SuppressPollInstrumentErrors | (Inherited from DriverMemberAttribute.)
Top
See Also

Reference

DriverMethodAttribute Class
MindWorks.Nimbus Namespace


DriverNode Class

Inheritance Hierarchy
SystemObject
MindWorks.NimbusDriverNode
MindWorks.NimbusDriver
MindWorks.NimbusRepCap
MindWorks.NimbusRepCapCollection

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public abstract class DriverNode
public ref class DriverNode abstract

The DriverNode type exposes the following members.

Constructors
 | Name | Description
Protected method | DriverNode | Initializes a new instance of the DriverNode class
Protected method | DriverNode(DriverNode) | Initializes a new instance of the DriverNode class
Top
Properties
 | Name | Description
Protected property | CollectionStyleRepCaps |
Protected property | DriverInfo |
Protected property | IO |
Protected property | IsMessageBasedIOSession |
Protected property | IsRegisterBasedIOSession |
Protected property | ParameterStyleRepCaps |
Protected property | Parent |
Protected property | RegisterIO |
Protected property | Root |
Protected property | SelectorStyleRepCaps |
Protected property | Session |
Protected property | VisaSession |
Top
Methods
 | Name | Description
Protected method | AcquireLock |
Protected method | AcquireLock(PrecisionTimeSpan) |
Protected method | AddPhysicalName |
 | AlmostEqual |
Protected method | CacheContainsValue |
Protected method | CheckDisposed |
Protected method | ConvertEnumToString |
Protected method | ConvertStringToEnumTEnum |
 | CreateInstanceTNode |
Protected method | ExpandSelector |
Protected method | ExpandSingleSelector |
Protected method | GetActivePhysicalName |
Protected method | GetActivePhysicalNames |
Protected method | GetCacheValue(Object) |
Protected method | GetCacheValueT(T) |
Protected method | GetCacheValueT(String, T) |
Protected method | GetDefaultValueForSimulation |
Protected method | GetDynamicRepCapNames |
 | GetRepCapCollectionInterfaceImplementedByType |
Protected method | GetRepCapManager(String) |
Protected method | GetRepCapManagerT(String) |
Protected method | InitNode |
Protected method | InstrumentInFamily |
Protected method | InstrumentIsModel |
Protected method | InvalidateAllCacheEntries |
Protected method | InvalidateCacheEntry |
Protected method | PollInstrumentErrors |
Protected method | RemovePhysicalName |
Protected method | ResetObjectState |
Protected method | SendCoercionEvent |
Protected method | SendInterchangeEvent |
Protected method | SendWarningEvent |
Protected method | TryConvertEnumToString |
Protected method | TryConvertStringToEnumTEnum |
Protected method | UpdateCacheValue(Object) |
Protected method | UpdateCacheValue(String, Object) |
Top
See Also

Reference

MindWorks.Nimbus Namespace


DriverNode Constructor

Overload List
 | Name | Description
Protected method | DriverNode | Initializes a new instance of the DriverNode class
Protected method | DriverNode(DriverNode) | Initializes a new instance of the DriverNode class
Top
See Also

Reference

DriverNode Class
MindWorks.Nimbus Namespace


DriverNode Constructor

Initializes a new instance of the DriverNode class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected DriverNode()
protected:
DriverNode()
See Also

Reference

DriverNode Class
DriverNode Overload
MindWorks.Nimbus Namespace


DriverNode Constructor (DriverNode)

Initializes a new instance of the DriverNode class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected DriverNode(
    DriverNode parent
)
protected:
DriverNode(
    DriverNode^ parent
)

Parameters

parent
Type: MindWorks.NimbusDriverNode
See Also

Reference

DriverNode Class
DriverNode Overload
MindWorks.Nimbus Namespace


DriverNode Properties

The DriverNode type exposes the following members.

Properties
 | Name | Description
Protected property | CollectionStyleRepCaps |
Protected property | DriverInfo |
Protected property | IO |
Protected property | IsMessageBasedIOSession |
Protected property | IsRegisterBasedIOSession |
Protected property | ParameterStyleRepCaps |
Protected property | Parent |
Protected property | RegisterIO |
Protected property | Root |
Protected property | SelectorStyleRepCaps |
Protected property | Session |
Protected property | VisaSession |
Top
See Also

Reference

DriverNode Class
MindWorks.Nimbus Namespace


DriverNode.CollectionStyleRepCaps Property

Pacific MindWorks Nimbus Driver Studio

DriverNodeCollectionStyleRepCaps Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected internal ReadOnlyDictionary<Type, RepCapCollection> CollectionStyleRepCaps { get; }
protected public:
property ReadOnlyDictionary<Type^, RepCapCollection^>^ CollectionStyleRepCaps {
    ReadOnlyDictionary<Type^, RepCapCollection^>^ get ();
}

Property Value

Type: ReadOnlyDictionaryType, RepCapCollection
See Also

Reference

DriverNode Class
MindWorks.Nimbus Namespace


DriverNode.DriverInfo Property

Pacific MindWorks Nimbus Driver Studio

DriverNodeDriverInfo Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected virtual DriverInfo DriverInfo { get; }
protected:
virtual property DriverInfo^ DriverInfo {
    DriverInfo^ get ();
}

Property Value

Type: DriverInfo
See Also

Reference

DriverNode Class
MindWorks.Nimbus Namespace


DriverNode.IO Property

Pacific MindWorks Nimbus Driver Studio

DriverNodeIO Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected virtual IMessageBasedSession IO { get; }
protected:
virtual property IMessageBasedSession^ IO {
    IMessageBasedSession^ get ();
}

Property Value

Type: IMessageBasedSession
See Also

Reference

DriverNode Class
MindWorks.Nimbus Namespace


DriverNode.IsMessageBasedIOSession Property

Pacific MindWorks Nimbus Driver Studio

DriverNodeIsMessageBasedIOSession Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected bool IsMessageBasedIOSession { get; }
protected:
property bool IsMessageBasedIOSession {
    bool get ();
}

Property Value

Type: Boolean
See Also

Reference

DriverNode Class
MindWorks.Nimbus Namespace


DriverNode.IsRegisterBasedIOSession Property

Pacific MindWorks Nimbus Driver Studio

DriverNodeIsRegisterBasedIOSession Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected bool IsRegisterBasedIOSession { get; }
protected:
property bool IsRegisterBasedIOSession {
    bool get ();
}

Property Value

Type: Boolean
See Also

Reference

DriverNode Class
MindWorks.Nimbus Namespace


DriverNode.ParameterStyleRepCaps Property

Pacific MindWorks Nimbus Driver Studio

DriverNodeParameterStyleRepCaps Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected internal ReadOnlyDictionary<string, ParameterStyleRepCapManager> ParameterStyleRepCaps { get; }
protected public:
property ReadOnlyDictionary<String^, ParameterStyleRepCapManager^>^ ParameterStyleRepCaps {
    ReadOnlyDictionary<String^, ParameterStyleRepCapManager^>^ get ();
}

Property Value

Type: ReadOnlyDictionaryString, ParameterStyleRepCapManager
See Also

Reference

DriverNode Class
MindWorks.Nimbus Namespace


DriverNode.Parent Property

Pacific MindWorks Nimbus Driver Studio

DriverNodeParent Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal DriverNode Parent { get; }
internal:
property DriverNode^ Parent {
    DriverNode^ get ();
}

Property Value

Type: DriverNode
See Also

Reference

DriverNode Class
MindWorks.Nimbus Namespace


DriverNode.RegisterIO Property

Pacific MindWorks Nimbus Driver Studio

DriverNodeRegisterIO Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected virtual IRegisterBasedSession RegisterIO { get; }
protected:
virtual property IRegisterBasedSession^ RegisterIO {
    IRegisterBasedSession^ get ();
}

Property Value

Type: IRegisterBasedSession
See Also

Reference

DriverNode Class
MindWorks.Nimbus Namespace


DriverNode.Root Property

Pacific MindWorks Nimbus Driver Studio

DriverNodeRoot Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal Driver Root { get; }
internal:
property Driver^ Root {
    Driver^ get ();
}

Property Value

Type: Driver
See Also

Reference

DriverNode Class
MindWorks.Nimbus Namespace


DriverNode.SelectorStyleRepCaps Property

Pacific MindWorks Nimbus Driver Studio

DriverNodeSelectorStyleRepCaps Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected internal ReadOnlyDictionary<string, SelectorStyleRepCapManager> SelectorStyleRepCaps { get; }
protected public:
property ReadOnlyDictionary<String^, SelectorStyleRepCapManager^>^ SelectorStyleRepCaps {
    ReadOnlyDictionary<String^, SelectorStyleRepCapManager^>^ get ();
}

Property Value

Type: ReadOnlyDictionaryString, SelectorStyleRepCapManager
See Also

Reference

DriverNode Class
MindWorks.Nimbus Namespace


DriverNode.Session Property

Pacific MindWorks Nimbus Driver Studio

DriverNodeSession Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal virtual SessionInfo Session { get; }
internal:
virtual property SessionInfo^ Session {
    SessionInfo^ get ();
}

Property Value

Type: SessionInfo
See Also

Reference

DriverNode Class
MindWorks.Nimbus Namespace


DriverNode.VisaSession Property

Pacific MindWorks Nimbus Driver Studio

DriverNodeVisaSession Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected virtual IVisaSession VisaSession { get; }
protected:
virtual property IVisaSession^ VisaSession {
    IVisaSession^ get ();
}

Property Value

Type: IVisaSession
See Also

Reference

DriverNode Class
MindWorks.Nimbus Namespace


DriverNode Methods

The DriverNode type exposes the following members.

Methods
 | Name | Description
Protected method | AcquireLock |
Protected method | AcquireLock(PrecisionTimeSpan) |
Protected method | AddPhysicalName |
 | AlmostEqual |
Protected method | CacheContainsValue |
Protected method | CheckDisposed |
Protected method | ConvertEnumToString |
Protected method | ConvertStringToEnumTEnum |
 | CreateInstanceTNode |
Protected method | ExpandSelector |
Protected method | ExpandSingleSelector |
Protected method | GetActivePhysicalName |
Protected method | GetActivePhysicalNames |
Protected method | GetCacheValue(Object) |
Protected method | GetCacheValueT(T) |
Protected method | GetCacheValueT(String, T) |
Protected method | GetDefaultValueForSimulation |
Protected method | GetDynamicRepCapNames |
 | GetRepCapCollectionInterfaceImplementedByType |
Protected method | GetRepCapManager(String) |
Protected method | GetRepCapManagerT(String) |
Protected method | InitNode |
Protected method | InstrumentInFamily |
Protected method | InstrumentIsModel |
Protected method | InvalidateAllCacheEntries |
Protected method | InvalidateCacheEntry |
Protected method | PollInstrumentErrors |
Protected method | RemovePhysicalName |
Protected method | ResetObjectState |
Protected method | SendCoercionEvent |
Protected method | SendInterchangeEvent |
Protected method | SendWarningEvent |
Protected method | TryConvertEnumToString |
Protected method | TryConvertStringToEnumTEnum |
Protected method | UpdateCacheValue(Object) |
Protected method | UpdateCacheValue(String, Object) |
Top
See Also

Reference

DriverNode Class
MindWorks.Nimbus Namespace


DriverNode.AcquireLock Method

Pacific MindWorks Nimbus Driver Studio

DriverNodeAcquireLock Method

Overload List
 | Name | Description
Protected method | AcquireLock |
Protected method | AcquireLock(PrecisionTimeSpan) |
Top
See Also

Reference

DriverNode Class
MindWorks.Nimbus Namespace


DriverNode.AcquireLock Method

Pacific MindWorks Nimbus Driver Studio

DriverNodeAcquireLock Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected virtual IIviDriverLock AcquireLock()
protected:
virtual IIviDriverLock^ AcquireLock()

Return Value

Type: IIviDriverLock
See Also

Reference

DriverNode Class
AcquireLock Overload
MindWorks.Nimbus Namespace


DriverNode.AcquireLock Method (PrecisionTimeSpan)

Pacific MindWorks Nimbus Driver Studio

DriverNodeAcquireLock Method (PrecisionTimeSpan)

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected virtual IIviDriverLock AcquireLock(
    PrecisionTimeSpan maxTime
)
protected:
virtual IIviDriverLock^ AcquireLock(
    PrecisionTimeSpan maxTime
)

Parameters

maxTime
Type: PrecisionTimeSpan

Return Value

Type: IIviDriverLock
See Also

Reference

DriverNode Class
AcquireLock Overload
MindWorks.Nimbus Namespace


DriverNode.AddPhysicalName Method

Pacific MindWorks Nimbus Driver Studio

DriverNodeAddPhysicalName Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal virtual PhysicalName AddPhysicalName(
    string repCapName,
    string fullPhysicalName
)
internal:
virtual PhysicalName^ AddPhysicalName(
    String^ repCapName,
    String^ fullPhysicalName
)

Parameters

repCapName
Type: SystemString
fullPhysicalName
Type: SystemString

Return Value

Type: PhysicalName
See Also

Reference

DriverNode Class
MindWorks.Nimbus Namespace


DriverNode.AlmostEqual Method

Pacific MindWorks Nimbus Driver Studio

DriverNodeAlmostEqual Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static bool AlmostEqual(
    double value1,
    double value2
)
internal:
static bool AlmostEqual(
    double value1,
    double value2
)

Parameters

value1
Type: SystemDouble
value2
Type: SystemDouble

Return Value

Type: Boolean
See Also

Reference

DriverNode Class
MindWorks.Nimbus Namespace


DriverNode.CacheContainsValue Method

Pacific MindWorks Nimbus Driver Studio

DriverNodeCacheContainsValue Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected virtual bool CacheContainsValue(
    Object value
)
protected:
virtual bool CacheContainsValue(
    Object^ value
)

Parameters

value
Type: SystemObject

Return Value

Type: Boolean
See Also

Reference

DriverNode Class
MindWorks.Nimbus Namespace


DriverNode.CheckDisposed Method

Pacific MindWorks Nimbus Driver Studio

DriverNodeCheckDisposed Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected virtual void CheckDisposed()
protected:
virtual void CheckDisposed()
See Also

Reference

DriverNode Class
MindWorks.Nimbus Namespace


DriverNode.ConvertEnumToString Method

Pacific MindWorks Nimbus Driver Studio

DriverNodeConvertEnumToString Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal virtual string ConvertEnumToString(
    Enum member
)
internal:
virtual String^ ConvertEnumToString(
    Enum^ member
)

Parameters

member
Type: SystemEnum

Return Value

Type: String
See Also

Reference

DriverNode Class
MindWorks.Nimbus Namespace


DriverNode.ConvertStringToEnum(TEnum) Method

Pacific MindWorks Nimbus Driver Studio

DriverNodeConvertStringToEnumTEnum Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal virtual Enum ConvertStringToEnum<TEnum>(
    string data
)

internal:
generic<typename TEnum>
virtual Enum^ ConvertStringToEnum(
    String^ data
)

Parameters

data
Type: SystemString

Type Parameters

TEnum

Return Value

Type: Enum
See Also

Reference

DriverNode Class
MindWorks.Nimbus Namespace


DriverNode.CreateInstance(TNode) Method

Pacific MindWorks Nimbus Driver Studio

DriverNodeCreateInstanceTNode Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected static TNode CreateInstance<TNode>(
    DriverNode parent
)
where TNode : new(), DriverNode

protected:
generic<typename TNode>
where TNode : gcnew(), DriverNode
static TNode CreateInstance(
    DriverNode^ parent
)

Parameters

parent
Type: MindWorks.NimbusDriverNode

Type Parameters

TNode

Return Value

Type: TNode
See Also

Reference

DriverNode Class
MindWorks.Nimbus Namespace


DriverNode.ExpandSelector Method

Pacific MindWorks Nimbus Driver Studio

DriverNodeExpandSelector Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal virtual IList<PhysicalName> ExpandSelector(
    string repCapName,
    string selector
)
internal:
virtual IList<PhysicalName^>^ ExpandSelector(
    String^ repCapName,
    String^ selector
)

Parameters

repCapName
Type: SystemString
selector
Type: SystemString

Return Value

Type: IList PhysicalName
See Also

Reference

DriverNode Class
MindWorks.Nimbus Namespace


DriverNode.ExpandSingleSelector Method

Pacific MindWorks Nimbus Driver Studio

DriverNodeExpandSingleSelector Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal virtual PhysicalName ExpandSingleSelector(
    string repCapName,
    string selector
)
internal:
virtual PhysicalName^ ExpandSingleSelector(
    String^ repCapName,
    String^ selector
)

Parameters

repCapName
Type: SystemString
selector
Type: SystemString

Return Value

Type: PhysicalName
See Also

Reference

DriverNode Class
MindWorks.Nimbus Namespace


DriverNode.GetActivePhysicalName Method

Pacific MindWorks Nimbus Driver Studio

DriverNodeGetActivePhysicalName Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal virtual PhysicalName GetActivePhysicalName(
    string repCapName
)
internal:
virtual PhysicalName^ GetActivePhysicalName(
    String^ repCapName
)

Parameters

repCapName
Type: SystemString

Return Value

Type: PhysicalName
See Also

Reference

DriverNode Class
MindWorks.Nimbus Namespace


DriverNode.GetActivePhysicalNames Method

Pacific MindWorks Nimbus Driver Studio

DriverNodeGetActivePhysicalNames Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal virtual IList<PhysicalName> GetActivePhysicalNames(
    string repCapName
)
internal:
virtual IList<PhysicalName^>^ GetActivePhysicalNames(
    String^ repCapName
)

Parameters

repCapName
Type: SystemString

Return Value

Type: IList PhysicalName
See Also

Reference

DriverNode Class
MindWorks.Nimbus Namespace


DriverNode.GetCacheValue Method

Pacific MindWorks Nimbus Driver Studio

DriverNodeGetCacheValue Method

Overload List
 | Name | Description
Protected method | GetCacheValueT(T) |
Protected method | GetCacheValue(Object) |
Protected method | GetCacheValueT(String, T) |
Top
See Also

Reference

DriverNode Class
MindWorks.Nimbus Namespace


DriverNode.GetCacheValue(T) Method (T)

Pacific MindWorks Nimbus Driver Studio

DriverNodeGetCacheValueT Method (T)

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected virtual bool GetCacheValue<T>(
    out T value
)

protected:
generic<typename T>
virtual bool GetCacheValue(
    [OutAttribute] T% value
)

Parameters

value
Type: T

Type Parameters

T

Return Value

Type: Boolean
See Also

Reference

DriverNode Class
GetCacheValue Overload
MindWorks.Nimbus Namespace


DriverNode.GetCacheValue Method (Object)

Pacific MindWorks Nimbus Driver Studio

DriverNodeGetCacheValue Method (Object)

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected virtual bool GetCacheValue(
    out Object value
)
protected:
virtual bool GetCacheValue(
    [OutAttribute] Object^% value
)

Parameters

value
Type: SystemObject

Return Value

Type: Boolean
See Also

Reference

DriverNode Class
GetCacheValue Overload
MindWorks.Nimbus Namespace


DriverNode.GetCacheValue(T) Method (String, T)

Pacific MindWorks Nimbus Driver Studio

DriverNodeGetCacheValueT Method (String, T)

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected virtual bool GetCacheValue<T>(
    string key,
    out T value
)

protected:
generic<typename T>
virtual bool GetCacheValue(
    String^ key,
    [OutAttribute] T% value
)

Parameters

key
Type: SystemString
value
Type: T

Type Parameters

T

Return Value

Type: Boolean
See Also

Reference

DriverNode Class
GetCacheValue Overload
MindWorks.Nimbus Namespace


DriverNode.GetDefaultValueForSimulation Method

Pacific MindWorks Nimbus Driver Studio

DriverNodeGetDefaultValueForSimulation Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected virtual Object GetDefaultValueForSimulation(
    Type targetType,
    string defaultValue
)
protected:
virtual Object^ GetDefaultValueForSimulation(
    Type^ targetType,
    String^ defaultValue
)

Parameters

targetType
Type: SystemType
defaultValue
Type: SystemString

Return Value

Type: Object
See Also

Reference

DriverNode Class
MindWorks.Nimbus Namespace


DriverNode.GetDynamicRepCapNames Method

Pacific MindWorks Nimbus Driver Studio

DriverNodeGetDynamicRepCapNames Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected virtual void GetDynamicRepCapNames(
    string repCapName,
    IList<string> physicalNames
)
protected:
virtual void GetDynamicRepCapNames(
    String^ repCapName,
    IList<String^>^ physicalNames
)

Parameters

repCapName
Type: SystemString
physicalNames
Type: System.Collections.GenericIList String
See Also

Reference

DriverNode Class
MindWorks.Nimbus Namespace


DriverNode.GetRepCapCollectionInterfaceImplementedByType Method

Pacific MindWorks Nimbus Driver Studio

DriverNodeGetRepCapCollectionInterfaceImplementedByType Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static Type GetRepCapCollectionInterfaceImplementedByType(
    Type type
)
internal:
static Type^ GetRepCapCollectionInterfaceImplementedByType(
    Type^ type
)

Parameters

type
Type: SystemType

Return Value

Type: Type
See Also

Reference

DriverNode Class
MindWorks.Nimbus Namespace


DriverNode.GetRepCapManager Method

Pacific MindWorks Nimbus Driver Studio

DriverNodeGetRepCapManager Method

Overload List
 | Name | Description
Protected method | GetRepCapManager(String) |
Protected method | GetRepCapManagerT(String) |
Top
See Also

Reference

DriverNode Class
MindWorks.Nimbus Namespace


DriverNode.GetRepCapManager Method (String)

Pacific MindWorks Nimbus Driver Studio

DriverNodeGetRepCapManager Method (String)

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal virtual RepCapManager GetRepCapManager(
    string repCapName
)
internal:
virtual RepCapManager^ GetRepCapManager(
    String^ repCapName
)

Parameters

repCapName
Type: SystemString

Return Value

Type: RepCapManager
See Also

Reference

DriverNode Class
GetRepCapManager Overload
MindWorks.Nimbus Namespace


DriverNode.GetRepCapManager(T) Method (String)

Pacific MindWorks Nimbus Driver Studio

DriverNodeGetRepCapManagerT Method (String)

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal virtual T GetRepCapManager<T>(
    string repCapName
)
where T : RepCapManager

internal:
generic<typename T>
where T : RepCapManager
virtual T GetRepCapManager(
    String^ repCapName
)

Parameters

repCapName
Type: SystemString

Type Parameters

T

Return Value

Type: T
See Also

Reference

DriverNode Class
GetRepCapManager Overload
MindWorks.Nimbus Namespace


DriverNode.InitNode Method

Pacific MindWorks Nimbus Driver Studio

DriverNodeInitNode Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal virtual void InitNode()
internal:
virtual void InitNode()
See Also

Reference

DriverNode Class
MindWorks.Nimbus Namespace


DriverNode.InstrumentInFamily Method

Pacific MindWorks Nimbus Driver Studio

DriverNodeInstrumentInFamily Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected virtual bool InstrumentInFamily(
    string family
)
protected:
virtual bool InstrumentInFamily(
    String^ family
)

Parameters

family
Type: SystemString

Return Value

Type: Boolean
See Also

Reference

DriverNode Class
MindWorks.Nimbus Namespace


DriverNode.InstrumentIsModel Method

Pacific MindWorks Nimbus Driver Studio

DriverNodeInstrumentIsModel Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected virtual bool InstrumentIsModel(
    string model
)
protected:
virtual bool InstrumentIsModel(
    String^ model
)

Parameters

model
Type: SystemString

Return Value

Type: Boolean
See Also

Reference

DriverNode Class
MindWorks.Nimbus Namespace


DriverNode.InvalidateAllCacheEntries Method

Pacific MindWorks Nimbus Driver Studio

DriverNodeInvalidateAllCacheEntries Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected virtual void InvalidateAllCacheEntries()
protected:
virtual void InvalidateAllCacheEntries()
See Also

Reference

DriverNode Class
MindWorks.Nimbus Namespace


DriverNode.InvalidateCacheEntry Method

Pacific MindWorks Nimbus Driver Studio

DriverNodeInvalidateCacheEntry Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected virtual void InvalidateCacheEntry(
    string key
)
protected:
virtual void InvalidateCacheEntry(
    String^ key
)

Parameters

key
Type: SystemString
See Also

Reference

DriverNode Class
MindWorks.Nimbus Namespace


DriverNode.PollInstrumentErrors Method

Pacific MindWorks Nimbus Driver Studio

DriverNodePollInstrumentErrors Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected virtual void PollInstrumentErrors()
protected:
virtual void PollInstrumentErrors()
See Also

Reference

DriverNode Class
MindWorks.Nimbus Namespace


DriverNode.RemovePhysicalName Method

Pacific MindWorks Nimbus Driver Studio

DriverNodeRemovePhysicalName Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal virtual void RemovePhysicalName(
    string repCapName,
    string fullPhysicalName
)
internal:
virtual void RemovePhysicalName(
    String^ repCapName,
    String^ fullPhysicalName
)

Parameters

repCapName
Type: SystemString
fullPhysicalName
Type: SystemString
See Also

Reference

DriverNode Class
MindWorks.Nimbus Namespace


DriverNode.ResetObjectState Method

Pacific MindWorks Nimbus Driver Studio

DriverNodeResetObjectState Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected virtual void ResetObjectState()
protected:
virtual void ResetObjectState()
See Also

Reference

DriverNode Class
MindWorks.Nimbus Namespace


DriverNode.SendCoercionEvent Method

Pacific MindWorks Nimbus Driver Studio

DriverNodeSendCoercionEvent Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected virtual void SendCoercionEvent(
    Object originalValue,
    Object coercedValue
)
protected:
virtual void SendCoercionEvent(
    Object^ originalValue,
    Object^ coercedValue
)

Parameters

originalValue
Type: SystemObject
coercedValue
Type: SystemObject
See Also

Reference

DriverNode Class
MindWorks.Nimbus Namespace


DriverNode.SendInterchangeEvent Method

Pacific MindWorks Nimbus Driver Studio

DriverNodeSendInterchangeEvent Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected virtual void SendInterchangeEvent(
    InterchangeCheckWarningEventArgs args
)
protected:
virtual void SendInterchangeEvent(
    InterchangeCheckWarningEventArgs^ args
)

Parameters

args
Type: InterchangeCheckWarningEventArgs
See Also

Reference

DriverNode Class
MindWorks.Nimbus Namespace


DriverNode.SendWarningEvent Method

Pacific MindWorks Nimbus Driver Studio

DriverNodeSendWarningEvent Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected virtual void SendWarningEvent(
    WarningEventArgs args
)
protected:
virtual void SendWarningEvent(
    WarningEventArgs^ args
)

Parameters

args
Type: WarningEventArgs
See Also

Reference

DriverNode Class
MindWorks.Nimbus Namespace


DriverNode.TryConvertEnumToString Method

Pacific MindWorks Nimbus Driver Studio

DriverNodeTryConvertEnumToString Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal virtual bool TryConvertEnumToString(
    Enum member,
    out string result
)
internal:
virtual bool TryConvertEnumToString(
    Enum^ member,
    [OutAttribute] String^% result
)

Parameters

member
Type: SystemEnum
result
Type: SystemString

Return Value

Type: Boolean
See Also

Reference

DriverNode Class
MindWorks.Nimbus Namespace


DriverNode.TryConvertStringToEnum(TEnum) Method

Pacific MindWorks Nimbus Driver Studio

DriverNodeTryConvertStringToEnumTEnum Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal bool TryConvertStringToEnum<TEnum>(
    string data,
    out Enum member
)

internal:
generic<typename TEnum>
bool TryConvertStringToEnum(
    String^ data,
    [OutAttribute] Enum^% member
)

Parameters

data
Type: SystemString
member
Type: SystemEnum

Type Parameters

TEnum

Return Value

Type: Boolean
See Also

Reference

DriverNode Class
MindWorks.Nimbus Namespace


DriverNode.UpdateCacheValue Method

Pacific MindWorks Nimbus Driver Studio

DriverNodeUpdateCacheValue Method

Overload List
 | Name | Description
Protected method | UpdateCacheValue(Object) |
Protected method | UpdateCacheValue(String, Object) |
Top
See Also

Reference

DriverNode Class
MindWorks.Nimbus Namespace


DriverNode.UpdateCacheValue Method (Object)

Pacific MindWorks Nimbus Driver Studio

DriverNodeUpdateCacheValue Method (Object)

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected virtual void UpdateCacheValue(
    Object value
)
protected:
virtual void UpdateCacheValue(
    Object^ value
)

Parameters

value
Type: SystemObject
See Also

Reference

DriverNode Class
UpdateCacheValue Overload
MindWorks.Nimbus Namespace


DriverNode.UpdateCacheValue Method (String, Object)

Pacific MindWorks Nimbus Driver Studio

DriverNodeUpdateCacheValue Method (String, Object)

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected virtual void UpdateCacheValue(
    string key,
    Object value
)
protected:
virtual void UpdateCacheValue(
    String^ key,
    Object^ value
)

Parameters

key
Type: SystemString
value
Type: SystemObject
See Also

Reference

DriverNode Class
UpdateCacheValue Overload
MindWorks.Nimbus Namespace


DriverNodeHelper Class

Inheritance Hierarchy
SystemObject
MindWorks.NimbusDriverNodeHelper

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal class DriverNodeHelper
internal ref class DriverNodeHelper

The DriverNodeHelper type exposes the following members.

Constructors
 | Name | Description
Public method | DriverNodeHelper | Initializes a new instance of the DriverNodeHelper class
Top
See Also

Reference

MindWorks.Nimbus Namespace


DriverNodeHelper Constructor

Initializes a new instance of the DriverNodeHelper class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public DriverNodeHelper()
public:
DriverNodeHelper()
See Also

Reference

DriverNodeHelper Class
MindWorks.Nimbus Namespace


DriverPropertyAttribute Class

Inheritance Hierarchy
SystemObject
SystemAttribute
MindWorks.NimbusNimbusAttribute
MindWorks.NimbusNimbusCodeWeaverAttribute
MindWorks.NimbusDriverMemberAttribute
MindWorks.NimbusDriverPropertyAttribute

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal sealed class DriverPropertyAttribute : DriverMemberAttribute
internal ref class DriverPropertyAttribute sealed : public DriverMemberAttribute

The DriverPropertyAttribute type exposes the following members.

Constructors
 | Name | Description
Protected method | DriverPropertyAttribute | Initializes a new instance of the DriverPropertyAttribute class
Top
Properties
 | Name | Description
Public property | Lock | (Inherited from DriverMemberAttribute.)
Public property | LockTimeoutMilliseconds | (Inherited from DriverMemberAttribute.)
Public property | SuppressAll | (Inherited from NimbusCodeWeaverAttribute.)
Public property | SuppressObjectDisposedCheck | (Inherited from DriverMemberAttribute.)
Public property | SuppressPollInstrumentErrors | (Inherited from DriverMemberAttribute.)
Top
See Also

Reference

MindWorks.Nimbus Namespace


DriverPropertyAttribute Constructor

Initializes a new instance of the DriverPropertyAttribute class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal DriverPropertyAttribute()
internal:
DriverPropertyAttribute()
See Also

Reference

DriverPropertyAttribute Class
MindWorks.Nimbus Namespace


DriverPropertyAttribute Properties

The DriverPropertyAttribute type exposes the following members.

Properties
 | Name | Description
Public property | Lock | (Inherited from DriverMemberAttribute.)
Public property | LockTimeoutMilliseconds | (Inherited from DriverMemberAttribute.)
Public property | SuppressAll | (Inherited from NimbusCodeWeaverAttribute.)
Public property | SuppressObjectDisposedCheck | (Inherited from DriverMemberAttribute.)
Public property | SuppressPollInstrumentErrors | (Inherited from DriverMemberAttribute.)
Top
See Also

Reference

DriverPropertyAttribute Class
MindWorks.Nimbus Namespace


DriverSessionAttribute Class

Inheritance Hierarchy
SystemObject
SystemAttribute
MindWorks.NimbusNimbusAttribute
MindWorks.NimbusDriverSessionAttribute

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal sealed class DriverSessionAttribute : NimbusAttribute
internal ref class DriverSessionAttribute sealed : public NimbusAttribute

The DriverSessionAttribute type exposes the following members.

Constructors
 | Name | Description
Protected method | DriverSessionAttribute | Initializes a new instance of the DriverSessionAttribute class
Top
Properties
 | Name | Description
Public property | Cache |
Public property | DriverSetup |
Public property | HardwareAsset |
Public property | InterchangeCheck |
Public property | QueryInstrumentStatus |
Public property | RangeCheck |
Public property | RecordCoercions |
Protected property | SessionName |
Public property | Simulate |
Top
See Also

Reference

MindWorks.Nimbus Namespace


DriverSessionAttribute Constructor

Initializes a new instance of the DriverSessionAttribute class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal DriverSessionAttribute(
    string sessionName
)
internal:
DriverSessionAttribute(
    String^ sessionName
)

Parameters

sessionName
Type: SystemString
See Also

Reference

DriverSessionAttribute Class
MindWorks.Nimbus Namespace


DriverSessionAttribute Properties

The DriverSessionAttribute type exposes the following members.

Properties
 | Name | Description
Public property | Cache |
Public property | DriverSetup |
Public property | HardwareAsset |
Public property | InterchangeCheck |
Public property | QueryInstrumentStatus |
Public property | RangeCheck |
Public property | RecordCoercions |
Protected property | SessionName |
Public property | Simulate |
Top
See Also

Reference

DriverSessionAttribute Class
MindWorks.Nimbus Namespace


DriverSessionAttribute.Cache Property

Pacific MindWorks Nimbus Driver Studio

DriverSessionAttributeCache Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public bool Cache { get; set; }
public:
property bool Cache {
    bool get ();
    void set (bool value);
}

Property Value

Type: Boolean
See Also

Reference

DriverSessionAttribute Class
MindWorks.Nimbus Namespace


DriverSessionAttribute.DriverSetup Property

Pacific MindWorks Nimbus Driver Studio

DriverSessionAttributeDriverSetup Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public string DriverSetup { get; set; }
public:
property String^ DriverSetup {
    String^ get ();
    void set (String^ value);
}

Property Value

Type: String
See Also

Reference

DriverSessionAttribute Class
MindWorks.Nimbus Namespace


DriverSessionAttribute.HardwareAsset Property

Pacific MindWorks Nimbus Driver Studio

DriverSessionAttributeHardwareAsset Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public string HardwareAsset { get; set; }
public:
property String^ HardwareAsset {
    String^ get ();
    void set (String^ value);
}

Property Value

Type: String
See Also

Reference

DriverSessionAttribute Class
MindWorks.Nimbus Namespace


DriverSessionAttribute.InterchangeCheck Property

Pacific MindWorks Nimbus Driver Studio

DriverSessionAttributeInterchangeCheck Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public bool InterchangeCheck { get; set; }
public:
property bool InterchangeCheck {
    bool get ();
    void set (bool value);
}

Property Value

Type: Boolean
See Also

Reference

DriverSessionAttribute Class
MindWorks.Nimbus Namespace


DriverSessionAttribute.QueryInstrumentStatus Property

Pacific MindWorks Nimbus Driver Studio

DriverSessionAttributeQueryInstrumentStatus Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public bool QueryInstrumentStatus { get; set; }
public:
property bool QueryInstrumentStatus {
    bool get ();
    void set (bool value);
}

Property Value

Type: Boolean
See Also

Reference

DriverSessionAttribute Class
MindWorks.Nimbus Namespace


DriverSessionAttribute.RangeCheck Property

Pacific MindWorks Nimbus Driver Studio

DriverSessionAttributeRangeCheck Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public bool RangeCheck { get; set; }
public:
property bool RangeCheck {
    bool get ();
    void set (bool value);
}

Property Value

Type: Boolean
See Also

Reference

DriverSessionAttribute Class
MindWorks.Nimbus Namespace


DriverSessionAttribute.RecordCoercions Property

Pacific MindWorks Nimbus Driver Studio

DriverSessionAttributeRecordCoercions Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public bool RecordCoercions { get; set; }
public:
property bool RecordCoercions {
    bool get ();
    void set (bool value);
}

Property Value

Type: Boolean
See Also

Reference

DriverSessionAttribute Class
MindWorks.Nimbus Namespace


DriverSessionAttribute.SessionName Property

Pacific MindWorks Nimbus Driver Studio

DriverSessionAttributeSessionName Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal string SessionName { get; }
internal:
property String^ SessionName {
    String^ get ();
}

Property Value

Type: String
See Also

Reference

DriverSessionAttribute Class
MindWorks.Nimbus Namespace


DriverSessionAttribute.Simulate Property

Pacific MindWorks Nimbus Driver Studio

DriverSessionAttributeSimulate Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public bool Simulate { get; set; }
public:
property bool Simulate {
    bool get ();
    void set (bool value);
}

Property Value

Type: Boolean
See Also

Reference

DriverSessionAttribute Class
MindWorks.Nimbus Namespace


EnumCommandAttribute Class

Inheritance Hierarchy
SystemObject
SystemAttribute
MindWorks.NimbusNimbusAttribute
MindWorks.NimbusModelSpecificNimbusAttribute
MindWorks.NimbusEnumCommandAttribute

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal sealed class EnumCommandAttribute : ModelSpecificNimbusAttribute
internal ref class EnumCommandAttribute sealed : public ModelSpecificNimbusAttribute

The EnumCommandAttribute type exposes the following members.

Constructors
 | Name | Description
Protected method | EnumCommandAttribute | Initializes a new instance of the EnumCommandAttribute class
Top
Properties
 | Name | Description
Public property | AdditionalResponses |
Public property | Command |
Public property | EnumType |
Public property | MemberValue |
Public property | Models | (Inherited from ModelSpecificNimbusAttribute.)
Top
See Also

Reference

MindWorks.Nimbus Namespace


EnumCommandAttribute Constructor

Initializes a new instance of the EnumCommandAttribute class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal EnumCommandAttribute(
    Type enumType,
    int memberValue,
    string command,
    params string[] models
)
internal:
EnumCommandAttribute(
    Type^ enumType,
    int memberValue,
    String^ command,
    ... array<String^>^ models
)

Parameters

enumType
Type: SystemType
memberValue
Type: SystemInt32
command
Type: SystemString
models
Type: SystemString
See Also

Reference

EnumCommandAttribute Class
MindWorks.Nimbus Namespace


EnumCommandAttribute Properties

The EnumCommandAttribute type exposes the following members.

Properties
 | Name | Description
Public property | AdditionalResponses |
Public property | Command |
Public property | EnumType |
Public property | MemberValue |
Public property | Models | (Inherited from ModelSpecificNimbusAttribute.)
Top
See Also

Reference

EnumCommandAttribute Class
MindWorks.Nimbus Namespace


EnumCommandAttribute.AdditionalResponses Property

Pacific MindWorks Nimbus Driver Studio

EnumCommandAttributeAdditionalResponses Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public string AdditionalResponses { get; set; }
public:
property String^ AdditionalResponses {
    String^ get ();
    void set (String^ value);
}

Property Value

Type: String
See Also

Reference

EnumCommandAttribute Class
MindWorks.Nimbus Namespace


EnumCommandAttribute.Command Property

Pacific MindWorks Nimbus Driver Studio

EnumCommandAttributeCommand Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public string Command { get; }
public:
property String^ Command {
    String^ get ();
}

Property Value

Type: String
See Also

Reference

EnumCommandAttribute Class
MindWorks.Nimbus Namespace


EnumCommandAttribute.EnumType Property

Pacific MindWorks Nimbus Driver Studio

EnumCommandAttributeEnumType Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public Type EnumType { get; }
public:
property Type^ EnumType {
    Type^ get ();
}

Property Value

Type: Type
See Also

Reference

EnumCommandAttribute Class
MindWorks.Nimbus Namespace


EnumCommandAttribute.MemberValue Property

Pacific MindWorks Nimbus Driver Studio

EnumCommandAttributeMemberValue Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public int MemberValue { get; }
public:
property int MemberValue {
    int get ();
}

Property Value

Type: Int32
See Also

Reference

EnumCommandAttribute Class
MindWorks.Nimbus Namespace


ErrorService Class

Inheritance Hierarchy
SystemObject
MindWorks.NimbusErrorService

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static class ErrorService
internal ref class ErrorService abstract sealed

The ErrorService type exposes the following members.

Methods
Name | Description
ConfigurationServer |
ConfigurationStoreLoad |
DataArrayTooSmall |
FileFormat |
IdQuery |
InstrumentStatus |
InvalidOptionValue |
InvalidSpectrumDataType |
InvalidSpectrumDataType(String) |
InvalidWaveformDataType |
InvalidWaveformDataType(String) |
IO |
IOTimeout |
MaxTimeExceeded |
NotATime |
ObjectDisposed |
OperationNotAvailableInSimulationMode |
OperationNotSupported |
OperationNotSupportedForModel |
OperationPending |
OptionMissing |
OptionStringFormat |
OutOfRange(String, String, Array) |
OutOfRange(String, String, String) |
OutOfRange(String, String, Double, Double, Boolean, Boolean) |
ResetFailed |
ResetNotSupported |
SelectorFormat |
SelectorHierarchy |
SelectorName |
SelectorNameRequired |
SelectorRange |
SimulationState |
SoftwareModuleNotFound |
TriggerNotSoftware |
TriggerNotSoftware(String) |
UnexpectedResponse |
UnexpectedResponse(String) |
UnknownOption |
UnknownPhysicalName |
ValidPointCountExceedsCapacity |
ValueNotSupported |
Top
See Also

Reference

MindWorks.Nimbus Namespace


ErrorService Methods

The ErrorService type exposes the following members.

Methods
Name | Description
ConfigurationServer |
ConfigurationStoreLoad |
DataArrayTooSmall |
FileFormat |
IdQuery |
InstrumentStatus |
InvalidOptionValue |
InvalidSpectrumDataType |
InvalidSpectrumDataType(String) |
InvalidWaveformDataType |
InvalidWaveformDataType(String) |
IO |
IOTimeout |
MaxTimeExceeded |
NotATime |
ObjectDisposed |
OperationNotAvailableInSimulationMode |
OperationNotSupported |
OperationNotSupportedForModel |
OperationPending |
OptionMissing |
OptionStringFormat |
OutOfRange(String, String, Array) |
OutOfRange(String, String, String) |
OutOfRange(String, String, Double, Double, Boolean, Boolean) |
ResetFailed |
ResetNotSupported |
SelectorFormat |
SelectorHierarchy |
SelectorName |
SelectorNameRequired |
SelectorRange |
SimulationState |
SoftwareModuleNotFound |
TriggerNotSoftware |
TriggerNotSoftware(String) |
UnexpectedResponse |
UnexpectedResponse(String) |
UnknownOption |
UnknownPhysicalName |
ValidPointCountExceedsCapacity |
ValueNotSupported |
Top
See Also

Reference

ErrorService Class
MindWorks.Nimbus Namespace


ErrorService.ConfigurationServer Method

Pacific MindWorks Nimbus Driver Studio

ErrorServiceConfigurationServer Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static Exception ConfigurationServer(
    Exception innerException
)
internal:
static Exception^ ConfigurationServer(
    Exception^ innerException
)

Parameters

innerException
Type: SystemException

Return Value

Type: Exception
See Also

Reference

ErrorService Class
MindWorks.Nimbus Namespace


ErrorService.ConfigurationStoreLoad Method

Pacific MindWorks Nimbus Driver Studio

ErrorServiceConfigurationStoreLoad Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static Exception ConfigurationStoreLoad(
    Exception innerException
)
internal:
static Exception^ ConfigurationStoreLoad(
    Exception^ innerException
)

Parameters

innerException
Type: SystemException

Return Value

Type: Exception
See Also

Reference

ErrorService Class
MindWorks.Nimbus Namespace


ErrorService.DataArrayTooSmall Method

Pacific MindWorks Nimbus Driver Studio

ErrorServiceDataArrayTooSmall Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static Exception DataArrayTooSmall(
    string measuredElements,
    string capacity
)
internal:
static Exception^ DataArrayTooSmall(
    String^ measuredElements,
    String^ capacity
)

Parameters

measuredElements
Type: SystemString
capacity
Type: SystemString

Return Value

Type: Exception
See Also

Reference

ErrorService Class
MindWorks.Nimbus Namespace


ErrorService.FileFormat Method

Pacific MindWorks Nimbus Driver Studio

ErrorServiceFileFormat Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static Exception FileFormat(
    Uri uri
)
internal:
static Exception^ FileFormat(
    Uri^ uri
)

Parameters

uri
Type: SystemUri

Return Value

Type: Exception
See Also

Reference

ErrorService Class
MindWorks.Nimbus Namespace


ErrorService.IdQuery Method

Pacific MindWorks Nimbus Driver Studio

ErrorServiceIdQuery Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static Exception IdQuery()
internal:
static Exception^ IdQuery()

Return Value

Type: Exception
See Also

Reference

ErrorService Class
MindWorks.Nimbus Namespace


ErrorService.InstrumentStatus Method

Pacific MindWorks Nimbus Driver Studio

ErrorServiceInstrumentStatus Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static Exception InstrumentStatus()
internal:
static Exception^ InstrumentStatus()

Return Value

Type: Exception
See Also

Reference

ErrorService Class
MindWorks.Nimbus Namespace


ErrorService.InvalidOptionValue Method

Pacific MindWorks Nimbus Driver Studio

ErrorServiceInvalidOptionValue Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static Exception InvalidOptionValue(
    string optionName,
    string optionValue
)
internal:
static Exception^ InvalidOptionValue(
    String^ optionName,
    String^ optionValue
)

Parameters

optionName
Type: SystemString
optionValue
Type: SystemString

Return Value

Type: Exception
See Also

Reference

ErrorService Class
MindWorks.Nimbus Namespace


ErrorService.InvalidSpectrumDataType Method

Pacific MindWorks Nimbus Driver Studio

ErrorServiceInvalidSpectrumDataType Method

Overload List
Name | Description
InvalidSpectrumDataType |
InvalidSpectrumDataType(String) |
Top
See Also

Reference

ErrorService Class
MindWorks.Nimbus Namespace


ErrorService.InvalidSpectrumDataType Method

Pacific MindWorks Nimbus Driver Studio

ErrorServiceInvalidSpectrumDataType Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static Exception InvalidSpectrumDataType()
internal:
static Exception^ InvalidSpectrumDataType()

Return Value

Type: Exception
See Also

Reference

ErrorService Class
InvalidSpectrumDataType Overload
MindWorks.Nimbus Namespace


ErrorService.InvalidSpectrumDataType Method (String)

Pacific MindWorks Nimbus Driver Studio

ErrorServiceInvalidSpectrumDataType Method (String)

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static Exception InvalidSpectrumDataType(
    string type
)
internal:
static Exception^ InvalidSpectrumDataType(
    String^ type
)

Parameters

type
Type: SystemString

Return Value

Type: Exception
See Also

Reference

ErrorService Class
InvalidSpectrumDataType Overload
MindWorks.Nimbus Namespace


ErrorService.InvalidWaveformDataType Method

Pacific MindWorks Nimbus Driver Studio

ErrorServiceInvalidWaveformDataType Method

Overload List
Name | Description
InvalidWaveformDataType |
InvalidWaveformDataType(String) |
Top
See Also

Reference

ErrorService Class
MindWorks.Nimbus Namespace


ErrorService.InvalidWaveformDataType Method

Pacific MindWorks Nimbus Driver Studio

ErrorServiceInvalidWaveformDataType Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static Exception InvalidWaveformDataType()
internal:
static Exception^ InvalidWaveformDataType()

Return Value

Type: Exception
See Also

Reference

ErrorService Class
InvalidWaveformDataType Overload
MindWorks.Nimbus Namespace


ErrorService.InvalidWaveformDataType Method (String)

Pacific MindWorks Nimbus Driver Studio

ErrorServiceInvalidWaveformDataType Method (String)

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static Exception InvalidWaveformDataType(
    string type
)
internal:
static Exception^ InvalidWaveformDataType(
    String^ type
)

Parameters

type
Type: SystemString

Return Value

Type: Exception
See Also

Reference

ErrorService Class
InvalidWaveformDataType Overload
MindWorks.Nimbus Namespace


ErrorService.IO Method

Pacific MindWorks Nimbus Driver Studio

ErrorServiceIO Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static Exception IO(
    Exception innerException
)
internal:
static Exception^ IO(
    Exception^ innerException
)

Parameters

innerException
Type: SystemException

Return Value

Type: Exception
See Also

Reference

ErrorService Class
MindWorks.Nimbus Namespace


ErrorService.IOTimeout Method

Pacific MindWorks Nimbus Driver Studio

ErrorServiceIOTimeout Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static Exception IOTimeout(
    string timeout
)
internal:
static Exception^ IOTimeout(
    String^ timeout
)

Parameters

timeout
Type: SystemString

Return Value

Type: Exception
See Also

Reference

ErrorService Class
MindWorks.Nimbus Namespace


ErrorService.MaxTimeExceeded Method

Pacific MindWorks Nimbus Driver Studio

ErrorServiceMaxTimeExceeded Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static Exception MaxTimeExceeded(
    string timeout
)
internal:
static Exception^ MaxTimeExceeded(
    String^ timeout
)

Parameters

timeout
Type: SystemString

Return Value

Type: Exception
See Also

Reference

ErrorService Class
MindWorks.Nimbus Namespace


ErrorService.NotATime Method

Pacific MindWorks Nimbus Driver Studio

ErrorServiceNotATime Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static Exception NotATime(
    string paramName
)
internal:
static Exception^ NotATime(
    String^ paramName
)

Parameters

paramName
Type: SystemString

Return Value

Type: Exception
See Also

Reference

ErrorService Class
MindWorks.Nimbus Namespace


ErrorService.ObjectDisposed Method

Pacific MindWorks Nimbus Driver Studio

ErrorServiceObjectDisposed Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static Exception ObjectDisposed(
    string objectName
)
internal:
static Exception^ ObjectDisposed(
    String^ objectName
)

Parameters

objectName
Type: SystemString

Return Value

Type: Exception
See Also

Reference

ErrorService Class
MindWorks.Nimbus Namespace


ErrorService.OperationNotAvailableInSimulationMode Method

Pacific MindWorks Nimbus Driver Studio

ErrorServiceOperationNotAvailableInSimulationMode Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static Exception OperationNotAvailableInSimulationMode(
    string operation
)
internal:
static Exception^ OperationNotAvailableInSimulationMode(
    String^ operation
)

Parameters

operation
Type: SystemString

Return Value

Type: Exception
See Also

Reference

ErrorService Class
MindWorks.Nimbus Namespace


ErrorService.OperationNotSupported Method

Pacific MindWorks Nimbus Driver Studio

ErrorServiceOperationNotSupported Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static Exception OperationNotSupported(
    string typeName,
    string methodName
)
internal:
static Exception^ OperationNotSupported(
    String^ typeName,
    String^ methodName
)

Parameters

typeName
Type: SystemString
methodName
Type: SystemString

Return Value

Type: Exception
See Also

Reference

ErrorService Class
MindWorks.Nimbus Namespace


ErrorService.OperationNotSupportedForModel Method

Pacific MindWorks Nimbus Driver Studio

ErrorServiceOperationNotSupportedForModel Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static Exception OperationNotSupportedForModel(
    string typeName,
    string methodName,
    string model
)
internal:
static Exception^ OperationNotSupportedForModel(
    String^ typeName,
    String^ methodName,
    String^ model
)

Parameters

typeName
Type: SystemString
methodName
Type: SystemString
model
Type: SystemString

Return Value

Type: Exception
See Also

Reference

ErrorService Class
MindWorks.Nimbus Namespace


ErrorService.OperationPending Method

Pacific MindWorks Nimbus Driver Studio

ErrorServiceOperationPending Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static Exception OperationPending()
internal:
static Exception^ OperationPending()

Return Value

Type: Exception
See Also

Reference

ErrorService Class
MindWorks.Nimbus Namespace


ErrorService.OptionMissing Method

Pacific MindWorks Nimbus Driver Studio

ErrorServiceOptionMissing Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static Exception OptionMissing(
    string optionName
)
internal:
static Exception^ OptionMissing(
    String^ optionName
)

Parameters

optionName
Type: SystemString

Return Value

Type: Exception
See Also

Reference

ErrorService Class
MindWorks.Nimbus Namespace


ErrorService.OptionStringFormat Method

Pacific MindWorks Nimbus Driver Studio

ErrorServiceOptionStringFormat Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static Exception OptionStringFormat()
internal:
static Exception^ OptionStringFormat()

Return Value

Type: Exception
See Also

Reference

ErrorService Class
MindWorks.Nimbus Namespace


ErrorService.OutOfRange Method

Pacific MindWorks Nimbus Driver Studio

ErrorServiceOutOfRange Method

Overload List
Name | Description
OutOfRange(String, String, Array) |
OutOfRange(String, String, String) |
OutOfRange(String, String, Double, Double, Boolean, Boolean) |
Top
See Also

Reference

ErrorService Class
MindWorks.Nimbus Namespace


ErrorService.OutOfRange Method (String, String, Array)

Pacific MindWorks Nimbus Driver Studio

ErrorServiceOutOfRange Method (String, String, Array)

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static Exception OutOfRange(
    string parameterName,
    string parameterValue,
    Array allowedValues
)
internal:
static Exception^ OutOfRange(
    String^ parameterName,
    String^ parameterValue,
    Array^ allowedValues
)

Parameters

parameterName
Type: SystemString
parameterValue
Type: SystemString
allowedValues
Type: SystemArray

Return Value

Type: Exception
See Also

Reference

ErrorService Class
OutOfRange Overload
MindWorks.Nimbus Namespace


ErrorService.OutOfRange Method (String, String, String)

Pacific MindWorks Nimbus Driver Studio

ErrorServiceOutOfRange Method (String, String, String)

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static Exception OutOfRange(
    string parameterName,
    string parameterValue,
    string allowedRange
)
internal:
static Exception^ OutOfRange(
    String^ parameterName,
    String^ parameterValue,
    String^ allowedRange
)

Parameters

parameterName
Type: SystemString
parameterValue
Type: SystemString
allowedRange
Type: SystemString

Return Value

Type: Exception
See Also

Reference

ErrorService Class
OutOfRange Overload
MindWorks.Nimbus Namespace


ErrorService.OutOfRange Method (String, String, Double, Double, Boolean, Boolean)

Pacific MindWorks Nimbus Driver Studio

ErrorServiceOutOfRange Method (String, String, Double, Double, Boolean, Boolean)

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static Exception OutOfRange(
    string parameterName,
    string parameterValue,
    double min,
    double max,
    bool minInclusive,
    bool maxInclusive
)
internal:
static Exception^ OutOfRange(
    String^ parameterName,
    String^ parameterValue,
    double min,
    double max,
    bool minInclusive,
    bool maxInclusive
)

Parameters

parameterName
Type: SystemString
parameterValue
Type: SystemString
min
Type: SystemDouble
max
Type: SystemDouble
minInclusive
Type: SystemBoolean
maxInclusive
Type: SystemBoolean

Return Value

Type: Exception
See Also

Reference

ErrorService Class
OutOfRange Overload
MindWorks.Nimbus Namespace


ErrorService.ResetFailed Method

Pacific MindWorks Nimbus Driver Studio

ErrorServiceResetFailed Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static Exception ResetFailed(
    Exception innerException
)
internal:
static Exception^ ResetFailed(
    Exception^ innerException
)

Parameters

innerException
Type: SystemException

Return Value

Type: Exception
See Also

Reference

ErrorService Class
MindWorks.Nimbus Namespace


ErrorService.ResetNotSupported Method

Pacific MindWorks Nimbus Driver Studio

ErrorServiceResetNotSupported Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static Exception ResetNotSupported()
internal:
static Exception^ ResetNotSupported()

Return Value

Type: Exception
See Also

Reference

ErrorService Class
MindWorks.Nimbus Namespace


ErrorService.SelectorFormat Method

Pacific MindWorks Nimbus Driver Studio

ErrorServiceSelectorFormat Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static Exception SelectorFormat(
    string selector
)
internal:
static Exception^ SelectorFormat(
    String^ selector
)

Parameters

selector
Type: SystemString

Return Value

Type: Exception
See Also

Reference

ErrorService Class
MindWorks.Nimbus Namespace


ErrorService.SelectorHierarchy Method

Pacific MindWorks Nimbus Driver Studio

ErrorServiceSelectorHierarchy Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static Exception SelectorHierarchy(
    string selector
)
internal:
static Exception^ SelectorHierarchy(
    String^ selector
)

Parameters

selector
Type: SystemString

Return Value

Type: Exception
See Also

Reference

ErrorService Class
MindWorks.Nimbus Namespace


ErrorService.SelectorName Method

Pacific MindWorks Nimbus Driver Studio

ErrorServiceSelectorName Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static Exception SelectorName(
    string repeatedCapabilityName,
    string selector
)
internal:
static Exception^ SelectorName(
    String^ repeatedCapabilityName,
    String^ selector
)

Parameters

repeatedCapabilityName
Type: SystemString
selector
Type: SystemString

Return Value

Type: Exception
See Also

Reference

ErrorService Class
MindWorks.Nimbus Namespace


ErrorService.SelectorNameRequired Method

Pacific MindWorks Nimbus Driver Studio

ErrorServiceSelectorNameRequired Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static Exception SelectorNameRequired(
    string repeatedCapabilityName
)
internal:
static Exception^ SelectorNameRequired(
    String^ repeatedCapabilityName
)

Parameters

repeatedCapabilityName
Type: SystemString

Return Value

Type: Exception
See Also

Reference

ErrorService Class
MindWorks.Nimbus Namespace


ErrorService.SelectorRange Method

Pacific MindWorks Nimbus Driver Studio

ErrorServiceSelectorRange Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static Exception SelectorRange(
    string selector
)
internal:
static Exception^ SelectorRange(
    String^ selector
)

Parameters

selector
Type: SystemString

Return Value

Type: Exception
See Also

Reference

ErrorService Class
MindWorks.Nimbus Namespace


ErrorService.SimulationState Method

Pacific MindWorks Nimbus Driver Studio

ErrorServiceSimulationState Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static Exception SimulationState()
internal:
static Exception^ SimulationState()

Return Value

Type: Exception
See Also

Reference

ErrorService Class
MindWorks.Nimbus Namespace


ErrorService.SoftwareModuleNotFound Method

Pacific MindWorks Nimbus Driver Studio

ErrorServiceSoftwareModuleNotFound Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static Exception SoftwareModuleNotFound(
    string driverSession,
    string softwareModule
)
internal:
static Exception^ SoftwareModuleNotFound(
    String^ driverSession,
    String^ softwareModule
)

Parameters

driverSession
Type: SystemString
softwareModule
Type: SystemString

Return Value

Type: Exception
See Also

Reference

ErrorService Class
MindWorks.Nimbus Namespace


ErrorService.TriggerNotSoftware Method

Pacific MindWorks Nimbus Driver Studio

ErrorServiceTriggerNotSoftware Method

Overload List
Name | Description
TriggerNotSoftware |
TriggerNotSoftware(String) |
Top
See Also

Reference

ErrorService Class
MindWorks.Nimbus Namespace


ErrorService.TriggerNotSoftware Method

Pacific MindWorks Nimbus Driver Studio

ErrorServiceTriggerNotSoftware Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static Exception TriggerNotSoftware()
internal:
static Exception^ TriggerNotSoftware()

Return Value

Type: Exception
See Also

Reference

ErrorService Class
TriggerNotSoftware Overload
MindWorks.Nimbus Namespace


ErrorService.TriggerNotSoftware Method (String)

Pacific MindWorks Nimbus Driver Studio

ErrorServiceTriggerNotSoftware Method (String)

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static Exception TriggerNotSoftware(
    string triggerSource
)
internal:
static Exception^ TriggerNotSoftware(
    String^ triggerSource
)

Parameters

triggerSource
Type: SystemString

Return Value

Type: Exception
See Also

Reference

ErrorService Class
TriggerNotSoftware Overload
MindWorks.Nimbus Namespace


ErrorService.UnexpectedResponse Method

Pacific MindWorks Nimbus Driver Studio

ErrorServiceUnexpectedResponse Method

Overload List
Name | Description
UnexpectedResponse |
UnexpectedResponse(String) |
Top
See Also

Reference

ErrorService Class
MindWorks.Nimbus Namespace


ErrorService.UnexpectedResponse Method

Pacific MindWorks Nimbus Driver Studio

ErrorServiceUnexpectedResponse Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static Exception UnexpectedResponse()
internal:
static Exception^ UnexpectedResponse()

Return Value

Type: Exception
See Also

Reference

ErrorService Class
UnexpectedResponse Overload
MindWorks.Nimbus Namespace


ErrorService.UnexpectedResponse Method (String)

Pacific MindWorks Nimbus Driver Studio

ErrorServiceUnexpectedResponse Method (String)

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static Exception UnexpectedResponse(
    string message
)
internal:
static Exception^ UnexpectedResponse(
    String^ message
)

Parameters

message
Type: SystemString

Return Value

Type: Exception
See Also

Reference

ErrorService Class
UnexpectedResponse Overload
MindWorks.Nimbus Namespace


ErrorService.UnknownOption Method

Pacific MindWorks Nimbus Driver Studio

ErrorServiceUnknownOption Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static Exception UnknownOption(
    string optionName
)
internal:
static Exception^ UnknownOption(
    String^ optionName
)

Parameters

optionName
Type: SystemString

Return Value

Type: Exception
See Also

Reference

ErrorService Class
MindWorks.Nimbus Namespace


ErrorService.UnknownPhysicalName Method

Pacific MindWorks Nimbus Driver Studio

ErrorServiceUnknownPhysicalName Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static Exception UnknownPhysicalName(
    string driverSession,
    string repeatedCapabilityName,
    string virtualName,
    string physicalName
)
internal:
static Exception^ UnknownPhysicalName(
    String^ driverSession,
    String^ repeatedCapabilityName,
    String^ virtualName,
    String^ physicalName
)

Parameters

driverSession
Type: SystemString
repeatedCapabilityName
Type: SystemString
virtualName
Type: SystemString
physicalName
Type: SystemString

Return Value

Type: Exception
See Also

Reference

ErrorService Class
MindWorks.Nimbus Namespace


ErrorService.ValidPointCountExceedsCapacity Method

Pacific MindWorks Nimbus Driver Studio

ErrorServiceValidPointCountExceedsCapacity Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static Exception ValidPointCountExceedsCapacity(
    string validPointCount,
    string capacity
)
internal:
static Exception^ ValidPointCountExceedsCapacity(
    String^ validPointCount,
    String^ capacity
)

Parameters

validPointCount
Type: SystemString
capacity
Type: SystemString

Return Value

Type: Exception
See Also

Reference

ErrorService Class
MindWorks.Nimbus Namespace


ErrorService.ValueNotSupported Method

Pacific MindWorks Nimbus Driver Studio

ErrorServiceValueNotSupported Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static Exception ValueNotSupported(
    string paramName,
    string value
)
internal:
static Exception^ ValueNotSupported(
    String^ paramName,
    String^ value
)

Parameters

paramName
Type: SystemString
value
Type: SystemString

Return Value

Type: Exception
See Also

Reference

ErrorService Class
MindWorks.Nimbus Namespace


HardwareAssetAttribute Class

Inheritance Hierarchy
SystemObject
SystemAttribute
MindWorks.NimbusNimbusAttribute
MindWorks.NimbusHardwareAssetAttribute

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal sealed class HardwareAssetAttribute : NimbusAttribute
internal ref class HardwareAssetAttribute sealed : public NimbusAttribute

The HardwareAssetAttribute type exposes the following members.

Constructors
 | Name | Description
Protected method | HardwareAssetAttribute | Initializes a new instance of the HardwareAssetAttribute class
Top
Properties
 | Name | Description
Protected property | Name |
Protected property | ResourceDescriptor |
Top
See Also

Reference

MindWorks.Nimbus Namespace


HardwareAssetAttribute Constructor

Initializes a new instance of the HardwareAssetAttribute class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal HardwareAssetAttribute(
    string name,
    string resourceDescriptor
)
internal:
HardwareAssetAttribute(
    String^ name,
    String^ resourceDescriptor
)

Parameters

name
Type: SystemString
resourceDescriptor
Type: SystemString
See Also

Reference

HardwareAssetAttribute Class
MindWorks.Nimbus Namespace


HardwareAssetAttribute Properties

The HardwareAssetAttribute type exposes the following members.

Properties
 | Name | Description
Protected property | Name |
Protected property | ResourceDescriptor |
Top
See Also

Reference

HardwareAssetAttribute Class
MindWorks.Nimbus Namespace


HardwareAssetAttribute.Name Property

Pacific MindWorks Nimbus Driver Studio

HardwareAssetAttributeName Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal string Name { get; }
internal:
property String^ Name {
    String^ get ();
}

Property Value

Type: String
See Also

Reference

HardwareAssetAttribute Class
MindWorks.Nimbus Namespace


HardwareAssetAttribute.ResourceDescriptor Property

Pacific MindWorks Nimbus Driver Studio

HardwareAssetAttributeResourceDescriptor Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal string ResourceDescriptor { get; }
internal:
property String^ ResourceDescriptor {
    String^ get ();
}

Property Value

Type: String
See Also

Reference

HardwareAssetAttribute Class
MindWorks.Nimbus Namespace


ICacheEquatable Interface

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal interface ICacheEquatable
internal interface class ICacheEquatable

The ICacheEquatable type exposes the following members.

Methods
 | Name | Description
Public method | IsEqualTo |
Top
See Also

Reference

MindWorks.Nimbus Namespace


ICacheEquatable Methods

The ICacheEquatable type exposes the following members.

Methods
 | Name | Description
Public method | IsEqualTo |
Top
See Also

Reference

ICacheEquatable Interface
MindWorks.Nimbus Namespace


ICacheEquatable.IsEqualTo Method

Pacific MindWorks Nimbus Driver Studio

ICacheEquatableIsEqualTo Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
bool IsEqualTo(
    Object obj
)
bool IsEqualTo(
    Object^ obj
)

Parameters

obj
Type: SystemObject

Return Value

Type: Boolean
See Also

Reference

ICacheEquatable Interface
MindWorks.Nimbus Namespace


InitOptions Class

Inheritance Hierarchy
SystemObject
MindWorks.NimbusInitOptions

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal class InitOptions : ICloneable
internal ref class InitOptions : ICloneable

The InitOptions type exposes the following members.

Constructors
 | Name | Description
Public method | InitOptions | Initializes a new instance of the InitOptions class
Top
Properties
 | Name | Description
Public property | CachingEnabled |
Public property | CoercionRecordingEnabled |
Public property | InterchangeCheckingEnabled |
Public property | QueryInstrumentStatusEnabled |
Public property | RangeCheckingEnabled |
Public property | SimulationEnabled |
Top
Methods
 | Name | Description
Public method | Clone |
Public method | InitializeToIviDefinedDefaults |
Top
See Also

Reference

MindWorks.Nimbus Namespace


InitOptions Constructor

Initializes a new instance of the InitOptions class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public InitOptions()
public:
InitOptions()
See Also

Reference

InitOptions Class
MindWorks.Nimbus Namespace


InitOptions Properties

The InitOptions type exposes the following members.

Properties
 | Name | Description
Public property | CachingEnabled |
Public property | CoercionRecordingEnabled |
Public property | InterchangeCheckingEnabled |
Public property | QueryInstrumentStatusEnabled |
Public property | RangeCheckingEnabled |
Public property | SimulationEnabled |
Top
See Also

Reference

InitOptions Class
MindWorks.Nimbus Namespace


InitOptions.CachingEnabled Property

Pacific MindWorks Nimbus Driver Studio

InitOptionsCachingEnabled Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public bool CachingEnabled { get; set; }
public:
property bool CachingEnabled {
    bool get ();
    void set (bool value);
}

Property Value

Type: Boolean
See Also

Reference

InitOptions Class
MindWorks.Nimbus Namespace


InitOptions.CoercionRecordingEnabled Property

Pacific MindWorks Nimbus Driver Studio

InitOptionsCoercionRecordingEnabled Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public bool CoercionRecordingEnabled { get; set; }
public:
property bool CoercionRecordingEnabled {
    bool get ();
    void set (bool value);
}

Property Value

Type: Boolean
See Also

Reference

InitOptions Class
MindWorks.Nimbus Namespace


InitOptions.InterchangeCheckingEnabled Property

Pacific MindWorks Nimbus Driver Studio

InitOptionsInterchangeCheckingEnabled Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public bool InterchangeCheckingEnabled { get; set; }
public:
property bool InterchangeCheckingEnabled {
    bool get ();
    void set (bool value);
}

Property Value

Type: Boolean
See Also

Reference

InitOptions Class
MindWorks.Nimbus Namespace


InitOptions.QueryInstrumentStatusEnabled Property

Pacific MindWorks Nimbus Driver Studio

InitOptionsQueryInstrumentStatusEnabled Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public bool QueryInstrumentStatusEnabled { get; set; }
public:
property bool QueryInstrumentStatusEnabled {
    bool get ();
    void set (bool value);
}

Property Value

Type: Boolean
See Also

Reference

InitOptions Class
MindWorks.Nimbus Namespace


InitOptions.RangeCheckingEnabled Property

Pacific MindWorks Nimbus Driver Studio

InitOptionsRangeCheckingEnabled Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public bool RangeCheckingEnabled { get; set; }
public:
property bool RangeCheckingEnabled {
    bool get ();
    void set (bool value);
}

Property Value

Type: Boolean
See Also

Reference

InitOptions Class
MindWorks.Nimbus Namespace


InitOptions.SimulationEnabled Property

Pacific MindWorks Nimbus Driver Studio

InitOptionsSimulationEnabled Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public bool SimulationEnabled { get; set; }
public:
property bool SimulationEnabled {
    bool get ();
    void set (bool value);
}

Property Value

Type: Boolean
See Also

Reference

InitOptions Class
MindWorks.Nimbus Namespace


InitOptions Methods

The InitOptions type exposes the following members.

Methods
 | Name | Description
Public method | Clone |
Public method | InitializeToIviDefinedDefaults |
Top
See Also

Reference

InitOptions Class
MindWorks.Nimbus Namespace


InitOptions.Clone Method

Pacific MindWorks Nimbus Driver Studio

InitOptionsClone Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public Object Clone()
public:
virtual Object^ Clone() sealed

Return Value

Type: Object

Implements

ICloneableClone
See Also

Reference

InitOptions Class
MindWorks.Nimbus Namespace


InitOptions.InitializeToIviDefinedDefaults Method

Pacific MindWorks Nimbus Driver Studio

InitOptionsInitializeToIviDefinedDefaults Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public void InitializeToIviDefinedDefaults()
public:
void InitializeToIviDefinedDefaults()
See Also

Reference

InitOptions Class
MindWorks.Nimbus Namespace


InstrumentFamiliesAttribute Class

Inheritance Hierarchy
SystemObject
SystemAttribute
MindWorks.NimbusNimbusAttribute
MindWorks.NimbusInstrumentFamiliesAttribute

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal sealed class InstrumentFamiliesAttribute : NimbusAttribute
internal ref class InstrumentFamiliesAttribute sealed : public NimbusAttribute

The InstrumentFamiliesAttribute type exposes the following members.

Constructors
 | Name | Description
Public method | InstrumentFamiliesAttribute | Initializes a new instance of the InstrumentFamiliesAttribute class
Top
See Also

Reference

MindWorks.Nimbus Namespace


InstrumentFamiliesAttribute Constructor

Initializes a new instance of the InstrumentFamiliesAttribute class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public InstrumentFamiliesAttribute()
public:
InstrumentFamiliesAttribute()
See Also

Reference

InstrumentFamiliesAttribute Class
MindWorks.Nimbus Namespace


InstrumentModelsAttribute Class

Inheritance Hierarchy
SystemObject
SystemAttribute
MindWorks.NimbusNimbusAttribute
MindWorks.NimbusInstrumentModelsAttribute

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal sealed class InstrumentModelsAttribute : NimbusAttribute
internal ref class InstrumentModelsAttribute sealed : public NimbusAttribute

The InstrumentModelsAttribute type exposes the following members.

Constructors
 | Name | Description
Protected method | InstrumentModelsAttribute | Initializes a new instance of the InstrumentModelsAttribute class
Top
Properties
 | Name | Description
Public property | DefaultModelForSimulation |
Top
See Also

Reference

MindWorks.Nimbus Namespace


InstrumentModelsAttribute Constructor

Initializes a new instance of the InstrumentModelsAttribute class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal InstrumentModelsAttribute(
    string defaultModel
)
internal:
InstrumentModelsAttribute(
    String^ defaultModel
)

Parameters

defaultModel
Type: SystemString
See Also

Reference

InstrumentModelsAttribute Class
MindWorks.Nimbus Namespace


InstrumentModelsAttribute Properties

The InstrumentModelsAttribute type exposes the following members.

Properties
 | Name | Description
Public property | DefaultModelForSimulation |
Top
See Also

Reference

InstrumentModelsAttribute Class
MindWorks.Nimbus Namespace


InstrumentModelsAttribute.DefaultModelForSimulation Property

Pacific MindWorks Nimbus Driver Studio

InstrumentModelsAttributeDefaultModelForSimulation Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public string DefaultModelForSimulation { get; }
public:
property String^ DefaultModelForSimulation {
    String^ get ();
}

Property Value

Type: String
See Also

Reference

InstrumentModelsAttribute Class
MindWorks.Nimbus Namespace


InvalidateCacheEntriesAttribute Class

Inheritance Hierarchy
SystemObject
SystemAttribute
MindWorks.NimbusNimbusAttribute
MindWorks.NimbusNimbusCodeWeaverAttribute
MindWorks.NimbusInvalidateCacheEntriesAttribute

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal sealed class InvalidateCacheEntriesAttribute : NimbusCodeWeaverAttribute
internal ref class InvalidateCacheEntriesAttribute sealed : public NimbusCodeWeaverAttribute

The InvalidateCacheEntriesAttribute type exposes the following members.

Constructors
 | Name | Description
Protected method | InvalidateCacheEntriesAttribute | Initializes a new instance of the InvalidateCacheEntriesAttribute class
Top
Properties
 | Name | Description
Protected property | Keys |
Public property | SuppressAll | (Inherited from NimbusCodeWeaverAttribute.)
Top
Fields
Name | Description
CacheKeyParser |
Top
See Also

Reference

MindWorks.Nimbus Namespace


InvalidateCacheEntriesAttribute Constructor

Initializes a new instance of the InvalidateCacheEntriesAttribute class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal InvalidateCacheEntriesAttribute(
    params string[] keys
)
internal:
InvalidateCacheEntriesAttribute(
    ... array<String^>^ keys
)

Parameters

keys
Type: SystemString
See Also

Reference

InvalidateCacheEntriesAttribute Class
MindWorks.Nimbus Namespace


InvalidateCacheEntriesAttribute Properties

The InvalidateCacheEntriesAttribute type exposes the following members.

Properties
 | Name | Description
Protected property | Keys |
Public property | SuppressAll | (Inherited from NimbusCodeWeaverAttribute.)
Top
See Also

Reference

InvalidateCacheEntriesAttribute Class
MindWorks.Nimbus Namespace


InvalidateCacheEntriesAttribute.Keys Property

Pacific MindWorks Nimbus Driver Studio

InvalidateCacheEntriesAttributeKeys Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal IList<string> Keys { get; }
internal:
property IList<String^>^ Keys {
    IList<String^>^ get ();
}

Property Value

Type: IList String
See Also

Reference

InvalidateCacheEntriesAttribute Class
MindWorks.Nimbus Namespace


InvalidateCacheEntriesAttribute Fields

The InvalidateCacheEntriesAttribute type exposes the following members.

Fields
Name | Description
CacheKeyParser |
Top
See Also

Reference

InvalidateCacheEntriesAttribute Class
MindWorks.Nimbus Namespace


InvalidateCacheEntriesAttribute.CacheKeyParser Field

Pacific MindWorks Nimbus Driver Studio

InvalidateCacheEntriesAttributeCacheKeyParser Field

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static readonly Regex CacheKeyParser
internal:
static initonly Regex^ CacheKeyParser

Field Value

Type: Regex
See Also

Reference

InvalidateCacheEntriesAttribute Class
MindWorks.Nimbus Namespace


IOConstants Class

Inheritance Hierarchy
SystemObject
MindWorks.NimbusIOConstants

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public static class IOConstants
public ref class IOConstants abstract sealed

The IOConstants type exposes the following members.

Fields
Name | Description
CurrentTimeout |
DefaultTimeout |
Top
See Also

Reference

MindWorks.Nimbus Namespace


IOConstants Fields

The IOConstants type exposes the following members.

Fields
Name | Description
CurrentTimeout |
DefaultTimeout |
Top
See Also

Reference

IOConstants Class
MindWorks.Nimbus Namespace


IOConstants.CurrentTimeout Field

Pacific MindWorks Nimbus Driver Studio

IOConstantsCurrentTimeout Field

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public const int CurrentTimeout = -1
public:
literal int CurrentTimeout = -1

Field Value

Type: Int32
See Also

Reference

IOConstants Class
MindWorks.Nimbus Namespace


IOConstants.DefaultTimeout Field

Pacific MindWorks Nimbus Driver Studio

IOConstantsDefaultTimeout Field

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public const int DefaultTimeout = 2000
public:
literal int DefaultTimeout = 2000

Field Value

Type: Int32
See Also

Reference

IOConstants Class
MindWorks.Nimbus Namespace


LogicalNameAttribute Class

Inheritance Hierarchy
SystemObject
SystemAttribute
MindWorks.NimbusNimbusAttribute
MindWorks.NimbusLogicalNameAttribute

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal sealed class LogicalNameAttribute : NimbusAttribute
internal ref class LogicalNameAttribute sealed : public NimbusAttribute

The LogicalNameAttribute type exposes the following members.

Constructors
 | Name | Description
Protected method | LogicalNameAttribute | Initializes a new instance of the LogicalNameAttribute class
Top
Properties
 | Name | Description
Protected property | DriverSession |
Protected property | LogicalName |
Top
See Also

Reference

MindWorks.Nimbus Namespace


LogicalNameAttribute Constructor

Initializes a new instance of the LogicalNameAttribute class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal LogicalNameAttribute(
    string logicalName,
    string driverSession
)
internal:
LogicalNameAttribute(
    String^ logicalName,
    String^ driverSession
)

Parameters

logicalName
Type: SystemString
driverSession
Type: SystemString
See Also

Reference

LogicalNameAttribute Class
MindWorks.Nimbus Namespace


LogicalNameAttribute Properties

The LogicalNameAttribute type exposes the following members.

Properties
 | Name | Description
Protected property | DriverSession |
Protected property | LogicalName |
Top
See Also

Reference

LogicalNameAttribute Class
MindWorks.Nimbus Namespace


LogicalNameAttribute.DriverSession Property

Pacific MindWorks Nimbus Driver Studio

LogicalNameAttributeDriverSession Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal string DriverSession { get; }
internal:
property String^ DriverSession {
    String^ get ();
}

Property Value

Type: String
See Also

Reference

LogicalNameAttribute Class
MindWorks.Nimbus Namespace


LogicalNameAttribute.LogicalName Property

Pacific MindWorks Nimbus Driver Studio

LogicalNameAttributeLogicalName Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal string LogicalName { get; }
internal:
property String^ LogicalName {
    String^ get ();
}

Property Value

Type: String
See Also

Reference

LogicalNameAttribute Class
MindWorks.Nimbus Namespace


ModelSpecificNimbusAttribute Class

Inheritance Hierarchy
SystemObject
SystemAttribute
MindWorks.NimbusNimbusAttribute
MindWorks.NimbusModelSpecificNimbusAttribute
MindWorks.NimbusCommandAttribute
MindWorks.NimbusEnumCommandAttribute

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal abstract class ModelSpecificNimbusAttribute : NimbusAttribute
internal ref class ModelSpecificNimbusAttribute abstract : public NimbusAttribute

The ModelSpecificNimbusAttribute type exposes the following members.

Constructors
 | Name | Description
Public method | ModelSpecificNimbusAttribute | Initializes a new instance of the ModelSpecificNimbusAttribute class
Public method | ModelSpecificNimbusAttribute(String) | Initializes a new instance of the ModelSpecificNimbusAttribute class
Top
Properties
 | Name | Description
Public property | Models |
Top
See Also

Reference

MindWorks.Nimbus Namespace


ModelSpecificNimbusAttribute Constructor

Overload List
 | Name | Description
Public method | ModelSpecificNimbusAttribute | Initializes a new instance of the ModelSpecificNimbusAttribute class
Public method | ModelSpecificNimbusAttribute(String) | Initializes a new instance of the ModelSpecificNimbusAttribute class
Top
See Also

Reference

ModelSpecificNimbusAttribute Class
MindWorks.Nimbus Namespace


ModelSpecificNimbusAttribute Constructor

Initializes a new instance of the ModelSpecificNimbusAttribute class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public ModelSpecificNimbusAttribute()
public:
ModelSpecificNimbusAttribute()
See Also

Reference

ModelSpecificNimbusAttribute Class
ModelSpecificNimbusAttribute Overload
MindWorks.Nimbus Namespace


ModelSpecificNimbusAttribute Constructor (String[])

Pacific MindWorks Nimbus Driver Studio

ModelSpecificNimbusAttribute Constructor (String)

Initializes a new instance of the ModelSpecificNimbusAttribute class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public ModelSpecificNimbusAttribute(
    string[] models
)
public:
ModelSpecificNimbusAttribute(
    array<String^>^ models
)

Parameters

models
Type: SystemString
See Also

Reference

ModelSpecificNimbusAttribute Class
ModelSpecificNimbusAttribute Overload
MindWorks.Nimbus Namespace


ModelSpecificNimbusAttribute Properties

The ModelSpecificNimbusAttribute type exposes the following members.

Properties
 | Name | Description
Public property | Models |
Top
See Also

Reference

ModelSpecificNimbusAttribute Class
MindWorks.Nimbus Namespace


ModelSpecificNimbusAttribute.Models Property

Pacific MindWorks Nimbus Driver Studio

ModelSpecificNimbusAttributeModels Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public string[] Models { get; }
public:
property array<String^>^ Models {
    array<String^>^ get ();
}

Property Value

Type: String
See Also

Reference

ModelSpecificNimbusAttribute Class
MindWorks.Nimbus Namespace


ModelSpecificNimbusCodeWeaverAttribute Class

Inheritance Hierarchy
SystemObject
SystemAttribute
MindWorks.NimbusNimbusAttribute
MindWorks.NimbusNimbusCodeWeaverAttribute
MindWorks.NimbusModelSpecificNimbusCodeWeaverAttribute
MindWorks.NimbusRangeCheckDiscreteAttribute
MindWorks.NimbusRangeCheckMinMaxAttribute
MindWorks.NimbusRangeCheckStringAttribute
MindWorks.NimbusSimulationAttribute

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal abstract class ModelSpecificNimbusCodeWeaverAttribute : NimbusCodeWeaverAttribute
internal ref class ModelSpecificNimbusCodeWeaverAttribute abstract : public NimbusCodeWeaverAttribute

The ModelSpecificNimbusCodeWeaverAttribute type exposes the following members.

Constructors
 | Name | Description
Public method | ModelSpecificNimbusCodeWeaverAttribute | Initializes a new instance of the ModelSpecificNimbusCodeWeaverAttribute class
Public method | ModelSpecificNimbusCodeWeaverAttribute(String) | Initializes a new instance of the ModelSpecificNimbusCodeWeaverAttribute class
Top
Properties
 | Name | Description
Public property | Models |
Public property | SuppressAll | (Inherited from NimbusCodeWeaverAttribute.)
Top
See Also

Reference

MindWorks.Nimbus Namespace


ModelSpecificNimbusCodeWeaverAttribute Constructor

Overload List
 | Name | Description
Public method | ModelSpecificNimbusCodeWeaverAttribute | Initializes a new instance of the ModelSpecificNimbusCodeWeaverAttribute class
Public method | ModelSpecificNimbusCodeWeaverAttribute(String) | Initializes a new instance of the ModelSpecificNimbusCodeWeaverAttribute class
Top
See Also

Reference

ModelSpecificNimbusCodeWeaverAttribute Class
MindWorks.Nimbus Namespace


ModelSpecificNimbusCodeWeaverAttribute Constructor

Initializes a new instance of the ModelSpecificNimbusCodeWeaverAttribute class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public ModelSpecificNimbusCodeWeaverAttribute()
public:
ModelSpecificNimbusCodeWeaverAttribute()
See Also

Reference

ModelSpecificNimbusCodeWeaverAttribute Class
ModelSpecificNimbusCodeWeaverAttribute Overload
MindWorks.Nimbus Namespace


ModelSpecificNimbusCodeWeaverAttribute Constructor (String[])

Pacific MindWorks Nimbus Driver Studio

ModelSpecificNimbusCodeWeaverAttribute Constructor (String)

Initializes a new instance of the ModelSpecificNimbusCodeWeaverAttribute class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public ModelSpecificNimbusCodeWeaverAttribute(
    string[] models
)
public:
ModelSpecificNimbusCodeWeaverAttribute(
    array<String^>^ models
)

Parameters

models
Type: SystemString
See Also

Reference

ModelSpecificNimbusCodeWeaverAttribute Class
ModelSpecificNimbusCodeWeaverAttribute Overload
MindWorks.Nimbus Namespace


ModelSpecificNimbusCodeWeaverAttribute Properties

The ModelSpecificNimbusCodeWeaverAttribute type exposes the following members.

Properties
 | Name | Description
Public property | Models |
Public property | SuppressAll | (Inherited from NimbusCodeWeaverAttribute.)
Top
See Also

Reference

ModelSpecificNimbusCodeWeaverAttribute Class
MindWorks.Nimbus Namespace


ModelSpecificNimbusCodeWeaverAttribute.Models Property

Pacific MindWorks Nimbus Driver Studio

ModelSpecificNimbusCodeWeaverAttributeModels Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public string[] Models { get; }
public:
property array<String^>^ Models {
    array<String^>^ get ();
}

Property Value

Type: String
See Also

Reference

ModelSpecificNimbusCodeWeaverAttribute Class
MindWorks.Nimbus Namespace


NclStrings Class

Inheritance Hierarchy
SystemObject
MindWorks.NimbusNclStrings

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static class NclStrings
internal ref class NclStrings abstract sealed

The NclStrings type exposes the following members.

Methods
Name | Description
AttributeValidationFailed |
AttributeValidationFailedWithDetails |
CacheKeySyntaxError |
CannotSpecifyParentOnSelectorStyleRepeatedCapabilityAttribute |
CoercionEvent |
ConfigurableInitialSettingAttributeDuplicateKeyNameMessage |
ConfigurableInitialSettingAttributeValueOverflowMessage |
ConfigurableInitialSettingAttributeValueOverflowResolution |
ConfigurableInitialSettingAttributeValueTypeUnsupportedMessage |
ConfigurableInitialSettingAttributeValueTypeUnsupportedResolution |
CouldNotCreateCacheKeyForMethod |
CouldNotCreateCacheKeyForProperty |
CouldNotCreateRepCap |
CouldNotFindRepCapClass |
CouldNotFindRepCapCollectionClass |
DriverSessionAndCapabilitiesAttributesSpecifyInconsistentInterchangeChecking |
DuplicatePhysicalNamesAttribute |
EmptyPhysicalNamesListInPhysicalNamesAttribute |
EmptyPhysicalNamesListInRepeatedCapabilityAttribute |
ErrorQueryParseError |
FailedToCreateVisaSession |
IdnQueryParseError |
InvalidDriverAssemblyName |
InvalidParentPhysicalNameSpecifiedOnNestedRepCap |
InvalidRangeInPhysicalNamesAttribute |
InvalidRangeInRepeatedCapabilityAttribute |
InvalidUseOfRepCapCollectionWithCache |
IOFunctionMustBeManuallyImplemented |
MissingPhysicalNamesAttribute |
NestedPhysicalNamesMustHaveDepthTwo |
NestedPhysicalNameSpecifiedOnNonNestedRepCap |
NestedRepeatedCapabilitiesInvalidParentMessage |
NestedRepeatedCapabilitiesMustHaveParentMessage |
NestedRepeatedCapabilitiesMustHaveParentResolution |
OperationNotAvailableInSimulationMode |
OperationNotSupported |
OperationNotSupportedForModel |
ParentRepeatedCapabilityNotFound |
PhysicalNamesAttributeAppliedToWrongClass |
PropertyDoesNotExist |
RangeCheckDiscreteNaNMessage |
RangeCheckDuplicateAllowedValuesMessage |
RangeCheckEmptyAllowedValuesMessage |
RangeCheckMinNotLessThanMaxMessage |
RepeatedCapabilityAttributeCannotHaveEmptyRepCapName |
RepeatedCapabilityNotDefined |
RepeatedCapabilityNotDefinedAsParameterStyle |
RepeatedCapabilityNotDefinedAsSelectorStyle |
SelfTestParseError |
SyntaxErrorInPhysicalNamesAttribute |
SyntaxErrorInPhysicalNamesListInRepeatedCapabilityAttribute |
SyntaxErrorInRepCapSelector |
ValidationExpressionInvalid |
Top
Fields
Name | Description
CannotReadMutipleRepCaps |
ConfigurableInitialSettingAttributeDuplicateKeyNameResolution |
ConfigurableInitialSettingAttributeKeyNameEmptyMessage |
ConfigurableInitialSettingAttributeKeyNameEmptyResolution |
CouldNotPerformErrorQuery |
CouldNotPerformSelfTest |
DefaultModelMustBeInInstrumentModelsList |
DriverSessionAndCapabilitiesAttributesRequireConsistentInterchangeChecking |
DuplicateFamiliesInInstrumentModelsAttributes |
DuplicateInstrumentClassNames |
DuplicateModelsInInstrumentModelsAttributes |
ErrorQueryNoError |
FamilyCannotBeSetToModel |
IndexPropertyNotAvailable |
InstrumentModelsAttributeMustSpecifyDefaultModel |
MustSpecifyPrimaryInstrumentClass |
NestedRepeatedCapabilitiesInvalidParentResolution |
NoInstrumentModelDeclarationsFound |
OneInstrumentModelsAttributeMustSpecifyDefaultModel |
OnlyOneInstrumentModelsAttributeCanSpecifyDefaultModel |
OnlyOneSupportedInstrumentClassAttributeCanSpecifyPrimary |
OperationRequiresSingleEntryCacheKey |
PhysicalNamePropertyNotAvailable |
RangeCheckDiscreteNaNResolution |
RangeCheckDuplicateAllowedValuesResolution |
RangeCheckEmptyAllowedValuesResolution |
RangeCheckMinNotLessThanMaxResolution |
SelectorNameRequired |
SelfTestPassed |
SimulationDefaultValueShouldBeSpecified |
SingleRepeatedCapbilityIdentifierRequired |
SyntaxErrorInCacheKey |
VirtualNamePropertyNotAvailable |
Top
See Also

Reference

MindWorks.Nimbus Namespace


NclStrings Methods

The NclStrings type exposes the following members.

Methods
Name | Description
AttributeValidationFailed |
AttributeValidationFailedWithDetails |
CacheKeySyntaxError |
CannotSpecifyParentOnSelectorStyleRepeatedCapabilityAttribute |
CoercionEvent |
ConfigurableInitialSettingAttributeDuplicateKeyNameMessage |
ConfigurableInitialSettingAttributeValueOverflowMessage |
ConfigurableInitialSettingAttributeValueOverflowResolution |
ConfigurableInitialSettingAttributeValueTypeUnsupportedMessage |
ConfigurableInitialSettingAttributeValueTypeUnsupportedResolution |
CouldNotCreateCacheKeyForMethod |
CouldNotCreateCacheKeyForProperty |
CouldNotCreateRepCap |
CouldNotFindRepCapClass |
CouldNotFindRepCapCollectionClass |
DriverSessionAndCapabilitiesAttributesSpecifyInconsistentInterchangeChecking |
DuplicatePhysicalNamesAttribute |
EmptyPhysicalNamesListInPhysicalNamesAttribute |
EmptyPhysicalNamesListInRepeatedCapabilityAttribute |
ErrorQueryParseError |
FailedToCreateVisaSession |
IdnQueryParseError |
InvalidDriverAssemblyName |
InvalidParentPhysicalNameSpecifiedOnNestedRepCap |
InvalidRangeInPhysicalNamesAttribute |
InvalidRangeInRepeatedCapabilityAttribute |
InvalidUseOfRepCapCollectionWithCache |
IOFunctionMustBeManuallyImplemented |
MissingPhysicalNamesAttribute |
NestedPhysicalNamesMustHaveDepthTwo |
NestedPhysicalNameSpecifiedOnNonNestedRepCap |
NestedRepeatedCapabilitiesInvalidParentMessage |
NestedRepeatedCapabilitiesMustHaveParentMessage |
NestedRepeatedCapabilitiesMustHaveParentResolution |
OperationNotAvailableInSimulationMode |
OperationNotSupported |
OperationNotSupportedForModel |
ParentRepeatedCapabilityNotFound |
PhysicalNamesAttributeAppliedToWrongClass |
PropertyDoesNotExist |
RangeCheckDiscreteNaNMessage |
RangeCheckDuplicateAllowedValuesMessage |
RangeCheckEmptyAllowedValuesMessage |
RangeCheckMinNotLessThanMaxMessage |
RepeatedCapabilityAttributeCannotHaveEmptyRepCapName |
RepeatedCapabilityNotDefined |
RepeatedCapabilityNotDefinedAsParameterStyle |
RepeatedCapabilityNotDefinedAsSelectorStyle |
SelfTestParseError |
SyntaxErrorInPhysicalNamesAttribute |
SyntaxErrorInPhysicalNamesListInRepeatedCapabilityAttribute |
SyntaxErrorInRepCapSelector |
ValidationExpressionInvalid |
Top
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.AttributeValidationFailed Method

Pacific MindWorks Nimbus Driver Studio

NclStringsAttributeValidationFailed Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string AttributeValidationFailed(
    string attribute,
    string target
)
internal:
static String^ AttributeValidationFailed(
    String^ attribute,
    String^ target
)

Parameters

attribute
Type: SystemString
target
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.AttributeValidationFailedWithDetails Method

Pacific MindWorks Nimbus Driver Studio

NclStringsAttributeValidationFailedWithDetails Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string AttributeValidationFailedWithDetails(
    string attribute,
    string target,
    string details
)
internal:
static String^ AttributeValidationFailedWithDetails(
    String^ attribute,
    String^ target,
    String^ details
)

Parameters

attribute
Type: SystemString
target
Type: SystemString
details
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.CacheKeySyntaxError Method

Pacific MindWorks Nimbus Driver Studio

NclStringsCacheKeySyntaxError Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string CacheKeySyntaxError(
    string cacheKey
)
internal:
static String^ CacheKeySyntaxError(
    String^ cacheKey
)

Parameters

cacheKey
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.CannotSpecifyParentOnSelectorStyleRepeatedCapabilityAttribute Method

Pacific MindWorks Nimbus Driver Studio

NclStringsCannotSpecifyParentOnSelectorStyleRepeatedCapabilityAttribute Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string CannotSpecifyParentOnSelectorStyleRepeatedCapabilityAttribute(
    string param1,
    string param2,
    string param3
)
internal:
static String^ CannotSpecifyParentOnSelectorStyleRepeatedCapabilityAttribute(
    String^ param1,
    String^ param2,
    String^ param3
)

Parameters

param1
Type: SystemString
param2
Type: SystemString
param3
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.CoercionEvent Method

Pacific MindWorks Nimbus Driver Studio

NclStringsCoercionEvent Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string CoercionEvent(
    string typeName,
    Object originalValue,
    Object coercedValue
)
internal:
static String^ CoercionEvent(
    String^ typeName,
    Object^ originalValue,
    Object^ coercedValue
)

Parameters

typeName
Type: SystemString
originalValue
Type: SystemObject
coercedValue
Type: SystemObject

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.ConfigurableInitialSettingAttributeDuplicateKeyNameMessage Method

Pacific MindWorks Nimbus Driver Studio

NclStringsConfigurableInitialSettingAttributeDuplicateKeyNameMessage Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string ConfigurableInitialSettingAttributeDuplicateKeyNameMessage(
    string keyName
)
internal:
static String^ ConfigurableInitialSettingAttributeDuplicateKeyNameMessage(
    String^ keyName
)

Parameters

keyName
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.ConfigurableInitialSettingAttributeValueOverflowMessage Method

Pacific MindWorks Nimbus Driver Studio

NclStringsConfigurableInitialSettingAttributeValueOverflowMessage Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string ConfigurableInitialSettingAttributeValueOverflowMessage(
    string target,
    double value,
    double maxValue
)
internal:
static String^ ConfigurableInitialSettingAttributeValueOverflowMessage(
    String^ target,
    double value,
    double maxValue
)

Parameters

target
Type: SystemString
value
Type: SystemDouble
maxValue
Type: SystemDouble

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.ConfigurableInitialSettingAttributeValueOverflowResolution Method

Pacific MindWorks Nimbus Driver Studio

NclStringsConfigurableInitialSettingAttributeValueOverflowResolution Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string ConfigurableInitialSettingAttributeValueOverflowResolution(
    double maxResolution
)
internal:
static String^ ConfigurableInitialSettingAttributeValueOverflowResolution(
    double maxResolution
)

Parameters

maxResolution
Type: SystemDouble

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.ConfigurableInitialSettingAttributeValueTypeUnsupportedMessage Method

Pacific MindWorks Nimbus Driver Studio

NclStringsConfigurableInitialSettingAttributeValueTypeUnsupportedMessage Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string ConfigurableInitialSettingAttributeValueTypeUnsupportedMessage(
    string target,
    string type
)
internal:
static String^ ConfigurableInitialSettingAttributeValueTypeUnsupportedMessage(
    String^ target,
    String^ type
)

Parameters

target
Type: SystemString
type
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.ConfigurableInitialSettingAttributeValueTypeUnsupportedResolution Method

Pacific MindWorks Nimbus Driver Studio

NclStringsConfigurableInitialSettingAttributeValueTypeUnsupportedResolution Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string ConfigurableInitialSettingAttributeValueTypeUnsupportedResolution(
    string allowedTypes
)
internal:
static String^ ConfigurableInitialSettingAttributeValueTypeUnsupportedResolution(
    String^ allowedTypes
)

Parameters

allowedTypes
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.CouldNotCreateCacheKeyForMethod Method

Pacific MindWorks Nimbus Driver Studio

NclStringsCouldNotCreateCacheKeyForMethod Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string CouldNotCreateCacheKeyForMethod(
    string typeName,
    string methodName
)
internal:
static String^ CouldNotCreateCacheKeyForMethod(
    String^ typeName,
    String^ methodName
)

Parameters

typeName
Type: SystemString
methodName
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.CouldNotCreateCacheKeyForProperty Method

Pacific MindWorks Nimbus Driver Studio

NclStringsCouldNotCreateCacheKeyForProperty Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string CouldNotCreateCacheKeyForProperty(
    string typeName,
    string methodName
)
internal:
static String^ CouldNotCreateCacheKeyForProperty(
    String^ typeName,
    String^ methodName
)

Parameters

typeName
Type: SystemString
methodName
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.CouldNotCreateRepCap Method

Pacific MindWorks Nimbus Driver Studio

NclStringsCouldNotCreateRepCap Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string CouldNotCreateRepCap(
    string repCap,
    string physicalName
)
internal:
static String^ CouldNotCreateRepCap(
    String^ repCap,
    String^ physicalName
)

Parameters

repCap
Type: SystemString
physicalName
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.CouldNotFindRepCapClass Method

Pacific MindWorks Nimbus Driver Studio

NclStringsCouldNotFindRepCapClass Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string CouldNotFindRepCapClass(
    string interfaceName
)
internal:
static String^ CouldNotFindRepCapClass(
    String^ interfaceName
)

Parameters

interfaceName
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.CouldNotFindRepCapCollectionClass Method

Pacific MindWorks Nimbus Driver Studio

NclStringsCouldNotFindRepCapCollectionClass Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string CouldNotFindRepCapCollectionClass(
    string interfaceName
)
internal:
static String^ CouldNotFindRepCapCollectionClass(
    String^ interfaceName
)

Parameters

interfaceName
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.DriverSessionAndCapabilitiesAttributesSpecifyInconsistentInterchangeChecking Method

Pacific MindWorks Nimbus Driver Studio

NclStringsDriverSessionAndCapabilitiesAttributesSpecifyInconsistentInterchangeChecking Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string DriverSessionAndCapabilitiesAttributesSpecifyInconsistentInterchangeChecking(
    string driverSessionInterchangeCheck,
    string driverCapabilitiesInterchangeCheck
)
internal:
static String^ DriverSessionAndCapabilitiesAttributesSpecifyInconsistentInterchangeChecking(
    String^ driverSessionInterchangeCheck,
    String^ driverCapabilitiesInterchangeCheck
)

Parameters

driverSessionInterchangeCheck
Type: SystemString
driverCapabilitiesInterchangeCheck
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.DuplicatePhysicalNamesAttribute Method

Pacific MindWorks Nimbus Driver Studio

NclStringsDuplicatePhysicalNamesAttribute Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string DuplicatePhysicalNamesAttribute(
    string target
)
internal:
static String^ DuplicatePhysicalNamesAttribute(
    String^ target
)

Parameters

target
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.EmptyPhysicalNamesListInPhysicalNamesAttribute Method

Pacific MindWorks Nimbus Driver Studio

NclStringsEmptyPhysicalNamesListInPhysicalNamesAttribute Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string EmptyPhysicalNamesListInPhysicalNamesAttribute(
    string className,
    string collectionClass
)
internal:
static String^ EmptyPhysicalNamesListInPhysicalNamesAttribute(
    String^ className,
    String^ collectionClass
)

Parameters

className
Type: SystemString
collectionClass
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.EmptyPhysicalNamesListInRepeatedCapabilityAttribute Method

Pacific MindWorks Nimbus Driver Studio

NclStringsEmptyPhysicalNamesListInRepeatedCapabilityAttribute Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string EmptyPhysicalNamesListInRepeatedCapabilityAttribute(
    string repCap,
    string target
)
internal:
static String^ EmptyPhysicalNamesListInRepeatedCapabilityAttribute(
    String^ repCap,
    String^ target
)

Parameters

repCap
Type: SystemString
target
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.ErrorQueryParseError Method

Pacific MindWorks Nimbus Driver Studio

NclStringsErrorQueryParseError Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string ErrorQueryParseError(
    string response
)
internal:
static String^ ErrorQueryParseError(
    String^ response
)

Parameters

response
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.FailedToCreateVisaSession Method

Pacific MindWorks Nimbus Driver Studio

NclStringsFailedToCreateVisaSession Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string FailedToCreateVisaSession(
    string resourceDescriptor
)
internal:
static String^ FailedToCreateVisaSession(
    String^ resourceDescriptor
)

Parameters

resourceDescriptor
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.IdnQueryParseError Method

Pacific MindWorks Nimbus Driver Studio

NclStringsIdnQueryParseError Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string IdnQueryParseError(
    string response
)
internal:
static String^ IdnQueryParseError(
    String^ response
)

Parameters

response
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.InvalidDriverAssemblyName Method

Pacific MindWorks Nimbus Driver Studio

NclStringsInvalidDriverAssemblyName Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string InvalidDriverAssemblyName(
    string assemblyName
)
internal:
static String^ InvalidDriverAssemblyName(
    String^ assemblyName
)

Parameters

assemblyName
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.InvalidParentPhysicalNameSpecifiedOnNestedRepCap Method

Pacific MindWorks Nimbus Driver Studio

NclStringsInvalidParentPhysicalNameSpecifiedOnNestedRepCap Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string InvalidParentPhysicalNameSpecifiedOnNestedRepCap(
    string repCap,
    string physicalName,
    string parentRepCap
)
internal:
static String^ InvalidParentPhysicalNameSpecifiedOnNestedRepCap(
    String^ repCap,
    String^ physicalName,
    String^ parentRepCap
)

Parameters

repCap
Type: SystemString
physicalName
Type: SystemString
parentRepCap
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.InvalidRangeInPhysicalNamesAttribute Method

Pacific MindWorks Nimbus Driver Studio

NclStringsInvalidRangeInPhysicalNamesAttribute Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string InvalidRangeInPhysicalNamesAttribute(
    string className
)
internal:
static String^ InvalidRangeInPhysicalNamesAttribute(
    String^ className
)

Parameters

className
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.InvalidRangeInRepeatedCapabilityAttribute Method

Pacific MindWorks Nimbus Driver Studio

NclStringsInvalidRangeInRepeatedCapabilityAttribute Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string InvalidRangeInRepeatedCapabilityAttribute(
    string repCap,
    string target
)
internal:
static String^ InvalidRangeInRepeatedCapabilityAttribute(
    String^ repCap,
    String^ target
)

Parameters

repCap
Type: SystemString
target
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.InvalidUseOfRepCapCollectionWithCache Method

Pacific MindWorks Nimbus Driver Studio

NclStringsInvalidUseOfRepCapCollectionWithCache Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string InvalidUseOfRepCapCollectionWithCache(
    string interfaceName
)
internal:
static String^ InvalidUseOfRepCapCollectionWithCache(
    String^ interfaceName
)

Parameters

interfaceName
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.IOFunctionMustBeManuallyImplemented Method

Pacific MindWorks Nimbus Driver Studio

NclStringsIOFunctionMustBeManuallyImplemented Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string IOFunctionMustBeManuallyImplemented(
    string memberName
)
internal:
static String^ IOFunctionMustBeManuallyImplemented(
    String^ memberName
)

Parameters

memberName
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.MissingPhysicalNamesAttribute Method

Pacific MindWorks Nimbus Driver Studio

NclStringsMissingPhysicalNamesAttribute Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string MissingPhysicalNamesAttribute(
    string target
)
internal:
static String^ MissingPhysicalNamesAttribute(
    String^ target
)

Parameters

target
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.NestedPhysicalNamesMustHaveDepthTwo Method

Pacific MindWorks Nimbus Driver Studio

NclStringsNestedPhysicalNamesMustHaveDepthTwo Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string NestedPhysicalNamesMustHaveDepthTwo(
    string repCap,
    int depth
)
internal:
static String^ NestedPhysicalNamesMustHaveDepthTwo(
    String^ repCap,
    int depth
)

Parameters

repCap
Type: SystemString
depth
Type: SystemInt32

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.NestedPhysicalNameSpecifiedOnNonNestedRepCap Method

Pacific MindWorks Nimbus Driver Studio

NclStringsNestedPhysicalNameSpecifiedOnNonNestedRepCap Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string NestedPhysicalNameSpecifiedOnNonNestedRepCap(
    string repCap
)
internal:
static String^ NestedPhysicalNameSpecifiedOnNonNestedRepCap(
    String^ repCap
)

Parameters

repCap
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.NestedRepeatedCapabilitiesInvalidParentMessage Method

Pacific MindWorks Nimbus Driver Studio

NclStringsNestedRepeatedCapabilitiesInvalidParentMessage Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string NestedRepeatedCapabilitiesInvalidParentMessage(
    string target,
    string repCap,
    string parentRepCap
)
internal:
static String^ NestedRepeatedCapabilitiesInvalidParentMessage(
    String^ target,
    String^ repCap,
    String^ parentRepCap
)

Parameters

target
Type: SystemString
repCap
Type: SystemString
parentRepCap
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.NestedRepeatedCapabilitiesMustHaveParentMessage Method

Pacific MindWorks Nimbus Driver Studio

NclStringsNestedRepeatedCapabilitiesMustHaveParentMessage Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string NestedRepeatedCapabilitiesMustHaveParentMessage(
    string target,
    string repCap
)
internal:
static String^ NestedRepeatedCapabilitiesMustHaveParentMessage(
    String^ target,
    String^ repCap
)

Parameters

target
Type: SystemString
repCap
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.NestedRepeatedCapabilitiesMustHaveParentResolution Method

Pacific MindWorks Nimbus Driver Studio

NclStringsNestedRepeatedCapabilitiesMustHaveParentResolution Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string NestedRepeatedCapabilitiesMustHaveParentResolution(
    string parentRepCapName,
    string repCapName
)
internal:
static String^ NestedRepeatedCapabilitiesMustHaveParentResolution(
    String^ parentRepCapName,
    String^ repCapName
)

Parameters

parentRepCapName
Type: SystemString
repCapName
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.OperationNotAvailableInSimulationMode Method

Pacific MindWorks Nimbus Driver Studio

NclStringsOperationNotAvailableInSimulationMode Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string OperationNotAvailableInSimulationMode(
    string operation
)
internal:
static String^ OperationNotAvailableInSimulationMode(
    String^ operation
)

Parameters

operation
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.OperationNotSupported Method

Pacific MindWorks Nimbus Driver Studio

NclStringsOperationNotSupported Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string OperationNotSupported(
    string typeName,
    string methodName
)
internal:
static String^ OperationNotSupported(
    String^ typeName,
    String^ methodName
)

Parameters

typeName
Type: SystemString
methodName
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.OperationNotSupportedForModel Method

Pacific MindWorks Nimbus Driver Studio

NclStringsOperationNotSupportedForModel Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string OperationNotSupportedForModel(
    string typeName,
    string methodName,
    string model
)
internal:
static String^ OperationNotSupportedForModel(
    String^ typeName,
    String^ methodName,
    String^ model
)

Parameters

typeName
Type: SystemString
methodName
Type: SystemString
model
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.ParentRepeatedCapabilityNotFound Method

Pacific MindWorks Nimbus Driver Studio

NclStringsParentRepeatedCapabilityNotFound Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string ParentRepeatedCapabilityNotFound(
    string repCap,
    string parent
)
internal:
static String^ ParentRepeatedCapabilityNotFound(
    String^ repCap,
    String^ parent
)

Parameters

repCap
Type: SystemString
parent
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.PhysicalNamesAttributeAppliedToWrongClass Method

Pacific MindWorks Nimbus Driver Studio

NclStringsPhysicalNamesAttributeAppliedToWrongClass Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string PhysicalNamesAttributeAppliedToWrongClass(
    string className
)
internal:
static String^ PhysicalNamesAttributeAppliedToWrongClass(
    String^ className
)

Parameters

className
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.PropertyDoesNotExist Method

Pacific MindWorks Nimbus Driver Studio

NclStringsPropertyDoesNotExist Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string PropertyDoesNotExist(
    string property,
    string typeName
)
internal:
static String^ PropertyDoesNotExist(
    String^ property,
    String^ typeName
)

Parameters

property
Type: SystemString
typeName
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.RangeCheckDiscreteNaNMessage Method

Pacific MindWorks Nimbus Driver Studio

NclStringsRangeCheckDiscreteNaNMessage Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string RangeCheckDiscreteNaNMessage(
    string typeName,
    string memberName
)
internal:
static String^ RangeCheckDiscreteNaNMessage(
    String^ typeName,
    String^ memberName
)

Parameters

typeName
Type: SystemString
memberName
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.RangeCheckDuplicateAllowedValuesMessage Method

Pacific MindWorks Nimbus Driver Studio

NclStringsRangeCheckDuplicateAllowedValuesMessage Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string RangeCheckDuplicateAllowedValuesMessage(
    string attribute,
    string typeName,
    string memberName
)
internal:
static String^ RangeCheckDuplicateAllowedValuesMessage(
    String^ attribute,
    String^ typeName,
    String^ memberName
)

Parameters

attribute
Type: SystemString
typeName
Type: SystemString
memberName
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.RangeCheckEmptyAllowedValuesMessage Method

Pacific MindWorks Nimbus Driver Studio

NclStringsRangeCheckEmptyAllowedValuesMessage Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string RangeCheckEmptyAllowedValuesMessage(
    string attribute,
    string typeName,
    string memberName
)
internal:
static String^ RangeCheckEmptyAllowedValuesMessage(
    String^ attribute,
    String^ typeName,
    String^ memberName
)

Parameters

attribute
Type: SystemString
typeName
Type: SystemString
memberName
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.RangeCheckMinNotLessThanMaxMessage Method

Pacific MindWorks Nimbus Driver Studio

NclStringsRangeCheckMinNotLessThanMaxMessage Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string RangeCheckMinNotLessThanMaxMessage(
    string typeName,
    string memberName,
    double minValue,
    double maxValue
)
internal:
static String^ RangeCheckMinNotLessThanMaxMessage(
    String^ typeName,
    String^ memberName,
    double minValue,
    double maxValue
)

Parameters

typeName
Type: SystemString
memberName
Type: SystemString
minValue
Type: SystemDouble
maxValue
Type: SystemDouble

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.RepeatedCapabilityAttributeCannotHaveEmptyRepCapName Method

Pacific MindWorks Nimbus Driver Studio

NclStringsRepeatedCapabilityAttributeCannotHaveEmptyRepCapName Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string RepeatedCapabilityAttributeCannotHaveEmptyRepCapName(
    string target
)
internal:
static String^ RepeatedCapabilityAttributeCannotHaveEmptyRepCapName(
    String^ target
)

Parameters

target
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.RepeatedCapabilityNotDefined Method

Pacific MindWorks Nimbus Driver Studio

NclStringsRepeatedCapabilityNotDefined Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string RepeatedCapabilityNotDefined(
    string repCap
)
internal:
static String^ RepeatedCapabilityNotDefined(
    String^ repCap
)

Parameters

repCap
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.RepeatedCapabilityNotDefinedAsParameterStyle Method

Pacific MindWorks Nimbus Driver Studio

NclStringsRepeatedCapabilityNotDefinedAsParameterStyle Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string RepeatedCapabilityNotDefinedAsParameterStyle(
    string repCap
)
internal:
static String^ RepeatedCapabilityNotDefinedAsParameterStyle(
    String^ repCap
)

Parameters

repCap
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.RepeatedCapabilityNotDefinedAsSelectorStyle Method

Pacific MindWorks Nimbus Driver Studio

NclStringsRepeatedCapabilityNotDefinedAsSelectorStyle Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string RepeatedCapabilityNotDefinedAsSelectorStyle(
    string repCap
)
internal:
static String^ RepeatedCapabilityNotDefinedAsSelectorStyle(
    String^ repCap
)

Parameters

repCap
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.SelfTestParseError Method

Pacific MindWorks Nimbus Driver Studio

NclStringsSelfTestParseError Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string SelfTestParseError(
    string response
)
internal:
static String^ SelfTestParseError(
    String^ response
)

Parameters

response
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.SyntaxErrorInPhysicalNamesAttribute Method

Pacific MindWorks Nimbus Driver Studio

NclStringsSyntaxErrorInPhysicalNamesAttribute Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string SyntaxErrorInPhysicalNamesAttribute(
    string className
)
internal:
static String^ SyntaxErrorInPhysicalNamesAttribute(
    String^ className
)

Parameters

className
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.SyntaxErrorInPhysicalNamesListInRepeatedCapabilityAttribute Method

Pacific MindWorks Nimbus Driver Studio

NclStringsSyntaxErrorInPhysicalNamesListInRepeatedCapabilityAttribute Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string SyntaxErrorInPhysicalNamesListInRepeatedCapabilityAttribute(
    string repCap,
    string target
)
internal:
static String^ SyntaxErrorInPhysicalNamesListInRepeatedCapabilityAttribute(
    String^ repCap,
    String^ target
)

Parameters

repCap
Type: SystemString
target
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.SyntaxErrorInRepCapSelector Method

Pacific MindWorks Nimbus Driver Studio

NclStringsSyntaxErrorInRepCapSelector Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string SyntaxErrorInRepCapSelector(
    string selector
)
internal:
static String^ SyntaxErrorInRepCapSelector(
    String^ selector
)

Parameters

selector
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.ValidationExpressionInvalid Method

Pacific MindWorks Nimbus Driver Studio

NclStringsValidationExpressionInvalid Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string ValidationExpressionInvalid(
    string exceptionMessage
)
internal:
static String^ ValidationExpressionInvalid(
    String^ exceptionMessage
)

Parameters

exceptionMessage
Type: SystemString

Return Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings Fields

The NclStrings type exposes the following members.

Fields
Name | Description
CannotReadMutipleRepCaps |
ConfigurableInitialSettingAttributeDuplicateKeyNameResolution |
ConfigurableInitialSettingAttributeKeyNameEmptyMessage |
ConfigurableInitialSettingAttributeKeyNameEmptyResolution |
CouldNotPerformErrorQuery |
CouldNotPerformSelfTest |
DefaultModelMustBeInInstrumentModelsList |
DriverSessionAndCapabilitiesAttributesRequireConsistentInterchangeChecking |
DuplicateFamiliesInInstrumentModelsAttributes |
DuplicateInstrumentClassNames |
DuplicateModelsInInstrumentModelsAttributes |
ErrorQueryNoError |
FamilyCannotBeSetToModel |
IndexPropertyNotAvailable |
InstrumentModelsAttributeMustSpecifyDefaultModel |
MustSpecifyPrimaryInstrumentClass |
NestedRepeatedCapabilitiesInvalidParentResolution |
NoInstrumentModelDeclarationsFound |
OneInstrumentModelsAttributeMustSpecifyDefaultModel |
OnlyOneInstrumentModelsAttributeCanSpecifyDefaultModel |
OnlyOneSupportedInstrumentClassAttributeCanSpecifyPrimary |
OperationRequiresSingleEntryCacheKey |
PhysicalNamePropertyNotAvailable |
RangeCheckDiscreteNaNResolution |
RangeCheckDuplicateAllowedValuesResolution |
RangeCheckEmptyAllowedValuesResolution |
RangeCheckMinNotLessThanMaxResolution |
SelectorNameRequired |
SelfTestPassed |
SimulationDefaultValueShouldBeSpecified |
SingleRepeatedCapbilityIdentifierRequired |
SyntaxErrorInCacheKey |
VirtualNamePropertyNotAvailable |
Top
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.CannotReadMutipleRepCaps Field

Pacific MindWorks Nimbus Driver Studio

NclStringsCannotReadMutipleRepCaps Field

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal const string CannotReadMutipleRepCaps = "The active repeated capability selector cannot specify more than one physical name when performing a get operation."
internal:
literal String^ CannotReadMutipleRepCaps = "The active repeated capability selector cannot specify more than one physical name when performing a get operation."

Field Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.ConfigurableInitialSettingAttributeDuplicateKeyNameResolution Field

Pacific MindWorks Nimbus Driver Studio

NclStringsConfigurableInitialSettingAttributeDuplicateKeyNameResolution Field

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal const string ConfigurableInitialSettingAttributeDuplicateKeyNameResolution = "Ensure that unique key names are used."
internal:
literal String^ ConfigurableInitialSettingAttributeDuplicateKeyNameResolution = "Ensure that unique key names are used."

Field Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.ConfigurableInitialSettingAttributeKeyNameEmptyMessage Field

Pacific MindWorks Nimbus Driver Studio

NclStringsConfigurableInitialSettingAttributeKeyNameEmptyMessage Field

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal const string ConfigurableInitialSettingAttributeKeyNameEmptyMessage = "Key names used with ConfigurableInitialSetting attribute cannot be empty or null."
internal:
literal String^ ConfigurableInitialSettingAttributeKeyNameEmptyMessage = "Key names used with ConfigurableInitialSetting attribute cannot be empty or null."

Field Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.ConfigurableInitialSettingAttributeKeyNameEmptyResolution Field

Pacific MindWorks Nimbus Driver Studio

NclStringsConfigurableInitialSettingAttributeKeyNameEmptyResolution Field

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal const string ConfigurableInitialSettingAttributeKeyNameEmptyResolution = "Remove or correct the ConfigurableInitialSetting attribute that has an empty or null key name."
internal:
literal String^ ConfigurableInitialSettingAttributeKeyNameEmptyResolution = "Remove or correct the ConfigurableInitialSetting attribute that has an empty or null key name."

Field Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.CouldNotPerformErrorQuery Field

Pacific MindWorks Nimbus Driver Studio

NclStringsCouldNotPerformErrorQuery Field

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal const string CouldNotPerformErrorQuery = "Could not perform error query."
internal:
literal String^ CouldNotPerformErrorQuery = "Could not perform error query."

Field Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.CouldNotPerformSelfTest Field

Pacific MindWorks Nimbus Driver Studio

NclStringsCouldNotPerformSelfTest Field

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal const string CouldNotPerformSelfTest = "Could not perform self test."
internal:
literal String^ CouldNotPerformSelfTest = "Could not perform self test."

Field Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.DefaultModelMustBeInInstrumentModelsList Field

Pacific MindWorks Nimbus Driver Studio

NclStringsDefaultModelMustBeInInstrumentModelsList Field

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal const string DefaultModelMustBeInInstrumentModelsList = "The DefaultModelForSimulation must be set to one of the models listed in the InstrumentModels attribute."
internal:
literal String^ DefaultModelMustBeInInstrumentModelsList = "The DefaultModelForSimulation must be set to one of the models listed in the InstrumentModels attribute."

Field Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.DriverSessionAndCapabilitiesAttributesRequireConsistentInterchangeChecking Field

Pacific MindWorks Nimbus Driver Studio

NclStringsDriverSessionAndCapabilitiesAttributesRequireConsistentInterchangeChecking Field

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal const string DriverSessionAndCapabilitiesAttributesRequireConsistentInterchangeChecking = "Update the DriverCapabilities attribute to indicate interchange checking is supported, or remove interchange checking from the DriverSession attribute."
internal:
literal String^ DriverSessionAndCapabilitiesAttributesRequireConsistentInterchangeChecking = "Update the DriverCapabilities attribute to indicate interchange checking is supported, or remove interchange checking from the DriverSession attribute."

Field Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.DuplicateFamiliesInInstrumentModelsAttributes Field

Pacific MindWorks Nimbus Driver Studio

NclStringsDuplicateFamiliesInInstrumentModelsAttributes Field

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal const string DuplicateFamiliesInInstrumentModelsAttributes = "The InstrumentModels attributes contain duplicate family names."
internal:
literal String^ DuplicateFamiliesInInstrumentModelsAttributes = "The InstrumentModels attributes contain duplicate family names."

Field Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.DuplicateInstrumentClassNames Field

Pacific MindWorks Nimbus Driver Studio

NclStringsDuplicateInstrumentClassNames Field

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal const string DuplicateInstrumentClassNames = "The SupportedInstrumentClass attribute contains duplicate instrument class names."
internal:
literal String^ DuplicateInstrumentClassNames = "The SupportedInstrumentClass attribute contains duplicate instrument class names."

Field Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.DuplicateModelsInInstrumentModelsAttributes Field

Pacific MindWorks Nimbus Driver Studio

NclStringsDuplicateModelsInInstrumentModelsAttributes Field

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal const string DuplicateModelsInInstrumentModelsAttributes = "The InstrumentModels attributes contain duplicate model names."
internal:
literal String^ DuplicateModelsInInstrumentModelsAttributes = "The InstrumentModels attributes contain duplicate model names."

Field Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.ErrorQueryNoError Field

Pacific MindWorks Nimbus Driver Studio

NclStringsErrorQueryNoError Field

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal const string ErrorQueryNoError = "No error."
internal:
literal String^ ErrorQueryNoError = "No error."

Field Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.FamilyCannotBeSetToModel Field

Pacific MindWorks Nimbus Driver Studio

NclStringsFamilyCannotBeSetToModel Field

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal const string FamilyCannotBeSetToModel = "The Family cannot be set to one of the specified models."
internal:
literal String^ FamilyCannotBeSetToModel = "The Family cannot be set to one of the specified models."

Field Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.IndexPropertyNotAvailable Field

Pacific MindWorks Nimbus Driver Studio

NclStringsIndexPropertyNotAvailable Field

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal const string IndexPropertyNotAvailable = "The Index property is only available on repeated capabilities."
internal:
literal String^ IndexPropertyNotAvailable = "The Index property is only available on repeated capabilities."

Field Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.InstrumentModelsAttributeMustSpecifyDefaultModel Field

Pacific MindWorks Nimbus Driver Studio

NclStringsInstrumentModelsAttributeMustSpecifyDefaultModel Field

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal const string InstrumentModelsAttributeMustSpecifyDefaultModel = "The InstrumentModels attribute must specify the DefaultModelForSimulation."
internal:
literal String^ InstrumentModelsAttributeMustSpecifyDefaultModel = "The InstrumentModels attribute must specify the DefaultModelForSimulation."

Field Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.MustSpecifyPrimaryInstrumentClass Field

Pacific MindWorks Nimbus Driver Studio

NclStringsMustSpecifyPrimaryInstrumentClass Field

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal const string MustSpecifyPrimaryInstrumentClass = "One SupportedInstrumentClass attribute must specify the primary instrument class."
internal:
literal String^ MustSpecifyPrimaryInstrumentClass = "One SupportedInstrumentClass attribute must specify the primary instrument class."

Field Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.NestedRepeatedCapabilitiesInvalidParentResolution Field

Pacific MindWorks Nimbus Driver Studio

NclStringsNestedRepeatedCapabilitiesInvalidParentResolution Field

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal const string NestedRepeatedCapabilitiesInvalidParentResolution = "Correct the repeated capability name so that a valid parent repeated capability name is specified."
internal:
literal String^ NestedRepeatedCapabilitiesInvalidParentResolution = "Correct the repeated capability name so that a valid parent repeated capability name is specified."

Field Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.NoInstrumentModelDeclarationsFound Field

Pacific MindWorks Nimbus Driver Studio

NclStringsNoInstrumentModelDeclarationsFound Field

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal const string NoInstrumentModelDeclarationsFound = "No instrument model declarations could be located for the driver."
internal:
literal String^ NoInstrumentModelDeclarationsFound = "No instrument model declarations could be located for the driver."

Field Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.OneInstrumentModelsAttributeMustSpecifyDefaultModel Field

Pacific MindWorks Nimbus Driver Studio

NclStringsOneInstrumentModelsAttributeMustSpecifyDefaultModel Field

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal const string OneInstrumentModelsAttributeMustSpecifyDefaultModel = "One InstrumentModels attribute must specify the DefaultModelForSimulation."
internal:
literal String^ OneInstrumentModelsAttributeMustSpecifyDefaultModel = "One InstrumentModels attribute must specify the DefaultModelForSimulation."

Field Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.OnlyOneInstrumentModelsAttributeCanSpecifyDefaultModel Field

Pacific MindWorks Nimbus Driver Studio

NclStringsOnlyOneInstrumentModelsAttributeCanSpecifyDefaultModel Field

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal const string OnlyOneInstrumentModelsAttributeCanSpecifyDefaultModel = "Only one InstrumentModels attribute can specify the default model for simulation."
internal:
literal String^ OnlyOneInstrumentModelsAttributeCanSpecifyDefaultModel = "Only one InstrumentModels attribute can specify the default model for simulation."

Field Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.OnlyOneSupportedInstrumentClassAttributeCanSpecifyPrimary Field

Pacific MindWorks Nimbus Driver Studio

NclStringsOnlyOneSupportedInstrumentClassAttributeCanSpecifyPrimary Field

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal const string OnlyOneSupportedInstrumentClassAttributeCanSpecifyPrimary = "Only one SupportedInstrumentClass attribute can specify the primary instrument class."
internal:
literal String^ OnlyOneSupportedInstrumentClassAttributeCanSpecifyPrimary = "Only one SupportedInstrumentClass attribute can specify the primary instrument class."

Field Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.OperationRequiresSingleEntryCacheKey Field

Pacific MindWorks Nimbus Driver Studio

NclStringsOperationRequiresSingleEntryCacheKey Field

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal const string OperationRequiresSingleEntryCacheKey = "Invalid cache key.The current operation requires a cache key that specifies only a single entry."
internal:
literal String^ OperationRequiresSingleEntryCacheKey = "Invalid cache key.The current operation requires a cache key that specifies only a single entry."

Field Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.PhysicalNamePropertyNotAvailable Field

Pacific MindWorks Nimbus Driver Studio

NclStringsPhysicalNamePropertyNotAvailable Field

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal const string PhysicalNamePropertyNotAvailable = "The PhysicalName property is only available on repeated capabilities."
internal:
literal String^ PhysicalNamePropertyNotAvailable = "The PhysicalName property is only available on repeated capabilities."

Field Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.RangeCheckDiscreteNaNResolution Field

Pacific MindWorks Nimbus Driver Studio

NclStringsRangeCheckDiscreteNaNResolution Field

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal const string RangeCheckDiscreteNaNResolution = "Correct or remove the invalid floating point value."
internal:
literal String^ RangeCheckDiscreteNaNResolution = "Correct or remove the invalid floating point value."

Field Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.RangeCheckDuplicateAllowedValuesResolution Field

Pacific MindWorks Nimbus Driver Studio

NclStringsRangeCheckDuplicateAllowedValuesResolution Field

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal const string RangeCheckDuplicateAllowedValuesResolution = "Each item listed in AllowedValues must be unique."
internal:
literal String^ RangeCheckDuplicateAllowedValuesResolution = "Each item listed in AllowedValues must be unique."

Field Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.RangeCheckEmptyAllowedValuesResolution Field

Pacific MindWorks Nimbus Driver Studio

NclStringsRangeCheckEmptyAllowedValuesResolution Field

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal const string RangeCheckEmptyAllowedValuesResolution = "At least one value must be specified for the AllowedValues property."
internal:
literal String^ RangeCheckEmptyAllowedValuesResolution = "At least one value must be specified for the AllowedValues property."

Field Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.RangeCheckMinNotLessThanMaxResolution Field

Pacific MindWorks Nimbus Driver Studio

NclStringsRangeCheckMinNotLessThanMaxResolution Field

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal const string RangeCheckMinNotLessThanMaxResolution = "The value specified for Min must be less than the value specified for Max."
internal:
literal String^ RangeCheckMinNotLessThanMaxResolution = "The value specified for Min must be less than the value specified for Max."

Field Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.SelectorNameRequired Field

Pacific MindWorks Nimbus Driver Studio

NclStringsSelectorNameRequired Field

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal const string SelectorNameRequired = "The repeated capability selector name is required."
internal:
literal String^ SelectorNameRequired = "The repeated capability selector name is required."

Field Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.SelfTestPassed Field

Pacific MindWorks Nimbus Driver Studio

NclStringsSelfTestPassed Field

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal const string SelfTestPassed = "Self test passed."
internal:
literal String^ SelfTestPassed = "Self test passed."

Field Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.SimulationDefaultValueShouldBeSpecified Field

Pacific MindWorks Nimbus Driver Studio

NclStringsSimulationDefaultValueShouldBeSpecified Field

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal const string SimulationDefaultValueShouldBeSpecified = "The Default value for the Simulation attribute should be specified when the mode is ConstantValue or LastValueSet."
internal:
literal String^ SimulationDefaultValueShouldBeSpecified = "The Default value for the Simulation attribute should be specified when the mode is ConstantValue or LastValueSet."

Field Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.SingleRepeatedCapbilityIdentifierRequired Field

Pacific MindWorks Nimbus Driver Studio

NclStringsSingleRepeatedCapbilityIdentifierRequired Field

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal const string SingleRepeatedCapbilityIdentifierRequired = "Only a single repeated capability identifier can be specified for the current operation."
internal:
literal String^ SingleRepeatedCapbilityIdentifierRequired = "Only a single repeated capability identifier can be specified for the current operation."

Field Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.SyntaxErrorInCacheKey Field

Pacific MindWorks Nimbus Driver Studio

NclStringsSyntaxErrorInCacheKey Field

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal const string SyntaxErrorInCacheKey = "Syntax error in cache key."
internal:
literal String^ SyntaxErrorInCacheKey = "Syntax error in cache key."

Field Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NclStrings.VirtualNamePropertyNotAvailable Field

Pacific MindWorks Nimbus Driver Studio

NclStringsVirtualNamePropertyNotAvailable Field

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal const string VirtualNamePropertyNotAvailable = "The VirtualName property is only available on repeated capabilities."
internal:
literal String^ VirtualNamePropertyNotAvailable = "The VirtualName property is only available on repeated capabilities."

Field Value

Type: String
See Also

Reference

NclStrings Class
MindWorks.Nimbus Namespace


NimbusAttribute Class

Inheritance Hierarchy
SystemObject
SystemAttribute
MindWorks.NimbusNimbusAttribute
More...

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal abstract class NimbusAttribute : Attribute
internal ref class NimbusAttribute abstract : public Attribute

The NimbusAttribute type exposes the following members.

Constructors
 | Name | Description
Protected method | NimbusAttribute | Initializes a new instance of the NimbusAttribute class
Top
See Also

Reference

MindWorks.Nimbus Namespace
Inheritance Hierarchy
SystemObject
SystemAttribute
MindWorks.NimbusNimbusAttribute
MindWorks.NimbusBooleanCommandAttribute
MindWorks.NimbusConfigurableInitialSettingAttribute
MindWorks.NimbusDriverCapabilitiesAttribute
MindWorks.NimbusDriverDescriptionAttribute
MindWorks.NimbusDriverSessionAttribute
MindWorks.NimbusHardwareAssetAttribute
MindWorks.NimbusInstrumentFamiliesAttribute
MindWorks.NimbusInstrumentModelsAttribute
MindWorks.NimbusLogicalNameAttribute
MindWorks.NimbusModelSpecificNimbusAttribute
MindWorks.NimbusNimbusCodeWeaverAttribute
MindWorks.NimbusPhysicalNamesAttribute
MindWorks.NimbusRepeatedCapabilityAttribute
MindWorks.NimbusSCPICompliantAttribute
MindWorks.NimbusSupportedInstrumentClassAttribute


NimbusAttribute Constructor

Initializes a new instance of the NimbusAttribute class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected NimbusAttribute()
protected:
NimbusAttribute()
See Also

Reference

NimbusAttribute Class
MindWorks.Nimbus Namespace


NimbusCodeWeaverAttribute Class

Inheritance Hierarchy
SystemObject
SystemAttribute
MindWorks.NimbusNimbusAttribute
MindWorks.NimbusNimbusCodeWeaverAttribute
More...

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal abstract class NimbusCodeWeaverAttribute : NimbusAttribute
internal ref class NimbusCodeWeaverAttribute abstract : public NimbusAttribute

The NimbusCodeWeaverAttribute type exposes the following members.

Constructors
 | Name | Description
Protected method | NimbusCodeWeaverAttribute | Initializes a new instance of the NimbusCodeWeaverAttribute class
Top
Properties
 | Name | Description
Public property | SuppressAll |
Top
See Also

Reference

MindWorks.Nimbus Namespace
Inheritance Hierarchy
SystemObject
SystemAttribute
MindWorks.NimbusNimbusAttribute
MindWorks.NimbusNimbusCodeWeaverAttribute
MindWorks.NimbusCacheAttribute
MindWorks.NimbusDriverMemberAttribute
MindWorks.NimbusInvalidateCacheEntriesAttribute
MindWorks.NimbusModelSpecificNimbusCodeWeaverAttribute
MindWorks.NimbusNotSupportedAttribute
MindWorks.NimbusNullAllowedAttribute


NimbusCodeWeaverAttribute Constructor

Initializes a new instance of the NimbusCodeWeaverAttribute class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected NimbusCodeWeaverAttribute()
protected:
NimbusCodeWeaverAttribute()
See Also

Reference

NimbusCodeWeaverAttribute Class
MindWorks.Nimbus Namespace


NimbusCodeWeaverAttribute Properties

The NimbusCodeWeaverAttribute type exposes the following members.

Properties
 | Name | Description
Public property | SuppressAll |
Top
See Also

Reference

NimbusCodeWeaverAttribute Class
MindWorks.Nimbus Namespace


NimbusCodeWeaverAttribute.SuppressAll Property

Pacific MindWorks Nimbus Driver Studio

NimbusCodeWeaverAttributeSuppressAll Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public bool SuppressAll { get; set; }
public:
property bool SuppressAll {
    bool get ();
    void set (bool value);
}

Property Value

Type: Boolean
See Also

Reference

NimbusCodeWeaverAttribute Class
MindWorks.Nimbus Namespace


NotSupportedAttribute Class

Inheritance Hierarchy
SystemObject
SystemAttribute
MindWorks.NimbusNimbusAttribute
MindWorks.NimbusNimbusCodeWeaverAttribute
MindWorks.NimbusNotSupportedAttribute

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal sealed class NotSupportedAttribute : NimbusCodeWeaverAttribute
internal ref class NotSupportedAttribute sealed : public NimbusCodeWeaverAttribute

The NotSupportedAttribute type exposes the following members.

Constructors
 | Name | Description
Protected method | NotSupportedAttribute | Initializes a new instance of the NotSupportedAttribute class
Top
Properties
 | Name | Description
Public property | SuppressAll | (Inherited from NimbusCodeWeaverAttribute.)
Protected property | UnsupportedModelsAndFamilies |
Top
See Also

Reference

MindWorks.Nimbus Namespace


NotSupportedAttribute Constructor

Initializes a new instance of the NotSupportedAttribute class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal NotSupportedAttribute(
    params string[] unsupportedModelsAndFamilies
)
internal:
NotSupportedAttribute(
    ... array<String^>^ unsupportedModelsAndFamilies
)

Parameters

unsupportedModelsAndFamilies
Type: SystemString
See Also

Reference

NotSupportedAttribute Class
MindWorks.Nimbus Namespace


NotSupportedAttribute Properties

The NotSupportedAttribute type exposes the following members.

Properties
 | Name | Description
Public property | SuppressAll | (Inherited from NimbusCodeWeaverAttribute.)
Protected property | UnsupportedModelsAndFamilies |
Top
See Also

Reference

NotSupportedAttribute Class
MindWorks.Nimbus Namespace


NotSupportedAttribute.UnsupportedModelsAndFamilies Property

Pacific MindWorks Nimbus Driver Studio

NotSupportedAttributeUnsupportedModelsAndFamilies Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal IList<string> UnsupportedModelsAndFamilies { get; }
internal:
property IList<String^>^ UnsupportedModelsAndFamilies {
    IList<String^>^ get ();
}

Property Value

Type: IList String
See Also

Reference

NotSupportedAttribute Class
MindWorks.Nimbus Namespace


NullAllowedAttribute Class

Inheritance Hierarchy
SystemObject
SystemAttribute
MindWorks.NimbusNimbusAttribute
MindWorks.NimbusNimbusCodeWeaverAttribute
MindWorks.NimbusNullAllowedAttribute

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal sealed class NullAllowedAttribute : NimbusCodeWeaverAttribute
internal ref class NullAllowedAttribute sealed : public NimbusCodeWeaverAttribute

The NullAllowedAttribute type exposes the following members.

Constructors
 | Name | Description
Public method | NullAllowedAttribute | Initializes a new instance of the NullAllowedAttribute class
Top
Properties
 | Name | Description
Public property | SuppressAll | (Inherited from NimbusCodeWeaverAttribute.)
Top
See Also

Reference

MindWorks.Nimbus Namespace


NullAllowedAttribute Constructor

Initializes a new instance of the NullAllowedAttribute class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public NullAllowedAttribute()
public:
NullAllowedAttribute()
See Also

Reference

NullAllowedAttribute Class
MindWorks.Nimbus Namespace


NullAllowedAttribute Properties

The NullAllowedAttribute type exposes the following members.

Properties
 | Name | Description
Public property | SuppressAll | (Inherited from NimbusCodeWeaverAttribute.)
Top
See Also

Reference

NullAllowedAttribute Class
MindWorks.Nimbus Namespace


ParameterStyleRepCapManager Class

Inheritance Hierarchy
SystemObject
MindWorks.NimbusRepCapManager
MindWorks.NimbusParameterStyleRepCapManager

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public class ParameterStyleRepCapManager : RepCapManager
public ref class ParameterStyleRepCapManager : public RepCapManager

The ParameterStyleRepCapManager type exposes the following members.

Constructors
 | Name | Description
Protected method | ParameterStyleRepCapManager | Initializes a new instance of the ParameterStyleRepCapManager class
Top
Properties
 | Name | Description
Protected property | Parent | (Inherited from RepCapManager.)
Protected property | PhysicalNames | (Inherited from RepCapManager.)
Protected property | RepCapName | (Inherited from RepCapManager.)
Protected property | Session | (Inherited from RepCapManager.)
Protected property | UseQualifiedPhysicalNames | (Inherited from RepCapManager.)
Top
Methods
 | Name | Description
Protected method | AddPhysicalName | (Inherited from RepCapManager.)
Protected method | ExpandSelector | (Inherited from RepCapManager.)
Protected method | GetNumberOfAncestors | (Inherited from RepCapManager.)
Protected method | IsPhysicalNameDefined | (Inherited from RepCapManager.)
Protected method | LookupPhysicalName | (Inherited from RepCapManager.)
Protected method | RemovePhysicalName | (Inherited from RepCapManager.)
Protected method | TryLookupPhysicalName | (Inherited from RepCapManager.)
Top
See Also

Reference

MindWorks.Nimbus Namespace


ParameterStyleRepCapManager Constructor

Initializes a new instance of the ParameterStyleRepCapManager class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal ParameterStyleRepCapManager(
    string repCapName,
    SessionInfo session,
    bool useQualifiedPhysicalNames,
    IRepCapManager parent
)
internal:
ParameterStyleRepCapManager(
    String^ repCapName,
    SessionInfo^ session,
    bool useQualifiedPhysicalNames,
    IRepCapManager^ parent
)

Parameters

repCapName
Type: SystemString
session
Type: MindWorks.NimbusSessionInfo
useQualifiedPhysicalNames
Type: SystemBoolean
parent
Type: IRepCapManager
See Also

Reference

ParameterStyleRepCapManager Class
MindWorks.Nimbus Namespace


ParameterStyleRepCapManager Properties

The ParameterStyleRepCapManager type exposes the following members.

Properties
 | Name | Description
Protected property | Parent | (Inherited from RepCapManager.)
Protected property | PhysicalNames | (Inherited from RepCapManager.)
Protected property | RepCapName | (Inherited from RepCapManager.)
Protected property | Session | (Inherited from RepCapManager.)
Protected property | UseQualifiedPhysicalNames | (Inherited from RepCapManager.)
Top
See Also

Reference

ParameterStyleRepCapManager Class
MindWorks.Nimbus Namespace


ParameterStyleRepCapManager Methods

The ParameterStyleRepCapManager type exposes the following members.

Methods
 | Name | Description
Protected method | AddPhysicalName | (Inherited from RepCapManager.)
Protected method | ExpandSelector | (Inherited from RepCapManager.)
Protected method | GetNumberOfAncestors | (Inherited from RepCapManager.)
Protected method | IsPhysicalNameDefined | (Inherited from RepCapManager.)
Protected method | LookupPhysicalName | (Inherited from RepCapManager.)
Protected method | RemovePhysicalName | (Inherited from RepCapManager.)
Protected method | TryLookupPhysicalName | (Inherited from RepCapManager.)
Top
See Also

Reference

ParameterStyleRepCapManager Class
MindWorks.Nimbus Namespace


PhysicalName Class

Inheritance Hierarchy
SystemObject
MindWorks.NimbusPhysicalName

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal class PhysicalName
internal ref class PhysicalName

The PhysicalName type exposes the following members.

Constructors
 | Name | Description
Protected method | PhysicalName | Initializes a new instance of the PhysicalName class
Top
Properties
 | Name | Description
Protected property | ExportedName |
Protected property | FullName |
Protected property | Index |
Protected property | Manager |
Protected property | Name |
Protected property | Parent |
Protected property | QualifiedFullName |
Protected property | QualifiedName |
Top
See Also

Reference

MindWorks.Nimbus Namespace


PhysicalName Constructor

Initializes a new instance of the PhysicalName class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal PhysicalName(
    string fullName,
    IRepCapManager manager
)
internal:
PhysicalName(
    String^ fullName,
    IRepCapManager^ manager
)

Parameters

fullName
Type: SystemString
manager
Type: IRepCapManager
See Also

Reference

PhysicalName Class
MindWorks.Nimbus Namespace


PhysicalName Properties

The PhysicalName type exposes the following members.

Properties
 | Name | Description
Protected property | ExportedName |
Protected property | FullName |
Protected property | Index |
Protected property | Manager |
Protected property | Name |
Protected property | Parent |
Protected property | QualifiedFullName |
Protected property | QualifiedName |
Top
See Also

Reference

PhysicalName Class
MindWorks.Nimbus Namespace


PhysicalName.ExportedName Property

Pacific MindWorks Nimbus Driver Studio

PhysicalNameExportedName Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal string ExportedName { get; }
internal:
property String^ ExportedName {
    String^ get ();
}

Property Value

Type: String
See Also

Reference

PhysicalName Class
MindWorks.Nimbus Namespace


PhysicalName.FullName Property

Pacific MindWorks Nimbus Driver Studio

PhysicalNameFullName Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal string FullName { get; }
internal:
property String^ FullName {
    String^ get ();
}

Property Value

Type: String
See Also

Reference

PhysicalName Class
MindWorks.Nimbus Namespace


PhysicalName.Index Property

Pacific MindWorks Nimbus Driver Studio

PhysicalNameIndex Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal int Index { get; }
internal:
property int Index {
    int get ();
}

Property Value

Type: Int32
See Also

Reference

PhysicalName Class
MindWorks.Nimbus Namespace


PhysicalName.Manager Property

Pacific MindWorks Nimbus Driver Studio

PhysicalNameManager Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal IRepCapManager Manager { get; }
internal:
property IRepCapManager^ Manager {
    IRepCapManager^ get ();
}

Property Value

Type: IRepCapManager
See Also

Reference

PhysicalName Class
MindWorks.Nimbus Namespace


PhysicalName.Name Property

Pacific MindWorks Nimbus Driver Studio

PhysicalNameName Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal string Name { get; }
internal:
property String^ Name {
    String^ get ();
}

Property Value

Type: String
See Also

Reference

PhysicalName Class
MindWorks.Nimbus Namespace


PhysicalName.Parent Property

Pacific MindWorks Nimbus Driver Studio

PhysicalNameParent Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal PhysicalName Parent { get; }
internal:
property PhysicalName^ Parent {
    PhysicalName^ get ();
}

Property Value

Type: PhysicalName
See Also

Reference

PhysicalName Class
MindWorks.Nimbus Namespace


PhysicalName.QualifiedFullName Property

Pacific MindWorks Nimbus Driver Studio

PhysicalNameQualifiedFullName Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal string QualifiedFullName { get; }
internal:
property String^ QualifiedFullName {
    String^ get ();
}

Property Value

Type: String
See Also

Reference

PhysicalName Class
MindWorks.Nimbus Namespace


PhysicalName.QualifiedName Property

Pacific MindWorks Nimbus Driver Studio

PhysicalNameQualifiedName Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal string QualifiedName { get; }
internal:
property String^ QualifiedName {
    String^ get ();
}

Property Value

Type: String
See Also

Reference

PhysicalName Class
MindWorks.Nimbus Namespace


PhysicalNamesAttribute Class

Inheritance Hierarchy
SystemObject
SystemAttribute
MindWorks.NimbusNimbusAttribute
MindWorks.NimbusPhysicalNamesAttribute

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal sealed class PhysicalNamesAttribute : NimbusAttribute
internal ref class PhysicalNamesAttribute sealed : public NimbusAttribute

The PhysicalNamesAttribute type exposes the following members.

Constructors
 | Name | Description
Public method | PhysicalNamesAttribute | Initializes a new instance of the PhysicalNamesAttribute class
Top
Properties
 | Name | Description
Protected property | PhysicalNames |
Public property | UseQualifiedNames |
Top
See Also

Reference

MindWorks.Nimbus Namespace


PhysicalNamesAttribute Constructor

Initializes a new instance of the PhysicalNamesAttribute class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public PhysicalNamesAttribute(
    string physicalNames
)
public:
PhysicalNamesAttribute(
    String^ physicalNames
)

Parameters

physicalNames
Type: SystemString
See Also

Reference

PhysicalNamesAttribute Class
MindWorks.Nimbus Namespace


PhysicalNamesAttribute Properties

The PhysicalNamesAttribute type exposes the following members.

Properties
 | Name | Description
Protected property | PhysicalNames |
Public property | UseQualifiedNames |
Top
See Also

Reference

PhysicalNamesAttribute Class
MindWorks.Nimbus Namespace


PhysicalNamesAttribute.PhysicalNames Property

Pacific MindWorks Nimbus Driver Studio

PhysicalNamesAttributePhysicalNames Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal string PhysicalNames { get; }
internal:
property String^ PhysicalNames {
    String^ get ();
}

Property Value

Type: String
See Also

Reference

PhysicalNamesAttribute Class
MindWorks.Nimbus Namespace


PhysicalNamesAttribute.UseQualifiedNames Property

Pacific MindWorks Nimbus Driver Studio

PhysicalNamesAttributeUseQualifiedNames Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public bool UseQualifiedNames { get; set; }
public:
property bool UseQualifiedNames {
    bool get ();
    void set (bool value);
}

Property Value

Type: Boolean
See Also

Reference

PhysicalNamesAttribute Class
MindWorks.Nimbus Namespace


RangeCheckDiscreteAttribute Class

Inheritance Hierarchy
SystemObject
SystemAttribute
MindWorks.NimbusNimbusAttribute
MindWorks.NimbusNimbusCodeWeaverAttribute
MindWorks.NimbusModelSpecificNimbusCodeWeaverAttribute
MindWorks.NimbusRangeCheckDiscreteAttribute

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal sealed class RangeCheckDiscreteAttribute : ModelSpecificNimbusCodeWeaverAttribute
internal ref class RangeCheckDiscreteAttribute sealed : public ModelSpecificNimbusCodeWeaverAttribute

The RangeCheckDiscreteAttribute type exposes the following members.

Constructors
 | Name | Description
Protected method | RangeCheckDiscreteAttribute | Initializes a new instance of the RangeCheckDiscreteAttribute class
Top
Properties
 | Name | Description
Public property | AllowedValues |
Public property | CoercionStyle |
Public property | Models | (Inherited from ModelSpecificNimbusCodeWeaverAttribute.)
Public property | SuppressAll | (Inherited from NimbusCodeWeaverAttribute.)
Top
See Also

Reference

MindWorks.Nimbus Namespace


RangeCheckDiscreteAttribute Constructor

Initializes a new instance of the RangeCheckDiscreteAttribute class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal RangeCheckDiscreteAttribute(
    string allowedValues,
    params string[] models
)
internal:
RangeCheckDiscreteAttribute(
    String^ allowedValues,
    ... array<String^>^ models
)

Parameters

allowedValues
Type: SystemString
models
Type: SystemString
See Also

Reference

RangeCheckDiscreteAttribute Class
MindWorks.Nimbus Namespace


RangeCheckDiscreteAttribute Properties

The RangeCheckDiscreteAttribute type exposes the following members.

Properties
 | Name | Description
Public property | AllowedValues |
Public property | CoercionStyle |
Public property | Models | (Inherited from ModelSpecificNimbusCodeWeaverAttribute.)
Public property | SuppressAll | (Inherited from NimbusCodeWeaverAttribute.)
Top
See Also

Reference

RangeCheckDiscreteAttribute Class
MindWorks.Nimbus Namespace


RangeCheckDiscreteAttribute.AllowedValues Property

Pacific MindWorks Nimbus Driver Studio

RangeCheckDiscreteAttributeAllowedValues Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public IEnumerable<double> AllowedValues { get; }
public:
property IEnumerable<double>^ AllowedValues {
    IEnumerable<double>^ get ();
}

Property Value

Type: IEnumerable Double
See Also

Reference

RangeCheckDiscreteAttribute Class
MindWorks.Nimbus Namespace


RangeCheckDiscreteAttribute.CoercionStyle Property

Pacific MindWorks Nimbus Driver Studio

RangeCheckDiscreteAttributeCoercionStyle Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public CoercionStyle CoercionStyle { get; set; }
public:
property CoercionStyle CoercionStyle {
    CoercionStyle get ();
    void set (CoercionStyle value);
}

Property Value

Type: CoercionStyle
See Also

Reference

RangeCheckDiscreteAttribute Class
MindWorks.Nimbus Namespace


RangeCheckMinMaxAttribute Class

Inheritance Hierarchy
SystemObject
SystemAttribute
MindWorks.NimbusNimbusAttribute
MindWorks.NimbusNimbusCodeWeaverAttribute
MindWorks.NimbusModelSpecificNimbusCodeWeaverAttribute
MindWorks.NimbusRangeCheckMinMaxAttribute

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal sealed class RangeCheckMinMaxAttribute : ModelSpecificNimbusCodeWeaverAttribute
internal ref class RangeCheckMinMaxAttribute sealed : public ModelSpecificNimbusCodeWeaverAttribute

The RangeCheckMinMaxAttribute type exposes the following members.

Constructors
 | Name | Description
Protected method | RangeCheckMinMaxAttribute | Initializes a new instance of the RangeCheckMinMaxAttribute class
Top
Properties
 | Name | Description
Public property | Max |
Public property | MaxInclusive |
Public property | Min |
Public property | MinInclusive |
Public property | Models | (Inherited from ModelSpecificNimbusCodeWeaverAttribute.)
Public property | SuppressAll | (Inherited from NimbusCodeWeaverAttribute.)
Top
See Also

Reference

MindWorks.Nimbus Namespace


RangeCheckMinMaxAttribute Constructor

Initializes a new instance of the RangeCheckMinMaxAttribute class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal RangeCheckMinMaxAttribute(
    double min,
    double max,
    params string[] models
)
internal:
RangeCheckMinMaxAttribute(
    double min,
    double max,
    ... array<String^>^ models
)

Parameters

min
Type: SystemDouble
max
Type: SystemDouble
models
Type: SystemString
See Also

Reference

RangeCheckMinMaxAttribute Class
MindWorks.Nimbus Namespace


RangeCheckMinMaxAttribute Properties

The RangeCheckMinMaxAttribute type exposes the following members.

Properties
 | Name | Description
Public property | Max |
Public property | MaxInclusive |
Public property | Min |
Public property | MinInclusive |
Public property | Models | (Inherited from ModelSpecificNimbusCodeWeaverAttribute.)
Public property | SuppressAll | (Inherited from NimbusCodeWeaverAttribute.)
Top
See Also

Reference

RangeCheckMinMaxAttribute Class
MindWorks.Nimbus Namespace


RangeCheckMinMaxAttribute.Max Property

Pacific MindWorks Nimbus Driver Studio

RangeCheckMinMaxAttributeMax Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public double Max { get; }
public:
property double Max {
    double get ();
}

Property Value

Type: Double
See Also

Reference

RangeCheckMinMaxAttribute Class
MindWorks.Nimbus Namespace


RangeCheckMinMaxAttribute.MaxInclusive Property

Pacific MindWorks Nimbus Driver Studio

RangeCheckMinMaxAttributeMaxInclusive Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public bool MaxInclusive { get; set; }
public:
property bool MaxInclusive {
    bool get ();
    void set (bool value);
}

Property Value

Type: Boolean
See Also

Reference

RangeCheckMinMaxAttribute Class
MindWorks.Nimbus Namespace


RangeCheckMinMaxAttribute.Min Property

Pacific MindWorks Nimbus Driver Studio

RangeCheckMinMaxAttributeMin Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public double Min { get; }
public:
property double Min {
    double get ();
}

Property Value

Type: Double
See Also

Reference

RangeCheckMinMaxAttribute Class
MindWorks.Nimbus Namespace


RangeCheckMinMaxAttribute.MinInclusive Property

Pacific MindWorks Nimbus Driver Studio

RangeCheckMinMaxAttributeMinInclusive Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public bool MinInclusive { get; set; }
public:
property bool MinInclusive {
    bool get ();
    void set (bool value);
}

Property Value

Type: Boolean
See Also

Reference

RangeCheckMinMaxAttribute Class
MindWorks.Nimbus Namespace


RangeCheckStringAttribute Class

Inheritance Hierarchy
SystemObject
SystemAttribute
MindWorks.NimbusNimbusAttribute
MindWorks.NimbusNimbusCodeWeaverAttribute
MindWorks.NimbusModelSpecificNimbusCodeWeaverAttribute
MindWorks.NimbusRangeCheckStringAttribute

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal sealed class RangeCheckStringAttribute : ModelSpecificNimbusCodeWeaverAttribute
internal ref class RangeCheckStringAttribute sealed : public ModelSpecificNimbusCodeWeaverAttribute

The RangeCheckStringAttribute type exposes the following members.

Constructors
 | Name | Description
Protected method | RangeCheckStringAttribute | Initializes a new instance of the RangeCheckStringAttribute class
Top
Properties
 | Name | Description
Public property | AllowedValues |
Public property | Models | (Inherited from ModelSpecificNimbusCodeWeaverAttribute.)
Public property | SuppressAll | (Inherited from NimbusCodeWeaverAttribute.)
Top
See Also

Reference

MindWorks.Nimbus Namespace


RangeCheckStringAttribute Constructor

Initializes a new instance of the RangeCheckStringAttribute class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal RangeCheckStringAttribute(
    string allowedValues,
    params string[] models
)
internal:
RangeCheckStringAttribute(
    String^ allowedValues,
    ... array<String^>^ models
)

Parameters

allowedValues
Type: SystemString
models
Type: SystemString
See Also

Reference

RangeCheckStringAttribute Class
MindWorks.Nimbus Namespace


RangeCheckStringAttribute Properties

The RangeCheckStringAttribute type exposes the following members.

Properties
 | Name | Description
Public property | AllowedValues |
Public property | Models | (Inherited from ModelSpecificNimbusCodeWeaverAttribute.)
Public property | SuppressAll | (Inherited from NimbusCodeWeaverAttribute.)
Top
See Also

Reference

RangeCheckStringAttribute Class
MindWorks.Nimbus Namespace


RangeCheckStringAttribute.AllowedValues Property

Pacific MindWorks Nimbus Driver Studio

RangeCheckStringAttributeAllowedValues Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public IEnumerable<string> AllowedValues { get; }
public:
property IEnumerable<String^>^ AllowedValues {
    IEnumerable<String^>^ get ();
}

Property Value

Type: IEnumerable String
See Also

Reference

RangeCheckStringAttribute Class
MindWorks.Nimbus Namespace


RepCap Class

Inheritance Hierarchy
SystemObject
MindWorks.NimbusDriverNode
MindWorks.NimbusRepCap

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal class RepCap : DriverNode, IIviRepeatedCapabilityIdentification
internal ref class RepCap : public DriverNode,
    IIviRepeatedCapabilityIdentification

The RepCap type exposes the following members.

Constructors
 | Name | Description
Public method | RepCap | Initializes a new instance of the RepCap class
Top
Properties
 | Name | Description
Protected property | CacheKeyPrefix | (Overrides DriverNode.CacheKeyPrefix.)
Protected property | CollectionStyleRepCaps | (Inherited from DriverNode.)
Protected property | DriverInfo | (Inherited from DriverNode.)
Protected property | Index |
Protected property | IO | (Inherited from DriverNode.)
Protected property | IsMessageBasedIOSession | (Inherited from DriverNode.)
Protected property | IsRegisterBasedIOSession | (Inherited from DriverNode.)
Public property | Name |
Protected property | ParameterStyleRepCaps | (Inherited from DriverNode.)
Public property | Parent |
Protected property | PhysicalName |
Protected property | PhysicalNameObject |
Protected property | RegisterIO | (Inherited from DriverNode.)
Protected property | Root | (Inherited from DriverNode.)
Protected property | SelectorStyleRepCaps | (Inherited from DriverNode.)
Protected property | Session | (Inherited from DriverNode.)
Protected property | VirtualName |
Protected property | VisaSession | (Inherited from DriverNode.)
Top
Methods
 | Name | Description
Protected method | AcquireLock | (Inherited from DriverNode.)
Protected method | AcquireLock(PrecisionTimeSpan) | (Inherited from DriverNode.)
Protected method | AddPhysicalName | (Inherited from DriverNode.)
Protected method | CacheContainsValue | (Inherited from DriverNode.)
Protected method | CheckDisposed | (Inherited from DriverNode.)
Protected method | ConvertEnumToString | (Inherited from DriverNode.)
Protected method | ConvertStringToEnumTEnum | (Inherited from DriverNode.)
 | CreateInstanceTRepCap |
Protected method | ExpandSelector | (Inherited from DriverNode.)
Protected method | ExpandSingleSelector | (Inherited from DriverNode.)
Protected method | GetActivePhysicalName | (Inherited from DriverNode.)
Protected method | GetActivePhysicalNames | (Inherited from DriverNode.)
Protected method | GetCacheValue(Object) | (Inherited from DriverNode.)
Protected method | GetCacheValueT(T) | (Inherited from DriverNode.)
Protected method | GetCacheValueT(String, T) | (Inherited from DriverNode.)
Protected method | GetDefaultValueForSimulation | (Inherited from DriverNode.)
Protected method | GetDynamicRepCapNames | (Inherited from DriverNode.)
Protected method | GetRepCapManager(String) | (Inherited from DriverNode.)
Protected method | InitNode | (Inherited from DriverNode.)
Protected method | InstrumentInFamily | (Inherited from DriverNode.)
Protected method | InstrumentIsModel | (Inherited from DriverNode.)
Protected method | InvalidateAllCacheEntries | (Inherited from DriverNode.)
Protected method | InvalidateCacheEntry | (Inherited from DriverNode.)
Protected method | PollInstrumentErrors | (Inherited from DriverNode.)
Protected method | RemovePhysicalName | (Inherited from DriverNode.)
Protected method | ResetObjectState | (Inherited from DriverNode.)
Protected method | SendCoercionEvent | (Inherited from DriverNode.)
Protected method | SendInterchangeEvent | (Inherited from DriverNode.)
Protected method | SendWarningEvent | (Inherited from DriverNode.)
Protected method | TryConvertEnumToString | (Inherited from DriverNode.)
Protected method | TryConvertStringToEnumTEnum | (Inherited from DriverNode.)
Protected method | UpdateCacheValue(Object) | (Inherited from DriverNode.)
Protected method | UpdateCacheValue(String, Object) | (Inherited from DriverNode.)
Top
See Also

Reference

MindWorks.Nimbus Namespace


RepCap Constructor

Initializes a new instance of the RepCap class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public RepCap()
public:
RepCap()
See Also

Reference

RepCap Class
MindWorks.Nimbus Namespace


RepCap Properties

The RepCap type exposes the following members.

Properties
 | Name | Description
Protected property | CacheKeyPrefix | (Overrides DriverNode.CacheKeyPrefix.)
Protected property | CollectionStyleRepCaps | (Inherited from DriverNode.)
Protected property | DriverInfo | (Inherited from DriverNode.)
Protected property | Index |
Protected property | IO | (Inherited from DriverNode.)
Protected property | IsMessageBasedIOSession | (Inherited from DriverNode.)
Protected property | IsRegisterBasedIOSession | (Inherited from DriverNode.)
Public property | Name |
Protected property | ParameterStyleRepCaps | (Inherited from DriverNode.)
Public property | Parent |
Protected property | PhysicalName |
Protected property | PhysicalNameObject |
Protected property | RegisterIO | (Inherited from DriverNode.)
Protected property | Root | (Inherited from DriverNode.)
Protected property | SelectorStyleRepCaps | (Inherited from DriverNode.)
Protected property | Session | (Inherited from DriverNode.)
Protected property | VirtualName |
Protected property | VisaSession | (Inherited from DriverNode.)
Top
See Also

Reference

RepCap Class
MindWorks.Nimbus Namespace


RepCap.CacheKeyPrefix Property

Pacific MindWorks Nimbus Driver Studio

RepCapCacheKeyPrefix Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected override string CacheKeyPrefix { get; }
protected:
virtual property String^ CacheKeyPrefix {
    String^ get () override;
}

Property Value

Type: String
See Also

Reference

RepCap Class
MindWorks.Nimbus Namespace


RepCap.Index Property

Pacific MindWorks Nimbus Driver Studio

RepCapIndex Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal int Index { get; set; }
internal:
property int Index {
    int get ();
    void set (int value);
}

Property Value

Type: Int32
See Also

Reference

RepCap Class
MindWorks.Nimbus Namespace


RepCap.Name Property

Pacific MindWorks Nimbus Driver Studio

RepCapName Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public string Name { get; }
public:
virtual property String^ Name {
    String^ get () sealed;
}

Property Value

Type: String

Implements

IIviRepeatedCapabilityIdentification.Name
See Also

Reference

RepCap Class
MindWorks.Nimbus Namespace


RepCap.Parent Property

Pacific MindWorks Nimbus Driver Studio

RepCapParent Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public RepCapCollection Parent { get; }
public:
property RepCapCollection^ Parent {
    RepCapCollection^ get ();
}

Property Value

Type: RepCapCollection
See Also

Reference

RepCap Class
MindWorks.Nimbus Namespace


RepCap.PhysicalName Property

Pacific MindWorks Nimbus Driver Studio

RepCapPhysicalName Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal string PhysicalName { get; }
internal:
property String^ PhysicalName {
    String^ get ();
}

Property Value

Type: String
See Also

Reference

RepCap Class
MindWorks.Nimbus Namespace


RepCap.PhysicalNameObject Property

Pacific MindWorks Nimbus Driver Studio

RepCapPhysicalNameObject Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal PhysicalName PhysicalNameObject { get; }
internal:
property PhysicalName^ PhysicalNameObject {
    PhysicalName^ get ();
}

Property Value

Type: PhysicalName
See Also

Reference

RepCap Class
MindWorks.Nimbus Namespace


RepCap.VirtualName Property

Pacific MindWorks Nimbus Driver Studio

RepCapVirtualName Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal string VirtualName { get; }
internal:
property String^ VirtualName {
    String^ get ();
}

Property Value

Type: String
See Also

Reference

RepCap Class
MindWorks.Nimbus Namespace


RepCap Methods

The RepCap type exposes the following members.

Methods
 | Name | Description
Protected method | AcquireLock | (Inherited from DriverNode.)
Protected method | AcquireLock(PrecisionTimeSpan) | (Inherited from DriverNode.)
Protected method | AddPhysicalName | (Inherited from DriverNode.)
Protected method | CacheContainsValue | (Inherited from DriverNode.)
Protected method | CheckDisposed | (Inherited from DriverNode.)
Protected method | ConvertEnumToString | (Inherited from DriverNode.)
Protected method | ConvertStringToEnumTEnum | (Inherited from DriverNode.)
 | CreateInstanceTRepCap |
Protected method | ExpandSelector | (Inherited from DriverNode.)
Protected method | ExpandSingleSelector | (Inherited from DriverNode.)
Protected method | GetActivePhysicalName | (Inherited from DriverNode.)
Protected method | GetActivePhysicalNames | (Inherited from DriverNode.)
Protected method | GetCacheValue(Object) | (Inherited from DriverNode.)
Protected method | GetCacheValueT(T) | (Inherited from DriverNode.)
Protected method | GetCacheValueT(String, T) | (Inherited from DriverNode.)
Protected method | GetDefaultValueForSimulation | (Inherited from DriverNode.)
Protected method | GetDynamicRepCapNames | (Inherited from DriverNode.)
Protected method | GetRepCapManager(String) | (Inherited from DriverNode.)
Protected method | InitNode | (Inherited from DriverNode.)
Protected method | InstrumentInFamily | (Inherited from DriverNode.)
Protected method | InstrumentIsModel | (Inherited from DriverNode.)
Protected method | InvalidateAllCacheEntries | (Inherited from DriverNode.)
Protected method | InvalidateCacheEntry | (Inherited from DriverNode.)
Protected method | PollInstrumentErrors | (Inherited from DriverNode.)
Protected method | RemovePhysicalName | (Inherited from DriverNode.)
Protected method | ResetObjectState | (Inherited from DriverNode.)
Protected method | SendCoercionEvent | (Inherited from DriverNode.)
Protected method | SendInterchangeEvent | (Inherited from DriverNode.)
Protected method | SendWarningEvent | (Inherited from DriverNode.)
Protected method | TryConvertEnumToString | (Inherited from DriverNode.)
Protected method | TryConvertStringToEnumTEnum | (Inherited from DriverNode.)
Protected method | UpdateCacheValue(Object) | (Inherited from DriverNode.)
Protected method | UpdateCacheValue(String, Object) | (Inherited from DriverNode.)
Top
See Also

Reference

RepCap Class
MindWorks.Nimbus Namespace


RepCap.CreateInstance(TRepCap) Method

Pacific MindWorks Nimbus Driver Studio

RepCapCreateInstanceTRepCap Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static TRepCap CreateInstance<TRepCap>(
    RepCapCollection parent,
    int index,
    string physicalName
)
where TRepCap : new(), RepCap

internal:
generic<typename TRepCap>
where TRepCap : gcnew(), RepCap
static TRepCap CreateInstance(
    RepCapCollection^ parent,
    int index,
    String^ physicalName
)

Parameters

parent
Type: MindWorks.NimbusRepCapCollection
index
Type: SystemInt32
physicalName
Type: SystemString

Type Parameters

TRepCap

Return Value

Type: TRepCap
See Also

Reference

RepCap Class
MindWorks.Nimbus Namespace


RepCapCollection Class

Inheritance Hierarchy
SystemObject
MindWorks.NimbusDriverNode
MindWorks.NimbusRepCapCollection
MindWorks.NimbusRepCapCollectionTRepCap

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public abstract class RepCapCollection : DriverNode
public ref class RepCapCollection abstract : public DriverNode

The RepCapCollection type exposes the following members.

Constructors
 | Name | Description
Protected method | RepCapCollection | Initializes a new instance of the RepCapCollection class
Top
Properties
 | Name | Description
Protected property | CacheKeyPrefix | (Overrides DriverNode.CacheKeyPrefix.)
Protected property | CollectionStyleRepCaps | (Inherited from DriverNode.)
Protected property | DriverInfo | (Inherited from DriverNode.)
Protected property | Index |
Protected property | IO | (Inherited from DriverNode.)
Protected property | IsMessageBasedIOSession | (Inherited from DriverNode.)
Protected property | IsRegisterBasedIOSession | (Inherited from DriverNode.)
Protected property | NodeCount |
Protected property | ParameterStyleRepCaps | (Inherited from DriverNode.)
Protected property | Parent | (Inherited from DriverNode.)
Protected property | PhysicalName |
Protected property | PhysicalNameObject |
Protected property | RegisterIO | (Inherited from DriverNode.)
Protected property | RepCapName |
Protected property | Root | (Inherited from DriverNode.)
Protected property | SelectorStyleRepCaps | (Inherited from DriverNode.)
Protected property | Session | (Inherited from DriverNode.)
Protected property | UseQualifiedPhysicalNames |
Protected property | VirtualName |
Protected property | VisaSession | (Inherited from DriverNode.)
Top
Methods
 | Name | Description
Protected method | AcquireLock | (Inherited from DriverNode.)
Protected method | AcquireLock(PrecisionTimeSpan) | (Inherited from DriverNode.)
Protected method | AddPhysicalName | (Inherited from DriverNode.)
Protected method | CacheContainsValue | (Inherited from DriverNode.)
Protected method | CheckDisposed | (Inherited from DriverNode.)
Protected method | ConvertEnumToString | (Inherited from DriverNode.)
Protected method | ConvertStringToEnumTEnum | (Inherited from DriverNode.)
Protected method | ExpandSelector | (Inherited from DriverNode.)
Protected method | ExpandSingleSelector | (Inherited from DriverNode.)
Protected method | GetActivePhysicalName | (Inherited from DriverNode.)
Protected method | GetActivePhysicalNames | (Inherited from DriverNode.)
Protected method | GetCacheValue(Object) | (Inherited from DriverNode.)
Protected method | GetCacheValueT(T) | (Inherited from DriverNode.)
Protected method | GetCacheValueT(String, T) | (Inherited from DriverNode.)
Protected method | GetDefaultValueForSimulation | (Inherited from DriverNode.)
Protected method | GetDynamicRepCapNames | (Inherited from DriverNode.)
Protected method | GetNodes |
Protected method | GetRepCapManager(String) | (Inherited from DriverNode.)
Protected method | InitNode | (Inherited from DriverNode.)
Protected method | InstrumentInFamily | (Inherited from DriverNode.)
Protected method | InstrumentIsModel | (Inherited from DriverNode.)
Protected method | InvalidateAllCacheEntries | (Inherited from DriverNode.)
Protected method | InvalidateCacheEntry | (Inherited from DriverNode.)
Protected method | PollInstrumentErrors | (Inherited from DriverNode.)
Protected method | RemovePhysicalName | (Inherited from DriverNode.)
Protected method | ResetObjectState | (Inherited from DriverNode.)
Protected method | SendCoercionEvent | (Inherited from DriverNode.)
Protected method | SendInterchangeEvent | (Inherited from DriverNode.)
Protected method | SendWarningEvent | (Inherited from DriverNode.)
Protected method | TryConvertEnumToString | (Inherited from DriverNode.)
Protected method | TryConvertStringToEnumTEnum | (Inherited from DriverNode.)
Protected method | UpdateCacheValue(Object) | (Inherited from DriverNode.)
Protected method | UpdateCacheValue(String, Object) | (Inherited from DriverNode.)
Top
See Also

Reference

MindWorks.Nimbus Namespace


RepCapCollection Constructor

Initializes a new instance of the RepCapCollection class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal RepCapCollection(
    DriverNode parent,
    string repCapName
)
internal:
RepCapCollection(
    DriverNode^ parent,
    String^ repCapName
)

Parameters

parent
Type: MindWorks.NimbusDriverNode
repCapName
Type: SystemString
See Also

Reference

RepCapCollection Class
MindWorks.Nimbus Namespace


RepCapCollection Properties

The RepCapCollection type exposes the following members.

Properties
 | Name | Description
Protected property | CacheKeyPrefix | (Overrides DriverNode.CacheKeyPrefix.)
Protected property | CollectionStyleRepCaps | (Inherited from DriverNode.)
Protected property | DriverInfo | (Inherited from DriverNode.)
Protected property | Index |
Protected property | IO | (Inherited from DriverNode.)
Protected property | IsMessageBasedIOSession | (Inherited from DriverNode.)
Protected property | IsRegisterBasedIOSession | (Inherited from DriverNode.)
Protected property | NodeCount |
Protected property | ParameterStyleRepCaps | (Inherited from DriverNode.)
Protected property | Parent | (Inherited from DriverNode.)
Protected property | PhysicalName |
Protected property | PhysicalNameObject |
Protected property | RegisterIO | (Inherited from DriverNode.)
Protected property | RepCapName |
Protected property | Root | (Inherited from DriverNode.)
Protected property | SelectorStyleRepCaps | (Inherited from DriverNode.)
Protected property | Session | (Inherited from DriverNode.)
Protected property | UseQualifiedPhysicalNames |
Protected property | VirtualName |
Protected property | VisaSession | (Inherited from DriverNode.)
Top
See Also

Reference

RepCapCollection Class
MindWorks.Nimbus Namespace


RepCapCollection.CacheKeyPrefix Property

Pacific MindWorks Nimbus Driver Studio

RepCapCollectionCacheKeyPrefix Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
protected override string CacheKeyPrefix { get; }
protected:
virtual property String^ CacheKeyPrefix {
    String^ get () override;
}

Property Value

Type: String
See Also

Reference

RepCapCollection Class
MindWorks.Nimbus Namespace


RepCapCollection.Index Property

Pacific MindWorks Nimbus Driver Studio

RepCapCollectionIndex Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal abstract int Index { get; }
internal:
virtual property int Index {
    int get () abstract;
}

Property Value

Type: Int32
See Also

Reference

RepCapCollection Class
MindWorks.Nimbus Namespace


RepCapCollection.NodeCount Property

Pacific MindWorks Nimbus Driver Studio

RepCapCollectionNodeCount Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal abstract int NodeCount { get; }
internal:
virtual property int NodeCount {
    int get () abstract;
}

Property Value

Type: Int32
See Also

Reference

RepCapCollection Class
MindWorks.Nimbus Namespace


RepCapCollection.PhysicalName Property

Pacific MindWorks Nimbus Driver Studio

RepCapCollectionPhysicalName Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal virtual string PhysicalName { get; }
internal:
virtual property String^ PhysicalName {
    String^ get ();
}

Property Value

Type: String
See Also

Reference

RepCapCollection Class
MindWorks.Nimbus Namespace


RepCapCollection.PhysicalNameObject Property

Pacific MindWorks Nimbus Driver Studio

RepCapCollectionPhysicalNameObject Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal abstract PhysicalName PhysicalNameObject { get; }
internal:
virtual property PhysicalName^ PhysicalNameObject {
    PhysicalName^ get () abstract;
}

Property Value

Type: PhysicalName
See Also

Reference

RepCapCollection Class
MindWorks.Nimbus Namespace


RepCapCollection.RepCapName Property

Pacific MindWorks Nimbus Driver Studio

RepCapCollectionRepCapName Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal string RepCapName { get; }
internal:
property String^ RepCapName {
    String^ get ();
}

Property Value

Type: String
See Also

Reference

RepCapCollection Class
MindWorks.Nimbus Namespace


RepCapCollection.UseQualifiedPhysicalNames Property

Pacific MindWorks Nimbus Driver Studio

RepCapCollectionUseQualifiedPhysicalNames Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal bool UseQualifiedPhysicalNames { get; set; }
internal:
property bool UseQualifiedPhysicalNames {
    bool get ();
    void set (bool value);
}

Property Value

Type: Boolean
See Also

Reference

RepCapCollection Class
MindWorks.Nimbus Namespace


RepCapCollection.VirtualName Property

Pacific MindWorks Nimbus Driver Studio

RepCapCollectionVirtualName Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal abstract string VirtualName { get; }
internal:
virtual property String^ VirtualName {
    String^ get () abstract;
}

Property Value

Type: String
See Also

Reference

RepCapCollection Class
MindWorks.Nimbus Namespace


RepCapCollection Methods

The RepCapCollection type exposes the following members.

Methods
 | Name | Description
Protected method | AcquireLock | (Inherited from DriverNode.)
Protected method | AcquireLock(PrecisionTimeSpan) | (Inherited from DriverNode.)
Protected method | AddPhysicalName | (Inherited from DriverNode.)
Protected method | CacheContainsValue | (Inherited from DriverNode.)
Protected method | CheckDisposed | (Inherited from DriverNode.)
Protected method | ConvertEnumToString | (Inherited from DriverNode.)
Protected method | ConvertStringToEnumTEnum | (Inherited from DriverNode.)
Protected method | ExpandSelector | (Inherited from DriverNode.)
Protected method | ExpandSingleSelector | (Inherited from DriverNode.)
Protected method | GetActivePhysicalName | (Inherited from DriverNode.)
Protected method | GetActivePhysicalNames | (Inherited from DriverNode.)
Protected method | GetCacheValue(Object) | (Inherited from DriverNode.)
Protected method | GetCacheValueT(T) | (Inherited from DriverNode.)
Protected method | GetCacheValueT(String, T) | (Inherited from DriverNode.)
Protected method | GetDefaultValueForSimulation | (Inherited from DriverNode.)
Protected method | GetDynamicRepCapNames | (Inherited from DriverNode.)
Protected method | GetNodes |
Protected method | GetRepCapManager(String) | (Inherited from DriverNode.)
Protected method | InitNode | (Inherited from DriverNode.)
Protected method | InstrumentInFamily | (Inherited from DriverNode.)
Protected method | InstrumentIsModel | (Inherited from DriverNode.)
Protected method | InvalidateAllCacheEntries | (Inherited from DriverNode.)
Protected method | InvalidateCacheEntry | (Inherited from DriverNode.)
Protected method | PollInstrumentErrors | (Inherited from DriverNode.)
Protected method | RemovePhysicalName | (Inherited from DriverNode.)
Protected method | ResetObjectState | (Inherited from DriverNode.)
Protected method | SendCoercionEvent | (Inherited from DriverNode.)
Protected method | SendInterchangeEvent | (Inherited from DriverNode.)
Protected method | SendWarningEvent | (Inherited from DriverNode.)
Protected method | TryConvertEnumToString | (Inherited from DriverNode.)
Protected method | TryConvertStringToEnumTEnum | (Inherited from DriverNode.)
Protected method | UpdateCacheValue(Object) | (Inherited from DriverNode.)
Protected method | UpdateCacheValue(String, Object) | (Inherited from DriverNode.)
Top
See Also

Reference

RepCapCollection Class
MindWorks.Nimbus Namespace


RepCapCollection.GetNodes Method

Pacific MindWorks Nimbus Driver Studio

RepCapCollectionGetNodes Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal abstract IEnumerable<RepCap> GetNodes()
internal:
virtual IEnumerable<RepCap^>^ GetNodes() abstract

Return Value

Type: IEnumerable RepCap
See Also

Reference

RepCapCollection Class
MindWorks.Nimbus Namespace


RepCapCollection(TRepCap) Class

Pacific MindWorks Nimbus Driver Studio

RepCapCollectionTRepCap Class

Inheritance Hierarchy
SystemObject
MindWorks.NimbusDriverNode
MindWorks.NimbusRepCapCollection
MindWorks.NimbusRepCapCollectionTRepCap

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal class RepCapCollection<TRepCap> : RepCapCollection,
    IEnumerable<TRepCap>, IEnumerable
where TRepCap : new(), RepCap

generic<typename TRepCap>
where TRepCap : gcnew(), RepCap
internal ref class RepCapCollection : public RepCapCollection,
    IEnumerable<TRepCap>, IEnumerable

Type Parameters

TRepCap

The RepCapCollectionTRepCap type exposes the following members.

Constructors
 | Name | Description
Protected method | RepCapCollectionTRepCap | Initializes a new instance of the RepCapCollectionTRepCap class
Top
Properties
 | Name | Description
Protected property | CacheKeyPrefix | (Inherited from RepCapCollection.)
Protected property | CollectionStyleRepCaps | (Inherited from DriverNode.)
Protected property | Count |
Protected property | DriverInfo | (Inherited from DriverNode.)
Protected property | Index | (Overrides RepCapCollectionIndex.)
Protected property | IO | (Inherited from DriverNode.)
Protected property | IsMessageBasedIOSession | (Inherited from DriverNode.)
Protected property | IsRegisterBasedIOSession | (Inherited from DriverNode.)
Protected property | ItemInt32 |
Protected property | ItemString |
Protected property | NodeCount | (Overrides RepCapCollectionNodeCount.)
Protected property | ParameterStyleRepCaps | (Inherited from DriverNode.)
Protected property | Parent | (Inherited from DriverNode.)
Protected property | PhysicalName | (Inherited from RepCapCollection.)
Protected property | PhysicalNameObject | (Overrides RepCapCollectionPhysicalNameObject.)
Protected property | RegisterIO | (Inherited from DriverNode.)
Protected property | RepCapName | (Inherited from RepCapCollection.)
Protected property | Root | (Inherited from DriverNode.)
Protected property | SelectorStyleRepCaps | (Inherited from DriverNode.)
Protected property | Session | (Inherited from DriverNode.)
Protected property | UseQualifiedPhysicalNames | (Inherited from RepCapCollection.)
Protected property | VirtualName | (Overrides RepCapCollectionVirtualName.)
Protected property | VisaSession | (Inherited from DriverNode.)
Top
Methods
 | Name | Description
Protected method | AcquireLock | (Inherited from DriverNode.)
Protected method | AcquireLock(PrecisionTimeSpan) | (Inherited from DriverNode.)
Protected method | AddPhysicalName | (Inherited from DriverNode.)
Protected method | AddRepCap |
Protected method | CacheContainsValue | (Inherited from DriverNode.)
Protected method | CheckDisposed | (Inherited from DriverNode.)
Protected method | ConvertEnumToString | (Inherited from DriverNode.)
Protected method | ConvertStringToEnumTEnum | (Inherited from DriverNode.)
Protected method | ExpandSelector | (Inherited from DriverNode.)
Protected method | ExpandSingleSelector | (Inherited from DriverNode.)
Protected method | GetActivePhysicalName | (Inherited from DriverNode.)
Protected method | GetActivePhysicalNames | (Inherited from DriverNode.)
Protected method | GetCacheValue(Object) | (Inherited from DriverNode.)
Protected method | GetCacheValueT(T) | (Inherited from DriverNode.)
Protected method | GetCacheValueT(String, T) | (Inherited from DriverNode.)
Protected method | GetDefaultValueForSimulation | (Inherited from DriverNode.)
Protected method | GetDynamicRepCapNames | (Inherited from DriverNode.)
Public method | GetEnumerator |
Protected method | GetNodes | (Overrides RepCapCollectionGetNodes.)
Protected method | GetRepCap |
Protected method | GetRepCapManager(String) | (Inherited from DriverNode.)
Protected method | InitNode | (Overrides DriverNodeInitNode.)
Protected method | InstrumentInFamily | (Inherited from DriverNode.)
Protected method | InstrumentIsModel | (Inherited from DriverNode.)
Protected method | InvalidateAllCacheEntries | (Inherited from DriverNode.)
Protected method | InvalidateCacheEntry | (Inherited from DriverNode.)
Protected method | PollInstrumentErrors | (Inherited from DriverNode.)
Protected method | RemovePhysicalName | (Inherited from DriverNode.)
Protected method | RemoveRepCap |
Protected method | ResetObjectState | (Inherited from DriverNode.)
Protected method | SendCoercionEvent | (Inherited from DriverNode.)
Protected method | SendInterchangeEvent | (Inherited from DriverNode.)
Protected method | SendWarningEvent | (Inherited from DriverNode.)
Protected method | TryConvertEnumToString | (Inherited from DriverNode.)
Protected method | TryConvertStringToEnumTEnum | (Inherited from DriverNode.)
Protected method | UpdateCacheValue(Object) | (Inherited from DriverNode.)
Protected method | UpdateCacheValue(String, Object) | (Inherited from DriverNode.)
Top
See Also

Reference

MindWorks.Nimbus Namespace


RepCapCollection(TRepCap) Constructor

Pacific MindWorks Nimbus Driver Studio

RepCapCollectionTRepCap Constructor

Initializes a new instance of the RepCapCollectionTRepCap class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal RepCapCollection(
    DriverNode parent,
    string repCapName
)
internal:
RepCapCollection(
    DriverNode^ parent,
    String^ repCapName
)

Parameters

parent
Type: MindWorks.NimbusDriverNode
repCapName
Type: SystemString
See Also

Reference

RepCapCollectionTRepCap Class
MindWorks.Nimbus Namespace


RepCapCollection(TRepCap) Properties

Pacific MindWorks Nimbus Driver Studio

RepCapCollectionTRepCap Properties

The RepCapCollectionTRepCap generic type exposes the following members.

Properties
 | Name | Description
Protected property | CacheKeyPrefix | (Inherited from RepCapCollection.)
Protected property | CollectionStyleRepCaps | (Inherited from DriverNode.)
Protected property | Count |
Protected property | DriverInfo | (Inherited from DriverNode.)
Protected property | Index | (Overrides RepCapCollectionIndex.)
Protected property | IO | (Inherited from DriverNode.)
Protected property | IsMessageBasedIOSession | (Inherited from DriverNode.)
Protected property | IsRegisterBasedIOSession | (Inherited from DriverNode.)
Protected property | ItemInt32 |
Protected property | ItemString |
Protected property | NodeCount | (Overrides RepCapCollectionNodeCount.)
Protected property | ParameterStyleRepCaps | (Inherited from DriverNode.)
Protected property | Parent | (Inherited from DriverNode.)
Protected property | PhysicalName | (Inherited from RepCapCollection.)
Protected property | PhysicalNameObject | (Overrides RepCapCollectionPhysicalNameObject.)
Protected property | RegisterIO | (Inherited from DriverNode.)
Protected property | RepCapName | (Inherited from RepCapCollection.)
Protected property | Root | (Inherited from DriverNode.)
Protected property | SelectorStyleRepCaps | (Inherited from DriverNode.)
Protected property | Session | (Inherited from DriverNode.)
Protected property | UseQualifiedPhysicalNames | (Inherited from RepCapCollection.)
Protected property | VirtualName | (Overrides RepCapCollectionVirtualName.)
Protected property | VisaSession | (Inherited from DriverNode.)
Top
See Also

Reference

RepCapCollectionTRepCap Class
MindWorks.Nimbus Namespace


RepCapCollection(TRepCap).Count Property

Pacific MindWorks Nimbus Driver Studio

RepCapCollectionTRepCapCount Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal int Count { get; }
internal:
property int Count {
    int get ();
}

Property Value

Type: Int32
See Also

Reference

RepCapCollectionTRepCap Class
MindWorks.Nimbus Namespace


RepCapCollection(TRepCap).Index Property

Pacific MindWorks Nimbus Driver Studio

RepCapCollectionTRepCapIndex Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal override int Index { get; }
internal:
virtual property int Index {
    int get () override;
}

Property Value

Type: Int32
See Also

Reference

RepCapCollectionTRepCap Class
MindWorks.Nimbus Namespace


RepCapCollection(TRepCap).Item Property

Pacific MindWorks Nimbus Driver Studio

RepCapCollectionTRepCapItem Property

Overload List
 | Name | Description
Protected property | ItemInt32 |
Protected property | ItemString |
Top
See Also

Reference

RepCapCollectionTRepCap Class
MindWorks.Nimbus Namespace


RepCapCollection(TRepCap).Item Property (Int32)

Pacific MindWorks Nimbus Driver Studio

RepCapCollectionTRepCapItem Property (Int32)

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal TRepCap this[
    int index
] { get; }
internal:
property TRepCap default[int index] {
    TRepCap get (int index);
}

Parameters

index
Type: SystemInt32

Property Value

Type: TRepCap
See Also

Reference

RepCapCollectionTRepCap Class
Item Overload
MindWorks.Nimbus Namespace


RepCapCollection(TRepCap).Item Property (String)

Pacific MindWorks Nimbus Driver Studio

RepCapCollectionTRepCapItem Property (String)

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal TRepCap this[
    string name
] { get; }
internal:
property TRepCap default[String^ name] {
    TRepCap get (String^ name);
}

Parameters

name
Type: SystemString

Property Value

Type: TRepCap
See Also

Reference

RepCapCollectionTRepCap Class
Item Overload
MindWorks.Nimbus Namespace


RepCapCollection(TRepCap).NodeCount Property

Pacific MindWorks Nimbus Driver Studio

RepCapCollectionTRepCapNodeCount Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal override int NodeCount { get; }
internal:
virtual property int NodeCount {
    int get () override;
}

Property Value

Type: Int32
See Also

Reference

RepCapCollectionTRepCap Class
MindWorks.Nimbus Namespace


RepCapCollection(TRepCap).PhysicalNameObject Property

Pacific MindWorks Nimbus Driver Studio

RepCapCollectionTRepCapPhysicalNameObject Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal override PhysicalName PhysicalNameObject { get; }
internal:
virtual property PhysicalName^ PhysicalNameObject {
    PhysicalName^ get () override;
}

Property Value

Type: PhysicalName
See Also

Reference

RepCapCollectionTRepCap Class
MindWorks.Nimbus Namespace


RepCapCollection(TRepCap).VirtualName Property

Pacific MindWorks Nimbus Driver Studio

RepCapCollectionTRepCapVirtualName Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal override string VirtualName { get; }
internal:
virtual property String^ VirtualName {
    String^ get () override;
}

Property Value

Type: String
See Also

Reference

RepCapCollectionTRepCap Class
MindWorks.Nimbus Namespace


RepCapCollection(TRepCap) Methods

Pacific MindWorks Nimbus Driver Studio

RepCapCollectionTRepCap Methods

The RepCapCollectionTRepCap generic type exposes the following members.

Methods
 | Name | Description
Protected method | AcquireLock | (Inherited from DriverNode.)
Protected method | AcquireLock(PrecisionTimeSpan) | (Inherited from DriverNode.)
Protected method | AddPhysicalName | (Inherited from DriverNode.)
Protected method | AddRepCap |
Protected method | CacheContainsValue | (Inherited from DriverNode.)
Protected method | CheckDisposed | (Inherited from DriverNode.)
Protected method | ConvertEnumToString | (Inherited from DriverNode.)
Protected method | ConvertStringToEnumTEnum | (Inherited from DriverNode.)
Protected method | ExpandSelector | (Inherited from DriverNode.)
Protected method | ExpandSingleSelector | (Inherited from DriverNode.)
Protected method | GetActivePhysicalName | (Inherited from DriverNode.)
Protected method | GetActivePhysicalNames | (Inherited from DriverNode.)
Protected method | GetCacheValue(Object) | (Inherited from DriverNode.)
Protected method | GetCacheValueT(T) | (Inherited from DriverNode.)
Protected method | GetCacheValueT(String, T) | (Inherited from DriverNode.)
Protected method | GetDefaultValueForSimulation | (Inherited from DriverNode.)
Protected method | GetDynamicRepCapNames | (Inherited from DriverNode.)
Public method | GetEnumerator |
Protected method | GetNodes | (Overrides RepCapCollectionGetNodes.)
Protected method | GetRepCap |
Protected method | GetRepCapManager(String) | (Inherited from DriverNode.)
Protected method | InitNode | (Overrides DriverNodeInitNode.)
Protected method | InstrumentInFamily | (Inherited from DriverNode.)
Protected method | InstrumentIsModel | (Inherited from DriverNode.)
Protected method | InvalidateAllCacheEntries | (Inherited from DriverNode.)
Protected method | InvalidateCacheEntry | (Inherited from DriverNode.)
Protected method | PollInstrumentErrors | (Inherited from DriverNode.)
Protected method | RemovePhysicalName | (Inherited from DriverNode.)
Protected method | RemoveRepCap |
Protected method | ResetObjectState | (Inherited from DriverNode.)
Protected method | SendCoercionEvent | (Inherited from DriverNode.)
Protected method | SendInterchangeEvent | (Inherited from DriverNode.)
Protected method | SendWarningEvent | (Inherited from DriverNode.)
Protected method | TryConvertEnumToString | (Inherited from DriverNode.)
Protected method | TryConvertStringToEnumTEnum | (Inherited from DriverNode.)
Protected method | UpdateCacheValue(Object) | (Inherited from DriverNode.)
Protected method | UpdateCacheValue(String, Object) | (Inherited from DriverNode.)
Top
See Also

Reference

RepCapCollectionTRepCap Class
MindWorks.Nimbus Namespace


RepCapCollection(TRepCap).AddRepCap Method

Pacific MindWorks Nimbus Driver Studio

RepCapCollectionTRepCapAddRepCap Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal TRepCap AddRepCap(
    string physicalName
)
internal:
TRepCap AddRepCap(
    String^ physicalName
)

Parameters

physicalName
Type: SystemString

Return Value

Type: TRepCap
See Also

Reference

RepCapCollectionTRepCap Class
MindWorks.Nimbus Namespace


RepCapCollection(TRepCap).GetEnumerator Method

Pacific MindWorks Nimbus Driver Studio

RepCapCollectionTRepCapGetEnumerator Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public IEnumerator GetEnumerator()
public:
virtual IEnumerator^ GetEnumerator() sealed

Return Value

Type: IEnumerator

Implements

IEnumerableGetEnumerator
See Also

Reference

RepCapCollectionTRepCap Class
MindWorks.Nimbus Namespace


RepCapCollection(TRepCap).GetNodes Method

Pacific MindWorks Nimbus Driver Studio

RepCapCollectionTRepCapGetNodes Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal override IEnumerable<RepCap> GetNodes()
internal:
virtual IEnumerable<RepCap^>^ GetNodes() override

Return Value

Type: IEnumerable RepCap
See Also

Reference

RepCapCollectionTRepCap Class
MindWorks.Nimbus Namespace


RepCapCollection(TRepCap).GetRepCap Method

Pacific MindWorks Nimbus Driver Studio

RepCapCollectionTRepCapGetRepCap Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal TRepCap GetRepCap(
    string name
)
internal:
TRepCap GetRepCap(
    String^ name
)

Parameters

name
Type: SystemString

Return Value

Type: TRepCap
See Also

Reference

RepCapCollectionTRepCap Class
MindWorks.Nimbus Namespace


RepCapCollection(TRepCap).InitNode Method

Pacific MindWorks Nimbus Driver Studio

RepCapCollectionTRepCapInitNode Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal override void InitNode()
internal:
virtual void InitNode() override
See Also

Reference

RepCapCollectionTRepCap Class
MindWorks.Nimbus Namespace


RepCapCollection(TRepCap).RemoveRepCap Method

Pacific MindWorks Nimbus Driver Studio

RepCapCollectionTRepCapRemoveRepCap Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal bool RemoveRepCap(
    string physicalName,
    bool throwIfNotFound
)
internal:
bool RemoveRepCap(
    String^ physicalName,
    bool throwIfNotFound
)

Parameters

physicalName
Type: SystemString
throwIfNotFound
Type: SystemBoolean

Return Value

Type: Boolean
See Also

Reference

RepCapCollectionTRepCap Class
MindWorks.Nimbus Namespace


RepCapManager Class

Inheritance Hierarchy
SystemObject
MindWorks.NimbusRepCapManager
MindWorks.NimbusParameterStyleRepCapManager
MindWorks.NimbusSelectorStyleRepCapManager

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public abstract class RepCapManager
public ref class RepCapManager abstract

The RepCapManager type exposes the following members.

Constructors
 | Name | Description
Protected method | RepCapManager | Initializes a new instance of the RepCapManager class
Top
Properties
 | Name | Description
Protected property | Parent |
Protected property | PhysicalNames |
Protected property | RepCapName |
Protected property | Session |
Protected property | UseQualifiedPhysicalNames |
Top
Methods
 | Name | Description
Protected method | AddPhysicalName |
Protected method | ExpandSelector |
Protected method | GetNumberOfAncestors |
 | GetNumberOfAncestors(IRepCapManager) |
Protected method | IsPhysicalNameDefined |
Protected method | LookupPhysicalName |
Protected method | RemovePhysicalName |
Protected method | TryLookupPhysicalName |
Top
See Also

Reference

MindWorks.Nimbus Namespace


RepCapManager Constructor

Initializes a new instance of the RepCapManager class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal RepCapManager(
    string repCapName,
    SessionInfo session,
    bool useQualifiedPhysicalNames,
    IRepCapManager parent
)
internal:
RepCapManager(
    String^ repCapName,
    SessionInfo^ session,
    bool useQualifiedPhysicalNames,
    IRepCapManager^ parent
)

Parameters

repCapName
Type: SystemString
session
Type: MindWorks.NimbusSessionInfo
useQualifiedPhysicalNames
Type: SystemBoolean
parent
Type: IRepCapManager
See Also

Reference

RepCapManager Class
MindWorks.Nimbus Namespace


RepCapManager Properties

The RepCapManager type exposes the following members.

Properties
 | Name | Description
Protected property | Parent |
Protected property | PhysicalNames |
Protected property | RepCapName |
Protected property | Session |
Protected property | UseQualifiedPhysicalNames |
Top
See Also

Reference

RepCapManager Class
MindWorks.Nimbus Namespace


RepCapManager.Parent Property

Pacific MindWorks Nimbus Driver Studio

RepCapManagerParent Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal IRepCapManager Parent { get; }
internal:
property IRepCapManager^ Parent {
    IRepCapManager^ get ();
}

Property Value

Type: IRepCapManager
See Also

Reference

RepCapManager Class
MindWorks.Nimbus Namespace


RepCapManager.PhysicalNames Property

Pacific MindWorks Nimbus Driver Studio

RepCapManagerPhysicalNames Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal IList<PhysicalName> PhysicalNames { get; }
internal:
property IList<PhysicalName^>^ PhysicalNames {
    IList<PhysicalName^>^ get ();
}

Property Value

Type: IList PhysicalName
See Also

Reference

RepCapManager Class
MindWorks.Nimbus Namespace


RepCapManager.RepCapName Property

Pacific MindWorks Nimbus Driver Studio

RepCapManagerRepCapName Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal string RepCapName { get; }
internal:
property String^ RepCapName {
    String^ get ();
}

Property Value

Type: String
See Also

Reference

RepCapManager Class
MindWorks.Nimbus Namespace


RepCapManager.Session Property

Pacific MindWorks Nimbus Driver Studio

RepCapManagerSession Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal SessionInfo Session { get; }
internal:
property SessionInfo^ Session {
    SessionInfo^ get ();
}

Property Value

Type: SessionInfo
See Also

Reference

RepCapManager Class
MindWorks.Nimbus Namespace


RepCapManager.UseQualifiedPhysicalNames Property

Pacific MindWorks Nimbus Driver Studio

RepCapManagerUseQualifiedPhysicalNames Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal bool UseQualifiedPhysicalNames { get; }
internal:
property bool UseQualifiedPhysicalNames {
    bool get ();
}

Property Value

Type: Boolean
See Also

Reference

RepCapManager Class
MindWorks.Nimbus Namespace


RepCapManager Methods

The RepCapManager type exposes the following members.

Methods
 | Name | Description
Protected method | AddPhysicalName |
Protected method | ExpandSelector |
Protected method | GetNumberOfAncestors |
 | GetNumberOfAncestors(IRepCapManager) |
Protected method | IsPhysicalNameDefined |
Protected method | LookupPhysicalName |
Protected method | RemovePhysicalName |
Protected method | TryLookupPhysicalName |
Top
See Also

Reference

RepCapManager Class
MindWorks.Nimbus Namespace


RepCapManager.AddPhysicalName Method

Pacific MindWorks Nimbus Driver Studio

RepCapManagerAddPhysicalName Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal virtual PhysicalName AddPhysicalName(
    string fullPhysicalName
)
internal:
virtual PhysicalName^ AddPhysicalName(
    String^ fullPhysicalName
)

Parameters

fullPhysicalName
Type: SystemString

Return Value

Type: PhysicalName
See Also

Reference

RepCapManager Class
MindWorks.Nimbus Namespace


RepCapManager.ExpandSelector Method

Pacific MindWorks Nimbus Driver Studio

RepCapManagerExpandSelector Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal IList<PhysicalName> ExpandSelector(
    string selector
)
internal:
IList<PhysicalName^>^ ExpandSelector(
    String^ selector
)

Parameters

selector
Type: SystemString

Return Value

Type: IList PhysicalName
See Also

Reference

RepCapManager Class
MindWorks.Nimbus Namespace


RepCapManager.GetNumberOfAncestors Method

Pacific MindWorks Nimbus Driver Studio

RepCapManagerGetNumberOfAncestors Method

Overload List
 | Name | Description
Protected method | GetNumberOfAncestors |
 | GetNumberOfAncestors(IRepCapManager) |
Top
See Also

Reference

RepCapManager Class
MindWorks.Nimbus Namespace


RepCapManager.GetNumberOfAncestors Method

Pacific MindWorks Nimbus Driver Studio

RepCapManagerGetNumberOfAncestors Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal int GetNumberOfAncestors()
internal:
int GetNumberOfAncestors()

Return Value

Type: Int32
See Also

Reference

RepCapManager Class
GetNumberOfAncestors Overload
MindWorks.Nimbus Namespace


RepCapManager.GetNumberOfAncestors Method (IRepCapManager)

Pacific MindWorks Nimbus Driver Studio

RepCapManagerGetNumberOfAncestors Method (IRepCapManager)

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static int GetNumberOfAncestors(
    IRepCapManager mananger
)
internal:
static int GetNumberOfAncestors(
    IRepCapManager^ mananger
)

Parameters

mananger
Type: IRepCapManager

Return Value

Type: Int32
See Also

Reference

RepCapManager Class
GetNumberOfAncestors Overload
MindWorks.Nimbus Namespace


RepCapManager.IsPhysicalNameDefined Method

Pacific MindWorks Nimbus Driver Studio

RepCapManagerIsPhysicalNameDefined Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal bool IsPhysicalNameDefined(
    string fullName
)
internal:
bool IsPhysicalNameDefined(
    String^ fullName
)

Parameters

fullName
Type: SystemString

Return Value

Type: Boolean
See Also

Reference

RepCapManager Class
MindWorks.Nimbus Namespace


RepCapManager.LookupPhysicalName Method

Pacific MindWorks Nimbus Driver Studio

RepCapManagerLookupPhysicalName Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal PhysicalName LookupPhysicalName(
    string fullName
)
internal:
PhysicalName^ LookupPhysicalName(
    String^ fullName
)

Parameters

fullName
Type: SystemString

Return Value

Type: PhysicalName
See Also

Reference

RepCapManager Class
MindWorks.Nimbus Namespace


RepCapManager.RemovePhysicalName Method

Pacific MindWorks Nimbus Driver Studio

RepCapManagerRemovePhysicalName Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal virtual void RemovePhysicalName(
    string fullPhysicalName
)
internal:
virtual void RemovePhysicalName(
    String^ fullPhysicalName
)

Parameters

fullPhysicalName
Type: SystemString
See Also

Reference

RepCapManager Class
MindWorks.Nimbus Namespace


RepCapManager.TryLookupPhysicalName Method

Pacific MindWorks Nimbus Driver Studio

RepCapManagerTryLookupPhysicalName Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal bool TryLookupPhysicalName(
    string fullName,
    out PhysicalName physicalName
)
internal:
bool TryLookupPhysicalName(
    String^ fullName,
    [OutAttribute] PhysicalName^% physicalName
)

Parameters

fullName
Type: SystemString
physicalName
Type: MindWorks.NimbusPhysicalName

Return Value

Type: Boolean
See Also

Reference

RepCapManager Class
MindWorks.Nimbus Namespace


RepCapSelector Class

Inheritance Hierarchy
SystemObject
MindWorks.NimbusRepCapSelector

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal class RepCapSelector
internal ref class RepCapSelector

The RepCapSelector type exposes the following members.

Properties
 | Name | Description
Protected property | IsEmpty |
Protected property | IsNested |
Protected property | IsSingleIdentifier |
Protected property | PathSegments |
Protected property | Source |
Top
Methods
Name | Description
CreateEmptySelector |
ExpandToPhysicalNames |
IsValidCollectionStyleSelector |
Parse |
TryParse |
Top
See Also

Reference

MindWorks.Nimbus Namespace


RepCapSelector Properties

The RepCapSelector type exposes the following members.

Properties
 | Name | Description
Protected property | IsEmpty |
Protected property | IsNested |
Protected property | IsSingleIdentifier |
Protected property | PathSegments |
Protected property | Source |
Top
See Also

Reference

RepCapSelector Class
MindWorks.Nimbus Namespace


RepCapSelector.IsEmpty Property

Pacific MindWorks Nimbus Driver Studio

RepCapSelectorIsEmpty Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal bool IsEmpty { get; }
internal:
property bool IsEmpty {
    bool get ();
}

Property Value

Type: Boolean
See Also

Reference

RepCapSelector Class
MindWorks.Nimbus Namespace


RepCapSelector.IsNested Property

Pacific MindWorks Nimbus Driver Studio

RepCapSelectorIsNested Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal bool IsNested { get; }
internal:
property bool IsNested {
    bool get ();
}

Property Value

Type: Boolean
See Also

Reference

RepCapSelector Class
MindWorks.Nimbus Namespace


RepCapSelector.IsSingleIdentifier Property

Pacific MindWorks Nimbus Driver Studio

RepCapSelectorIsSingleIdentifier Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal bool IsSingleIdentifier { get; }
internal:
property bool IsSingleIdentifier {
    bool get ();
}

Property Value

Type: Boolean
See Also

Reference

RepCapSelector Class
MindWorks.Nimbus Namespace


RepCapSelector.PathSegments Property

Pacific MindWorks Nimbus Driver Studio

RepCapSelectorPathSegments Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal ReadOnlyCollection<PathSegment> PathSegments { get; }
internal:
property ReadOnlyCollection<PathSegment^>^ PathSegments {
    ReadOnlyCollection<PathSegment^>^ get ();
}

Property Value

Type: ReadOnlyCollection PathSegment
See Also

Reference

RepCapSelector Class
MindWorks.Nimbus Namespace


RepCapSelector.Source Property

Pacific MindWorks Nimbus Driver Studio

RepCapSelectorSource Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal string Source { get; }
internal:
property String^ Source {
    String^ get ();
}

Property Value

Type: String
See Also

Reference

RepCapSelector Class
MindWorks.Nimbus Namespace


RepCapSelector Methods

The RepCapSelector type exposes the following members.

Methods
Name | Description
CreateEmptySelector |
ExpandToPhysicalNames |
IsValidCollectionStyleSelector |
Parse |
TryParse |
Top
See Also

Reference

RepCapSelector Class
MindWorks.Nimbus Namespace


RepCapSelector.CreateEmptySelector Method

Pacific MindWorks Nimbus Driver Studio

RepCapSelectorCreateEmptySelector Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static RepCapSelector CreateEmptySelector()
internal:
static RepCapSelector^ CreateEmptySelector()

Return Value

Type: RepCapSelector
See Also

Reference

RepCapSelector Class
MindWorks.Nimbus Namespace


RepCapSelector.ExpandToPhysicalNames Method

Pacific MindWorks Nimbus Driver Studio

RepCapSelectorExpandToPhysicalNames Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static IEnumerable<string> ExpandToPhysicalNames(
    RepCapSelector selector,
    SessionInfo sessionInfo
)
internal:
static IEnumerable<String^>^ ExpandToPhysicalNames(
    RepCapSelector^ selector,
    SessionInfo^ sessionInfo
)

Parameters

selector
Type: MindWorks.NimbusRepCapSelector
sessionInfo
Type: MindWorks.NimbusSessionInfo

Return Value

Type: IEnumerable String
See Also

Reference

RepCapSelector Class
MindWorks.Nimbus Namespace


RepCapSelector.IsValidCollectionStyleSelector Method

Pacific MindWorks Nimbus Driver Studio

RepCapSelectorIsValidCollectionStyleSelector Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static bool IsValidCollectionStyleSelector(
    string selector
)
internal:
static bool IsValidCollectionStyleSelector(
    String^ selector
)

Parameters

selector
Type: SystemString

Return Value

Type: Boolean
See Also

Reference

RepCapSelector Class
MindWorks.Nimbus Namespace


RepCapSelector.Parse Method

Pacific MindWorks Nimbus Driver Studio

RepCapSelectorParse Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static RepCapSelector Parse(
    string selector
)
internal:
static RepCapSelector^ Parse(
    String^ selector
)

Parameters

selector
Type: SystemString

Return Value

Type: RepCapSelector
See Also

Reference

RepCapSelector Class
MindWorks.Nimbus Namespace


RepCapSelector.TryParse Method

Pacific MindWorks Nimbus Driver Studio

RepCapSelectorTryParse Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static bool TryParse(
    string selector,
    out RepCapSelector parsedSelector
)
internal:
static bool TryParse(
    String^ selector,
    [OutAttribute] RepCapSelector^% parsedSelector
)

Parameters

selector
Type: SystemString
parsedSelector
Type: MindWorks.NimbusRepCapSelector

Return Value

Type: Boolean
See Also

Reference

RepCapSelector Class
MindWorks.Nimbus Namespace


RepeatedCapabilityAttribute Class

Inheritance Hierarchy
SystemObject
SystemAttribute
MindWorks.NimbusNimbusAttribute
MindWorks.NimbusRepeatedCapabilityAttribute

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal sealed class RepeatedCapabilityAttribute : NimbusAttribute
internal ref class RepeatedCapabilityAttribute sealed : public NimbusAttribute

The RepeatedCapabilityAttribute type exposes the following members.

Constructors
 | Name | Description
Public method | RepeatedCapabilityAttribute | Initializes a new instance of the RepeatedCapabilityAttribute class
Top
Properties
 | Name | Description
Protected property | Parent |
Protected property | PhysicalNames |
Protected property | RepCapName |
Protected property | Style |
Public property | UseQualifiedNames |
Top
See Also

Reference

MindWorks.Nimbus Namespace


RepeatedCapabilityAttribute Constructor

Initializes a new instance of the RepeatedCapabilityAttribute class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public RepeatedCapabilityAttribute(
    string repeatedCapabilityName,
    string physicalNames,
    RepeatedCapabilityStyle style
)
public:
RepeatedCapabilityAttribute(
    String^ repeatedCapabilityName,
    String^ physicalNames,
    RepeatedCapabilityStyle style
)

Parameters

repeatedCapabilityName
Type: SystemString
physicalNames
Type: SystemString
style
Type: MindWorks.NimbusRepeatedCapabilityStyle
See Also

Reference

RepeatedCapabilityAttribute Class
MindWorks.Nimbus Namespace


RepeatedCapabilityAttribute Properties

The RepeatedCapabilityAttribute type exposes the following members.

Properties
 | Name | Description
Protected property | Parent |
Protected property | PhysicalNames |
Protected property | RepCapName |
Protected property | Style |
Public property | UseQualifiedNames |
Top
See Also

Reference

RepeatedCapabilityAttribute Class
MindWorks.Nimbus Namespace


RepeatedCapabilityAttribute.Parent Property

Pacific MindWorks Nimbus Driver Studio

RepeatedCapabilityAttributeParent Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal string Parent { get; }
internal:
property String^ Parent {
    String^ get ();
}

Property Value

Type: String
See Also

Reference

RepeatedCapabilityAttribute Class
MindWorks.Nimbus Namespace


RepeatedCapabilityAttribute.PhysicalNames Property

Pacific MindWorks Nimbus Driver Studio

RepeatedCapabilityAttributePhysicalNames Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal string PhysicalNames { get; }
internal:
property String^ PhysicalNames {
    String^ get ();
}

Property Value

Type: String
See Also

Reference

RepeatedCapabilityAttribute Class
MindWorks.Nimbus Namespace


RepeatedCapabilityAttribute.RepCapName Property

Pacific MindWorks Nimbus Driver Studio

RepeatedCapabilityAttributeRepCapName Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal string RepCapName { get; }
internal:
property String^ RepCapName {
    String^ get ();
}

Property Value

Type: String
See Also

Reference

RepeatedCapabilityAttribute Class
MindWorks.Nimbus Namespace


RepeatedCapabilityAttribute.Style Property

Pacific MindWorks Nimbus Driver Studio

RepeatedCapabilityAttributeStyle Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal RepeatedCapabilityStyle Style { get; }
internal:
property RepeatedCapabilityStyle Style {
    RepeatedCapabilityStyle get ();
}

Property Value

Type: RepeatedCapabilityStyle
See Also

Reference

RepeatedCapabilityAttribute Class
MindWorks.Nimbus Namespace


RepeatedCapabilityAttribute.UseQualifiedNames Property

Pacific MindWorks Nimbus Driver Studio

RepeatedCapabilityAttributeUseQualifiedNames Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public bool UseQualifiedNames { get; set; }
public:
property bool UseQualifiedNames {
    bool get ();
    void set (bool value);
}

Property Value

Type: Boolean
See Also

Reference

RepeatedCapabilityAttribute Class
MindWorks.Nimbus Namespace


RepeatedCapabilityStyle Enumeration

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal enum RepeatedCapabilityStyle
internal enum class RepeatedCapabilityStyle
Members
Member name | Value | Description
Parameter | 0 |
Selector | 1 |
See Also

Reference

MindWorks.Nimbus Namespace


SCPICompliantAttribute Class

Inheritance Hierarchy
SystemObject
SystemAttribute
MindWorks.NimbusNimbusAttribute
MindWorks.NimbusSCPICompliantAttribute

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal sealed class SCPICompliantAttribute : NimbusAttribute
internal ref class SCPICompliantAttribute sealed : public NimbusAttribute

The SCPICompliantAttribute type exposes the following members.

Constructors
 | Name | Description
Protected method | SCPICompliantAttribute | Initializes a new instance of the SCPICompliantAttribute class
Top
Properties
 | Name | Description
Protected property | Compliant |
Top
See Also

Reference

MindWorks.Nimbus Namespace


SCPICompliantAttribute Constructor

Initializes a new instance of the SCPICompliantAttribute class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal SCPICompliantAttribute(
    bool compliant
)
internal:
SCPICompliantAttribute(
    bool compliant
)

Parameters

compliant
Type: SystemBoolean
See Also

Reference

SCPICompliantAttribute Class
MindWorks.Nimbus Namespace


SCPICompliantAttribute Properties

The SCPICompliantAttribute type exposes the following members.

Properties
 | Name | Description
Protected property | Compliant |
Top
See Also

Reference

SCPICompliantAttribute Class
MindWorks.Nimbus Namespace


SCPICompliantAttribute.Compliant Property

Pacific MindWorks Nimbus Driver Studio

SCPICompliantAttributeCompliant Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal bool Compliant { get; set; }
internal:
property bool Compliant {
    bool get ();
    void set (bool value);
}

Property Value

Type: Boolean
See Also

Reference

SCPICompliantAttribute Class
MindWorks.Nimbus Namespace


SelectorStyleRepCapManager Class

Inheritance Hierarchy
SystemObject
MindWorks.NimbusRepCapManager
MindWorks.NimbusSelectorStyleRepCapManager

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public class SelectorStyleRepCapManager : RepCapManager
public ref class SelectorStyleRepCapManager : public RepCapManager

The SelectorStyleRepCapManager type exposes the following members.

Constructors
 | Name | Description
Protected method | SelectorStyleRepCapManager | Initializes a new instance of the SelectorStyleRepCapManager class
Top
Properties
 | Name | Description
Protected property | ActivePhysicalNames |
Protected property | ActiveSelector |
Protected property | Parent | (Inherited from RepCapManager.)
Protected property | PhysicalNames | (Inherited from RepCapManager.)
Protected property | RepCapName | (Inherited from RepCapManager.)
Protected property | Session | (Inherited from RepCapManager.)
Protected property | UseQualifiedPhysicalNames | (Inherited from RepCapManager.)
Top
Methods
 | Name | Description
Protected method | AddPhysicalName | (Inherited from RepCapManager.)
Protected method | ExpandSelector | (Inherited from RepCapManager.)
Protected method | GetActivePhysicalName |
Protected method | GetNumberOfAncestors | (Inherited from RepCapManager.)
Protected method | IsPhysicalNameDefined | (Inherited from RepCapManager.)
Protected method | LookupPhysicalName | (Inherited from RepCapManager.)
Protected method | RemovePhysicalName | (Inherited from RepCapManager.)
Protected method | TryLookupPhysicalName | (Inherited from RepCapManager.)
Top
See Also

Reference

MindWorks.Nimbus Namespace


SelectorStyleRepCapManager Constructor

Initializes a new instance of the SelectorStyleRepCapManager class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal SelectorStyleRepCapManager(
    string repCapName,
    SessionInfo session,
    bool useQualifiedPhysicalNames
)
internal:
SelectorStyleRepCapManager(
    String^ repCapName,
    SessionInfo^ session,
    bool useQualifiedPhysicalNames
)

Parameters

repCapName
Type: SystemString
session
Type: MindWorks.NimbusSessionInfo
useQualifiedPhysicalNames
Type: SystemBoolean
See Also

Reference

SelectorStyleRepCapManager Class
MindWorks.Nimbus Namespace


SelectorStyleRepCapManager Properties

The SelectorStyleRepCapManager type exposes the following members.

Properties
 | Name | Description
Protected property | ActivePhysicalNames |
Protected property | ActiveSelector |
Protected property | Parent | (Inherited from RepCapManager.)
Protected property | PhysicalNames | (Inherited from RepCapManager.)
Protected property | RepCapName | (Inherited from RepCapManager.)
Protected property | Session | (Inherited from RepCapManager.)
Protected property | UseQualifiedPhysicalNames | (Inherited from RepCapManager.)
Top
See Also

Reference

SelectorStyleRepCapManager Class
MindWorks.Nimbus Namespace


SelectorStyleRepCapManager.ActivePhysicalNames Property

Pacific MindWorks Nimbus Driver Studio

SelectorStyleRepCapManagerActivePhysicalNames Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal IList<PhysicalName> ActivePhysicalNames { get; }
internal:
property IList<PhysicalName^>^ ActivePhysicalNames {
    IList<PhysicalName^>^ get ();
}

Property Value

Type: IList PhysicalName
See Also

Reference

SelectorStyleRepCapManager Class
MindWorks.Nimbus Namespace


SelectorStyleRepCapManager.ActiveSelector Property

Pacific MindWorks Nimbus Driver Studio

SelectorStyleRepCapManagerActiveSelector Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal string ActiveSelector { get; set; }
internal:
property String^ ActiveSelector {
    String^ get ();
    void set (String^ value);
}

Property Value

Type: String
See Also

Reference

SelectorStyleRepCapManager Class
MindWorks.Nimbus Namespace


SelectorStyleRepCapManager Methods

The SelectorStyleRepCapManager type exposes the following members.

Methods
 | Name | Description
Protected method | AddPhysicalName | (Inherited from RepCapManager.)
Protected method | ExpandSelector | (Inherited from RepCapManager.)
Protected method | GetActivePhysicalName |
Protected method | GetNumberOfAncestors | (Inherited from RepCapManager.)
Protected method | IsPhysicalNameDefined | (Inherited from RepCapManager.)
Protected method | LookupPhysicalName | (Inherited from RepCapManager.)
Protected method | RemovePhysicalName | (Inherited from RepCapManager.)
Protected method | TryLookupPhysicalName | (Inherited from RepCapManager.)
Top
See Also

Reference

SelectorStyleRepCapManager Class
MindWorks.Nimbus Namespace


SelectorStyleRepCapManager.GetActivePhysicalName Method

Pacific MindWorks Nimbus Driver Studio

SelectorStyleRepCapManagerGetActivePhysicalName Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal PhysicalName GetActivePhysicalName()
internal:
PhysicalName^ GetActivePhysicalName()

Return Value

Type: PhysicalName
See Also

Reference

SelectorStyleRepCapManager Class
MindWorks.Nimbus Namespace


SessionInfo Class

Inheritance Hierarchy
SystemObject
MindWorks.NimbusSessionInfo

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public class SessionInfo
public ref class SessionInfo

The SessionInfo type exposes the following members.

Properties
 | Name | Description
Protected property | ConfigSettings |
Protected property | DriverSetup |
Protected property | DriverSetupString |
Protected property | InitOptions |
Protected property | InitOptionsString |
Protected property | InstrumentFirmwareRevision |
Protected property | InstrumentManufacturer |
Protected property | InstrumentModel |
Protected property | InstrumentSerialNumber |
Protected property | LogicalName |
Protected property | OriginalInitOptions |
Protected property | ResourceDescriptor |
Protected property | TraceEnabled |
Top
Methods
 | Name | Description
 | Load |
 | ParseOptionBooleanValue |
Protected method | RestoreInitialOptions |
Protected method | TranslatePhysicalName |
Protected method | TranslateVirtualName |
Top
See Also

Reference

MindWorks.Nimbus Namespace


SessionInfo Properties

The SessionInfo type exposes the following members.

Properties
 | Name | Description
Protected property | ConfigSettings |
Protected property | DriverSetup |
Protected property | DriverSetupString |
Protected property | InitOptions |
Protected property | InitOptionsString |
Protected property | InstrumentFirmwareRevision |
Protected property | InstrumentManufacturer |
Protected property | InstrumentModel |
Protected property | InstrumentSerialNumber |
Protected property | LogicalName |
Protected property | OriginalInitOptions |
Protected property | ResourceDescriptor |
Protected property | TraceEnabled |
Top
See Also

Reference

SessionInfo Class
MindWorks.Nimbus Namespace


SessionInfo.ConfigSettings Property

Pacific MindWorks Nimbus Driver Studio

SessionInfoConfigSettings Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal ReadOnlyDictionary<string, Object> ConfigSettings { get; }
internal:
property ReadOnlyDictionary<String^, Object^>^ ConfigSettings {
    ReadOnlyDictionary<String^, Object^>^ get ();
}

Property Value

Type: ReadOnlyDictionaryString, Object
See Also

Reference

SessionInfo Class
MindWorks.Nimbus Namespace


SessionInfo.DriverSetup Property

Pacific MindWorks Nimbus Driver Studio

SessionInfoDriverSetup Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal ReadOnlyDictionary<string, string> DriverSetup { get; }
internal:
property ReadOnlyDictionary<String^, String^>^ DriverSetup {
    ReadOnlyDictionary<String^, String^>^ get ();
}

Property Value

Type: ReadOnlyDictionaryString, String
See Also

Reference

SessionInfo Class
MindWorks.Nimbus Namespace


SessionInfo.DriverSetupString Property

Pacific MindWorks Nimbus Driver Studio

SessionInfoDriverSetupString Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal string DriverSetupString { get; }
internal:
property String^ DriverSetupString {
    String^ get ();
}

Property Value

Type: String
See Also

Reference

SessionInfo Class
MindWorks.Nimbus Namespace


SessionInfo.InitOptions Property

Pacific MindWorks Nimbus Driver Studio

SessionInfoInitOptions Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal InitOptions InitOptions { get; }
internal:
property InitOptions^ InitOptions {
    InitOptions^ get ();
}

Property Value

Type: InitOptions
See Also

Reference

SessionInfo Class
MindWorks.Nimbus Namespace


SessionInfo.InitOptionsString Property

Pacific MindWorks Nimbus Driver Studio

SessionInfoInitOptionsString Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal string InitOptionsString { get; }
internal:
property String^ InitOptionsString {
    String^ get ();
}

Property Value

Type: String
See Also

Reference

SessionInfo Class
MindWorks.Nimbus Namespace


SessionInfo.InstrumentFirmwareRevision Property

Pacific MindWorks Nimbus Driver Studio

SessionInfoInstrumentFirmwareRevision Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal string InstrumentFirmwareRevision { get; set; }
internal:
property String^ InstrumentFirmwareRevision {
    String^ get ();
    void set (String^ value);
}

Property Value

Type: String
See Also

Reference

SessionInfo Class
MindWorks.Nimbus Namespace


SessionInfo.InstrumentManufacturer Property

Pacific MindWorks Nimbus Driver Studio

SessionInfoInstrumentManufacturer Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal string InstrumentManufacturer { get; set; }
internal:
property String^ InstrumentManufacturer {
    String^ get ();
    void set (String^ value);
}

Property Value

Type: String
See Also

Reference

SessionInfo Class
MindWorks.Nimbus Namespace


SessionInfo.InstrumentModel Property

Pacific MindWorks Nimbus Driver Studio

SessionInfoInstrumentModel Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal string InstrumentModel { get; set; }
internal:
property String^ InstrumentModel {
    String^ get ();
    void set (String^ value);
}

Property Value

Type: String
See Also

Reference

SessionInfo Class
MindWorks.Nimbus Namespace


SessionInfo.InstrumentSerialNumber Property

Pacific MindWorks Nimbus Driver Studio

SessionInfoInstrumentSerialNumber Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal string InstrumentSerialNumber { get; set; }
internal:
property String^ InstrumentSerialNumber {
    String^ get ();
    void set (String^ value);
}

Property Value

Type: String
See Also

Reference

SessionInfo Class
MindWorks.Nimbus Namespace


SessionInfo.LogicalName Property

Pacific MindWorks Nimbus Driver Studio

SessionInfoLogicalName Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal string LogicalName { get; }
internal:
property String^ LogicalName {
    String^ get ();
}

Property Value

Type: String
See Also

Reference

SessionInfo Class
MindWorks.Nimbus Namespace


SessionInfo.OriginalInitOptions Property

Pacific MindWorks Nimbus Driver Studio

SessionInfoOriginalInitOptions Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal InitOptions OriginalInitOptions { get; }
internal:
property InitOptions^ OriginalInitOptions {
    InitOptions^ get ();
}

Property Value

Type: InitOptions
See Also

Reference

SessionInfo Class
MindWorks.Nimbus Namespace


SessionInfo.ResourceDescriptor Property

Pacific MindWorks Nimbus Driver Studio

SessionInfoResourceDescriptor Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal string ResourceDescriptor { get; }
internal:
property String^ ResourceDescriptor {
    String^ get ();
}

Property Value

Type: String
See Also

Reference

SessionInfo Class
MindWorks.Nimbus Namespace


SessionInfo.TraceEnabled Property

Pacific MindWorks Nimbus Driver Studio

SessionInfoTraceEnabled Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal bool TraceEnabled { get; set; }
internal:
property bool TraceEnabled {
    bool get ();
    void set (bool value);
}

Property Value

Type: Boolean
See Also

Reference

SessionInfo Class
MindWorks.Nimbus Namespace


SessionInfo Methods

The SessionInfo type exposes the following members.

Methods
 | Name | Description
 | Load |
 | ParseOptionBooleanValue |
Protected method | RestoreInitialOptions |
Protected method | TranslatePhysicalName |
Protected method | TranslateVirtualName |
Top
See Also

Reference

SessionInfo Class
MindWorks.Nimbus Namespace


SessionInfo.Load Method

Pacific MindWorks Nimbus Driver Studio

SessionInfoLoad Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static SessionInfo Load(
    Driver driver,
    string resourceName,
    string options,
    string softwareModuleName
)
internal:
static SessionInfo^ Load(
    Driver^ driver,
    String^ resourceName,
    String^ options,
    String^ softwareModuleName
)

Parameters

driver
Type: MindWorks.NimbusDriver
resourceName
Type: SystemString
options
Type: SystemString
softwareModuleName
Type: SystemString

Return Value

Type: SessionInfo
See Also

Reference

SessionInfo Class
MindWorks.Nimbus Namespace


SessionInfo.ParseOptionBooleanValue Method

Pacific MindWorks Nimbus Driver Studio

SessionInfoParseOptionBooleanValue Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static bool ParseOptionBooleanValue(
    string name,
    string value
)
internal:
static bool ParseOptionBooleanValue(
    String^ name,
    String^ value
)

Parameters

name
Type: SystemString
value
Type: SystemString

Return Value

Type: Boolean
See Also

Reference

SessionInfo Class
MindWorks.Nimbus Namespace


SessionInfo.RestoreInitialOptions Method

Pacific MindWorks Nimbus Driver Studio

SessionInfoRestoreInitialOptions Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal void RestoreInitialOptions()
internal:
void RestoreInitialOptions()
See Also

Reference

SessionInfo Class
MindWorks.Nimbus Namespace


SessionInfo.TranslatePhysicalName Method

Pacific MindWorks Nimbus Driver Studio

SessionInfoTranslatePhysicalName Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal string TranslatePhysicalName(
    string physicalName
)
internal:
String^ TranslatePhysicalName(
    String^ physicalName
)

Parameters

physicalName
Type: SystemString

Return Value

Type: String
See Also

Reference

SessionInfo Class
MindWorks.Nimbus Namespace


SessionInfo.TranslateVirtualName Method

Pacific MindWorks Nimbus Driver Studio

SessionInfoTranslateVirtualName Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal string TranslateVirtualName(
    string virtualName
)
internal:
String^ TranslateVirtualName(
    String^ virtualName
)

Parameters

virtualName
Type: SystemString

Return Value

Type: String
See Also

Reference

SessionInfo Class
MindWorks.Nimbus Namespace


SimulationAttribute Class

Inheritance Hierarchy
SystemObject
SystemAttribute
MindWorks.NimbusNimbusAttribute
MindWorks.NimbusNimbusCodeWeaverAttribute
MindWorks.NimbusModelSpecificNimbusCodeWeaverAttribute
MindWorks.NimbusSimulationAttribute

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal sealed class SimulationAttribute : ModelSpecificNimbusCodeWeaverAttribute
internal ref class SimulationAttribute sealed : public ModelSpecificNimbusCodeWeaverAttribute

The SimulationAttribute type exposes the following members.

Constructors
 | Name | Description
Protected method | SimulationAttribute | Initializes a new instance of the SimulationAttribute class
Top
Properties
 | Name | Description
Public property | Default |
Public property | Mode |
Public property | Models | (Inherited from ModelSpecificNimbusCodeWeaverAttribute.)
Public property | SuppressAll | (Inherited from NimbusCodeWeaverAttribute.)
Top
See Also

Reference

MindWorks.Nimbus Namespace


SimulationAttribute Constructor

Initializes a new instance of the SimulationAttribute class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal SimulationAttribute(
    SimulationMode mode,
    params string[] models
)
internal:
SimulationAttribute(
    SimulationMode mode,
    ... array<String^>^ models
)

Parameters

mode
Type: MindWorks.NimbusSimulationMode
models
Type: SystemString
See Also

Reference

SimulationAttribute Class
MindWorks.Nimbus Namespace


SimulationAttribute Properties

The SimulationAttribute type exposes the following members.

Properties
 | Name | Description
Public property | Default |
Public property | Mode |
Public property | Models | (Inherited from ModelSpecificNimbusCodeWeaverAttribute.)
Public property | SuppressAll | (Inherited from NimbusCodeWeaverAttribute.)
Top
See Also

Reference

SimulationAttribute Class
MindWorks.Nimbus Namespace


SimulationAttribute.Default Property

Pacific MindWorks Nimbus Driver Studio

SimulationAttributeDefault Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public string Default { get; set; }
public:
property String^ Default {
    String^ get ();
    void set (String^ value);
}

Property Value

Type: String
See Also

Reference

SimulationAttribute Class
MindWorks.Nimbus Namespace


SimulationAttribute.Mode Property

Pacific MindWorks Nimbus Driver Studio

SimulationAttributeMode Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public SimulationMode Mode { get; }
public:
property SimulationMode Mode {
    SimulationMode get ();
}

Property Value

Type: SimulationMode
See Also

Reference

SimulationAttribute Class
MindWorks.Nimbus Namespace


SimulationMode Enumeration

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal enum SimulationMode
internal enum class SimulationMode
Members
Member name | Value | Description
Manual | 0 |
ConstantValue | 1 |
LastValue | 2 |
See Also

Reference

MindWorks.Nimbus Namespace


SupportedInstrumentClassAttribute Class

Inheritance Hierarchy
SystemObject
SystemAttribute
MindWorks.NimbusNimbusAttribute
MindWorks.NimbusSupportedInstrumentClassAttribute

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal sealed class SupportedInstrumentClassAttribute : NimbusAttribute
internal ref class SupportedInstrumentClassAttribute sealed : public NimbusAttribute

The SupportedInstrumentClassAttribute type exposes the following members.

Constructors
 | Name | Description
Protected method | SupportedInstrumentClassAttribute | Initializes a new instance of the SupportedInstrumentClassAttribute class
Top
Properties
 | Name | Description
Protected property | CapabilityGroups |
Protected property | InstrumentClassName |
Public property | IsPrimaryInstrumentClass |
Protected property | MajorVersion |
Protected property | MinorVersion |
Top
See Also

Reference

MindWorks.Nimbus Namespace


SupportedInstrumentClassAttribute Constructor

Initializes a new instance of the SupportedInstrumentClassAttribute class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal SupportedInstrumentClassAttribute(
    string instrumentClassName,
    int majorVersion,
    int minorVersion,
    string capabilityGroups
)
internal:
SupportedInstrumentClassAttribute(
    String^ instrumentClassName,
    int majorVersion,
    int minorVersion,
    String^ capabilityGroups
)

Parameters

instrumentClassName
Type: SystemString
majorVersion
Type: SystemInt32
minorVersion
Type: SystemInt32
capabilityGroups
Type: SystemString
See Also

Reference

SupportedInstrumentClassAttribute Class
MindWorks.Nimbus Namespace


SupportedInstrumentClassAttribute Properties

The SupportedInstrumentClassAttribute type exposes the following members.

Properties
 | Name | Description
Protected property | CapabilityGroups |
Protected property | InstrumentClassName |
Public property | IsPrimaryInstrumentClass |
Protected property | MajorVersion |
Protected property | MinorVersion |
Top
See Also

Reference

SupportedInstrumentClassAttribute Class
MindWorks.Nimbus Namespace


SupportedInstrumentClassAttribute.CapabilityGroups Property

Pacific MindWorks Nimbus Driver Studio

SupportedInstrumentClassAttributeCapabilityGroups Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal IList<string> CapabilityGroups { get; }
internal:
property IList<String^>^ CapabilityGroups {
    IList<String^>^ get ();
}

Property Value

Type: IList String
See Also

Reference

SupportedInstrumentClassAttribute Class
MindWorks.Nimbus Namespace


SupportedInstrumentClassAttribute.InstrumentClassName Property

Pacific MindWorks Nimbus Driver Studio

SupportedInstrumentClassAttributeInstrumentClassName Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal string InstrumentClassName { get; }
internal:
property String^ InstrumentClassName {
    String^ get ();
}

Property Value

Type: String
See Also

Reference

SupportedInstrumentClassAttribute Class
MindWorks.Nimbus Namespace


SupportedInstrumentClassAttribute.IsPrimaryInstrumentClass Property

Pacific MindWorks Nimbus Driver Studio

SupportedInstrumentClassAttributeIsPrimaryInstrumentClass Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public bool IsPrimaryInstrumentClass { get; set; }
public:
property bool IsPrimaryInstrumentClass {
    bool get ();
    void set (bool value);
}

Property Value

Type: Boolean
See Also

Reference

SupportedInstrumentClassAttribute Class
MindWorks.Nimbus Namespace


SupportedInstrumentClassAttribute.MajorVersion Property

Pacific MindWorks Nimbus Driver Studio

SupportedInstrumentClassAttributeMajorVersion Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal int MajorVersion { get; }
internal:
property int MajorVersion {
    int get ();
}

Property Value

Type: Int32
See Also

Reference

SupportedInstrumentClassAttribute Class
MindWorks.Nimbus Namespace


SupportedInstrumentClassAttribute.MinorVersion Property

Pacific MindWorks Nimbus Driver Studio

SupportedInstrumentClassAttributeMinorVersion Property

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal int MinorVersion { get; }
internal:
property int MinorVersion {
    int get ();
}

Property Value

Type: Int32
See Also

Reference

SupportedInstrumentClassAttribute Class
MindWorks.Nimbus Namespace


TextUtility Class

Inheritance Hierarchy
SystemObject
MindWorks.NimbusTextUtility

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal class TextUtility
internal ref class TextUtility

The TextUtility type exposes the following members.

Constructors
 | Name | Description
Public method | TextUtility | Initializes a new instance of the TextUtility class
Top
Methods
Name | Description
IsWhiteSpace |
RemoveWhiteSpace |
Top
See Also

Reference

MindWorks.Nimbus Namespace


TextUtility Constructor

Initializes a new instance of the TextUtility class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public TextUtility()
public:
TextUtility()
See Also

Reference

TextUtility Class
MindWorks.Nimbus Namespace


TextUtility Methods

The TextUtility type exposes the following members.

Methods
Name | Description
IsWhiteSpace |
RemoveWhiteSpace |
Top
See Also

Reference

TextUtility Class
MindWorks.Nimbus Namespace


TextUtility.IsWhiteSpace Method

Pacific MindWorks Nimbus Driver Studio

TextUtilityIsWhiteSpace Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static bool IsWhiteSpace(
    string text
)
internal:
static bool IsWhiteSpace(
    String^ text
)

Parameters

text
Type: SystemString

Return Value

Type: Boolean
See Also

Reference

TextUtility Class
MindWorks.Nimbus Namespace


TextUtility.RemoveWhiteSpace Method

Pacific MindWorks Nimbus Driver Studio

TextUtilityRemoveWhiteSpace Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static string RemoveWhiteSpace(
    string text
)
internal:
static String^ RemoveWhiteSpace(
    String^ text
)

Parameters

text
Type: SystemString

Return Value

Type: String
See Also

Reference

TextUtility Class
MindWorks.Nimbus Namespace


UsedInSession Enumeration

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal enum UsedInSession
internal enum class UsedInSession
Members
Member name | Value | Description
Optional | 0 |
Required | 1 |
See Also

Reference

MindWorks.Nimbus Namespace


Utility Class

Inheritance Hierarchy
SystemObject
MindWorks.NimbusUtility

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static class Utility
internal ref class Utility abstract sealed

The Utility type exposes the following members.

Methods
Name | Description
AnyT |
CastT |
CastIteratorT |
ContainsT(IEnumerableT, T) |
ContainsT(IEnumerableT, T, IEqualityComparerT) |
ContainsDuplicatesT |
CountT |
FirstOrDefaultT(IEnumerableT) |
FirstOrDefaultT(IEnumerableT, PredicateT) |
ToArrayT |
TypeImplementsInterface |
TypeOverridesMethod |
WhereT |
Top
See Also

Reference

MindWorks.Nimbus Namespace


Utility Methods

The Utility type exposes the following members.

Methods
Name | Description
AnyT |
CastT |
CastIteratorT |
ContainsT(IEnumerableT, T) |
ContainsT(IEnumerableT, T, IEqualityComparerT) |
ContainsDuplicatesT |
CountT |
FirstOrDefaultT(IEnumerableT) |
FirstOrDefaultT(IEnumerableT, PredicateT) |
ToArrayT |
TypeImplementsInterface |
TypeOverridesMethod |
WhereT |
Top
See Also

Reference

Utility Class
MindWorks.Nimbus Namespace


Utility.Any(T) Method

Pacific MindWorks Nimbus Driver Studio

UtilityAnyT Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static bool Any<T>(
    IEnumerable<T> source,
    Predicate<T> predicate
)

internal:
generic<typename T>
static bool Any(
    IEnumerable<T>^ source,
    Predicate<T>^ predicate
)

Parameters

source
Type: System.Collections.GenericIEnumerable T
predicate
Type: SystemPredicate T

Type Parameters

T

Return Value

Type: Boolean
See Also

Reference

Utility Class
MindWorks.Nimbus Namespace


Utility.Cast(T) Method

Pacific MindWorks Nimbus Driver Studio

UtilityCastT Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static IEnumerable<T> Cast<T>(
    IEnumerable source
)

internal:
generic<typename T>
static IEnumerable<T>^ Cast(
    IEnumerable^ source
)

Parameters

source
Type: System.CollectionsIEnumerable

Type Parameters

T

Return Value

Type: IEnumerable T
See Also

Reference

Utility Class
MindWorks.Nimbus Namespace


Utility.CastIterator(T) Method

Pacific MindWorks Nimbus Driver Studio

UtilityCastIteratorT Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static IEnumerable<T> CastIterator<T>(
    IEnumerable source
)

internal:
generic<typename T>
static IEnumerable<T>^ CastIterator(
    IEnumerable^ source
)

Parameters

source
Type: System.CollectionsIEnumerable

Type Parameters

T

Return Value

Type: IEnumerable T
See Also

Reference

Utility Class
MindWorks.Nimbus Namespace


Utility.Contains Method

Pacific MindWorks Nimbus Driver Studio

UtilityContains Method

Overload List
Name | Description
ContainsT(IEnumerableT, T) |
ContainsT(IEnumerableT, T, IEqualityComparerT) |
Top
See Also

Reference

Utility Class
MindWorks.Nimbus Namespace


Utility.Contains(T) Method (IEnumerable(T), T)

Pacific MindWorks Nimbus Driver Studio

UtilityContainsT Method (IEnumerableT, T)

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static bool Contains<T>(
    IEnumerable<T> source,
    T value
)

internal:
generic<typename T>
static bool Contains(
    IEnumerable<T>^ source,
    T value
)

Parameters

source
Type: System.Collections.GenericIEnumerable T
value
Type: T

Type Parameters

T

Return Value

Type: Boolean
See Also

Reference

Utility Class
Contains Overload
MindWorks.Nimbus Namespace


Utility.Contains(T) Method (IEnumerable(T), T, IEqualityComparer(T))

Pacific MindWorks Nimbus Driver Studio

UtilityContainsT Method (IEnumerableT, T, IEqualityComparerT)

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static bool Contains<T>(
    IEnumerable<T> source,
    T value,
    IEqualityComparer<T> comparer
)

internal:
generic<typename T>
static bool Contains(
    IEnumerable<T>^ source,
    T value,
    IEqualityComparer<T>^ comparer
)

Parameters

source
Type: System.Collections.GenericIEnumerable T
value
Type: T
comparer
Type: System.Collections.GenericIEqualityComparer T

Type Parameters

T

Return Value

Type: Boolean
See Also

Reference

Utility Class
Contains Overload
MindWorks.Nimbus Namespace


Utility.ContainsDuplicates(T) Method

Pacific MindWorks Nimbus Driver Studio

UtilityContainsDuplicatesT Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static bool ContainsDuplicates<T>(
    IEnumerable<T> source
)

internal:
generic<typename T>
static bool ContainsDuplicates(
    IEnumerable<T>^ source
)

Parameters

source
Type: System.Collections.GenericIEnumerable T

Type Parameters

T

Return Value

Type: Boolean
See Also

Reference

Utility Class
MindWorks.Nimbus Namespace


Utility.Count(T) Method

Pacific MindWorks Nimbus Driver Studio

UtilityCountT Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static int Count<T>(
    IEnumerable<T> source
)

internal:
generic<typename T>
static int Count(
    IEnumerable<T>^ source
)

Parameters

source
Type: System.Collections.GenericIEnumerable T

Type Parameters

T

Return Value

Type: Int32
See Also

Reference

Utility Class
MindWorks.Nimbus Namespace


Utility.FirstOrDefault Method

Pacific MindWorks Nimbus Driver Studio

UtilityFirstOrDefault Method

Overload List
Name | Description
FirstOrDefaultT(IEnumerableT) |
FirstOrDefaultT(IEnumerableT, PredicateT) |
Top
See Also

Reference

Utility Class
MindWorks.Nimbus Namespace


Utility.FirstOrDefault(T) Method (IEnumerable(T))

Pacific MindWorks Nimbus Driver Studio

UtilityFirstOrDefaultT Method (IEnumerableT)

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static T FirstOrDefault<T>(
    IEnumerable<T> source
)

internal:
generic<typename T>
static T FirstOrDefault(
    IEnumerable<T>^ source
)

Parameters

source
Type: System.Collections.GenericIEnumerable T

Type Parameters

T

Return Value

Type: T
See Also

Reference

Utility Class
FirstOrDefault Overload
MindWorks.Nimbus Namespace


Utility.FirstOrDefault(T) Method (IEnumerable(T), Predicate(T))

Pacific MindWorks Nimbus Driver Studio

UtilityFirstOrDefaultT Method (IEnumerableT, PredicateT)

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static T FirstOrDefault<T>(
    IEnumerable<T> source,
    Predicate<T> predicate
)

internal:
generic<typename T>
static T FirstOrDefault(
    IEnumerable<T>^ source,
    Predicate<T>^ predicate
)

Parameters

source
Type: System.Collections.GenericIEnumerable T
predicate
Type: SystemPredicate T

Type Parameters

T

Return Value

Type: T
See Also

Reference

Utility Class
FirstOrDefault Overload
MindWorks.Nimbus Namespace


Utility.ToArray(T) Method

Pacific MindWorks Nimbus Driver Studio

UtilityToArrayT Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static T[] ToArray<T>(
    IEnumerable<T> source
)

internal:
generic<typename T>
static array<T>^ ToArray(
    IEnumerable<T>^ source
)

Parameters

source
Type: System.Collections.GenericIEnumerable T

Type Parameters

T

Return Value

Type: T
See Also

Reference

Utility Class
MindWorks.Nimbus Namespace


Utility.TypeImplementsInterface Method

Pacific MindWorks Nimbus Driver Studio

UtilityTypeImplementsInterface Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static bool TypeImplementsInterface(
    Type type,
    Type intfType
)
internal:
static bool TypeImplementsInterface(
    Type^ type,
    Type^ intfType
)

Parameters

type
Type: SystemType
intfType
Type: SystemType

Return Value

Type: Boolean
See Also

Reference

Utility Class
MindWorks.Nimbus Namespace


Utility.TypeOverridesMethod Method

Pacific MindWorks Nimbus Driver Studio

UtilityTypeOverridesMethod Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static bool TypeOverridesMethod(
    Type targetType,
    MethodInfo virtualMethod
)
internal:
static bool TypeOverridesMethod(
    Type^ targetType,
    MethodInfo^ virtualMethod
)

Parameters

targetType
Type: SystemType
virtualMethod
Type: System.ReflectionMethodInfo

Return Value

Type: Boolean
See Also

Reference

Utility Class
MindWorks.Nimbus Namespace


Utility.Where(T) Method

Pacific MindWorks Nimbus Driver Studio

UtilityWhereT Method

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal static IEnumerable<T> Where<T>(
    IEnumerable<T> source,
    Predicate<T> predicate
)

internal:
generic<typename T>
static IEnumerable<T>^ Where(
    IEnumerable<T>^ source,
    Predicate<T>^ predicate
)

Parameters

source
Type: System.Collections.GenericIEnumerable T
predicate
Type: SystemPredicate T

Type Parameters

T

Return Value

Type: IEnumerable T
See Also

Reference

Utility Class
MindWorks.Nimbus Namespace


VisaTimeoutManager Class

Inheritance Hierarchy
SystemObject
MindWorks.NimbusVisaTimeoutManager

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal sealed class VisaTimeoutManager : IDisposable
internal ref class VisaTimeoutManager sealed : IDisposable

The VisaTimeoutManager type exposes the following members.

Constructors
 | Name | Description
Protected method | VisaTimeoutManager(IVisaSession, PrecisionTimeSpan) | Initializes a new instance of the VisaTimeoutManager class
Protected method | VisaTimeoutManager(IVisaSession, Int32) | Initializes a new instance of the VisaTimeoutManager class
Protected method | VisaTimeoutManager(IVisaSession, TimeSpan) | Initializes a new instance of the VisaTimeoutManager class
Top
Methods
 | Name | Description
Public method | Dispose | Releases all resources used by the VisaTimeoutManager
Top
See Also

Reference

MindWorks.Nimbus Namespace


VisaTimeoutManager Constructor

Overload List
 | Name | Description
Protected method | VisaTimeoutManager(IVisaSession, PrecisionTimeSpan) | Initializes a new instance of the VisaTimeoutManager class
Protected method | VisaTimeoutManager(IVisaSession, Int32) | Initializes a new instance of the VisaTimeoutManager class
Protected method | VisaTimeoutManager(IVisaSession, TimeSpan) | Initializes a new instance of the VisaTimeoutManager class
Top
See Also

Reference

VisaTimeoutManager Class
MindWorks.Nimbus Namespace


VisaTimeoutManager Constructor (IVisaSession, PrecisionTimeSpan)

Initializes a new instance of the VisaTimeoutManager class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal VisaTimeoutManager(
    IVisaSession session,
    PrecisionTimeSpan timeout
)
internal:
VisaTimeoutManager(
    IVisaSession^ session,
    PrecisionTimeSpan timeout
)

Parameters

session
Type: IVisaSession
timeout
Type: PrecisionTimeSpan
See Also

Reference

VisaTimeoutManager Class
VisaTimeoutManager Overload
MindWorks.Nimbus Namespace


VisaTimeoutManager Constructor (IVisaSession, Int32)

Initializes a new instance of the VisaTimeoutManager class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal VisaTimeoutManager(
    IVisaSession session,
    int timeout
)
internal:
VisaTimeoutManager(
    IVisaSession^ session,
    int timeout
)

Parameters

session
Type: IVisaSession
timeout
Type: SystemInt32
See Also

Reference

VisaTimeoutManager Class
VisaTimeoutManager Overload
MindWorks.Nimbus Namespace


VisaTimeoutManager Constructor (IVisaSession, TimeSpan)

Initializes a new instance of the VisaTimeoutManager class

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
internal VisaTimeoutManager(
    IVisaSession session,
    TimeSpan timeout
)
internal:
VisaTimeoutManager(
    IVisaSession^ session,
    TimeSpan timeout
)

Parameters

session
Type: IVisaSession
timeout
Type: SystemTimeSpan
See Also

Reference

VisaTimeoutManager Class
VisaTimeoutManager Overload
MindWorks.Nimbus Namespace


VisaTimeoutManager Methods

The VisaTimeoutManager type exposes the following members.

Methods
 | Name | Description
Public method | Dispose |
Top
See Also

Reference

VisaTimeoutManager Class
MindWorks.Nimbus Namespace


VisaTimeoutManager.Dispose Method

Pacific MindWorks Nimbus Driver Studio

VisaTimeoutManagerDispose Method

Releases all resources used by the VisaTimeoutManager

Namespace: MindWorks.Nimbus
Syntax
C#
C++
Copy
public void Dispose()
public:
virtual void Dispose() sealed

Implements

IDisposableDispose
See Also

Reference

VisaTimeoutManager Class
MindWorks.Nimbus Namespace


Developing an IVI-COM Driver

Developing an IVI-COM driver involves a number of tasks. The New IVI-COM Wizard is used to create the driver project. Various Nimbus features integrated into the Visual Studio IDE allow functionality to be added to the driver, while the Nimbus Template Library provides a rich set of support functions for implementing these features.

In This Section

Creating an IVI-COM Driver Project

Visual Studio Projects for an IVI-COM Driver

Understanding the Nimbus User Interface

Adding Functionality to an IVI-COM Driver

IVI-COM Item Editors

IVI-C Item Editors

Adding Support for Multiple Instrument Models

Implementing an IVI-COM Driver

Supporting .NET Client Applications

Tracing the Execution of an IVI-COM Driver

Testing an IVI-COM Driver

Testing an IVI-C Wrapper

Creating a MATLAB Wrapper

Versioning an IVI-COM Driver

The Nimbus Template Library (NTL)


Creating an IVI-COM Driver Project

The first step in developing an IVI-COM driver is to create the IVI driver project. Nimbus supplies a custom project type to the Visual Studio project system just for this purpose. The topics in this section explain how to run the New IVI-COM Driver Wizard as well as the Visual Studio projects that are created in the process. Also, the topics in this section explain the Visual Studio settings that must be properly configured to build the IVI-COM driver project.

In This Section

Using the IVI-COM Driver Wizard

Required Visual Studio Configuration Changes

Building the IVI-COM Driver


Using the IVI-COM Driver Wizard

The first step in creating an IVI-COM driver is running the New IVI-COM Driver Wizard. The wizard is launched from within the Visual Studio IDE, just as native Visual Studio project types.

To launch the New IVI-COM Driver Wizard

  1. From within Visual Studio, click on the File menu, select New and then choose Project.

  2. The standard Visual Studio New Project Dialog appears.

  3. Under Project types, choose Nimbus Projects and then select IVI-COM Driver from the Templates window.

  4. The New IVI-COM Driver Wizard appears.

Tip Tip

When filling out the wizard pages, keep in mind that any of the options selected can be changed later using the Driver Settings Editor.

The remaining topics in this section discuss each wizard page separately.

In This Section

General Page, New IVI-COM Driver Wizard

Instrument Classes Page, New IVI-COM Driver Wizard

LXI Compliance Page, New IVI-COM Driver Wizard

Features Page, New IVI-COM Driver Wizard

Projects Page, New IVI-COM Driver Wizard


General Page, New IVI-COM Driver Wizard

The General Page of the New IVI-COM Driver Wizard presents basic information about the IVI-COM driver project.

Driver name

The driver name is the primary identifier for the entire IVI-COM driver project. Virtually all names associated with the driver will be based on the driver name. The driver DLL, the IVI Configuration Store entries, the driver interfaces, the main driver class, and many other items are based on this entry.

Instrument manufacturer

The instrument manufacturer is used to identify the manufacturer of the instrument for which the driver is being written. This entry is used in the IVI Configuration Store registration as well as in the implementation of the IIviDriver.InstrumentManufactuer property.

Driver vendor

The driver vendor identifies the company responsible for development and support of the driver. This entry is used in the IVI Configuration Store registration as well as in the implementation of the IIviDriverComponentIdentity.Vendor property.

.NET assembly name prefix

This entry controls the name of the .NET interop assembly as well as that of any .NET policy files shipped with the driver. The IVI specifications require that this prefix represent the driver vendor. The full name of the .NET assemblies based on this prefix is displayed in the .NET assembly name text box just below this entry.

For more information on .NET interop assemblies, see the topic Supporting .NET Client Applications.

For more information on .NET policy files, see the topic Understanding .NET Versioning.

.NET assembly name

This is a read-only field that displays the .NET assembly names resulting from the choice entered in the .NET assembly name prefix field

Instrument model

The name of the instrument model for which the driver is being written. The driver must be able to use this string to identify the actual connected instrument during driver initialization, such as through the use of a "*IDN?" query. See the topic Understanding the Initialization Sequence for information on identifying the connected model.

If the driver is to support multiple instrument models, enter one of the most common models here. The Models Page of the Driver Settings Editor can be used to add models to the driver. See the topic Adding Support for Multiple Instrument Models for more information on multi-model drivers.


I/O Page, New IVI-COM Driver Wizard

Instrument I/O
I/O Type

The Nimbus I/O object can be used with either flavor of VISA (COM or conventional C). The selection made here determines which I/O provider will be used by the Nimbus I/O object. See the topic Using the I/O Object for details on making this selection.

VISA-C

Selecting this option instructs the I/O object to use VISA-C as its underlying I/O provider.

VISA-COM

Selecting this option instructs the I/O object to use VISA-COM as its underlying I/O provider.

None

Selecting this option informs Nimbus not to generate an I/O object. This option is chosen if you have an I/O library of your own, such as a custom I/O DLL you require to communicate with your instrument.

Integer format

Specifies the default format code to use for integer values in instrument command strings. Explicit format codes used in the instrument command override this setting.

See the topics under Working With Instrument Commands for more information.

Floating-point format

Specifies the default format code to use for floating-point values in instrument command strings. Explicit format codes used in the instrument command override this setting.

See the topics under Working With Instrument Commands for more information.

String format

Specifies the default format code to use for string values in instrument response strings. Explicit format codes used in the instrument command override this setting. This setting is only used for reading values from the instrument -- not for formatting values sent to the instrument.

See the topics under Working With Instrument Commands for more information.

Boolean True

Specifies a comma-separated list of instrument responses that should be interpreted as a boolean true. For instrument commands, the first string in the list will be used to send a boolean true to the device.

Boolean False

Specifies a comma-separated list of instrument responses that should be interpreted as a boolean false. For instrument commands, the first string in the list will be used to send a boolean false to the device.

SCPI compliant

Indicates whether the instrument uses SCPI-compliant instrument commands. Nimbus provides specialized support for SCPI-compliant instruments. See the topic Special Features For SCPI Commands for detailed information.

Generate direct I/O functions and attributes

This setting controls whether the wizard will generate the IVI-defined functions and attributes for directly communicating with the instrument using the underlying I/O mechanism. For a driver using VISA as its underlying I/O library, Nimbus will generate a working implementation of these functions and attributes. For a non-VISA-based driver, Nimbus will generate stub implementations that the driver developer must then fill in with an implementation appropriate for their specific I/O library.

The exact syntax and behavior of these functions is prescribed in IVI-3.4: API Sytle Guide.

Important note Important

In order to comply with the IVI Generation IVI-2014, drivers must implement these direct I/O functions and attributes. These functions and attributes can be created after the wizard runs, but it is typically easier to let the wizard create them upfront.

See Also

Other Resources

Communicating With Instruments
Working With Instrument Commands
Special Features for SCPI Commands


Instrument Classes Page, New IVI-COM Driver Wizard

The IVI Instrument Classes Page of the New IVI-COM Driver Wizard allows you to select which IVI instrument classes the driver supports. Check the box next to each instrument class you wish to support. Nimbus automatically adds the appropriate references to the driver project and creates code for implementing and testing the IVI-defined methods and properties in the selected instrument classes. In addition, the driver installer is created so that it properly registers the driver's capabilities in the end user's IVI Configuration Store.

Note Note

It is not necessary to decide which instrument classes will be supported when running the wizard. Support for specific instrument classes can be added and removed at any stage of development using commands available within the IDE. See the topic Adding Support for an Instrument Class for more information.

See Also

Other Resources

How IVI Drivers Provide Interchangeability
Adding Support for an Instrument Class


LXI Compliance Page, New IVI-COM Driver Wizard

The LXI Compliance Page of the New IVI-COM Driver Wizard allows you to select whether the instruments support LXI and which LXI extension groups are supported. Based upon the selections made here, Nimbus automatically creates a project with the appropriate LXI repeated capabilities and repeated capability names and the required IviLxiSync functions and attributes.

Note Note

It is not necessary to decide upon the degress of LXI compliance when running the wizard. Support for LXI can be added and removed at any stage of development using commands available within the IDE. See the topic Adding Support for LXI for more information.

Conformance

Indicates whether the driver supports any level of LXI conformance. No modifications are performed based on this selection alone, but by selecting LXI Core 2016, the checkboxes for the various LXI-defined extension groups become enabled and selecting those extension groups does cause Nimbus to modify the driver code.

LXI Extension Groups

Selecting any of the LXI-defined extension groups adds the IviLxiSync functions, attributes, and repeated capabilities to the driver.

For the added repeated capabilities, Nimbus adds the LXI-defined repeated capability names for LAN triggers (LAN0...7).

If LXI Wired Trigger Bus is selected, Nimbus adds LXI-defined repeated capability names for the LXI hardware trigger lines (LXI0...7).

See Also

Other Resources

Adding Support for LXI


Features Page, New IVI-COM Driver Wizard

The Features Page of the New IVI-COM Driver Wizard allows you to select various IVI driver features, such as adding an IVI-C wrapper.

Create an IVI-C wrapper

This setting controls whether Nimbus will generate an IVI-C wrapper for the driver.

For more information on IVI-C wrappers, see the topic Developing an IVI-C Driver.

Prefix

If IVI-C wrapper generation is enabled, this setting controls the IVI-C prefix for the driver. This prefix is very important as it controls the name of many items associated with the driver. The driver DLL itself will be named using this prefix, overriding the DLL name that would result from using the IVI-COM project name. The names of all IVI-C functions and attributes begin with this prefix. Additionally, the driver install location is governed by the prefix chosen here.

Important note Important

The IVI specifications require that the first two letters of this prefix match the official two-letter abbreviation assigned to the driver vendor by the IVI Foundation in the specification "VPP-9: Instrument Vendor Abbreviations" . If the driver vendor does not have an assigned two-letter prefix, one can be obtained from the IVI Foundation. Visit the IVI Foundation website for details.

Instrument class

Unlike IVI-COM drivers, IVI-C drivers can only support a single instrument class. This is a fundamental limitation of all IVI-C drivers and stems from the fact that IVI-C attributes are defined with numeric identifiers that are not unique across the various instrument classes. See the IVI Backgrounder section on Interchangeability for more information on this IVI-C limitation.

This setting selects which of the supported IVI-COM driver instrument classes should be supported by the IVI-C driver.

Automatically generate getter functions for IVI-C attributes

This setting controls whether getter functions are automatically generated when an IVI-C attribute is added to the driver.

Getter function prefix

This setting controls the name of automatically generated IVI-C attribute getter functions. For example, if an attribute named OUTPUT_VOLTAGE is created, and this setting is chosen to be Get, Nimbus will automatically generate an IVI-C getter function named GetOutputVoltage.

The name resulting from selections made here represent the initial name given to the getter function. Individual getter functions can be renamed as desired.

Automatically generate setter functions for IVI-C attributes

This setting controls whether setter functions are automatically generated when an IVI-C attribute is added to the driver.

Setter function prefix

This setting controls the name of automatically generated IVI-C attribute setter functions. For example, if an attribute named OUTPUT_VOLTAGE is created, and this setting is chosen to be Set, Nimbus will automatically generate an IVI-C setter function named SetOutputVoltage.

The name resulting from selections made here represent the initial name given to the setter function. Individual setter functions can be renamed as desired.

See Also

Other Resources

Developing an IVI-C Driver
Creating 64-Bit Driver Installers
Adding Attribute Getter and Setter Functions


Projects Page, New IVI-COM Driver Wizard

The Projects Page of the New IVI-COM Driver Wizard allows you to select which additional Nimbus-generated Visual Studio projects should be created and added to the driver solution.

Note Note

Any of the projects available via the wizard can be added later by right-clicking on the Solution node in Solution Explorer and choosing Add and then selecting New Project.

Create IVI-COM unit test

Specifies whether a Visual C# unit test project for the IVI-COM driver should be created and added to the driver solution.

Nimbus provides advanced IVI-COM driver unit testing features that integrate directly with the Visual Studio IDE. For more information, see the topic Testing an IVI-COM Driver.

Create IVI-COM help project

Specifies whether an IVI-COM driver help project for the IVI-COM driver should be created and added to the driver solution. The project is generated based on your per-user preferences for help projects.

Create IVI-COM setup project

Specifies whether an IVI-COM driver setup project for the IVI.NET driver should be created and added to the driver solution.

Create IVI-COM C++ application

This option creates a starter Visual C++ project for exercising the IVI-COM driver. The project is generated with the appropriate references, declarations, initialization and shutdown calls as well as basic error checking code. This project is a good starting point for building more involved C++ client applications or for simply testing driver operation in C++.

Create IVI-COM C# application

This option creates a starter Visual C# project for exercising the IVI-COM driver. The project is generated with the appropriate references, declarations, initialization and shutdown calls as well as basic error checking code. This project is a good starting point for building more involved C# client applications or for simply testing driver operation in C#.

Create IVI-COM Visual Basic application

This option creates a starter Visual Basic.NET project for exercising the IVI-COM driver. The project is generated with the appropriate references, declarations, initialization and shutdown calls as well as basic error checking code. This project is a good starting point for building more involved Visual Basic client applications or for simply testing driver operation in Visual Basic.

Create IVI-C unit test

Specifies whether a Visual C++ unit test project for the IVI-C wrapper should be created and added to the driver solution.

Nimbus provides advanced IVI-C driver unit testing features that integrate directly with the Visual Studio IDE. For more information, see the topic Testing an IVI-C Wrapper.

Create IVI-C C++ application

This option creates a starter Visual C++ project for exercising the IVI-C driver. The project is generated with the appropriate references, declarations, initialization and shutdown calls as well as basic error checking code. This project is a good starting point for building more involved IVI-C client applications or for simply testing the IVI-C wrapper operation.

See Also

Other Resources

Testing an IVI-COM Driver
Testing an IVI-C Wrapper


Required Visual Studio Configuration Changes

Before building an IVI-COM driver project, several configuration settings must be manually changed. The Visual Studio project system does not expose this functionality in a way that allows Nimbus to automatically perform these configuration changes, so this topic explains each step the driver developer must perform.

To configure the appropriate solution platforms

  1. From Solution Explorer, right click on the solution and choose Configuration Manager. The Configuration Manager Dialog Box appears.

  2. From the Active solution platform combo box, choose <Edit...>. The Edit Solution Platforms dialog box appears.

  3. The following platforms should be present:

    • Any CPU

    • Mixed Platforms

    • Win32

    • x64

    • x86

  4. Remove all platforms except for x86 and x64.

  5. Close the Edit Solution Platforms dialog.

  6. From the Configuration Manager dialog, choose the x86 platform from the Action solution platform combo box.

  7. Make sure that the Platform column setting and Build column setting for each project is set according to the table below. (Note the list of projects that appears depends upon the driver options chosen.)

    Project

    Platform

    Build

    <driverName>CppConsoleApplication

    Win32

    Checked

    <driverName>CsConsoleApplication

    x86

    Checked

    <driverName>CWrapperConsoleApplication

    Win32

    Checked

    <driverName>CWrapperUnitTest

    Win32

    Checked

    <driverName>Driver

    Win32

    Checked

    <driverName>Help

    Any CPU

    Unchecked

    <driverName>Setup

    x86

    Unchecked

    <driverName>UnitTest

    x86

    Checked

    <driverName>VbConsoleApplication

    x86

    Checked

  8. Use the Active solution configuration combo box to repeat the above settings for both Debug and Release configurations.

  9. From the Configuration Manager dialog, choose the x64 platform from the Action solution platform combo box.

  10. Make sure that the Platform column setting and Build column setting for each project is set according to the table below. (Note the list of projects that appears depends upon the driver options chosen.)

    Project

    Platform

    Build

    <driverName>CppConsoleApplication

    x64

    Checked

    <driverName>CsConsoleApplication

    x64

    Checked

    <driverName>CWrapperConsoleApplication

    x64

    Checked

    <driverName>CWrapperUnitTest

    x64

    Checked

    <driverName>Driver

    x64

    Checked

    <driverName>Help

    Any CPU

    Unchecked

    <driverName>Setup

    x64

    Unchecked

    <driverName>UnitTest

    x64

    Checked

    <driverName>VbConsoleApplication

    x64

    Checked

  11. Use the Active solution configuration combo box to repeat the above settings for both Debug and Release configurations.

See Also

Other Resources

Building the IVI-COM Driver


Building the IVI-COM Driver

Project Dependencies

A Nimbus driver solution consists of several Visual Studio projects. The topic Visual Studio Projects for an IVI-COM Driver discusses each of these projects. When these projects are created and added to the driver solution, Nimbus adds the appropriate build dependencies so that the projects are built in the proper order when the entire driver solution is built.

For example, the unit test project obviously relies upon the driver project, so Nimbus adds to the unit test project a dependency on the driver project. This ensures the driver project is built before the unit test project is built. Similarly, the driver setup project requires the driver and the help project to be built before it can be built, so it has dependencies on both of those projects.

To view the project dependencies

  1. From Solution Explorer, right click on the solution node (not the Nimbus node), and choose Properties.

  2. The Solution Property Pages Dialog appears.

  3. Choose Project Dependencies from the tree view on the left.

  4. Use the Project combo box on the right to view the project dependencies for the various Visual Studio projects in the driver solution.

Building the Driver

Building a complete Nimbus IVI driver requires up to three separate compilation steps. First, the build steps for 32-bit and 64-bit driver builds are separate because Visual Studio can only compile against one platform at a time. Also, the build step for compiling the help file and the driver installer is intentionally separate from the build step for compiling other projects in the driver solution because the help and installer projects are typically built less often than the driver project and the unit test projects. This is why the help and installer projects are unchecked in the x86 and x64 solution configurations.

Important note Important

Before building the driver, it is important to properly setup the Visual Studio solution build configurations. Visual Studio does not provide programmatic access to these settings, so Nimbus is unable to automatically configure them. The topic Required Visual Studio Configuration Changes provides details on what exactly must be done before building.

To perform a complete build of the IVI-COM driver:

  1. From the Solution Platforms combo box (typically near the top of the IDE), choose x86.

  2. From the Build menu, select Build Solution.

    This will perform a 32-bit compilation of the driver project, the unit test projects, and any client application projects in the solution. It will also generate the MATLAB® wrapper.

    For a Debug build, the output files will be placed in the following folder:

    • <solutionFolder>\build\Debug\x86

    For a Release build, the output files will be placed in the following folder:

    • <solutionFolder>\build\Release\x86

  3. From the Solution Platforms combo box, choose x64.

    Note Note

    If the x64 platform is not shown as an option in the Solution Platforms combo box, then the 64-bit C++ compiler was not installed when Visual Studio was installed. To install the 64-bit compiler, re-run the Visual Studio installer and select the 64-bit compiler from the installation options available under a Custom install.

  4. From the Build menu, select Build Solution.

    This will perform a 64-bit compilation of the driver project, the unit test projects, and any client application projects in the solution. It will also generate the MATLAB® wrapper.

    For a Debug build, the output files will be placed in the following folder:

    • <solutionFolder>\build\Debug\x64

    For a Release build, the output files will be placed in the following folder:

    • <solutionFolder>\build\Release\x64

See Also

Other Resources

Required Visual Studio Configuration Changes


Visual Studio Projects for an IVI-COM Driver

Nimbus supplies two custom project types to the Visual Studio project system that enable IVI-COM driver development, documentation, and installation.

  • IVI-COM Driver Help Project

    This project type is used to build the driver help file(s) for an associated IVI-COM driver. Each help project is associated with a single IVI-COM driver project, and includes the help template files used to control the look and feel of the driver documentation being produced. A driver help project may be created by the IVI-COM Driver Wizard based on your selections, or added to the driver solution later.

  • IVI-COM Driver Setup Project

    This project type is used to build the driver installer for an associated IVI-COM driver. Each setup project is associated with a single IVI-COM driver project, and includes the WiX source files used to produce the driver installer (MSI). A driver setup project may be created by the IVI-COM Driver Wizard based on your selections, or added to the driver solution later.

In addition to the above custom project types, Nimbus also supports adding six standard Visual Studio project types to a driver solution.

  • Unit Test Project

    This is a standard Visual Studio project type that enables unit testing of IVI-COM drivers. Although Nimbus leverages the standard Visual Studio unit testing framework, the Nimbus driver automatically adds and removes unit test methods from this project as you interact with the Nimbus driver designer.

  • C++ Console Application

    This is a standard Visual Studio project type for building a C++ console application that exercises the IVI-COM driver. After adding this type of project to a driver solution, Nimbus performs no further modifications. This provides a convenient way to create a starter application associated with your driver that can be used for additional testing or as sample code.

  • C# Console Application

    This is a standard Visual Studio project type for building a C# console application that exercises the IVI-COM driver. After adding this type of project to a driver solution, Nimbus performs no further modifications. This provides a convenient way to create a starter application associated with your driver that can be used for additional testing or as sample code.

  • Visual Basic Console Application

    This is a standard Visual Studio project type for building a Visual Basic console application that exercises the IVI-COM driver. After adding this type of project to a driver solution, Nimbus performs no further modifications. This provides a convenient way to create a starter application associated with your driver that can be used for additional testing or as sample code.

  • IVI-C Wrapper Unit Test Project

    This is a standard Visual Studio project type that enables unit testing of the IVI-C wrapper. Although Nimbus leverages the standard Visual Studio unit testing framework, the Nimbus driver automatically adds and removes unit test methods from this project as you interact with the Nimbus driver designer.

  • IVI-C Wrapper C++ Console Application

    This is a standard Visual Studio project type for building a C++ console application that exercises the IVI-C wrapper. After adding this type of project to a driver solution, Nimbus performs no further modifications. This provides a convenient way to create a starter application associated with your IVI-C wrapper that can be used for additional testing or as sample code.

Nimbus-Managed Files

There are a number of files in a Nimbus driver project that are automatically updated as part of the Nimbus roundtripping logic. For instance, when new methods or properties are added to a driver, the IDL definition for the driver interfaces must be updated by Nimbus. These IDL definitions are managed in a file named "<projectName>.nimbus.idl". Nimbus automatically updates this file, so it is important that users never manually make changes to such files. These are referred to as Nimbus-managed files, and they are easily distinguished from user-editable files because of how they are named. Nimbus-managed files typically end in an extension that includes "nimbus". For example, many Nimbus-managed files end in ".nimbus.h" or ".nimbus.cpp".

Important note Important

Any manual changes made to any Nimbus-managed file will be automatically overwritten by Nimbus whenever the driver project is edited. It is important to never directly edit a Nimbus-managed file.

There are only a few driver project files that a driver developer generally needs to edit -- the header file and .cpp file for the main driver class and the header and .cpp files for any repeated capability classes. These files contain the method and property definitions and implementation code for the entire driver API. The main driver header file is named "Co<projectName>.h" while the main implementation file is named "Co<projectName>.cpp". Similarly, a repeated capability header file is named "Co<projectName><repCapName>.h" and its implementation file is named "Co<projectName><repCapName>.cpp". Driver developers will work almost entirely within these files, greatly simplifying the task of managing driver project code.

Managing Multiple Drivers in a Solution

In some situations, it may be desirable to manage multiple IVI drivers in a single solution. Since a Nimbus IVI driver project is simply another type of Visual Studio project, this can be supported using standard Visual Studio techniques.

To add a Nimbus driver project to an existing solution

  1. From Solution Explorer, right-click on the Solution node.

  2. Choose Add and then either New Project... or Existing Project....

  3. For a new Nimbus IVI driver project, choose Nimbus Projects from the New Project Wizard and proceed as usual with the New IVI-COM Driver Wizard. For an existing Nimbus IVI driver project, browse to the .vcproj file for the desired driver.

  4. The added Nimbus IVI driver project will be loaded into Visual Studio with all of its associated projects -- setup, installer, unit test, etc. A separate Nimbus node with its subnodes will appear in Solution Explorer.


Accessing Driver Settings

Nimbus supplies a number of project-wide settings that are used to control important driver features. These are collectively referred to as the Driver Settings Editor. Note that unlike the per-user options which are applied across driver projects, the Driver Settings Editor pertain only to a specific driver project.

To access the IVI-COM driver settings

  1. From Solution Explorer, double-click the Driver Settings Editor node.

  2. A tabbed document window appears with various settings on each tab.

    The remaining topics in this section provide a detailed explanation of the properties available on each tab.

In This Section

General Page, IVI-COM Driver Settings

I/O Page, IVI-COM Driver Settings

Capability Groups Page, IVI-COM Driver Settings

Models Page, IVI-COM Driver Settings

LXI Page, IVI-COM Driver Settings

IVI-C Page, IVI-COM Driver Settings

MATLAB Page, IVI-COM Driver Settings

.NET Page, IVI-COM Driver Settings


General Page, IVI-COM Driver Settings

Instrument manufacturer

The instrument manufacturer is used to identify the manufacturer of the instrument for which the driver is being written. This entry is used in the IVI Configuration Store registration as well as in the implementation of the IIviDriverIdentity.InstrumentManufactuer property.

Driver vendor

The driver vendor identifies the company responsible for development and support of the driver. This entry is used in the IVI Configuration Store registration as well as in the implementation of the IIviDriverComponentIdentity.Vendor property.

Description

This entry is used in the IVI Configuration Store registration as well as in the implementation of the IIviDriverComponentIdentity.Description property.

Copyright

The copyright statement to use for your driver. This value is used in the .NET assembly metadata (AssemblyCopyright assembly-level attribute).

Version

The three entries here establish the four-part version number of the driver. The format of the version number is:

<major>.<minor>.<build>.<revision>

This version number is used in the following places:

  • The major and minor are used to for the IVI-COM type library version number. COM type libraries only support a two-digit version number.

  • All four digits are used to form the version number of the .NET interop assembly.

  • All four digits are used in the version number associated with the driver DLL.

  • All four digits are used in the version number associated with the driver installer.


I/O Page, IVI-COM Driver Settings

I/O type

The Nimbus I/O object can be used with either flavor of VISA (COM or conventional C). The selection made here determines which I/O provider will be used by the Nimbus I/O object. See the topic Using the I/O Object for details on making this selection.

VISA-C

Selecting this option instructs the I/O object to use VISA-C as its underlying I/O provider.

VISA-COM

Selecting this option instructs the I/O object to use VISA-COM as its underlying I/O provider.

None

Selecting this option informs Nimbus not to generate an I/O object. This option is chosen if you have an I/O library of your own, such as a custom I/O DLL you require to communicate with your instrument.

Instrument command formatting
Integer format

Specifies the default format code to use for integer values in instrument command strings. Explicit format codes used in the instrument command override this setting.

See the topics under Working With Instrument Commands for more information.

Floating-point format

Specifies the default format code to use for floating-point values in instrument command strings. Explicit format codes used in the instrument command override this setting.

See the topics under Working With Instrument Commands for more information.

String format

Specifies the default format code to use for string values in instrument response strings. Explicit format codes used in the instrument command override this setting. This setting is only used for reading values from the instrument -- not for formatting values sent to the instrument.

See the topics under Working With Instrument Commands for more information.

Boolean True

Specifies a comma-separated list of instrument responses that should be interpreted as a boolean true. For instrument commands, the first string in the list will be used to send a boolean true to the device.

Boolean False

Specifies a comma-separated list of instrument responses that should be interpreted as a boolean false. For instrument commands, the first string in the list will be used to send a boolean false to the device.

SCPI compliant

Indicates whether the instrument uses SCPI-compliant instrument commands. Nimbus provides specialized support for SCPI-compliant instruments. See the topic Special Features For SCPI Commands for detailed information.

See Also

Other Resources

Using the I/O Object
Working With Instrument Commands
Special Features For SCPI Commands


Instrument Classes Page, IVI-COM Driver Settings

The Instrument Classes Page of the Driver Settings Editors allows you to select which instrument classes will be supported by the driver. Nimbus performs a number of roundtripping operations based upon the selected instrument classes. Adding instrument classes by clicking the Add button in the list of Available instrument classes instructs Nimbus to add numerous items to the driver project.

Important note Important

By default, all of the class capability groups defined by a selected instrument class are marked as being supported by the driver. After adding an instrument class to the driver, it is important to visit the Capability Groups Page of the Driver Settings Editor to select the appropriate capability groups.

Available instrument classes

List of installed instrument classes that are available to be implemented by the driver. This list appearing here corresponds to the set of instrument class project files (.iviproj) installed in the NimbusInstallDir\IviInstrumentClasses folder.

Important note Important

Unlike IVI-COM drivers, IVI-C drivers can only support a single instrument class. This is a fundamental limitation of all IVI-C drivers and stems from the fact that IVI-C attributes are defined with numeric identifiers that are not unique across the various instrument classes. See the IVI Backgrounder section on Interchangeability for more information on this IVI-C limitation.

If more than one instrument class is implemented by the IVI-COM driver, then the one that you wish to support in the IVI-C driver must be selected via the IVI-C Page of the Driver Settings Editor.

Implemented instrument classes

Displays the list of instrument classes already implemented by the driver. The classes listed here do not appear in the list of Available instrument classes.

See Also

Other Resources

How IVI Drivers Provide Interchangeability


Capability Groups Page, IVI-COM Driver Settings

The Capability Groups page is used to specify which instrument class capability groups a driver supports. All extension groups for each instrument class supported by the driver are listed in the Capability Groups listbox. If the driver does not support any instrument classes, the listbox will be empty.

To specify that the driver supports a particular extension group, check the box next to the supported capability group. Nimbus uses the information specified here for the following purposes:

  • The list of supported groups is registered in the IVI Configuration Store.

  • The list of supported groups is used to implement the IIviDriver.GroupCapabilities property.

  • The list of supported groups is used in the generation of the IVI compliance information in the driver help file.

See Also

Other Resources

How IVI Drivers Provide Interchangeability


Models Page, IVI-COM Driver Settings

The Models Page is used to define the list of instrument models supported by the driver. Nimbus allows the driver's method and property behavior to vary based on model or family. The topic Adding Support for Multiple Instrument Models explains many of the multi-model Nimbus concepts.

To add a supported instrument model

  1. Right-click a model or family node.

  2. Choose Add Model.

  3. Enter the desired model name.

    Important note Important

    The name chosen here is NOT an arbitrary identifier. This name must exactly match the model string read from the device during initialization, such as the response to the "*IDN?" string. See the topic Adding Support for Multiple Instrument Models for an explanation of how Nimbus determines the connected instrument model.

Nimbus allows a driver to organize its supported list of models into related groups called families. Only a single level of hierarchy is supported -- in other words, you cannot have families of families. Unlike the instrument model names, the instrument family names are not used directly in any externally visible way. They are only used within Nimbus to group and organize models.

To add an instrument family

  1. Right-click an existing family.

  2. Choose Add Family.

  3. Enter the desired family name.

    Note Note

    The name chosen here is treated as an arbitrary identifier as does not need to match any actual identifier read from the instrument.

Nimbus supports the notion of a default model to handle the situation where the driver is operating in simulation mode and thus cannot determine what instrument model to use when executing driver-specific implementation code. The default model is used only for simulated driver sessions and only if no Model parameter is passed to Initialize.

See the topic Adding Support for Multiple Instrument Models for a discussion of the default instrument model.

To specify the default model for simulation

  1. Right-click an existing model.

  2. Choose Make default model.

  3. The selected model is shown in bold font.

See Also

Other Resources

Adding Support for Multiple Instrument Models


LXI Page, IVI-COM Driver Settings

This page allows you to change the level of LXI support offered by your driver. Refer to this page for a complete description of these options.

Note Note

Changing the level of LXI support is a fairly major operation. As a result, you may be prompted to confirm that you wish to proceed before the requested changes are applied to your driver project.

See Also

Other Resources

LXI Compliance Page, New IVI-COM Driver Wizard


IVI-C Page, IVI-COM Driver Settings

IVI-C wrapper support

The IVI-C Page is used to enable or disable the generation of an IVI-C wrapper for the IVI-COM driver.

Add/Remove button

Use this button to enable/disable generation of the IVI-C wrapper.

IVI-C prefix

If IVI-C wrapper generation is enabled, this setting controls the IVI-C prefix for the driver. This prefix is very important as it controls the name of many items associated with the driver. The driver DLL itself will be named using this prefix, overriding the DLL name that would result from using the IVI-COM project name. The names of all IVI-C functions and attributes begin with this prefix. Additionally, the driver install location is governed by the prefix chosen here.

Important note Important

The IVI specifications require that the first two letters of this prefix match the official two-letter abbreviation assigned to the driver vendor by the IVI Foundation in the specification "VPP-9: Instrument Vendor Abbreviations" . If the driver vendor does not have an assigned two-letter prefix, one can be obtained from the IVI Foundation. Visit the IVI Foundation website for details.

IVI-C instrument class

Unlike IVI-COM drivers, IVI-C drivers can only support a single instrument class. This is a fundamental limitation of all IVI-C drivers and stems from the fact that IVI-C attributes are defined with numeric identifiers that are not unique across the various instrument classes. See the IVI Backgrounder section on Interchangeability for more information on this IVI-C limitation.

This setting selects which of the supported IVI-COM driver instrument classes should be supported by the IVI-C driver.

Code generation
Automatically generate getter functions for IVI-C attributes

This setting controls whether getter functions are automatically generated when an IVI-C attribute is added to the driver.

Getter function prefix

This setting controls the name of automatically generated IVI-C attribute getter functions. For example, if an attribute named OUTPUT_VOLTAGE is created, and this setting is chosen to be Get, Nimbus will automatically generate an IVI-C getter function named GetOutputVoltage.

The name resulting from selections made here represent the initial name given to the getter function. Individual getter functions can be renamed as desired.

Automatically generate setter functions for IVI-C attributes

This setting controls whether setter functions are automatically generated when an IVI-C attribute is added to the driver.

Setter function prefix

This setting controls the name of automatically generated IVI-C attribute setter functions. For example, if an attribute named OUTPUT_VOLTAGE is created, and this setting is chosen to be Set, Nimbus will automatically generate an IVI-C setter function named SetOutputVoltage.

The name resulting from selections made here represent the initial name given to the setter function. Individual setter functions can be renamed as desired.

Synchronize Code

Use this button to bring up a dialog that allows you to update all getter and setter functions with the current selections made on this page.

See Also

Other Resources

Developing an IVI-C Driver
Managing IVI-C Driver Functionality
Linking IVI-COM and IVI-C Methods and Properties
Adding Attribute Getter and Setter Functions


MATLAB Page, IVI-COM Driver Settings

The MATLAB Page allows you to enable or disable the generation of a MATLAB® wrapper for the IVI-COM driver. All of the type names used in the MATLAB wrapper are based on the IVI-COM driver name, so no other settings are required.

Add/Remove button

Use this button to enable/disable generation of the MATLAB wrapper.

When MATLAB wrapper generation is enabled, Nimbus generates a specially formatted series of files with a .m extension. These .m files are integrated with the driver installer so that when the installer is on a machine with MATLAB available, the installer deploys the .m file in a location recognized by the MATLAB environment. This allows the driver to be used within MATLAB as if it were a native MATLAB class

Primary instrument class

If the underlying IVI-COM driver supports more than one instrument class, one instrument class must be chosen as the primary MATLAB instrument class. The generated MATLAB wrapper will derive from the corresponding MATLAB class. The other instrument classes supported by the driver will be accessible via reference properties.

See Also

Other Resources

Creating a MATLAB Wrapper


.NET Page, IVI-COM Driver Settings

Interop assembly code signing

Three different options are available for performing code-signing on the interop assembly used to access the IVI driver from .NET applications. It is important to understand the implications of each option before. For a detailed discussion of .NET code-signing, see the topic Supporting .NET Client Applications.

Use full signing with temporary Nimbus public-private key file

This option uses a "default", non-secure public-private key that ships with Nimbus. This option is useful when testing a driver and neither a fully public-private key pair nor a public key is available.

Caution note Caution

You should never ship a driver that has been built with this option selected. Always use a public-private key that represents the actual driver vendor.

Use delay signing with the following public key file

This is the preferred setting because it only requires the driver developer to have access to the public key file, rather than the full public-private key. Note that a driver compile with this option cannot be used from .NET without re-signing the interop assembly with the full public key. For a discussion of delay signing, see the topic Supporting .NET Client Applications.

Use full signing with the following public-private key file

This option enables a driver developer to sign the driver with the full public-private key so that it will be immediately usable from .NET without the need to perform a separate re-signing step.

Caution note Caution

Though convenient, this option is the least secure because it requires the driver developer to have direct access to the full public-private key pair. The public-private key that should be maintained in a secure location with limited access. The delay-signing option above is the recommended approach.

Interop assembly naming
Assembly name prefix

This entry controls the name of the .NET interop assembly as well as that of any .NET policy files shipped with the driver. The IVI specifications require that this prefix represent the driver vendor. The full name of the .NET assemblies based on this prefix is displayed in the Assembly name text box just below this entry.

For a detailed discussion of .NET interop assemblies, see the topic Supporting .NET Client Applications.

For more information on .NET policy files, see the topic Understanding .NET Versioning.

Assembly name

This is a read-only field that displays the .NET assembly name resulting from the choice entered in the Assembly name prefix field

See Also

Other Resources

Supporting .NET Client Applications


Adding Functionality to an IVI-COM Driver

One of the principal tasks in creating an IVI-COM driver is using the IVI-COM Designer and the IVI-C Designerto add functionality, such as methods, properties, and enumerations. IVI drivers also often support one or more IVI instrument classes. In addition, the driver might include repeated capabilities.

The topics in this section explain Nimbus is used to added various pieces of driver functionality.

In This Section

Managing IVI-C Driver Functionality

Properties vs. Methods

Understanding Parameter Direction

Defining New Data Types Inline

Adding a Method

Adding a Parameter

Adding a Property

Adding an Enumeration

Adding an Error

Adding a Warning

Adding a Child Interface

Adding a Repeated Capability

Merging Repeated Capabilities

Linking IVI-COM and IVI-C Methods and Properties

Adding Help Information

Adding State Caching to a Property

Adding Range Checking and Coercion to a Property

Adding Simulation to a Property

Adding Support for an Instrument Class

Adding Support for LXI

Adding a Type Library Reference


Managing IVI-C Driver Functionality

When IVI-C wrapper generation is enabled on the IVI-C Page of the Driver Settings Editor, Nimbus creates a complete IVI-C driver that is based on functionality in the underlying IVI-COM core driver. This topic introduces important concepts in understanding how the IVI-C driver functionality is defined and managed.

Important note Important

This topic only applies to IVI-COM driver projects that have enabled IVI-C wrapper generation on the IVI-C Page of the Driver Settings Editor.

The IVI-COM and IVI-C Designers

The Nimbus user interface offers two independent views of the functionality in a driver project -- one for the hierarchy of IVI-COM methods and properties and another for the hierarchy of IVI-C functions and attributes. Both designers are accessed by double-clicking the Driver Designer node under the Nimbus node in Solution Explorer. The Driver Designer that appears as a tabbed document window displays separate tabs for the IVI-COM Designer and the IVI-C Designer.

Tip Tip

The terminology used to describe IVI-C driver functionality is slightly different than that used to describe IVI-COM functionality. A method in IVI-COM is referred to as a function when speaking in the context of IVI-C. Similarly, a property in IVI-COM corresponds to an attribute in IVI-C. This terminology is used throughout the IVI specifications and is followed in this documentation as much as possible.

The IVI-COM Designer is referred to as the master view because it "pushes" changes made in it to the IVI-C hierarchy. For instance, when a method is added to the IVI-COM driver, a corresponding IVI-C function is also added to the driver project. Nimbus maintains the association between the IVI-COM method and the IVI-C function so that it can automatically generate the appropriate code to implement the IVI-C function in terms of the IVI-COM method.

When Nimbus automatically creates IVI-C items, such as IVI-C functions, attributes, and parameters, based on changes made in the IVI-COM Designer, various "transforms" may be required, such as translating IVI-COM data types like long and double to IVI-C data types like ViInt32 and ViReal64. The topic Linking IVI-COM and IVI-C Methods and Properties provides details on these automatic transforms.

Using the IVI-C Designer

It is critical to understand the difference in behavior when working from the IVI-COM Designer versus the IVI-C Designer. Since the IVI-COM Designer is the master view, changes made there typically affect both the IVI-COM and IVI-C hierarchies. By contrast, editing the IVI-C driver via the IVI-C Designer only affects the IVI-C hierarchy.

Important note Important

The IVI-C Designer does not push changes to the IVI-COM hierarchy.

As an example, using the IVI-C Designer renaming an IVI-C function from Configure to ConfigureTrigger will only rename the IVI-C function. The IVI-COM method will still be named Configure and the IVI-COM method and IVI-C function will still be linked with one another. Similarly, adding a function using the IVI-C Designer only adds the function to the IVI-C hierarchy -- a corresponding method is NOT added to the IVI-COM hierarchy. In fact, this is how IVI-C-only functions are created. IVI-C-only functions are discussed below.

Some changes made in the IVI-C Designer can be accommodated while maintaining the association between the IVI-COM item and the IVI-C item. The example of renaming a Configure function is one such situation. Another example is changing an IVI-C data type to a compatible type -- such as changing a parameter type from ViInt16 to ViInt32. Other changes, however, cannot be performed while the IVI-COM and IVI-C items are linked. For instance, if a function parameter data type is changed from ViReal64 to ViString, then there is no way to maintain the association between the IVI-C function and the IVI-COM method because Nimbus has no way to determine how the IVI-C function should be implemented in terms of the IVI-COM method. In such circumstances, Nimbus requires that the IVI-C function and IVI-COM method be unlinked from one another -- thereby creating an IVI-COM-only method and an IVI-C-only function that must be managed separately. The topic Linking IVI-COM and IVI-C Methods and Properties explains how IVI-C items can be unlinked and how IVI-C-only functions are implemented.

Navigating Between the IVI-COM and IVI-C Hierarchies

Nimbus offers two convenient ways to navigate between items in the IVI-COM hierarchy and their linked items in the IVI-C hierarchy:

  • From the tree view, right-click the desired item, such as an IVI-COM method, and choose Go to IVI-C .... The IVI-C Designer is immediately opened and linked item is selected. Correspondingly, a Go to IVI-COM... context menu command is available when working in the IVI-C Designer.

  • The Info Panel shows the linked IVI-COM or IVI-C item name as a hyperlink. Clicking it navigates to the linked item in the alternate view.

IVI-COM-only and IVI-C-only Methods and Properties

As discussed above, IVI-COM methods are initially created with an linked IVI-C function. Changes made to the IVI-COM method in the IVI-COM Designer, such as adding parameters, are "pushed" to the IVI-C function so that the two items stay in sync. Most of the time, this is the desired behavior. However, there are some instances where it is not possible or desirable to expose an IVI-COM method in the IVI-C driver. Such an IVI-COM method has no linked IVI-C function and is termed and IVI-COM-only method. Correspondingly, there are occaisions where an IVI-C function serves no useful purpose in the IVI-COM hierarchy. This requires IVI-C functions that have no IVI-COM counterpart -- these are termed IVI-C-only functions.

Nimbus fully supports the ability to create IVI-COM-only methods and IVI-C-only functions. In addition, other items, such as properties, function parameters, and enums can all be exposed in one of the hierarchies and not exposed in the others. The topic Linking IVI-COM and IVI-C Methods and Properties discusses how IVI-COM-only and IVI-C-only items are created and managed.

See Also

Other Resources

Developing an IVI-C Driver


Properties vs. Methods

One of the most fundamental design decisions driver developers face is whether to expose a particular driver capability as a method or as a property. The decision is not always clear cut. This topic will provide some prescriptive guidance on when one might choose to expose a property instead of a method, and vice versa.

Note Note

For purposes of this discussion, we will use the IVI-COM terminology -- method and property, as opposed to the IVI-C terminology function and attribute.

When to use a method

  • If the execution of the capability is going to take an extended or indeterminate amount of time, then exposing the capability as a method would be more consistent with the "principal of least surprise". Most users instinctively expect properties to execute fairly quickly and in constant time.

  • If an array of values needs to be read or written, then a method must be used. Array-type properties are not allowed, as per the IVI specifications.

  • An operation that performs a measurement, or operation, or significantly changes the state of the instrument should be exposed as a method.

  • If there are parameters associated with the capability, then it is usually best to use a method. Properties with parameters (known as parameterized properties) can be used, but the way in which these properties are accessed in various IDEs can be somewhat confusing for end users. For instance, C# always exposes parameterized properties as a pair of get_propName/set_propName accessor methods, even though the driver exposes a property. Even LabVIEW® interprets parameterized properties as methods -- forcing the developer to use an Invoke Node, which is for methods, instead of the Property Node that LabVIEW programmers expect to use when dealing with properties. In addition, it is very important to realize that parameterized properties are not supported at all in IVI-C drivers.

When to use a property

  • If the capability logically represents a setting within the instrument, such as the frequency or bandwidth, then it should be exposed as a property.

  • If the capability executes quickly and in fairly constant time, then it is a candidate for being exposed as a property.

  • If the data type is scalar (not an array), then it is a candidate for a property.

    Important note Important

    Arrays should never be exposed via properties. Array-type properties are explicitly prohibited by the IVI specification IVI-3.4: API Style Guide.

See Also

Other Resources

Adding a Method
Adding a Property


Understanding Parameter Direction

The IVI specifications prescribe specific rules for output parameters in IVI-COM drivers. These rules often leads to confusion -- both for the driver developer and for the end-user working with an IVI driver. This topic is dedicated to explaining output parameters in IVI-COM drivers.

IVI Requirements for Output Parameters

The IVI specifications require that all output parameters in IVI-COM drivers be specified as [in, out] when constructing the driver IDL file. An [in,out] parameter in IVI-COM is also referred to as a reference parameter (ref in C#) or a two-way parameter. The rule prohibiting [out]-only parameters holds even if the parameter is logically a pure output parameter -- such as with the Fetch function in IviScope, which returns an array of data from the device. The only exception to this rule is when the parameter is a method return value and marked as [out, retval] in the IDL. Thus there are no "pure" output parameters in IVI-COM drivers.

The reason this rule exists is historical -- to preserve compatibility with Visual Basic 6, which was the dominant Microsoft development tool at the time the original IVI-COM specifications were authored. Visual Basic 6 has a well-documented flaw whereby it leaks memory when using a COM component that has [out]-only parameters. The solution has always been to avoid [out]-only parameters in any component targeting Visual Basic 6, and to use [in, out] instead.

Using IVI Drivers with Output Parameters

The consequences of using [in, out] for all output parameters in IVI-COM drivers is quite visible. Consider the following IDL signature of the FetchWaveform method from the IviScope class-specification:

C++
Copy
HRESULT FetchWaveform([in, out] SAFEARRAY(double)* WaveformArray, [in, out] double* InitialX, [in, out] double* XIncrement);

As the name of the method implies, the parameters are all logically output parameters. However, as per the IVI specifications, each is specified as [in, out].

When using such a method from C#, each [in, out] parameter will appear as a ref parameter. Since C# requires that ref parameters be intialized prior to calling a method, this leads to a somewhat non-intuitive calling syntax where each parameter is "artificially" initialized to a dummy value simply to satisfy the C# compiler. The following code demonstrates how one would call the IviScope FetchWaveform method shown above.

C#
Copy
double[] WaveformArray = { 0 };
double InitialX = 0;
double XIncrement = 0;

driver.Measurements.Item("").FetchWaveform(ref WaveformArray, ref InitialX, ref XIncrement);
Note Note

It may be desirable to have parameters that logically are two-way parameters. For instance, a driver may wish to pass some existing data into the driver, have the driver operate on that data, and then return transformed data to the client in the same parameter. Or, a two-way parameter might be useful to allow arrays to be preallocated by the client and passed to the driver. This avoids having the driver reallocate an output array for each method call, as is the case for [out]-only parameters.

If an IVI specification denotes a parameters as [in, out] when the parameter is logically only an output parameter, the specification is supposed to indicate if the parameter "really" is a pure output parameter or if the driver must consider any data passed in via the parameter. At present, the IVI class specifications are not consistent here, but drivers should indicate this in their documentation.

How Nimbus Handles Output Parameters

The IVI-COM Parameter Editor offers three choices for parameter direction -- Input, Output, and Input/Output. As per the IVI specification requirements, Nimbus always generates [in, out] in the IDL method signature, even if Output is specified in the editor.

However, it is important to use the direction setting to tell Nimbus what the logical direction of the parameter is, even though the generated code is the same for Output and Input/Output. Doing so allows Nimbus to generate more efficient code. For instance, if a parameter is specified as Output, then Nimbus will not attempt to copy any data from the parameter, since the user will not have provided any. Had the parameter been specified as Input/Output, then Nimbus assumes there may be useful data in the parameter and will perform internal copy operations in some circumstances. For array parameters with a significant number of elements, this can impact driver performance.

Important note Important

When trying to decide between Output and Input/Output in the IVI-COM Parameter Editor always specify the logical direction of the parameter, even though Nimbus will generate the same IDL method signature for either choice. This allows Nimbus to generate the most efficient implementation code. Typically, choosing Output is the more appropriate option. True Input/Output parameters are rare in IVI-COM. In fact, at present there is only one IVI class specification with methods that have logical input/output parameters -- these are the various Fetch and Read methods in the IviDigitizer class specification.


Adding a Method

Before adding a method to a driver design, it is useful to consider if the capability might better be exposed from the driver as a property. The topic Properties vs. Methods provides a few guidelines on choosing between exposing driver capabilities as methods versus exposing them as properties.

To add an IVI-COM method to a driver

  1. From Solution Explorer, double-click the Driver Designer node under the Nimbus node.

  2. The Driver Designer opens as a tabbed document window. Select the IVI-COM tab.

  3. From the tree view expand the type library node for the instrument-specific hierarchy. This node is named "<driverName>Lib".

  4. Right-click on the desired location within the hierarchy and choose Add Method.

  5. A new method is added with a default name and the tree node enters edit mode. By default the method return type is Void, meaning that the method has no return type. However, the underlying COM return type is still a standard HRESULT. The return type specified is for client languages, such as Visual Basic and C#, that recognize COM return values.

  6. With the method node still in edit mode, type the desired name of the method followed by a colon (:) followed by the name of the return type, and hit the Enter key. The colon and return type can be excluded if the method has no return type (e.g. the Void return type is implied).

    Any of the following data types may be entered as a return type:

    • Void

    • Boolean

    • String

    • Byte

    • Int16

    • Int32

    • Int64

    • Single

    • Double

    • Any enum defined in the type library.

    • An array of any of the above -- designated by appending opening and closing square brackets ([]) to the type name.

      Example: Enter double[] for an array of double-precision floating-pointer numbers.

    Tip Tip

    When typing an enum as the return type, a shortened form of the enum name can be used. The project name prefix and the Enum suffix can be excluded. For example, if the desired return type is Acme4321TriggerSourceEnum, then type only TriggerSource and the full enum name will be expanded when the Enter key is pressed.

    When choosing a method name, the following naming rules apply:

    • The name must be unique within its parent interface. It need not be unique across the entire driver.

    • The name must contain only alphanumeric characters.

    • Spaces are not allowed.

    • The name must begin with a capital letter.

  7. After the method is added, the IVI-COM Method General Editor appears in the right portion of the IVI-COM Designer. See the help topic for that Item Editor for details on defining the method further.

  8. Once a method has been added, parameters can be added to the method. See the topic Adding a Parameter for details on adding parameters.

  9. If IVI-C wrapper generation is enabled on the IVI-C Page of the Driver Settings Editor, then an IVI-C function is automatically created at this time and linked to the IVI-COM method.

    To view the linked IVI-C function, right-click the IVI-COM method, and choose Go to IVI-C Function.

    To remove the linked IVI-C function, thereby creating an IVI-COM-only method, right-click the IVI-COM method, and choose Delete IVI-C Function.

    For a detailed discussion of the associations between IVI-COM methods and IVI-C functions, see the topics Managing IVI-C Driver Functionality and Linking IVI-COM and IVI-C Methods and Properties.

See Also

Other Resources

Adding a Property
Adding a Child Interface


Adding a Parameter

Parameters can be added to a method or a property. There are some special considerations when choosing between adding an Output parameter or an Input/Output parameter. You should review the topic Understanding Parameter Direction before choosing between these two options.

To add a parameter to a method or a property

  1. Right-click on the method or property in the IVI-COM Designer tree view and choose Add Parameter.

  2. A new parameter is added with a default name and the tree node enters edit mode. By default the parameter type is Double.

  3. With the parameter node still in edit mode, type the desired name of the parameter followed by a colon (:) followed by the name of the desired type, and hit the Enter key. The colon and type can be excluded if the desired type is Double.

    Any of the following data types may be entered as a parameter type:

    • Boolean

    • String

    • Byte

    • Int16

    • Int32

    • Int64

    • Single

    • Double

    • Any enum defined in the type library.

    • An array of any of the above -- designated by appending opening and closing square brackets ([]) to the type name.

      Example: Enter double[] for an array of double-precision floating-pointer numbers.

    Tip Tip

    When typing an enum as the parameter type, a shortened form of the enum name can be used. The project name prefix and the Enum suffix can be excluded. For example, if the desired parameter type is Acme4321TriggerSourceEnum, then type only TriggerSource and the full enum name will be expanded when the Enter key is pressed.

    When choosing a parameter name, the following naming rules apply:

    • The name must be unique within its parent method.

    • The name must contain only alphanumeric characters.

    • Spaces are not allowed.

    • The name must begin with a capital letter.

  4. After the parameter is added, the IVI-COM Parameter General Editor appears in the right portion of the IVI-COM Designer. See the help topic for that Item Editor for details on defining the method further.

  5. If IVI-C wrapper generation is enabled on the IVI-C Page of the Driver Settings Editor, then an IVI-C parameter is automatically created at this time and linked to the IVI-COM parameter. For array parameters, Nimbus automatically generates an extra IVI-C buffer size parameter to indicate the size of the array on input. If the array is an Output or Input/Output, Nimbus also generates an IVI-C actual size parameter to indicate the size of the array returned from the driver method.

    To view the linked IVI-C parameter, navigate to the parent method or property, right-click the IVI-COM method, and choose Go to IVI-C Function.

    For a detailed discussion of the associations between IVI-COM methods and IVI-C functions, see the topics Managing IVI-C Driver Functionality and Linking IVI-COM and IVI-C Methods and Properties.

See Also

Other Resources

Adding a Method
Adding a Property
Understanding Parameter Direction


Adding a Property

Before adding a property to a driver design, it is useful to consider if the capability might better be exposed from the driver as a method. The topic Properties vs. Methods provides a few guidelines on choosing between exposing driver capabilities as methods versus exposing them as properties.

To add an IVI-COM property to a driver

  1. From Solution Explorer, double-click the Driver Designer node under the Nimbus node.

  2. The Driver Designer opens as a tabbed document window. Select the IVI-COM tab.

  3. From the tree view expand the type library node for the instrument-specific hierarchy. This node is named "<driverName>Lib".

  4. Right-click on the desired location within the hierarchy and choose Add Property.

  5. A new property is added with a default name and the tree node enters edit mode. By default the property type is Double

  6. With the property node still in edit mode, type the desired name of the property followed by a colon (:) followed by the name of the return type, and hit the Enter key. The colon and type can be excluded if the desired property type is Double.

    Any of the following data types may be entered as a property type:

    • Boolean

    • String

    • Byte

    • Int16

    • Int32

    • Int64

    • Single

    • Double

    • Any enum defined in the type library.

    Tip Tip

    When typing an enum as the property type, a shortened form of the enum name can be used. The project name prefix and the Enum suffix can be excluded. For example, if the desired property type is Acme4321TriggerSourceEnum, then type only TriggerSource and the full enum name will be expanded when the Enter key is pressed.

    Note Note

    As per the IVI specifications, array properties are not allowed. All properties must read or write a single, scalar value.

    When choosing a property name, the following naming rules apply:

    • The name must be unique within its parent interface. It need not be unique across the entire driver.

    • The name must contain only alphanumeric characters.

    • Spaces are not allowed.

    • The name must begin with a capital letter.

    If a property type is not entered, Nimbus will automatically try to infer the property type from the name. The table below shows what property types are inferred from property names. If the property name does not match a condition in the table, then it will use the default Double property type.

    Property Name

    Data Type

    Ends with Enable or Enabled.

    Boolean

    Ends with Count, Length or Number.

    Int32

    Starts with Num.

    Int32

    Ends with Name or Text.

    String

  7. After the property is added, the IVI-COM Property General Editor appears in the right portion of the IVI-COM Designer. See the help topic for that Item Editor for details on defining the property further.

  8. Once a property has been added, parameters can be added to the property. See the topic Adding a Parameter for details on adding parameters.

  9. If IVI-C wrapper generation is enabled on the IVI-C Page of the Driver Settings Editor, then an IVI-C attribute is automatically created at this time and linked to the IVI-COM property.

    To view the linked IVI-C attribute, right-click the IVI-COM property, and choose Go to IVI-C Attribute.

    To remove the linked IVI-C attribute, thereby creating an IVI-COM-only property, right-click the IVI-COM property, and choose Delete IVI-C Attribute.

    For a detailed discussion of the associations between IVI-COM properties and IVI-C attributes, see the topics Managing IVI-C Driver Functionality and Linking IVI-COM and IVI-C Methods and Properties.

See Also

Other Resources

Adding a Method
Adding a Child Interface


Adding an Enumeration

To add an IVI-COM enum to a driver

  1. From Solution Explorer, double-click the Driver Designer node under the Nimbus node.

  2. The Driver Designer opens as a tabbed document window. Select the IVI-COM tab.

  3. From the tree view expand the type library node for the instrument-specific hierarchy. This node is named "<driverName>Lib".

  4. Right-click on the Enums node and choose Add Enum.

  5. A new enum is added with a default name and the tree node enters edit mode.

  6. With the enum node still in edit mode, type the desired name of the enum and hit the Enter key.

    Note Note

    By convention, enum names start with the project name and end with Enum. However, when typing an enum name in the tree view, a shortened form of the name can be used. The project name prefix and the Enum suffix can be excluded. For example, if the desired enum is Acme4321TriggerSourceEnum, then type only TriggerSource and the full enum name will be expanded when the Enter key is pressed.

    When choosing an enum name, the following naming rules apply:

    • The name must be unique within the driver.

    • The name must contain only alphanumeric characters.

    • Spaces are not allowed.

  7. After the enum is added, the IVI-COM Enum General Editor appears in the right portion of the IVI-COM Designer. See the help topic for that Item Editor for details on defining the enum further.

  8. If IVI-C wrapper generation is enabled on the IVI-C Page of the Driver Settings Editor, then an IVI-C enum is automatically created at this time and associated with the IVI-COM enum.

    To view the linked IVI-C enum, right-click the IVI-COM enum, and choose Go to IVI-C Enum.

    To remove the linked IVI-C enum, thereby creating an IVI-COM-only enum, right-click the IVI-COM enum, and choose Delete IVI-C Enum.

Tip Tip

Use the Info Panel in the lower portion of the IVI-COM Designer to view and navigate to methods and properties that use the enum.

To add an enum member to an enum

  1. Locate the enum to be modified under the Enums node in the Driver Designer

  2. Right click on the enum name and select Add Enum Member.

  3. A new enum member is added with a default name and the tree node enters edit mode.

  4. With the enum member node still in edit mode, type the desired name of the enum member and hit the Enter key.

    When choosing an enum member name, the following naming rules apply:

    • The member name must be unique within the enum being modified.

    • The name must contain only alphanumeric characters, and must start with an alphabetic character.

    • Spaces are not allowed.

    Tip Tip

    The enum member value can be entered in either hexadecimal or decimal format. It will be converted to the format configured for that enum. Right-click on the parent enum to see a context menu which enables or disables hexadecimal display mode.

  5. After the enum member is added, the Enum Member Editor appears in the right portion of the Driver Designer.

Shorthand notation for defining enums

Nimbus supports a convenient shorthand notation for defining enums. The enum and its members can be defined all at once when the enum is initially added.

After executing the Add Enum command, and while still in edit mode, the following text can be used to define a TriggerSource enum with members Internal, External, and Software.

TriggerSource; Internal, External, Software

In the above, the enum name TriggerSource is specified first, followed by a semicolon to delineate it from the enum member specifications. Enum members follow and are separated by commas.

This shorthand notation can also be used to define the enum member values, as in the following:

TriggerSource; Internal = 2, External = 0x15, Software = 47

Note that when assigning enum member values, either hex format or decimal format may be used.

Once an enum is defined, additional enum members can be added using this same shorthand notation, except that the enum name is excluded. After executing the Add Enum Member command, and while still in edit mode, the following text can be used to add a series of TTL trigger source lines to the existing TriggerSource enum from the above example:

TTL0, TTL1 = 5, TTL2 = 6, TTL3, TTL4, TTL5 = 0x14, TTL6, TTL7


Adding an Error

Defining custom errors in an IVI driver allows you to return errors with a proper COM HRESULT and a properly formatted error message that can be displayed by various COM-aware IDEs. Internally, the errors and warnings defined for a particular driver are managed as members of a special enum created in the type library. Typically, the enum that houses all of the driver's error and warning code definitions has a name that ends with ErrorCodesEnum.

To add an IVI-COM error to a driver

  1. From Solution Explorer, double-click the Driver Designer node under the Nimbus node.

  2. The Driver Designer opens as a tabbed document window. Select the IVI-COM tab.

  3. From the tree view expand the type library node for the instrument-specific hierarchy. This node is named "<driverName>Lib".

  4. Right-click on the Errors node and choose Add Error.

  5. A new error is added with a default name and the tree node enters edit mode.

  6. With the error node still in edit mode, type the desired name of the error and hit the Enter key.

    Note Note

    By convention, error names start with "E_<projectName>_". However, when typing an error name in the tree view, a shortened form of the name can be used. The "E_<projectName>_" prefix prefix can be excluded. For example, if the desired error is E_ACME4321_BAD_SWEEP, then type only BAD_SWEEP and the full error name will be expanded when the Enter key is pressed.

    When choosing an error name, the following naming rules apply:

    • The name must be unique within the driver.

    • The name must contain only alphanumeric characters and the underscore (_) character.

    • Spaces are not allowed.

    • The name must be uppercase.

  7. After the error is added, the IVI-COM Error General Editor appears in the right portion of the IVI-COM Designer. See the help topic for that Item Editor for details on defining the error further.

  8. If IVI-C wrapper generation is enabled on the IVI-C Page of the Driver Settings Editor, then an IVI-C error is automatically created at this time and associated with the IVI-COM error.

    To view the linked IVI-C error, right-click the IVI-COM error, and choose Go to IVI-C Error.

    To remove the linked IVI-C error, thereby creating an IVI-COM-only error, right-click the IVI-COM error, and choose Delete IVI-C Error.

See Also

Other Resources

Adding a Warning
Returning Errors from IVI-COM Drivers


Adding a Warning

Defining custom warnings in an IVI driver allows you to return warnings with a proper COM HRESULT and a properly formatted warning message that can be displayed by various COM-aware IDEs. Internally, the errors and warnings defined for a particular driver are managed as members of a special enum created in the type library. Typically, the enum that houses all of the driver's error and warning code definitions has a name that ends with ErrorCodesEnum.

To add an IVI-COM warning to a driver

  1. From Solution Explorer, double-click the Driver Designer node under the Nimbus node.

  2. The Driver Designer opens as a tabbed document window. Select the IVI-COM tab.

  3. From the tree view expand the type library node for the instrument-specific hierarchy. This node is named "<driverName>Lib".

  4. Right-click on the Warnings node and choose Add Warning.

  5. A new warning is added with a default name and the tree node enters edit mode.

  6. With the warning node still in edit mode, type the desired name of the error and hit the Enter key.

    Note Note

    By convention, warning names start with "S_<projectName>_". However, when typing an error name in the tree view, a shortened form of the name can be used. The "S_<projectName>_" prefix prefix can be excluded. For example, if the desired warning is S_ACME4321_SWEEP_BUSY, then type only SWEEP_BUSY and the full warning name will be expanded when the Enter key is pressed.

    When choosing a warning name, the following naming rules apply:

    • The name must be unique within the driver.

    • The name must contain only alphanumeric characters and the underscore (_) character.

    • Spaces are not allowed.

    • The name must be uppercase.

  7. After the warning is added, the IVI-COM Warning General Editor appears in the right portion of the IVI-COM Designer. See the help topic for that Item Editor for details on defining the warning further.

  8. If IVI-C wrapper generation is enabled on the IVI-C Page of the Driver Settings Editor, then an IVI-C warning is automatically created at this time and associated with the IVI-COM warning.

    To view the linked IVI-C warning, right-click the IVI-COM warning, and choose Go to IVI-C Warning.

    To remove the linked IVI-C warning, thereby creating an IVI-COM-only warning, right-click the IVI-COM warning, and choose Delete IVI-C Warning.

See Also

Other Resources

Adding an Error
Returning Errors from IVI-COM Drivers


Adding a Child Interface

To add a child interface to a driver

  1. From Solution Explorer, double-click the Driver Designer node under the Nimbus node.

  2. The Driver Designer opens as a tabbed document window. Select the IVI-COM tab.

  3. From the tree view expand the type library node for the instrument-specific hierarchy. This node is named "<driverName>Lib".

  4. Right-click on the desired location within the hierarchy and choose Add Child Interface.

  5. A new reference property is added with a default name and the tree node enters edit mode. Type the desired name for the reference property and hit the Enter key.

    An interface will be added to the driver with a name based on the chosen property name, as follows:

    I<driverName><propName>

    Note Note

    If the child interface is added at a level beneath a collection-style repeated capability Item property, then it is inherently part of the repeated capability. The interface will be a base interface of the repeated capability class and implemented on that class. Otherwise, the child interface is added as a base of the main driver class and implemented on that class.

  6. If IVI-C wrapper generation is enabled on the IVI-C Page of the Driver Settings Editor, then an IVI-C branch is automatically added to the IVI-C hierarchy as this point.

See Also

Other Resources

Adding a Method
Adding a Property


Adding a Repeated Capability

Repeated capabilities allow the driver to expose duplicate functionality in an instrument using IVI-defined functions and conventions. For instance, a single set of methods and properties can be defined for operating on a series of channels in an oscillscope. IVI terms this duplicate functionality a repeated capability.

For a complete discussion of repeated capabilities, see the IVI Backgrounder topic entitled Repeated Capabilities.

To add a repeated capability to a driver

  1. From Solution Explorer, double-click the Driver Designer node under the Nimbus node.

  2. The Driver Designer opens as a tabbed document window. Select the IVI-COM tab.

  3. From the tree view expand the type library node for the instrument-specific hierarchy. This node is named "<driverName>Lib".

  4. Right-click on the desired location within the hierarchy for the repeated capability methods and properties and choose Add Child Repeated Capability....

  5. The Add Child Repeated Capability Wizard appears.

The remaining topics in this section discuss each wizard page separately.

Tip Tip

After adding a repeated capability using the Wizard, you can bring up the Repeated Capabilities Editor by double-clicking the Driver Settings Editor in Solution Explorer and choosing the Repeated Capabilities tab. The Repeated Capabilities Editor allows you to view and edit characteristics of all driver repeated capabilities, such as the physical names defined for each repeated capability.

In This Section

Add Repeated Capability Dialog

See Also

Other Resources

Repeated Capabilities


Add Repeated Capability Dialog

For an introduction to IVI repeated capability topics, see the IVI Backgrounder topic entitled Repeated Capabilities.

Name

Specifies the repeated capability name. This name serves as a unique identifier for the repeated capability. The name chosen here is used registered by the driver installer in the IVI Configuration Store. In addition, the name chosen here is used as a base name for the following items:

  • I<driverName><repCapName> interface - the repeated capability interface on which the repeated capability methods and properties will be defined.

  • I<driverName><repCapName>s interface - (collection-style only) - collection interface on which the Count, Item, and Name properties will be defined.

  • repCapName>s property- (collection-style only) - reference property pointing to the repeated capability collection interface.

  • <driverName>repCapName> class - (collection-style only) - C++ class added to the driver source code for implementing the repeated capability methods and properties.

  • repCapName> property - (selector and parameter-style only) - reference property pointing to the repeated capability interface.

For example, if the name Channel is chosen for a collection-style repeated capability on a driver named Acme4321, then the following items would be created:

  • An IAcme4321Channel interface.

  • An IAcme4321Channels interface.

  • A property Channels that points to the IAcme4321Channels interface.

  • An IAcme4321Channels.Item property that returns an IAcme4321Channel interface.

  • An Acme4321Channel implementation class.

Style

The type of repeated capability to be added to the driver.

A discussion of the three types of IVI repeated capabilities can be found in the topic Repeated Capabilities.

Important note Important

IVI-C drivers do not support collection-style repeated capabilities. If the selected style is IVI-COM Collection, then the repeated capability will be treated as a parameter-style repeated capability when working with the IVI-C wrapper. This behavior is as per the IVI specifications.

See Also

Other Resources

Repeated Capabilities


Merging Repeated Capabilities

When two repeated capabilities exist in an IVI-COM driver, it may be the case that the two repeated capabilities represent the same physical entity on the device. In such cases, the repeated capabilities may be merged into a single repeated capability.

Consider the case of an IVI-COM driver that supports the IviScope instrument class. The driver will contain a repeated capability called "Channel", since this repeated capability is defined in the IviScope instrument class. If the driver developer adds support for the IviDigitizer instrument class, then Nimbus will create an additional repeated capability called "IviDigitizerChannel", since the IviDigitizer instrument also defines a repeated capability called "Channel". (Nimbus adds the "IviDigitizer" prefix to the repeated capability name to distinguish it from the one defined in the IviScope instrument class.) The result is a driver with two separate repeated capabilities -- one called "Channel", representing the repeated capability defined in IviScope, and another called "IviDigitizerChannel" representing the repeated capability defined in IviDigitizer. In most cases, these represent the same physical channel on the instrument. The Merge command should then be used to combine these two repeated capabilities into one.

When two repeated capabilities are merged, Nimbus does the following:

  1. Moves any methods or properties on the source repeated capability to the target repeated capability. Note that this is only done automatically for collection-style repeated capabilities. Methods and properties on parameter or selector-style repeated capabilities must be manually moved to the target repeated capability before executing the Merge command.

  2. Changes the associated repeated capability of all methods and properties on the source repeated capability to be associated with the target repeated capability.

  3. Deletes the source repeated capability along with any physical names defined on the repeated capability.

Note Note

Only repeated capabilities of the same style can be merged. For instance, you cannot merge a collection-style repeated capability with a parameter-style repeated capability

To merge two repeated capabilities:

  1. From Solution Explorer, double-click on the Driver Settings Editor node to bring up the Driver Settings Editor.

  2. Select the Repeated Capabilities page and right-click on the source repeated capability that you wish to merge. This is the repeated capability that will be deleted.

  3. Select Merge and then choose the target repeated capability.

    Caution note Caution

    This operation will result in the source repeated capability being deleted from the driver, so you will be prompted to confirm that you wish to proceed.


Linking IVI-COM and IVI-C Methods and Properties

When IVI-COM items, such as methods, properties, parameters, and enums, are added to the driver hierarchy using the IVI-COM Designer, corresponding items are automatically added to the IVI-C hierarchy. For instance, adding an IVI-COM method automatically adds a corresponding IVI-C function. Since IVI-COM and IVI-C represent data types, repeated capabilities, and other driver characteristics differently, Nimbus must perform various transformations when mapping between IVI-COM and IVI-C. In situations where an IVI-COM item cannot or should not be represented in IVI-C, or vice versa, Nimbus provides a means to implement IVI-COM-only and IVI-C-only items. This topic explains important aspects of managing the relationship between the IVI-COM driver and its associated IVI-C wrapper.

Important note Important

This topic only applies to IVI-COM driver projects that have enabled IVI-C wrapper generation on the IVI-C Page of the Driver Settings Editor.

The IVI-C ViSession Parameter

Every IVI-C function accepts a ViSession as its first parameter. The ViSession parameter identifies the instrument I/O session. Nimbus automatically adds a ViSession parameter to every IVI-C function it associates with an IVI-COM method. Inside the implementation of the IVI-C function, the Nimbus-generated code uses the ViSession parameter to locate the correct IVI-COM driver instance to call. The ViSession parameter cannot be deleted from an IVI-C driver function.

IVI-COM and IVI-C Return Types

At the raw IDL level, all IVI-COM methods return an HRESULT. The HRESULT return value is used to indicate various failure and success conditions. However, the Nimbus IVI-COM Method Editor allows a return type to be specified for each IVI-COM driver method. This is because many environments, such as C# and VB.NET, transform an IVI-COM HRESULT into an exception or other error mechanism. This allows an [out] parameter to be designated as the method's return value and simplifies the use of the IVI-COM method.

By contrast, IVI-C functions always return a ViStatus result. This means that if an IVI-COM method specifies anything other than Void as its return type, an [out] parameter of the specified type must be added to the corresponding IVI-C function function signature. Nimbus adds such an [out] parameter automatically when needed.

Mapping IVI-COM and IVI-C Data Types

When an IVI-COM method is associated with an IVI-C function, the method return type as well as the data type of each parameter must be mapped to an appropriate IVI-C data type. Similarly, an IVI-COM property type must be mapped to its corresponding IVI-C attribute type. Nimbus performs these transformations automatically when an IVI-COM method or property is created and when parameters are added. Most of these mappings are straightforward and are given in the table below:

IVI-COM Data Type | IVI-C Data Type
Boolean | ViBoolean
String | ViConstString (for [in] parameters) ViString, plus a BufferSize parameter (for [out] and [in,out] parameters) (See discussion below.)
Byte | ViChar
Int16 | ViInt16
Int32 | ViInt32
Int64 | ViInt64
Single | ViReal32
Double | ViReal64

Mapping Array Parameters

IVI-COM drivers use the SAFEARRAY data type for array parameters. One convenient feature of SAFEARRAYs is that they are self-describing -- the number and type of elements present in the array is maintained within the SAFEARRAY itself. IVI-C drivers, however, use C-style arrays. Since C-style arrays are simply pointers, extra parameters must be used with an IVI-C array to indicate the number of elements present. The IVI specifications prescribe specific naming and ordering conventions for these extra "array size" parameters. Nimbus automatically manages these extra IVI-C parameters as follows:

When a SAFERRAY parameter is added to an IVI-COM method or property

  1. An [in] parameter of type ViInt32 is added to the IVI-C function and placed just before the IVI-C array parameter. The parameter name is based upon the array parameter name, as follows:

    <arrayParamName>BufferSize

    This buffer size parameter is used to indicate how many elements (not bytes) have been allocated in the array by the caller. This helps ensure the function implementation does not try to access more elements than are available.

  2. A C-style array is added to the IVI-C function to represent the SAFEARRAY data itself.

  3. If the SAFEARRAY parameter is an [in,out] parameter, then an [out] parameter of type ViInt32 is added to the IVI-C function and placed just after the IVI-C array parameter. The parameter name is based upon the array parameter name, as follows:

    <arrayParamName>ActualSize

    This actual size parameter is used to indicate how many elements (not bytes) were filled in by the function implementation. This indicates to the caller how much of the allocated space, as indicated by the buffer size parameter, was actually used.

Mapping String Parameters

IVI-COM drivers use the BSTR data type for string parameters. Similar to the COM SAFEARRAY data type, the BSTR data type has the convenient feature of managing the string length internally. All BSTRs are length-prefixed, so extra parameters are never needed to indicate the number of characters present. IVI-C drivers, on the other hand, use character arrays (arrays of ViChar typedef'd to the ViString data type). When used as input parameters IVI-C strings do not need additional length parameters because the string is NULL-terminated and the length is easily determined by the function implementation. However, when strings are used as [out] parameters in IVI-C drivers, an additional buffer size parameter must be used to indicate to the function implementation how many characters have been allocated by the caller. The IVI specifications prescribe specific naming and ordering conventions for this extra "buffer size" parameter. Nimbus automatically manages this extra IVI-C parameter as follows:

When a string [out] parameter is added to an IVI-COM method or property

  1. An [in] parameter of type ViInt32 is added to the IVI-C function and placed just before the IVI-C ViString parameter. The parameter name is based upon the ViString parameter name, as follows:

    <stringParamName>BufferSize

    This buffer size parameter is used to indicate how many characters have been allocated in the string by the caller. This helps ensure the function implementation does not try to access more characters than are available.

  2. A ViString parameter is added to the IVI-C function to represent the BSTR data itself.

Mapping IVI-COM and IVI-C Repeated Capabilities

IVI-COM and IVI-C have a few important differences in the way they represent repeated capabilities. The first difference of note is that IVI-C drivers do not support collection-style repeated capabilities. IVI-COM and IVI-C drivers also use a different set of IVI-defined standard methods and properties to manage the repeated capability instances.

The table below presents the required repeated capability methods and properties for IVI-COM and IVI-C drivers based upon the type of repeated capability. For a discussion of the different types of repeated capabilities see the IVI Backgrounder topic on Repeated Capabilities.

Repeated Capability Style

IVI-COM

IVI-C

Collection-Style

  • Count property

  • Item property

  • Name property

  • Not supported.

Parameter-Style

  • <Capability>Count property (Ex: ChannelCount)

  • <Capability>Name property (Ex: ChannelName)

  • <CAPABILITY>_COUNT attribute (Ex: CHANNEL_COUNT)

  • Get<Capability>Name function (Ex: GetChannelName)

Selector-Style

  • <Capability>Count property (Ex: ChannelCount)

  • <Capability>Name property (Ex: ChannelName)

  • Active<Capability> property (Ex: ActiveChannel)

  • SetActive<Capability> method (Ex: SetActiveChannel)

  • <CAPABILITY>_COUNT attribute (Ex: CHANNEL_COUNT)

  • Get<Capability>Name function (Ex: GetChannelName)

  • ACTIVE_<CAPABILITY> attribute (Ex: ACTIVE_CHANNEL)

  • SetActive<Capability> function (Ex: SetActiveChannel)

As the table shows, different methods and properties must be maintained in the IVI-COM and IVI-C hierarchies based upon the type of repeated capability. Nimbus automatically handles each case by creating the appropriate IVI-C functions and attributes and associating them with their IVI-COM counterparts.

Collection-Style Repeated Capabilities and IVI-C

The case of collection-style repeated capabilities requires special handling since this type of repeated capability is not supported by IVI-C drivers. Whenever a collection-style repeated capability is added to a driver, Nimbus treats the repeated capability as a parameter-style repeated capability in the IVI-C hierarchy. This means Nimbus automatically creates the <CAPABILITY>_COUNT attribute and the Get<Capability>Name function and associates them with the IVI-COM Count and Name properties.

Important note Important

Collection-style repeated capabilities in an IVI-COM driver are always treated as parameter-style repeated capabilities in the IVI-C hierarchy.

Creating IVI-C Getter and Setter Functions

Reading and writing IVI-C attributes involves use of special attribute accessor functions that accept a #define'd constant representing the attribute ID and a value parameter. Because this programming model can be a bit cumbersome to work with in practice, the IVI specifications recommend that commonly used IVI-C attributes also expose a corresponding "getter" and "setter" function. By convention, setter functions often have names that begin with "Configure" and getter functions have names that begin with "Query" (although there is no hard requirement to follow these naming conventions).

Using an IVI-C setter or getter function in place of the attribute itself can simplify programming with the IVI-C driver, as shown in the simple example below:

C++
Copy
ViSession vi;
/* session initialization omitted for clarity */

/* Use the attribute and attribute accessor to set the sample rate to 1000 */
ViStatus status = IviScope_SetAttributeViReal64(vi, VI_NULL, IVISCOPE_ATTR_HORZ_SAMPLE_RATE, 1000);

/* Use the setter function to set the sample rate to 1000 */
status = IviScope_ConfigureSampleRate(vi, 1000);

Nimbus provides built-in support for the creation of IVI-C getter and setter functions and it maintains an association between these functions and the attribute so that they can be automatically implemented by Nimbus.

To create an IVI-C getter or setter function

  1. From Solution Explorer, double-click the IVI-COM node to bring up the IVI-COM Designer.

  2. Select a property from the IVI-COM hierarchy.

  3. Right-click on the property and choose Create IVI-C Getter Function or Create IVI-C Setter Function.

    Note Note

    The Create IVI-C Getter Function command will not be available if the property is write-only. Similarly, the Create IVI-C Setter Function command will not appear if the property is read-only. Also, if the getter or setter function already exists, then the corresponding context menu command will not be available.

Parameterized Properties and IVI-C Getters and Setters

A property that accepts parameters is known as a parameterized property. While IVI-COM drivers naturally support parameterized properties, there is no notion of a corresponding "parameterized attribute" in IVI-C. Thus, whenever a parameter is first added to an IVI-COM property, Nimbus automatically performs the following steps:

  1. If the IVI-COM property has an associated IVI-C attribute, the IVI-C attribute is deleted from the IVI-C hierarchy.

  2. If the IVI-COM property is read-write or read-only, an IVI-C getter function will be created and associated with the property. The getter function will be named as follows:

    Get<propertyName>

  3. If the IVI-COM property is read-write or write-only, an IVI-C setter function will be created and associated with the property. The setter function will be named as follows:

    Set<propertyName>

Creating IVI-COM-only and IVI-C Methods and Properties

There are some instances where it is not possible or desirable to expose an IVI-COM method in the IVI-C driver. Such an IVI-COM method has no associated IVI-C function and is termed an IVI-COM-only method. Correspondingly, there are occaisions where an IVI-C function serves no useful purpose in the IVI-COM hierarchy. This requires IVI-C functions that have no IVI-COM counterpart -- these are termed IVI-C-only functions.

IVI-COM-only methods and properties are established by deleting the associated IVI-C function or attribute.

To create an IVI-COM-only method or property

  1. From the IVI-COM Designer, select the desired method or property.

  2. For a method, right-click and choose Delete IVI-C Function.

    For a property, right-click and choose Delete IVI-C Attribute. If the property also has a getter and/or setter associated with it, then you can select Delete IVI-C Getter Function and/or Delete IVI-C Setter Function to remove those as well.

  3. The Info Panel should display None for the associated IVI-C items.

IVI-C-only functions and attributes are created by simply adding an IVI-C function or attribute directly using the IVI-C Designer. Recall that the IVI-C Designer does not push changes to the IVI-COM hierarchy, so anything created directly from the IVI-C Designer is inherently IVI-C-only.

Important note Important

Whenever an IVI-C-only function or attribute is created, it must be manually implemented in the <prefix>.cpp file within the driver project. See the topic Implementing IVI-C-Only Functions and Attributes for more information.

To create an IVI-C-only function or attribute

  1. From the IVI-C Designer, select the desired location within the IVI-C tree view.

  2. Right-click and choose Add Function or Add Attribute.

  3. The Info Panel shows that no IVI-COM method or property is associated with the item.

See Also

Other Resources

Managing IVI-C Driver Functionality


Adding Help Information

Most of the items in an IVI-COM driver (methods, properties, parameters, etc.) have help information associated with them. The help content is used to generate HTML help files as well as other help-based artifacts, such as the XML IntelliSense file and the type library help information. The topics under Creating a Driver Help File provide detailed information on how driver help content is used.

Irrespective of where Nimbus uses the help information for an item, the content for each item is managed from a single location -- the Help Editor.

To add help information to an item

  1. From Solution Explorer, double-click the Driver Designer node under the Nimbus node.

  2. The Driver Designer opens as a tabbed document window. Select the IVI-COM tab.

  3. From the tree view expand the type library node for the instrument-specific hierarchy. This node is named "<driverName>Lib".

  4. Select the desired item (method, property, parameter, etc.) from the tree view.

  5. On the right-side of the IVI-COM Designer, click the Help button along the lower section of the designer.

  6. The Help Editor appears. Select the Source view to enter HTML help content for each field defined by the help template. See the Help Editor topic for details.

See Also

Other Resources

Using the Help Editor


Adding State Caching to a Property

To add state caching to a property

  1. From Solution Explorer, double-click the Driver Designer node under the Nimbus node.

  2. The Driver Designer opens as a tabbed document window. Select the IVI-COM tab.

  3. From the tree view expand the type library node for the instrument-specific hierarchy. This node is named "<driverName>Lib".

  4. Select the desired property from the tree view.

  5. On the right-side of the IVI-COM Designer, click the State Caching button along the lower section of the designer.

  6. The State Caching Editor appears. See the State Caching Editor topic for details.

See Also

Other Resources

What All IVI Drivers Do -- Inherent Capabilities
State Caching Overview


Adding Range Checking and Coercion to a Property

To add range checking to a property

  1. From Solution Explorer, double-click the Driver Designer node under the Nimbus node.

  2. The Driver Designer opens as a tabbed document window. Select the IVI-COM tab.

  3. From the tree view expand the type library node for the instrument-specific hierarchy. This node is named "<driverName>Lib".

  4. Select the desired property from the tree view.

  5. On the right-side of the IVI-COM Designer, click the Range Checking button along the lower section of the designer.

  6. The Range Checking Editor appears. See the Range Checking Editor topic for details.

See Also

Other Resources

What All IVI Drivers Do -- Inherent Capabilities


Adding Simulation to a Property

To add simulation to a property

  1. From Solution Explorer, double-click the Driver Designer node under the Nimbus node.

  2. The Driver Designer opens as a tabbed document window. Select the IVI-COM tab.

  3. From the tree view expand the type library node for the instrument-specific hierarchy. This node is named "<driverName>Lib".

  4. Select the desired property from the tree view.

  5. On the right-side of the IVI-COM Designer, click the Simulation button along the lower section of the designer.

  6. The Simulation Editor appears. See the Simulation Editor topic for details.

See Also

Other Resources

What All IVI Drivers Do -- Inherent Capabilities
Implementing Simulation


Adding Support for an Instrument Class

To add support for an instrument class

  1. From Solution Explorer, double-click the Driver Settings Editor node under the Nimbus node.

  2. The Driver Settings Editor appears.

  3. Select the Instrument Classes tab.

  4. From the list of Available instrument classes, select the instrument class you wish to add to the driver, and select Add.

    Caution note Caution

    Adding support for an instrument class is a major operation and injects a large amount of code into the driver project and unit test project. Do not perform this operation until you are certain you wish to include support for the instrument class.

  5. When the operation completes, the newly added instrument classes will appear in the IVI.NET Driver Designer tree view. In addition, Nimbus performs a variety of tasks to add support for the selected instrument classes:

    • A reference to the instrument type library is added to the driver project.

    • Any repeated capabilities defined by the instrument class are added to the driver and any supporting interfaces, methods, properties, and classes are added to the driver hierarchy.

    • Implementation code for the methods and properties defined on the instrument class are added to the driver project.

    • Unit test code for exercising the instrument class methods and properties is added to the unit test project.

    • The driver installer is updated to register the driver with the IVI Configuration Store as supporting the selected instrument classes.

Important note Important

By default, all of the class capability groups defined by a selected instrument class are marked as being supported by the driver. After adding an instrument class to the driver, it is important to visit the Capability Groups Page of the Driver Settings Editor to select the appropriate capability groups.

Tip Tip

If the new instrument class contains a repeated capability that represents the same physical repeated capability as one already defined in the driver, then you may want to merge the repeated capabilities.

The remaining topics in this section discuss each wizard page separately.

In This Section

Instrument Classes Page, IVI-COM Driver Settings

Excluding IVI-C Functions and Attributes from an Instrument Class

See Also

Other Resources

How IVI Drivers Provide Interchangeability


Excluding IVI-C Functions and Attributes from an Instrument Class

When an IVI-COM driver supports a particular instrument class, all of the instrument class methods and properties are exposed to the end user, even if the driver does not support certain IVI-defined methods and properties. For IVI-COM methods exposed from the driver but not actually supported, the driver returns a specific IVI-defined error. The requirement to expose all methods and properties is a natural consequence of the interface-based programming model on which COM (and, hence, IVI-COM) is based.

With IVI-C drivers, however, functions and attributes defined in the instrument class need not be exposed from the IVI-C driver at all. Indeed, if an IVI-C driver does not support a particular IVI-defined function or attribute, then the item should not be exposed from the driver. Nimbus supplies a special command to exclude specific IVI-defined functions and attributes from an IVI-C driver.

To exclude a class-compliant function or attribute from the IVI-C driver

  1. From Solution Explorer, double-click the Driver Designer node under the Nimbus node.

  2. The Driver Designer opens as a tabbed document window. Choose the IVI-C tab.

  3. Click the Hierarchical button beneath the tree view on the left side of the IVI-C Designer.

    You can also work from the flat tree view of functions and attributes by clicking the Flat button beneath the tree view.

  4. Locate the IVI-defined function or attribute that you with to exclude. Note that IVI-defined items appear with greyed text in the tree views, indicating that their definition cannot be modified.

  5. Right-click on the function or attribute and choose Exclude from IVI-C Driver. The node now appears with a strikethrough.

    Nimbus will remove the implementation code for the function or attribute. It will also remove the function or attribute from the IVI-C driver header file (.h), import library (.lib), main DLL (.dll), function panel (.fp), and attribute information file (.sub).

    Caution note Caution

    If you exclude an IVI-C function or attribute that is manually implemented, Nimbus will automatically delete your custom code. Be sure no code of interest remains before executing this command.

  6. To restore an IVI-C function or attribute that has been excluded, right-click the item and choose Include in IVI-C Driver.


Adding Support for LXI

The level of LXI compliance supported by the driver can be changed at any stage of development. Nimbus performs a number of roundtripping operations based upon the specific level of LXI compliance chosen. For example, changing the conformance from None to LXI Core 2016 and adding support for LXI Event Messaging adds several repeated capabilities to the driver as well as a host of methods, properties, and interfaces. Correspondingly, decreasing the level of compliance will cause Nimbus to remove code from the project.

Caution note Caution

When decreasing the level of LXI compliance, Nimbus removes implementation and test code from the project. It is important to ensure that no code of interest exists in the LXI-related implementation and test files before changing the driver to support a lower level of LXI compliance.

The table below shows the modifications Nimbus performs on your driver project based upon the level of LXI compliance selected.

LXI Support Selected

Project Modifications Performed

No Support

No modifications.

Class A

  • Adds a reference to the IviLxiSync type library.

  • Creates the appropriate IviLxiSync interfaces and repeated capabilities.

  • Adds repeated capability names for LAN triggers (LAN0...7).

  • Adds repeated capability names for the LXI hardware trigger lines (LXI0...7).

Class B

  • Adds a reference to the IviLxiSync type library.

  • Creates the appropriate IviLxiSync interfaces and repeated capabilities.

  • Adds repeated capability names for LAN triggers (LAN0...7).

Class C

No modifications.

Tip Tip

If the IviLxiSync interfaces contain a repeated capability that represents the same physical repeated capability as one already defined in the driver, then you may want to merge the repeated capabilities.


Adding a Type Library Reference

A Nimbus driver can use data types defined in other type libraries installed on the Nimbus development machine. One common case in which this is needed is referencing the type library that houses the definitions of VISA-COM interfaces. Exposing the VISA interfaces directly from a Nimbus driver can be useful because it allows the end user to communicate directly with the underlying VISA I/O layer -- completely bypassing the driver logic.

For any data type defined in an external type library to be used in a Nimbus driver, a reference to the type library must be explicitly added to the Nimbus project. This allows Nimbus to add the appropriate importlib statement to the generated IDL source code for the driver.

Important note Important

Adding a type library reference will not update the driver installer to deploy the type library with the driver. The end user system must have the type library installed in order to use the driver.

To add a reference to a type library

  1. From Solution Explorer, double-click the Driver Designer node under the Nimbus node.

  2. The Driver Designer opens as a tabbed document window. Select the IVI-COM tab.

  3. From the tree view expand the type library node for the instrument-specific hierarchy. This node is named "<driverName>Lib".

  4. Right-click on the type library node and choose Add Type Library....

    The Add Type Library Reference Dialog appears and begins to scan your system registry for all registered COM type libraries. This process may take a few moments.

  5. Select the desired type library from the list of type libraries presented in the dialog and click OK.

  6. Nimbus adds a type library node to the IVI-COM Designer tree views for browsing the contents of the type library. The interfaces and enums in the type library may now be used as parameter types and property types in your Nimbus IVI-COM driver.

    Note Note

    The contents of an external type library can only be viewed in the Nimbus flat tree view, not in the hierarchical tree view. This is because, unlike IVI-COM drivers, type libraries generally do not represent a hierarchy of items. Rather, they are simply a flat list of interfaces and other data types.


IVI-COM Item Editors

When the IVI-COM Designer is open, a tree view of the driver methods, properties, and enums appears on the left, while a set of tabbed controls for the selected tree view item appears on the right. As the tree view selection changes, these controls are updated with the details of the selected item. Developers manipulate the selected item by working with these controls. Such an arrangement is often referred to in user interface design as a master-details view. Nimbus uses the term Item Editor to refer to the various tabbed controls available when workign with the IVI-COM Designer tree view.

The topics in this section explain each of the IVI-COM Item Editors in detail.

In This Section

IVI-COM Method General Editor

IVI-COM Parameter General Editor

IVI-COM Property General Editor

IVI-COM Property Simulation Editor

IVI-COM Property Range Checking Editor

IVI-COM Property State Caching Editor

IVI-COM Enum Editor

IVI-COM Enum Member Editor

IVI-COM Error Editor

IVI-COM Warning Editor

Using the Help Editor

See Also

Other Resources

Adding Functionality to an IVI-COM Driver


IVI-COM Method General Editor

Name

Name of the method. Method names must start with a capital letter and can contain only alphanumeric characters.

Return type

Return type of the method.

If an array is desired, append opening and closing square brakets ([]) to the type name. For example, to have the method return an array of double, enter Double[].

Tip Tip

The following syntax can be used in the Return type text box to create a new enum type and use that enum as the return type all in one operation:

new enum TriggerSource; Internal = 2, External = 0x15, Software = 47

See the topic Defining New Data Types Inline for more information on this feature.

Repeated capability

The repeated capability with which the method is associated.

Note Note

Not all repeated capabilites defined for the driver may appear in the Repeated capability combo box. This is because not all repeated capability transitions may be valid for the selected method. For instance, a method located on a collection-style repeated capability is inherently associated with that repeated capability based on its location within the driver hierarchy. Thus, it cannot be associated with a completely different repeated capability by using the Repeated capability combo box.

Implementation

Choosing the Instrument command option instructs Nimbus to automatically generate all of the implementation code needed to send the specified command and to read a response if the Response text box is non-empty.

Choosing the Manual option requires the driver developer to provide the method implementation. This choice is often used for methods that rely upon non-message-based device communications, such as register-based devices or drivers that rely upon a support DLL.

Choosing the Manual with instrument command option is the same as Manual except that the Command and Response textboxes are enabled and used to populate the Instrument Command section of the driver help page for the method. This is useful for methods that require manual implementation but that ultimately rely upon an instrument command in their manually added code.

Use standard method preamble

For manual method implementations, Nimbus can be instructed to still generate pre-processing code for features such as parameter validation, state-caching, and range-checking. If unchecked, Nimbus will not generate any pre-processing code and the driver developer must supply all method logic.

Caution note Caution

It is recommended that this option remain checked. Many Nimbus features can be "short-circuited" if the standard Nimbus pre-processing code is not generated. This option is intended for advanced scenarios.

Command

Specifies the command to send to the device. Nimbus supports a rich command and responseformatting syntax, which can include the parameters, repeated capabilities, and more. Please see the topic Working With Instrument Commands for a detailed discussion of automatic command formatting.

Clicking the editor icon at the far right end of the text box launches the Instrument Command Editor, which is useful for building instrument commands.

Response

Specifies the format of the response to read back from the device. Nimbus supports a rich command formatting syntax, which can include the parameters, repeated capabilities, and more. Please see the topic Working With Instrument Commands for a detailed discussion of automatic command formatting.

If no response is specified, Nimbus will only send the command specified in the Command text box -- no response will be read from the device.

Clicking the editor icon at the far right end of the text box launches the Instrument Command Editor, which is useful for building instrument responses.

Model-Specific Programming with the Models Window

The Method General Editor contains a collapsible Models Window in the right portion of the editor. This window is used for two purposes:

  • Specifying that a model or group of models does not support the method.

  • Customizing settings on a per-model or per-family basis.

Note Note

The Models Window cannot be used to define new models for the driver. The list of models supported by the driver is specified on the Models Page of the Driver Settings Editor.

The root node of the Models Window is labeled "All Models". This node can be thought of as the "default behavior" for the method. By default, all instrument models are supported for the method and all share the same command and response. Thus, the editor controls are initially only enabled when "All Models" is selected in the Models Window. This changes when model-specific behavior is specified, as explained below.

When you use the Models Window to specify that a method is not supported for a model, Nimbus will generate the necessary code to return the IVI-defined COM error E_IVI_METHOD_NOT_SUPPORTED.

To specify that a particular model is not supported

  1. From the Models Window, right-click on the desired model or family.

  2. Choose Remove model support.

  3. The selected model name appears with a strikethrough font.

    Note that if a family was selected, all models in the family appear with a strikethrough font, indicating that the E_IVI_METHOD_NOT_SUPPORTED error will be returned for those models as well.

  4. To re-enable support for a model, right-click the model and choose Add model support.

When customizing behavior on a per-model or per-family basis, Nimbus generates code that will send a different command and/or read a differently formatted response, based upon the actual model detected at runtime. See the discussion of the InitializeIdentification function to understand how Nimbus determines the connected model at runtime.

Only the instrument command and instrument response can be customized on a per-model basis. The return data type, repeated capability, and implementation style are all static characteristics of the method and cannot be changed dynamically based on the connected instrument model.

To customize the command or response for a model

  1. From the Models Window, right-click on the desired model or family.

  2. Choose Customize settings

  3. The Command and Reponse text boxes are enabled for the selected model, allowing model-specific values to be set. The model appears in bold font for the customized model.

    Note that if a family was selected, all models in the family appear in bold font, indicating that they will all share a custom command and/or resposne.

  4. To have a method return to using the default command and response for a model, right-click the model and choose Remove custom settings. The model appears in normal font and the editor controls are once again disabled when the model is selected, indicating that the model is controlled via the default settings specified when the "All Models" node is selected.

See Also

Other Resources

Adding Functionality to an IVI-COM Driver
Defining New Data Types Inline


IVI-COM Parameter General Editor

Name

Name of the parameter. Parameter names must start with a capital letter and can contain only alphanumeric characters.

Type

Data type of the method.

If an array is desired, append opening and closing square brakets ([]) to the type name. For example, to specify an array of double, enter Double[].

Tip Tip

The following syntax can be used in the Type text box to create a new enum type and use that enum as the type all in one operation:

new enum TriggerSource; Internal = 2, External = 0x15, Software = 47

See the topic Defining New Data Types Inline for more information on this feature.

Direction

Choose the Input to specify an input parameter.

Choose the Output to specify an output parameter.

Choose the Input/Output to specify an output parameter.

Important note Important

As per the IVI specifications, Nimbus generates [in, out] in the IDL method signature if either Output or Input/Output is specified. This is as per the IVI specifications. However, it is important to properly indicate the "logical" direction of the parameter here See the topic Understanding Parameter Direction for a detailed discussion of output parameters in IVI-COM drivers.

See Also

Other Resources

Adding Functionality to an IVI-COM Driver
Understanding Parameter Direction
Defining New Data Types Inline


IVI-COM Property General Editor

Name

Name of the property. Property names must start with a capital letter and can contain only alphanumeric characters.

Type

Data type of the property.

Note Note

As per the IVI specifications, array-type properties are not permitted. If you need to read or write an array, then use explicit "Get" and "Set" methods.

Tip Tip

The following syntax can be used in the Type text box to create a new enum type and use that enum as the type all in one operation:

new enum TriggerSource; Internal = 2, External = 0x15, Software = 47

See the topic Defining New Data Types Inline for more information on this feature.

Access

Indicates if the property is read-write, read-only, or write-only.

Repeated capability

The repeated capability with which the property is associated.

Note Note

Not all repeated capabilites defined for the driver may appear in the Repeated capability combo box. This is because not all repeated capability transitions may be valid for the selected property. For instance, a property located on a collection-style repeated capability is inherently associated with that repeated capability based on its location within the driver hierarchy. Thus, it cannot be associated with a completely different repeated capability by using the Repeated capability combo box.

Implementation

Choosing the Instrument command option instructs Nimbus to automatically generate all of the implementation code needed to send the specified commands and to read a response for the property getter, if the Response text box is non-empty.

Choosing the Manual option requires the driver developer to provide the implementation for the property getter and setter. This choice is often used for properties that rely upon non-message-based device communications, such as register-based devices or drivers that rely upon a support DLL.

Choosing the Manual with instrument command option is the same as Manual except that the command and response textboxes are enabled and used to populate the Instrument Command section of the driver help page for the property. This is useful for properties that require manual implementation but that ultimately rely upon an instrument command in their manually added code.

Use standard method preamble

For manual property implementations, Nimbus can be instructed to still generate pre-processing code for features such as parameter validation, state-caching, and range-checking. If unchecked, Nimbus will not generate any pre-processing code and the driver developer must supply all getter and setter method logic.

Caution note Caution

It is recommended that this option remain checked. Many Nimbus features can be "short-circuited" if the standard Nimbus pre-processing code is not generated. This option is intended for advanced scenarios.

Setter command

Specifies the command to send to the device when the value of the property is set (i.e. the property setter executes). This control is not enabled for read-only properties. Nimbus supports a rich command and response formatting syntax, which can include the parameters, repeated capabilities, and more. Please see the topic Working With Instrument Commands for a detailed discussion of automatic command formatting.

Clicking the editor icon at the far right end of the text box launches the Instrument Command Editor, which is useful for building instrument commands.

Getter command

Specifies the query to send to the device when the value of the property value is read (i.e. the property getter executes). This control is not enabled for write-only properties. Nimbus supports a rich command and response formatting syntax, which can include the parameters, repeated capabilities, and more. Please see the topic Working With Instrument Commands for a detailed discussion of automatic command formatting.

Clicking the editor icon at the far right end of the text box launches the Instrument Command Editor, which is useful for building instrument commands.

Getter response

Specifies the format of the response to read back from the device when the property value is read. This control is not enabled for write-only properties.

Clicking the editor icon at the far right end of the text box launches the Instrument Command Editor, which is useful for building instrument responses.

Model-Specific Programming with the Models Window

The Property General Editor contains a collapsible Models Window in the right portion of the editor. This window is used for two purposes:

  • Specifying that a model or group of models does not support the method.

  • Customizing settings on a per-model or per-family basis.

Note Note

The Models Window cannot be used to define new models for the driver. The list of models supported by the driver is specified on the Models Page of the Driver Settings Editor.

The root node of the Models Window is labeled "All Models". This node can be thought of as the "default behavior" for the property. By default, all instrument models are supported for the property and all share the same command and response. Thus, the editor controls are initially only enabled when "All Models" is selected in the Models Window. This changes when model-specific behavior is specified, as explained below.

When you use the Models Window to specify that a property is not supported for a model, Nimbus will generate the necessary code to return the IVI-defined COM error E_IVI_PROPERTY_NOT_SUPPORTED.

To specify that a particular model is not supported

  1. From the Models Window, right-click on the desired model or family.

  2. Choose Remove model support.

  3. The selected model name appears with a strikethrough font.

    Note that if a family was selected, all models in the family appear with a strikethrough font, indicating that the E_IVI_PROPERTY_NOT_SUPPORTED error will be returned for those models as well.

  4. To re-enable support for a model, right-click the model and choose Add model support.

When customizing behavior on a per-model or per-family basis, Nimbus generates code that will send different setter commands, getter commands, and/or read a differently formatted getter response, based upon the actual model detected at runtime. See the discussion of the InitializeIdentification function to understand how Nimbus determines the connected model at runtime.

Only the getter and setter commands and getter response can be customized on a per-model basis. The return data type, property access, repeated capability, and implementation style are all static characteristics of the property and cannot be changed dynamically based on the connected instrument model.

To customize the command or response for a model

  1. From the Models Window, right-click on the desired model or family.

  2. Choose Customize settings

  3. The Setter command, Getter command, and Getter reponse text boxes are enabled for the selected model, allowing model-specific values to be set. The model appears in bold font for the customized model.

    Note that if a family was selected, all models in the family appear in bold font, indicating that they will all share a custom command and/or resposne.

  4. To have a property return to using the default commands and response for a model, right-click the model and choose Remove custom settings. The model appears in normal font and the editor controls are once again disabled when the model is selected, indicating that the model is controlled via the default settings specified when the "All Models" node is selected.

See Also

Other Resources

Adding Functionality to an IVI-COM Driver
Defining New Data Types Inline


IVI-COM Property Simulation Editor

Nimbus offers two different styles of automatic simulation support -- returning a fixed value for the property and returning the last value to which the property was set.

Important note Important

The simulation logic for either option is only executed when simulation is enabled by the end user. This can be done by passing Simulate=True as part of the OptionString parameter to the driver's Initialize method, or it can be done after driver initialization via the IIviDriverOperation.Simulate property.

Manual

Specifies that no automatic simulated value should be returned for the property. Selecting this option indicates that the driver developer will manually implement simulation logic in the property implementation. See the GetSimulate function for an example of how this can be done.

Fixed value

Instructs Nimbus to simply return the value specified in the Value text box when the property is read in simulation mode. Setting the property to a different value has no effect on the driver behavior.

Last Value Set

Specifies that the driver should cache the value of the property when it is set and return the most recent value set when the property is read. If the property is read without having been set, then the value specified in the Default text box is returned.

Model-Specific Programming with the Models Window

The Property Simulation Editor contains a collapsible Models Window in the right portion of the editor. This window is used to customize simulation settings on a per-model or per-family basis.

Note Note

The Models Window cannot be used to define new models for the driver. The list of models supported by the driver is specified on the Models Page of the Driver Settings Editor.

The root node of the Models Window is labeled "All Models". This node can be thought of as the "default behavior" for the property. By default, all instrument models share the same simulation settings. Thus, the editor controls are initially only enabled when "All Models" is selected in the Models Window. This changes when model-specific behavior is specified, as explained below.

When simulation behavior on a per-model or per-family basis, Nimbus generates code that will use different simulated values based upon the actual model detected at runtime. See the discussion of the InitializeIdentification function to understand how Nimbus determines the connected model at runtime.

The only simulation settings that can be customized on a per-model basis are the constant returned when the Fixed Value option is chosen and the default value used when the Last Value Set option is chosen. The simulation style (manual, last value set, fixed) must be the same for all models.

To customize the simulation settings for a model

  1. From the Models Window, right-click on the desired model or family.

  2. Choose Customize settings

  3. The Value text boxes or the Default text box is enabled for the selected model, allowing a model-specific value to be set. The model appears in bold font for the customized model.

    Note that if a family was selected, all models in the family appear in bold font, indicating that they will all the same simulation values.

  4. To have a property return to using the simulation settings, right-click the model and choose Remove custom settings. The model appears in normal font and the editor controls are once again disabled when the model is selected, indicating that the model is controlled via the default settings specified when the "All Models" node is selected.

See Also

Other Resources

Adding Functionality to an IVI-COM Driver
Adding Support for an Instrument Class


IVI-COM Property Range Checking Editor

Nimbus offers three different styles of automatic range checking -- validation against a continous range of values, checking against a list of discrete values, or executing custom logic in a special range-checking function. In all cases, Nimbus generates code that returns the IVI-defined error E_IVI_INVALID_VALUE if the range check condition fails.

Important note Important

The range-checking logic for any option is only executed when range-checking is enabled by the end user. This can be done by passing RangeCheck=True as part of the OptionString parameter to the driver's Initialize method, or it can be done after driver initialization via the IIviDriverOperation.RangeCheck property.

None

Specifies that no automatic range checking should be performed on the property.

Continuous range

Enables range checking for the selected property against a continuous range of values between the specified Minimum and Maximum. The two Inclusive check boxes are used to specify if the Minimum and Maximum values are included in the list of valid values for the property.

Discrete values

Enables range checking for the selected property against a discrete set of values specifed as a comma-separated list.

Using this option also enables coercion of the property value. If the property value falls between two values in the list of Allowed values, then the Coercion combo box indicates whether the property value should rounded to the next higher value in the list (coerce Up), to the next lower value in the list (coerce Down), or should generate an error (coercion set to None).

Custom

Custom range checking allows custom code to be executed for performing the range checking and coercion logic. The specified Range check function is invoked at the proper time when range checking is enabled and the specified Coercion function is used to coerce property values. These two functions should be used instead of explicit code in the property implementation because Nimbus ensures that the logic in these two functions executes at the proper time relative to other Nimbus-generated code, such as simulation and state caching logic.

Use the Create button to create a new range check or coercion function that has the signature Nimbus requires.

Use the Select button to select an existing range check or coercion function that has the signature Nimbus requires. This option is useful if several properties need to share range checking logic.

Model-Specific Programming with the Models Window

The Property Range Checking Editor contains a collapsible Models Window in the right portion of the editor. This window is used to customize range-checking settings on a per-model or per-family basis.

Note Note

The Models Window cannot be used to define new models for the driver. The list of models supported by the driver is specified on the Models Page of the Driver Settings Editor.

The root node of the Models Window is labeled "All Models". This node can be thought of as the "default behavior" for the property. By default, all instrument models share the same range-checking settings. Thus, the editor controls are initially only enabled when "All Models" is selected in the Models Window. This changes when model-specific behavior is specified, as explained below.

When customizing range-checking behavior on a per-model or per-family basis, Nimbus generates code that will use different allowed values based upon the actual model detected at runtime. See the discussion of the InitializeIdentification function to understand how Nimbus determines the connected model at runtime.

The only range checking settings that can be customized on a per-model basis are the Minimum and Maximum values for continuous range checking and the Allowed values list for discrete range checking. The range checking style (none, continuous, discrete, custom) must be the same for all models. Additionally, only a single range-checking and coercion function can be specified, so any per-model behavior with custom range checking must be implemented explicitly in the Range check function and the Coercion function.

To customize the range checking settings for a model

  1. From the Models Window, right-click on the desired model or family.

  2. Choose Customize settings

  3. The Minimum and Maximum text boxes or the Allowed values text box are enabled for the selected model, allowing model-specific values to be set. The model appears in bold font for the customized model.

    Note that if a family was selected, all models in the family appear in bold font, indicating that they will all the same custom range checking values.

  4. To have a property return to using the default range checking settings, right-click the model and choose Remove custom settings. The model appears in normal font and the editor controls are once again disabled when the model is selected, indicating that the model is controlled via the default settings specified when the "All Models" node is selected.

See Also

Other Resources

Adding Functionality to an IVI-COM Driver
Adding Range Checking and Coercion to a Property


IVI-COM Property State Caching Editor

Nimbus allows state caching to be enabled on a property-by-property basis. The Property State Caching Editor allows the driver developer to enable or disable state caching for the selected property and to specify cache couplings. See the topic Understanding Nimbus State Caching for more information.

Important note Important

The state caching logic specified here is only executed when state caching is enabled by the end user. This can be done by passing Cache=True as part of the OptionString parameter to the driver's Initialize method, or it can be done after driver initialization via the IIviDriverOperation.Cache property.

Enabled

When checked, Nimbus will generate implementation code that caches the property value between calls. This can reduce I/O traffic if redundant calls to the property occur, but it can also lead to cache coherency issues (data in memory out-of-sync with the actual instrument settings) if the property couplings are not thorougly understood and properly specified.

Invalidation list

If state caching is enabled for a property, this list becomes available for specifying cache couplings. The list represents all of the methods and properties which, when executed, cause the cached property value to become invalid. A properly specified list of such coupled methods and properties is critical when state caching is enabled for a property.

To add a method or property to the invalidation list

  1. Click the "+" button to add a new entry.

  2. Enter a cache entry key. Cache keys are expressed in one of the following three formats:

    • PropertyName

      Use this format to invalidate a property defined on the same interface as the property being configured.

      For example, if the property being configured is defined on the IAcme4301Trigger interface, entering Frequency indicates that whenever this property's value is changed, any value previously cached by the implementation of IAcme4301Trigger.Frequency should be discarded.

    • InterfaceName.PropertyName

      Use this format to invalidate a property defined on the same class as the property being configured, where the property satisfies the implementation of the specified interface.

      For example, if the class containing the property being configured implements both the IIviDownconverterIFOutput and IIviDownconverterRFInput interfaces (both of which define a Frequency property), specifying IIviDownconverterIFOutput.Frequency indicates that whenever this property's value is changed, any value previously cached by the implementation of IIviDownconverterIFOutput.Frequency should be discarded. Any value previously cached by the implementation of IIviDownconverterRFInput.Frequency will not be affected.

    • CollectionStyleRepCapItemPath.InterfaceName.PropertyName

      Use this format to invalidate a property defined on a collection-style repeated capability interface.

      In this case, a combination of repeated capability names and repeated capability selectors are specified in addition to the appropriate interface and property name. Examples include:

      • Channel[CHANNEL1].Trace[TRACE2].IAcme4321Acquisition.Frequency

      • Channel[*].Trace[TRACE2].IAcme4321Acquisition.Frequency

      • Channel[CHANNEL1].Trace[*].IAcme4321Acquisition.Frequency

      • Channel[CHANNEL1-CHANNEL3].Trace[*].IAcme4321Acquisition.Frequency

      • Channel[*].Trace[TRACE2,TRACE4].IAcme4321Acquisition.Frequency

      • Channel[CHANNEL1,CHANNEL3-CHANNEL5].Trace[*].IAcme4321Acquisition.Frequency

  3. Press the enter key.

See Also

Other Resources

Adding Functionality to an IVI-COM Driver
State Caching Functions
State Caching Overview


IVI-COM Enum Editor

Name

Specifies the name of the enum. The following naming rules apply to the enum name:

  • The name can contain only alphanumeric characters.

  • The name must start with the project name.

  • The name must end with the Enum.

  • The name must be unique within the driver.

See Also

Other Resources

Adding Functionality to an IVI-COM Driver


IVI-COM Enum Member Editor

Name

Specifies the name of the enum member. The following naming rules apply to the enum member name:

  • The name can contain only alphanumeric characters.

  • The name must start with the project name.

  • The name must be unique within the driver.

Value

Specifies the numeric value of the enum member. The value should be unique within the parent enum.

See Also

Other Resources

Adding Functionality to an IVI-COM Driver


IVI-COM Error Editor

Name

Specifies the name of the error. The name must be all uppercase and having the following form:

E_<driverName>_<errorName>

Example: E_ACME4321_BAD_DATA

Value

Specifies the numeric value of the COM error HRESULT. As per the IVI specifications, all IVI-COM instrument-specific error codes have a base value of 0x80044000. This value appears as a read-only text box. The driver developer specifies the offset added to this base in the read-write text box. The resulting HRESULT value for the error is the sum of these two.

Message

This string will be formatted and placed in the COM error object so that client applications receive a textual description of the error.

The message can contain replacement tags (%1, %2, etc.) used to insert runtime values into the error message. For example, consider the following message definition:

Method %1 failed to switch to mode %2.

When the error is fired from within the driver using the error reporter object, the developer supplies runtime values for the two replacement tags to produce a final message that would look similar to the following.

Method Configure failed to switch to mode CDMA.

See Also

Other Resources

Adding Functionality to an IVI-COM Driver
Returning Errors from IVI-COM Drivers


IVI-COM Warning Editor

Name

Specifies the name of the warning. The name must be all uppercase and having the following form:

S_<driverName>_<errorName>

Example: S_ACME4321_OPERATION_PENDING

Value

Specifies the numeric value of the COM warning HRESULT. As per the IVI specifications, all IVI-COM instrument-specific warning codes have a base value of 0x00044000. This value appears as a read-only text box. The driver developer specifies the offset added to this base in the read-write text box. The resulting HRESULT value for the warning is the sum of these two.

Message

This string will be formatted and placed in the COM error object so that client applications receive a textual description of the warning.

The message can contain replacement tags (%1, %2, etc.) used to insert runtime values into the warning message. For example, consider the following message definition:

Method %1 received only %2 bytes of %3 expected.

When the warning is fired from within the driver using the error reporter object, the developer supplies runtime values for the two replacement tags to produce a final message that would look similar to the following.

Method Fetch received only 350 bytes of 512 expected.

See Also

Other Resources

Adding Functionality to an IVI-COM Driver
Returning Errors from IVI-COM Drivers


IVI-C Item Editors

When the IVI-C Designer is open, a tree view of the driver methods, properties, and enums appears on the left, while a set of tabbed controls for the selected tree view item appears on the right. As the tree view selection changes, these controls are updated with the details of the selected item. Developers manipulate the selected item by working with these controls. Such an arrangement is often referred to in user interface design as a master-details view. Nimbus uses the term Item Editor to refer to the various tabbed controls available when workign with the IVI-C Designer tree view.

The topics in this section explain each of the IVI-C Item Editors in detail.

In This Section

IVI-C Function General Editor

IVI-C Function Parameter General Editor

IVI-C Callback Function General Editor

IVI-C Attribute General Editor

IVI-C Enum Editor

IVI-C Enum Member Editor

IVI-C Error Editor

IVI-C Warning Editor

Using the Help Editor

See Also

Other Resources

Managing IVI-C Driver Functionality
Linking IVI-COM and IVI-C Methods and Properties


IVI-C Function General Editor

Name

Name of the function. Function names must start with a capital letter and can contain only alphanumeric characters.

Return type

Return type of the function.

If an array is desired, append opening and closing square brakets ([]) to the type name. For example, to have the method return an array of double, enter Double[].

Tip Tip

The following syntax can be used in the Return type text box to create a new enum type and use that enum as the return type all in one operation:

new enum TriggerSource; Internal = 2, External = 0x15, Software = 47

See the topic Defining New Data Types Inline for more information on this feature.

Display

Display name that will be used to identify the function in the function tree.

Repeated capability

The repeated capability with which the function is associated.

Implementation

Choosing the Automatic option instructs Nimbus to automatically generate all of the implementation code needed to implement the IVI-C function by delegating to the associated IVI-COM method. The function implementation will be generated in the <prefix>.nimbus.cpp file. Note that the Automatic implementation option is not available for IVI-C only functions.

Choosing the Manual option requires the driver developer to provide the function implementation. Nimbus will add a stub implementation in the <prefix>.cpp file.

Caution note Caution

When the Implementation setting is changed from Manual to Automatic, Nimbus deletes any manual implementation code in the <prefix>.cpp file. It is important that no code of interest remains in the manual function implementation in the <prefix>.cpp when this setting is changed.

See Also

Other Resources

Managing IVI-C Driver Functionality
Linking IVI-COM and IVI-C Methods and Properties
Defining New Data Types Inline


IVI-C Function Parameter General Editor

Name

Name of the parameter. Parameter names must start with a capital letter and can contain only alphanumeric characters.

Type

Data type of the parameter.

If an array is desired, append opening and closing square brakets ([]) to the type name. For example, to specify an array of double, enter Double[].

Tip Tip

The following syntax can be used in the Type text box to create a new enum type and use that enum as the type all in one operation:

new enum TriggerSource; Internal = 2, External = 0x15, Software = 47

See the topic Defining New Data Types Inline for more information on this feature.

Direction

Choose the Input to specify an input parameter.

Choose the Output to specify an output parameter.

Choose the Input/Output to specify an output parameter.

Buffer size

The buffer size combo box will only appear for array parameters and for string output parameters. Use this control to select which parameter indicates the number of array elements (or string characters) allocated by the caller. Only Int32 and Int64 parameters may be used as the buffer size parameter.

Actual size

The actual size combo box will only appear for array output parameters. Use this control to select which parameter indicates the number of array elements returned by the driver to the caller. Only Int32 and Int64 parameters may be used as the actual size parameter.

Tip Tip

For functions with more than one array parameter, each with the same number of elements, it is convenient to have all of the array parameters share a single buffer size parameter and a single actual size parameter. Nimbus initially creates separate buffer size and actual size parameters for each array parameter. Consolidate these by first visiting each array parameter and changing the Buffer size and Actual size combo boxes and then deleting the extra buffer size and actual size parameters. Note that you will not be able to delete a parameter if it is used by an array or string as a buffer size or actual size. Finally, order the parameters such that the shared buffer size parameter appears immediately before the first array parameter, then the array parameters, then the shared actual size parameter.

See Also

Other Resources

Defining New Data Types Inline


IVI-C Callback Function General Editor

Name

Name of the function. Callback function names must start with a capital letter and can contain only alphanumeric characters.

Return type

Return type of the function. Unlike normal IVI-C functions, callback functions can have return types other than ViStatus.

If an array is desired, append opening and closing square brakets ([]) to the type name. For example, to have the method return an array of double, enter Double[].

Tip Tip

The following syntax can be used in the Return type text box to create a new enum type and use that enum as the return type all in one operation:

new enum TriggerSource; Internal = 2, External = 0x15, Software = 47

See the topic Defining New Data Types Inline for more information on this feature.

See Also

Other Resources

Defining New Data Types Inline


IVI-C Attribute General Editor

Name

Name of the attribute. This name corresponds to the IVI-C macro name used in the <prefix>.h #define statement, except that the driver prefix and ATTR are excluded. Attribute names consist only of capital letters, numbers, and the underscore character and must start with a capital letter.

Type

Data type of the attribute.

Note Note

As per the IVI specifications, array-type properties are not permitted. If you need to read or write an array, then use explicit "Get" and "Set" methods.

Tip Tip

The following syntax can be used in the Type text box to create a new enum type and use that enum as the type all in one operation:

new enum TriggerSource; Internal = 2, External = 0x15, Software = 47

See the topic Defining New Data Types Inline for more information on this feature.

Display

Display name that will be used to identify the attribute in the function tree.

Access

Indicates if the attribute is read-write, read-only, or write-only

ID

The numeric value of the attribute macro used in the <prefix>.h #define statement. Note that IVI prescribes the base attribute value, so only the offset is editable.

Repeated capability

The repeated capability with which the function is associated.

Implementation

Choosing the Automatic option instructs Nimbus to automatically generate all of the implementation code needed to implement the IVI-C attribute by delegating to the associated IVI-COM property. The attribute implementation will be generated in the <prefix>.nimbus.cpp file. Note that the Automatic implementation option is not available for IVI-C only functions.

Choosing the Manual option requires the driver developer to provide the function implementation. Nimbus will add a stub implementation in the <prefix>.cpp file. The attribute getter will be generated with a name of the following form:

<prefix>_get_<ATTRIBUTE_NAME>

Similarly, the attribute setter will be generated with a name of the following form:

<prefix>_set_<ATTRIBUTE_NAME>

Caution note Caution

When the Implementation setting is changed from Manual to Automatic, Nimbus deletes any manual implementation code in the <prefix>.cpp file. It is important that no code of interest remains in the manual attribute implementation in the <prefix>.cpp when this setting is changed.

See Also

Other Resources

Managing IVI-C Driver Functionality
Linking IVI-COM and IVI-C Methods and Properties


IVI-C Enum Editor

Name

Name of the enum. Enum names must start with a capital letter and can contain only alphanumeric characters.

See Also

Other Resources

Managing IVI-C Driver Functionality
Linking IVI-COM and IVI-C Methods and Properties


IVI-C Enum Member Editor

Name

Name of the enum member. This name corresponds to the IVI-C macro name used in the <prefix>.h #define statement, except that the driver prefix and VAL are excluded. Attribute names consist only of capital letters, numbers, and the underscore character and must start with a capital letter.

Value

The numeric value of the enum member value macro used in the <prefix>.h #define statement.

Display

Display name that will be used to identify the enum member in function panel controls.

See Also

Other Resources

Managing IVI-C Driver Functionality
Linking IVI-COM and IVI-C Methods and Properties


IVI-C Error Editor

Name

Name of the error. This name corresponds to the IVI-C macro name used in the <prefix>.h #define statement, except that the driver prefix is excluded. Error names consist only of capital letters, numbers, and the underscore character and must start with a capital letter.

Value

The numeric value of the error code macro used in the <prefix>.h #define statement. Note that IVI prescribes the base error code value, so only the offset is editable.

Message

Error message that will be set on the driver session when the error is reported. Client applications use the GetError function to retrieve the error message;

See Also

Other Resources

Managing IVI-C Driver Functionality
Linking IVI-COM and IVI-C Methods and Properties


IVI-C Warning Editor

Name

Name of the warning. This name corresponds to the IVI-C macro name used in the <prefix>.h #define statement, except that the driver prefix is excluded. Warning names consist only of capital letters, numbers, and the underscore character and must start with a capital letter.

Value

The numeric value of the warning code macro used in the <prefix>.h #define statement. Note that IVI prescribes the base warning code value, so only the offset is editable.

Message

Warning message that will be set on the driver session when the warning is reported. Client applications use the GetError function to retrieve the error message;

See Also

Other Resources

Managing IVI-C Driver Functionality
Linking IVI-COM and IVI-C Methods and Properties


Implementing an IVI-COM Driver

The methods and properties comprising a Nimbus IVI driver can be implemented in a variety of ways. Often, methods and properties are implemented by specifying an instrument command, such as a SCPI command, and relying upon Nimbus to generate the code to send the specified command to the instrument. More complex methods and properties might require custom logic to be manually implemented in the driver method body.

Nimbus also supplies stock implementations of many standard IVI-defined methods and properties. While these pre-built implementations are often suitable as-is for many instruments, they may need to be slightly customized with pre-processing or post-processing logic. Drivers might also need to integrate external DLLs for specific pieces of driver logic.

The topics in this section explain how driver methods and properties are implemented within an IVI-COM driver.

In This Section

Working With Instrument Commands

Implementing Methods and Properties

Implementing IVI-C-Only Functions and Attributes

Implementing Dynamic Repeated Capabilities

State Caching Overview

Implementing Class-Compliant Interfaces

Special Notes on Implementing IviFgen

Implementing Simulation

Using Code from External DLLs

Customizing Config Store Registration

Customizing the Driver Inherent Capabilities

Customizing Driver Initialization And Shutdown


Working With Instrument Commands

By far, the most common way to implement Nimbus IVI-COM driver methods and properites is by specifying an instrument command and relying upon Nimbus to generate all of the necessary code to send the command and, optionally, to read back a response. Nimbus provides a powerful instrument command syntax that allows method parameters and other information to be automatically formatted into the command. In addition, a special editor is provided to assist in composing proper instrument commands.

In This Section

Instrument Command Syntax

Using the Instrument Command Editor

Special Features For SCPI Commands


Instrument Command Syntax

Nimbus provides a very flexible syntax for specifying instrument commands and responses that are associated with methods and properties. The command syntax described here applies to commands and responses entered in the Method General Editor or the Property General Editor.

When the user associates an instrument command or response with a property or method, Nimbus generates code to automatically format the command using the values of parameters passed to the method. Correspondingly, when responses are read back from an instrument, the results are parsed and assigned to [out] parameters according to the response string specified by the user. Commands and responses can contain parameter replacement tags to control how each parameter is associated with the command or response. Additionally, commands (not responses) may include repeated capability replacement tags for inserting the repeated capability instance name or index into the command string.

Parameter Replacement Tags

Parameter replacement tags are enclosed in curly braces { } and can appear anywhere within an instrument command. They have the following general form:

{<paramName> | value[:<formatSpec>]}

The paramName is the name of the parameter in the method signature.

The value keyword is used to refer to the property value itself when defining property setter commands and property getter responses. The value keyword is also used to refer to a method return value. Use of the {value} keyword is discussed further in the sections below.

The formatSpec is an optional format specification for the parameter. This format specification is similar to that supported by the C Run-Time Library's familiar sprintf function.

If no formatSpec is provided, then the default format specification is used. The default format specification only applies to integers, floating-point, and boolean parameters. These defaults are configured on the I/O Page of the Driver Settings Editor.

The simplest way to create proper format specifications is to use the Instrument Command Editor. Full documentation of the parameter format specification syntax can be found in the topic Parameter Format Specifications.

Special support is provided for formatting boolean and enum parameters.

Example: Basic Parameter Replacement

This example shows a Configure method that takes three parameters -- resolution bandwidth (ResBW), video bandwidth (VideoBW), and sweep time (SweepTime). Assume a method defined as follows

C++
Copy
HRESULT Configure([in] double ResBW, [in] double VideoBW, [in] double SweepTime);

The following instrument command is associated with the Configure method:

SENS:BAND{ResBW}; SWE:TIME{SweepTime:%d}; BAND:VID{VideoBW:%3.2f};

Given this method definition and the replacement tags shown, the instrument command would be formatted as follows:

  • The replacement tag {ResBW} would be replaced with the run-time value of the ResBW parameter. Since no format specification is provided, the default format for floating-point values would be applied.

  • The replacement tag {SweepTime:%d} would be replaced with the run-time value of the SweepTime parameter and formatted as a decimal as dictated by the %d format specification.

  • The replacement tag {VideoBW} would be replaced with the run-time value of the VideoBW parameter and formatted as a floating point number as dictated by the %3.2f format specification.

Formatting Property Setters

Property setters support a special {value} replacement tag to represent the value of the property itself. This special tag allows you to insert the runtime value of the property into the command string.

The following instrument command applied to a property setter would append the value of the property to the SENS:BAND string:

SENS:BAND {value}

Since most functionality in IVI-COM drivers is provided by properties, Nimbus simplifies the instrument command syntax by not requiring a replacement tag to be provided explicitly for property setters. Rather, the formatted property value will simply be appended to the command string. If the formatted parameter should appear elsewhere in the command string, then an explicit parameter replacement tag must be specified.

Given this shorthand notation, the following two instrument commands applied to a property setter produce identical results:

  • SENS:BAND

  • SENS:BAND {value}

Both command strings will append the formatted value of the property to the SENSE:BAND string. Note that in both cases the default parameter formatting for the property type will be applied, since no format specification is provided. If an alternate format specification is desired, then the {value} replacement tag must be specified.

The following example shows an instrument command using the {value} tag with a format specification:

SENS:BAND {value:%3.2e}

The above example will append the value of the property in exponentional form with a minimum length of 3 characters and 2 digits following the decimal point.

Properties may have parameters, and, thus, the associated instrument command may include parameter replacement tags, just as with methods. The following example demonstrates use of the {value} tag in conjunction with a normal parameter replacement tag.

:CURRent:AC:BANDwidth {value}, {ChannelList}

The above example would be valid for a property setter that accepted a parameter named ChannelList.

Formatting Property Getters

Property getters utilize the {value} tag in precisely the same way as methods use the tag for responses. Only the getter response string may use the {value} tag -- the getter command may only use [in] parameter tags and repeated capability tags, not the {value}. See the discussion in the following section on how to use the {value} tag in method responses.

Formatting Method Return Values

Methods often have a return value associated with them. Since there is no parameter name to reference, the {value} tag is used to represent the method return value. A method return value is effectively an [out] parameter, so the {value} tag can only be used in the method response. The {value} tag cannot be used in the method command.

Consider a method defined as follows in the IVI-COM designer:

C#
Copy
double[] Fetch(long Start, long NumPoints)

The method command might be the following:

CALC:DATA? {Start}, {NumPoints}

The above command uses parameter replacement tags for the two input parameters Start and NumPoints. After issuing the above command, the driver needs to read data from the instrument and assign the resulting array of double-precision floating point numbers to the return value of the method. This can be done with the following method response string.

{value:%,e}

The response string above uses the {value} tag with a format specification of %,e. This format specification indicates that the instrument response is a comma-separated list of floating-point numbers in ASCII format.

Formatting Boolean And Enum Parameters

When an instrument command parameter tag refers to a boolean or enum parameter, Nimbus must generate code that converts the boolean or enum value to a string. Correspondingly, when an instrument response uses a parameter tag that references a boolean or enum, the instrument response string must be parsed and converted to the appropriate boolean or enum value. These string-to-enum and boolean-to-enum mappings are configured with the Instrument Command Editor.

As an example, consider the definition of a simple TriggerSource property:

C++
Copy
[propput]
HRESULT TriggerSource([in] Acme4321TriggerSourceEnum Source);

[propget]
HRESULT TriggerSource([out,retval] Acme4321TriggerSourceEnum* Source);

The TriggerSource property is a read-write property of type Acme4321TriggerSource. The command for the setter is defined as:

TRIG:SOUR {value}

The command for the getter is defined as:

TRIG:SOUR?

Finally, the response for the getter is defined simply as:

{value}

When the setter is executed, the specified value for the Source parameter needs to be converted to a string and inserted into the setter command where the {value} tag appears. For instance, if the property were set to the value Acme4321TriggerSourceExternal, the enum value might need to be converted to EXT to produce the following command:

TRIG:SOUR EXT

Similarly, when the TRIG:SOUR? query is issued upon executing the property getter, the instrument might respond with a string such as INT (to represent an internal trigger source). This string needs to be converted to a valid Acme4321TriggerSourceEnum value, such as Acme4321TriggerSourceInternal.

These mappings between strings and enum (or boolean) values are established with the Instrument Command Editor.

Repeated Capability Replacement Tags

Instrument commands sent from methods implemented on repeated capability classes often need to incorporate runtime information about the specific repeated capability instance issuing the command. For example, a spectrum analyzer driver might define a repeated capability class to represent multiple traces stored in the instrument. A command that would read data from a specific trace might look something like the following:

DATA:TRACE4:READ?

Note that the 4 included in the command refers to a specific trace within the instrument.

Note Note

Repeated capability tags cannot appear in instrument response strings.

Repeated capability replacement tags are used to insert into command strings runtime information about the repeated capability instance sending the command. These special tags can be replaced by either the name or the index of the repeated capability.

For more information on repeated capabilities, see Repeated Capabilities.

Repeated capability replacement tags are enclosed in curly braces { } and can appear anywhere within an instrument command. They have the following general form:

{ [<className>.]rcindex[+|-<offset>] | rcname }

The rcindex keyword is used to insert into the command string the runtime value of the index of the repeated capability instance issuing the command. The rcindex keyword can optionally be followed by an offset, such as +1 or -3, to account for differences between how repeated capabilities are indexed by the driver and how the instrument expects them to appear in the command string.

The rcname keyword is used to insert into the command string the runtime value of the name of the repeated capability instance issuing the command.

The className is an optional parameter used to designate a class other than the class from which the command is being sent. This is most often useful when the name or index of a parent repeated capability must also be included in the command string.

Example: Using the repeated capability index in instrument commands

This example shows a Resolution property that is defined on a repeated capability that represents multiple markers. In order to set the resolution for the correct marker, the index of the current repeated capability instance must be included in the command string. Assume a property definition as follows:

C++
Copy
[propput]
HRESULT Resolution([in] double resolution);

The following instrument command is assigned to the Resolution property:

CALC:MARK{rcindex}:RES

If the Resolution property was executed from the fourth instance of the marker repeated capability, then the formatted string sent to the instrument would be as follows:

CALC:MARK3:RES

Example: Using the repeated capability index with an offset

In this example, the Resolution property of a marker repeated capability uses an instrument command with a positive offset of 1 for the repeated capability index. Assume a property definition as follows:

C++
Copy
[propput]
HRESULT Resolution([in] double resolution);

The following instrument command is assigned to the Resolution property:

CALC:MARK{rcindex+1}:RES

If the Resolution property was executed from the fourth instance of the marker repeated capability, then the formatted string sent to the instrument would be as follows:

CALC:MARK4:RES

Example: Using the repeated capability name in an instrument command

This example demonstrates the use of the rcname keyword to insert the name of the current repeated capability instance into the instrument command. Assume a property definition as follows:

C++
Copy
[propget]
HRESULT Amplitude([out, retval] double* pVal);

The following instrument command is assigned to the Amplitude property:

TRAC:DAT? {rcname}

Example: Building instrument commands with nested repeated capabilities

This example demonstrates the use of repeated capability replacement tags when nested repeated capabilities are involved.

Here, the command string includes two repeated capability replacement tags. One tag does not specify a className and, hence, implicitly refers to the class on which the method is defined (as in the previous examples). The other replacement tag refers to the Acme4321Display class, which is a parent repeated capability of the class on which the method is defined. Assume the following method definition:

C++
Copy
HRESULT StoreReferenceTrace();

The following instrument command is assigned to the StoreReferenceTrace method:

CALC:DISP{Acme4321Display.rcindex}:SRTR{rcindex}:REF

Assuming this method was invoked from the second instance of the trace repeated capability on the third instance of the display repeated capability, the following formatted command would be sent to the instrument:

CALC:DISP2:SRTR1:REF

See Also

Other Resources

Using the Instrument Command Editor


Parameter Format Specifications

The parameter format specifications that can be used in method and property commands and responses vary based upon the data type (integer, floating-point, string) as well as upon whether the parameter is an input parameter going to the instrument or an output parameter being read from the instrument. The topics in this section present detailed information on each type of parameter format specification.

In This Section

Formatting Integer Input Parameters

Formatting Integer Output Parameters

Formatting Floating-Point Input Parameters

Formatting Floating-Point Output Parameters

Formatting String Input Parameters

Formatting String Output Parameters

Formatting Enum and Boolean Parameters

Reading and Writing IEEE 488.2 Binary Block Data

Reading and Writing Raw Binary Data


Formatting Integer Input Parameters

Integers used as input parameters to method and property commands can be formatted in a variety of ways. Scalar integer parameters are formatted as ASCII text and sent to the instrument. Integer arrays can be sent to the instrument in the following formats:

  • An ASCII list of values separated by commas or another specified delimiter.

  • An IEEE 488.2 binary block.

  • A stream of raw binary data.

This topic presents the format specifications for sending data to the device as ASCII text. For detailed information on sending array data as IEEE binary blocks, see the topic Reading and Writing IEEE 488.2 Binary Block Data. For information on sending array data as raw binary, see the topic Reading and Writing Raw Binary Data.

Integers used as input parameters have format specifications of the following general form:

%[flags] [488.2 type] [width] [.precision] [delimiter] [d | o | x ]

Modifier

Interpretation

flags

+, -, 0

Controls justification and padding of the output, as follows:

  • - - left aligns the result with the given field width.

  • + - prefixes the output value with a sign (+ or –) if the output value is of a signed type. By default, a sign only appears for negative values.

  • 0 pads with zeros until the specified width is reached. If 0 and - appear together, the 0 is ignored.

488.2 type

The number is formatted in one of six standard IEEE 488.2 numeric formats. The supported formats are:

  • @1 - IEEE 488.2 NR1 format (integer without any decimal point). Example: 123

  • @2 - IEEE 488.2 NR2 format (number with at least one digit after the decimal point). Example: 123.45

  • @3 - IEEE 488.2 NR3 format (floating-point number in exponential form). Example: 1.2345E-67

  • @H - IEEE 488.2 hex format. Example: #HAF35B

  • @Q - IEEE 488.2 octal format. Example: #Q71234

  • @B - IEEE 488.2 binary format. Example: #B011101001

width

Specifies the minimum field width of the converted number. If the converted number is shorter than the field width, it will be padded on the left (or on the right if - is present in the flags field.

If @H, @Q, and @B is specified as the 488.2 type, then the width includes the #H, #Q, and #B strings, respectively.

precision

Minimum number of digits to send.

delimiter

The parameter must be an array of integers. The elements of the integer array are sent to the device with the specified delimiter between each element.

The following delimiters are supported. Note that the enclosing parentheses are not required for comma-separated lists:

  • , or (,) - comma-separated list

  • (;) - semicolon-separated list

  • (:) - colon-separated list

  • (s) - space-separated list

  • (t) - tab-separated list

  • (r) - carriage return-separated list

  • (n) - linefeed-separated list

type

  • d - number is formatted as a decimal integer.

  • o - number is formatted as an octal integer.

  • x - number is formatted as a hex integer.

Examples: Input Integer Parameter

Parameter Tag | Data Sent to Device
{Count:%-8d} | 1234\s\s\s\s Left justify. Pad with spaces.
{Count:%8d} | \s\s\s\s1234 Right justify. Pad with spaces.
{Count:%08d} | 00001234 Right justify. Pad with zeroes.
{CountArray:%,d} | 1,2,3 Comma-separated list.
{CountArray:%(;)d} | 1;2;3 Semi-colon separated list.
{CountArray:%04,d} | 0001,0002,0003 Field width specified applies to each element.
See Also

Other Resources

Parameter Format Specifications


Formatting Integer Output Parameters

Integers used as output parameters from method and property responses can be formatted in a variety of ways. Scalar integer parameters are read from the instrument as ASCII text and converted to numeric values. Integer arrays can be read from the instrument in the following formats:

  • An ASCII list of values separated by commas or another specified delimiter.

  • An IEEE 488.2 binary block.

  • A stream of raw binary data.

This topic presents the format specifications for reading data from the device as ASCII text. For detailed information on reading array data as IEEE binary blocks, see the topic Reading and Writing IEEE 488.2 Binary Block Data. For information on sending array data as raw binary, see the topic Reading and Writing Raw Binary Data.

Integers used as output parameters have format specifications of the following general form:

%[488.2 type] [delimiter] [d | o | x ]

Modifier

Interpretation

488.2 type

The number is expected to be in one of six standard IEEE 488.2 numeric formats. The supported formats are:

  • @1 - IEEE 488.2 NR1 format (integer without any decimal point). Example: 123

  • @2 - IEEE 488.2 NR2 format (number with at least one digit after the decimal point). Example: 123.45

  • @3 - IEEE 488.2 NR3 format (floating-point number in exponential form). Example: 1.2345E-67

  • @H - IEEE 488.2 hex format. Example: #HAF35B

  • @Q - IEEE 488.2 octal format. Example: #Q71234

  • @B - IEEE 488.2 binary format. Example: #B011101001

delimiter

The parameter must be an array of integers. The instrument response is interpreted as a delimited list of integers, where delimiter specifies the delimiter character.

The following delimiters are supported. Note that the enclosing parentheses are not required for comma-separated lists:

  • , or (,) - comma-separated list

  • (;) - semicolon-separated list

  • (:) - colon-separated list

  • (s) - space-separated list

  • (t) - tab-separated list

  • (r) - carriage return-separated list

  • (n) - linefeed-separated list

type

  • d - number is formatted as a decimal integer.

  • o - number is formatted as an octal integer.

  • x - number is formatted as a hex integer.

Examples: Output Integer Parameter

Parameter Tag | Data Expected from Device
{Count:%d} | Data from device: 3.14 Data copied to output parameter: 3
{Count:%@Hd} | Data from device: #H34E8 Data copied to output parameter: 13544 (decimal)
{CountArray:%@B,d} | Data from device: #B101,#B110,#B111 Data copied to output parameter: CountArray[0]: 5 (decimal) CountArray[1]: 6 (decimal) CountArray[2]: 7 (decimal)
See Also

Other Resources

Parameter Format Specifications


Formatting Floating-Point Input Parameters

Floating-point numbers used as input parameters to method and property commands can be formatted in a variety of ways. Scalar floating-point parameters are formatted as ASCII text and sent to the instrument. Floating-point arrays can be sent to the instrument in the following formats:

  • An ASCII list of values separated by commas or another specified delimiter.

  • An IEEE 488.2 binary block.

This topic presents the format specifications for sending data to the device as ASCII text. For detailed information on sending array data as IEEE binary blocks, see the topic Reading and Writing IEEE 488.2 Binary Block Data.

Floating-point numbers used as input parameters have format specifications of the following general form:

%[flags] [488.2 type] [width] [.precision] [delimiter] [f | e | E | g | G]

Modifier

Interpretation

flags

+, -, 0

Controls justification and padding of the output, as follows:

  • - - left aligns the result with the given field width.

  • + - prefixes the output value with a sign (+ or –) if the output value is of a signed type. By default, a sign only appears for negative values.

  • 0 pads with zeros until the specified width is reached. If 0 and - appear together, the 0 is ignored.

488.2 type

The number is formatted in one of six standard IEEE 488.2 numeric formats. The supported formats are:

  • @1 - IEEE 488.2 NR1 format (integer without any decimal point). Example: 123

  • @2 - IEEE 488.2 NR2 format (number with at least one digit after the decimal point). Example: 123.45

  • @3 - IEEE 488.2 NR3 format (floating-point number in exponential form). Example: 1.2345E-67

  • @H - IEEE 488.2 hex format. Example: #HAF35B

  • @Q - IEEE 488.2 octal format. Example: #Q71234

  • @B - IEEE 488.2 binary format. Example: #B011101001

width

Specifies the minimum field width of the converted number. If an argument is shorter than the field width, it will be padded on the left (or on the right if - is present in the flags field.

If @H, @Q, and @B is specified as the 488.2 type, then the width includes the #H, #Q, and #B strings, respectively.

precision

Maximum number of digits after the decimal point for %f, %e, %E.

Maximum number of significant digits for %g, %G.

The default precision is 6.

delimiter

The parameter must be an array of floating-point numbers. The elements of the array are sent to the device with the specified delimiter between each element.

The following delimiters are supported. Note that the enclosing parentheses are not required for comma-separated lists:

  • , or (,) - comma-separated list

  • (;) - semicolon-separated list

  • (:) - colon-separated list

  • (s) - space-separated list

  • (t) - tab-separated list

  • (r) - carriage return-separated list

  • (n) - linefeed-separated list

type

  • f - signed value having the form dddd.dddd

    where dddd is one or more digits.

    The number of digits before the decimal point depends on the magnitude of the number, and the number of digits after the decimal point depends on the requested precision.

    Example: 3.1415

  • e - signed value having the form d.dddde [+ | -]ddd

    where d is a single digit, dddd is one or more digits, ddd is exactly three digits.

    Example: 3.14e-123

  • E - identical to e format except that E rather than e introduces the exponent.

    Example: 3.14E-123

  • g - signed value in f or e format, whichever is more compact for the given value and precision.

    The e format is used only when the exponent of the value is less than –4 or greater than or equal to the precision.

    Trailing zeros are truncated, and the decimal point appears only if one or more digits follow it.

  • G - Identical to the g format, except that E, rather than e, introduces the exponent (where appropriate)..

Examples: Input Floating-Point Parameter

Parameter Tag | Data Sent to Device
{Frequency:%f} | 300.000000 Default precision is 6.
{Frequency:%4.2f} | 300.00 Field width is 4, but required length is greater.
{Frequency:%8.2f} | \s\s300.00 Width requires padding.
{Frequency:%8.2e} | 3.00e+02 Exponential notation.
{FrequencyArray:%4.2,3f} | 1.10,1.20,1.30 Comma-separated list.
{FrequencyArray:%4.2,3E} | 1.10E+00;1.20E+00;1.30E+00;1.40E+00 Semi-colon-separated list of exponential values.
See Also

Other Resources

Parameter Format Specifications


Formatting Floating-Point Output Parameters

Floating-point numbers used as output parameters in method and property responses can be formatted in a variety of ways. Scalar floating-point parameters are read from the instrument as ASCII text and converted to numeric values. Floating-point arrays can be read from the instrument in the following formats:

  • An ASCII list of values separated by commas or another specified delimiter.

  • An IEEE 488.2 binary block.

This topic presents the format specifications for reading data from the device as ASCII text. For detailed information on reading array data as IEEE binary blocks, see the topic Reading and Writing IEEE 488.2 Binary Block Data.

Floating-point numbers used as output parameters have format specifications of the following general form:

%[488.2 type] [.precision] [delimiter] [f | e | E | g | G]

Modifier

Interpretation

488.2 type

The number is expected to be in one of six standard IEEE 488.2 numeric formats. The supported formats are:

  • @1 - IEEE 488.2 NR1 format (integer without any decimal point). Example: 123

  • @2 - IEEE 488.2 NR2 format (number with at least one digit after the decimal point). Example: 123.45

  • @3 - IEEE 488.2 NR3 format (floating-point number in exponential form). Example: 1.2345E-67

  • @H - IEEE 488.2 hex format. Example: #HAF35B

  • @Q - IEEE 488.2 octal format. Example: #Q71234

  • @B - IEEE 488.2 binary format. Example: #B011101001

delimiter

The parameter must be an array of floating-point numbers. The elements of the array are sent to the device with the specified delimiter between each element.

The following delimiters are supported. Note that the enclosing parentheses are not required for comma-separated lists:

  • , or (,) - comma-separated list

  • (;) - semicolon-separated list

  • (:) - colon-separated list

  • (s) - space-separated list

  • (t) - tab-separated list

  • (r) - carriage return-separated list

  • (n) - linefeed-separated list

type

  • f - signed value having the form dddd.dddd

    where dddd is one or more digits.

    The number of digits before the decimal point depends on the magnitude of the number, and the number of digits after the decimal point depends on the requested precision.

    Example: 3.1415

  • e - signed value having the form d.dddde [+ | -]ddd

    where d is a single digit, dddd is one or more digits, ddd is exactly three digits.

    Example: 3.14e-123

  • E - identical to e format except that E rather than e introduces the exponent.

    Example: 3.14E-123

  • g - signed value in f or e format, whichever is more compact for the given value and precision.

    The e format is used only when the exponent of the value is less than –4 or greater than or equal to the precision.

    Trailing zeros are truncated, and the decimal point appears only if one or more digits follow it.

  • G - Identical to the g format, except that E, rather than e, introduces the exponent (where appropriate)..

Examples: Output Floating-Point Parameter

Parameter Tag | Data Expected from Device
{Frequency:%e} | Data from device: 1.53E-12 Data copied to output parameter: 1.5E-12
{FrequencyArray:%,e} | Data from device: 1.23,4.0E-56,0.789 Data copied to output parameter: FrequencyArray[0]: 1.23 FrequencyArray[1]: 4.0E-56 FrequencyArray[2]: 0.789
{FrequencyArray:%@H(:)g} | Data from device: #HA7B:#H12:#H4FDD Data copied to output parameter: FrequencyArray[0]: 2683 FrequencyArray[1]: 18 FrequencyArray[2]: 20445
See Also

Other Resources

Parameter Format Specifications


Formatting String Input Parameters

Strings used as input parameters to method and property commands can be formatted in a variety of ways. This topic explains the formatting options available for scalar parameters as well for string arrays.

Strings used as input parameters have format specifications of the following general form:

%[flags] [width] [.precision] [delimiter] [q | Q] s

Modifier

Interpretation

flags

-, 0

Controls justification and padding of the output, as follows:

  • - - left aligns the result with the given field width.

  • 0 - pads with zeros until the width is reached. If 0 and - appear together, the 0 is ignored.

width

Minimum field width of the output string.

precision

Maximum number of characters to send.

delimiter

The parameter must be an array of strings. The elements of the string array are sent to the device with the specified delimiter between each element.

The following delimiters are supported. Note that the enclosing parentheses are not required for comma-separated lists:

  • , or (,) - comma-separated list

  • (;) - semicolon-separated list

  • (:) - colon-separated list

  • (s) - space-separated list

  • (t) - tab-separated list

  • (r) - carriage return-separated list

  • (n) - linefeed-separated list

q

The string is formatted with enclosing single quotes (').

Q

The string is formatted with enclosing double quotes (").

Examples: Input String Parameter

Parameter Tag | Data Sent to Device
{Name:%15s} | \s\s\s\sHello World Minimum width is 15. Pad to the left.
{Name:%-15s} | Hello World\s\s\s\s Left justify. Pad to the right.
{Name:%.5s} | Hello Precision specifies maximum length.
{Name:%qs} | 'Hello World' Enclose in single quotes.
{Name:%15qs} | \s\s\s\s'Hello World' Padding is applied outside of the quotes.
{Name:%-15Qs} | "Hello World\s\s\s\s" Left justify. Enclose in double quotes.
{NamesArray:%,5qs} | '\s\sone','\s\stwo','three','\sfour' Field width and quotes applied to each element.
{NamesArray:%(:)Qs} | "one":"two":"three":"four" Colon-separated list. Each element enclosed in double quotes.
See Also

Other Resources

Parameter Format Specifications


Formatting String Output Parameters

Strings used as output parameters from method and property responses can be formatted in a variety of ways. This topic explains the formatting options available for scalar parameters as well for string arrays.

Strings used as output parameters have format specifications of the following general form:

%[width] [delimiter] [q | Q] s

Modifier

Interpretation

width

Maximum number of characters to read.

delimiter

The parameter must be an array of strings. The instrument response is interpreted as a delimited list of strings, where delimiter specifies the delimiter character.

The following delimiters are supported. Note that the enclosing parentheses are not required for comma-separated lists:

  • , or (,) - comma-separated list

  • (;) - semicolon-separated list

  • (:) - colon-separated list

  • (s) - space-separated list

  • (t) - tab-separated list

  • (r) - carriage return-separated list

  • (n) - linefeed-separated list

q

The string is expected to be read with surrounding single-quotes (') or double-quotes ("). Whitespace and delimiter characters enclosed in quotes are preserved.

Q

Same as q modifier except that the surrounding quotes are stripped before copying to the output parameter.

Example: Output String Parameter

Parameter Tag | Data Expected from Device
{Name:%s} | Data from device: Hello World Data copied to output parameter: Hello World
{Name:%qs} | Data from device: 'Hello World' Data copied to output parameter: 'Hello World'
{Name:%Qs} | Data from device: "Hello World" Data copied to output parameter: Hello World
{NamesArray:%,Qs} | Data from device: "one",'two',"three",'four' Data copied to output parameter: NamesArray[0]: one NamesArray[1]: two NamesArray[2]: three NamesArray[3]: four
See Also

Other Resources

Parameter Format Specifications


Formatting Enum and Boolean Parameters

Parameter tags that reference boolean or enum parameters to and from string values using the mappings configured in the Instrument Command Editor. Thus, the valid format specifications for boolean and enum parameter tags are the same as those for string parameters.

For details on formatting enum and boolean input parameters, see the topic Formatting String Input Parameters

For details on formatting enum and boolean output parameters, see the topic Formatting String Output Parameters

See Also

Other Resources

Parameter Format Specifications


Reading and Writing IEEE 488.2 Binary Block Data

Numeric arrays (integer and floating-point) can be sent to the device as standard IEEE 488.2 binary blocks. Correspondingly, binary block data can be read from the device and stored in a numeric array output parameter. With the exception of indefinite blocks not being supported for output parameters (reading from the instrument), the format specification presented in this topic is the same for input and output numeric arrays.

Numeric arrays used as input parameters require a format specification of the following general form to read or write IEEE 488.2 binary block data.

%[b | B]

Modifier | Interpretation
b | Data is sent (or read) as an IEEE 488.2 definite-length binary block.
B | Data is sent as an IEEE 488.2 indefinite-length binary block. Not valid when reading data (output parameters).

Examples: Numeric Array as IEEE 488.2 Binary Block

Parameter Tag | Interpretation
{AmplitudeArray:%b} | Data is sent (or read) as a definite-length binary block.
{AmplitudeArray:%B} | Data is sent as an indefinite-length binary block in IEEE 754 format. A terminating linefeed character (\n) is sent after the last byte of the block. Not valid for read operations.
See Also

Other Resources

Parameter Format Specifications


Reading and Writing Raw Binary Data

Integer arrays can be sent to the device as stream of raw binary data. Correspondingly, raw binary data can be read from the device and stored in an integer array output parameter. The format specification presented in this topic is the same for input and output integer arrays.

Note Note

Only integer array data can be read or written as raw binary. Floating-point array parameters cannot be read or written directly as raw binary data. However, floating-point array parameters can be read or written as IEEE 488.2 binary blocks. For more information, see the topic Reading and Writing IEEE 488.2 Binary Block Data.

Integer arrays used as input parameters require a format specification of the following general form to read or write raw binary data.

%[!ob | !ol] y

Modifier | Interpretation
!ob | Data is sent in big endian format. This is the default behavior if neither !ob nor !ol is present. Byte-swapping is automatically performed on all elements in the array argument.
!ol | Data is sent in little endian format.

Examples: Integer Array as Raw Binary

Parameter Tag | Interpretation
{AmplitudeArray:%y} | Data is sent as raw binary in big endian format.
{AmplitudeArray:%!oly} | Data is sent as raw binary in little endian format.
See Also

Other Resources

Parameter Format Specifications


Using the Instrument Command Editor

The Instrument Command Editor provides a convenient way to specify instrument commands and responses that utilize parameters in the command or response. The Parameters listbox lists the method or property parameters that can be used in the command or response. Use the Insert button to a insert parameter tag for the selected parameter into the command or response. You can also type directly into the Command or Response to add parameter tags.

Once a parameter tag is added to the command or response, the formatting options for the parameter appear in the editor. The formatting options that appear vary based upon the selected parameter type. As the formatting options are changed, the associated parameter tag is updated in the command or response. The syntax used to automatically compose the format specification in the parameter tags can also be entered directly, if desired. This syntax is fully documented for each parameter type in the topic Parameter Format Specifications.

Formatting Enum and Boolean Parameters

The Instrument Command Editor is the only means to associate enum members with command or response strings. When an enum parameter is selected in the Parameters listbox, a grid appears with two columns -- one listing each enum member and another available for entering device commands (or responses) to associate with the enum members. For an enum input parameter used in a method or property command, only a single string can be entered for each enum member. For an enum output parameter used in a method or property response, multiple comma-separated strings can be entered for each enum member. The list of values represent all of the possible device reponses that should be mapped to the same enum member.

Tip Tip

It is not necessary to enter the same string for both the command and response for a particular enum value. The command associated with an enum value is automatically included as a possible response. You only need enter response strings if the device might send one of several possible string responses.

String-to-value mappings for boolean parameters are configured in the same fashion as enum parameters. For boolean parameters, only the values VARIANT_TRUE and VARIANT_FALSE are available.

See Also

Other Resources

Instrument Command Syntax
Special Features For SCPI Commands


Special Features For SCPI Commands

Many instruments today follow the SCPI (Standard Commands for Programmable Instruments) standard supported command set. Nimbus offers special convenience features for SCPI-based instruments. By checking the SCPI compliant check box on the I/O Page of the Driver Settings Editor, you are telling Nimbus that the instrument commands associated with methods and properties are SCPI compliant.

When a driver project is SCPI-compliant, Nimbus automatically strips the optional characters from the SCPI command string. This allows the developer to enter the full verbose form of the SCPI command in the Method General Editor and have the full text appear in the help page for the method. However, the Nimbus-generated code that sends the command to the instrument will use the minimal form of the command.

Consider the SCPI command below:

[SENSe:]FREQuency[:VOLTage]:RANGe[:UPPer]

If this command is associated with a method or property via the Method General Editor, the command that will ultimately be sent to the instrument as follows:

FREQ:RANG

Note that all of the optional characters enclosed in square brackets have been removed, as have all of the lowercase characters.

Tip Tip

It is best to always enter the full SCPI command when associating instrument commands with methods and properties so that the full text shows up in the driver help file. Nimbus automatically adds the instrument commands to the driver help file index and builds a special page that maps instrument commands to driver methods and properties. Most users will expect to see the full form of the SCPI command in such contexts.

See Also

Other Resources

I/O Page, IVI-COM Driver Settings


Implementing Methods and Properties

The topics in this section explain the basics of IVI-COM driver method implementation. Some of the fundamental COM data types, such as the BSTR data type for strings and the SAFEARRAY data type for arrays, are explained. The Nimbus error reporting features are also explained in detail.

In This Section

Useful Data Types

Communicating With Instruments

Calling Driver Methods and Properties

Returning Errors from IVI-COM Drivers

Retrieving the Intrument Model

Retrieving Initialization Options

See Also

Other Resources

Working With Instrument Commands
Implementing IVI-C-Only Functions and Attributes
Implementing Dynamic Repeated Capabilities
Implementing Class-Compliant Interfaces
Implementing Simulation


Useful Data Types

The topics in this section present some of the most common data types used in implementing IVI-COM driver methods and properties. Each data type is presented with example code to demonstrate proper usage.

In This Section

BSTR Basics

SAFEARRAY Basics

CString Basics

CComBSTR Basics

_bstr_t Basics

CComSafeArray Basics

String Converter Classes


BSTR Basics

This topic describes common usage of the BSTR data type. It is generally easier to use smart data types rather than using BSTR directly. For more information on the smart data types, see _bstr_t Basics, CComBSTR Basics, and CString Basics.

Allocating a BSTR

When implementing a method that should return a BSTR, either as [out, retval], [in, out] or [out], the BSTR should be allocated by the driver and freed by the client application.

C++
Copy
HRESULT Acme4321::IAcme4321Display_get_Text(BSTR* val)
{
  HRESULT hr = S_OK;

  // Allocate a BSTR with a fixed string
  *val = ::SysAllocString(OLESTR("Hello world."));
  if (*val == NULL)
  {
    hr = ReportError(IDS_E_IVI_OUT_OF_MEMORY);
  }

  return hr;
}
Freeing a BSTR

When a client calls a driver that returns a BSTR, the client must free the BSTR that is allocated by the driver.

C++
Copy
// MyClient.cpp
void main()
{
  // Initialize COM, create instance of object...

  BSTR bstrText;
  hr = pDriver->get_Text(&bstrText);
  if (SUCCEEDED(hr))
  {
    // Do something with the string that is received...

    // Free the string
    ::SysFreeString(bstrText);
  }

  // Release instance of object, terminate COM...
}

When implementing a method that should return a BSTR, as [in, out], the BSTR should be freed by the server before allocating a new one. The new BSTR is then freed by the client.

C++
Copy
HRESULT Acme4321::IAcme4321Display_ReadWriteText(BSTR* val)
{
  HRESULT hr = S_OK;

  // Do something with the string that is passed in

  // ...

  // Free the string that is passed in
  ::SysFreeString(*val);

  // Allocate a BSTR with a fixed string
  *val = ::SysAllocString(OLESTR("Hello world."));
  if (*val == NULL)
  {
    hr = ReportError(IDS_E_IVI_OUT_OF_MEMORY);
  }

  return hr;
}
See Also

Other Resources

BSTR Data Type


SAFEARRAY Basics

This topic describes common usage of the SAFEARRAY data type. It is generally easier to use CComSafeArray rather than using SAFEARRAY directly. For more information on the CComSafeArray, see CComSafeArray Basics.

Returning a SAFEARRAY

When implementing a method that should return a SAFEARRAY, either as [out, retval], [in, out] or [out], the SAFEARRAY should be allocated by the driver and freed by the client application.

C++
Copy
HRESULT Acme4321::Acme4321Table_GetData(SAFEARRAY** val)
{
  HRESULT hr = S_OK;

  // Allocate a SAFEARRAY of double with 3 elements
  SAFEARRAY* psaData = ::SafeArrayCreateVector(VT_R8, 0, 3);
  if (psaData != NULL)
  {
    // Set the value of the 3 elements to 0.0
    for (long lIndex = 0; lIndex < 3; lIndex++)
    {
      double dVal = 0.0;
      hr = ::SafeArrayPutElement(psaData, &lIndex, (void*)&dVal);
      if (FAILED(hr))
        break;
    }

    if (SUCCEEDED(hr))
    {
      *val = psaData;
    }
    else
    {
      ::SafeArrayDestroy(psaData);
    }
  }
  else
  {
    hr = ReportError(IDS_E_IVI_OUT_OF_MEMORY);
  }

  return hr;
}
Receiving a SAFEARRAY

When a client application calls a driver that returns a SAFEARRAY, the client must free the SAFEARRAY that is allocated by the driver.

C++
Copy
// MyClient.cpp
void main()
{
  // Initialize COM, create instance of object...

  SAFEARRAY* psaData = NULL;
  hr = pDriver->GetData(&psaData);
  if (SUCCEEDED(hr))
  {
    // Determine the size of the array
    long lLowerBound;
    hr = ::SafeArrayGetLBound(psaData, 1, &lLowerBound);
    if (SUCCEEDED(hr))
    {
      long lUpperBound;
      hr = ::SafeArrayGetUBound(psaData, 1, &lUpperBound);
      if (SUCCEEDED(hr))
      {
        for (long lIndex = lLowerBound; lIndex <= lUpperBound; lIndex++)
        {
          double dVal;
          hr = ::SafeArrayGetElement(psaData, &lIndex, &dVal);
          if (SUCCEEDED(hr))
          {
            // Do something with dVal...
          }
        }
      }
    }

    // Free the array
    ::SafeArrayDestroy(psaData);
  }

  // Release instance of object, terminate COM...
}
See Also

Other Resources

SAFEARRAY Data Type


CString Basics

This section describes common usage of the CString smart data type.

Returning a BSTR

When implementing a method that should return a BSTR, either as [out, retval], [in, out] or [out], the BSTR should be allocated by the driver and freed by the client.

C++
Copy
HRESULT Acme4321::IAcme4321Display_get_Text(BSTR* val)
{
  HRESULT hr = S_OK;

  CString strText(_T("Hello world."));

  // Allocate a BSTR
  *val = strText.AllocSysString();

  return hr;
}

More information is available in the MSDN documentation for CString.

See Also

Other Resources

CString Class


CComBSTR Basics

This section describes common usage of the CComBSTR smart data type.

Returning a BSTR

When implementing a method that should return a BSTR, either as [out, retval], [in, out] or [out], the BSTR should be allocated by the driver and freed by the client.

C++
Copy
HRESULT Acme4321::IAcme4321Display_get_Text(BSTR* val)
{
  HRESULT hr = S_OK;

  CComBSTR bstrText(_T("Hello world."));

  // Assign the internal BSTR while transfering ownership
  *val = bstrText.Detach();

  return hr;
}

Although using Detach is preferred (it doesn't allocate a new BSTR unnecessarily), it is sometimes more appropriate to use CopyTo, as in the following example. Since the string we want to return is kept in a member variable, we do not want the internal BSTR ownership transferred to the caller.

C++
Copy
class Acme4321
{
...
  CComBSTR m_bstrText;
};

HRESULT Acme4321::IAcme4321Display_get_Text(BSTR* val)
{
  HRESULT hr = S_OK;

  // Copy the string
  hr = m_bstrText.CopyTo(val);

  return hr;
}

Receiving
Receiving a BSTR

When a client application calls a driver that returns a BSTR, the client must free the BSTR that is allocated by the driver.

C++
Copy
void main()
{
  // Initialize COM, create instance of object...

  CComBSTR bstrText;
  hr = pDriver->get_Text(&bstrText);
  if (SUCCEEDED(hr))
  {
    // Do something with the string that is received...
  }

  // String will be freed by the destructor

  // Release instance of object, terminate COM...
}

More information is available in the MSDN documentation for CComBSTR.

See Also

Other Resources

CComBSTR Class


_bstr_t Basics

This topic describes common usage of the _bstr_t smart data type.

Returning a BSTR

When implementing a method that should return a BSTR, either as [out, retval], [in, out] or [out], the BSTR should be allocated by the driver and freed by the client application.

C++
Copy
HRESULT Acme4321::IAcme4321Display_get_Text(BSTR* val)
{
  HRESULT hr = S_OK;

  _bstr_t bstrText(_T("Hello world."));

  // Assign the internal BSTR while transfering ownership
  *val = bstrText.Detach();

  return hr;
}

Although using Detach is preferred (it doesn't allocate a new BSTR unnecessarily), it is sometimes more appropriate to use copy, as in the following example. Since the string we want to return is kept in a member variable, we do not want the internal BSTR ownership transferred to the caller.

C++
Copy
class Acme4321
{
...
  _bstr_t m_bstrText;
};

HRESULT Acme4321::IAcme4321Display_get_Text(BSTR* val)
{
  HRESULT hr = S_OK;

  // Copy the string
  *val = m_bstrText.copy();

  return hr;
}
Receiving a BSTR

When a client calls a driver that returns a BSTR, the client must free the BSTR that is allocated by the driver.

C++
Copy
void main()
{
  // Initialize COM, create instance of object...

  _bstr_t bstrText;
  hr = pDriver->get_Text(bstrText.GetAddress());
  if (SUCCEEDED(hr))
  {
    // Do something with the string that is received...
  }

  // String will be freed by the destructor

  // Release instance of object, terminate COM...
}

When using #import with wrapper interfaces and smart data types, it is even easier to use properties or methods that return a BSTR, as the signatures in the wrapper interfaces are changed to use _bstr_t instead of BSTR.

C++
Copy
void main()
{
  // Initialize COM, create instance of object...

  // _com_error exception will be thrown if this fails
  _bstr_t bstrText = pDriver->Text;

  // Do something with the string that is received...

  // String will be freed by the destructor

  // Release instance of object, terminate COM...
}

More information is available in the MSDN documentation for _bstr_t.

See Also

Other Resources

_bstr_t Class


CComSafeArray Basics

This topic describes common usage of the CComSafeArray smart data type.

Creating and Returning a SAFEARRAY

When implementing a method that should return a SAFEARRAY, either as [out, retval], [in, out] or [out], the SAFEARRAY should be allocated by the driver and freed by the client. When you know in advance the size of the array that you are creating, it is better to call Create so that the memory is allocated up front and no reallocation is necessary.

C++
Copy
HRESULT Acme4321::IAcme1234Table_GetData(SAFEARRAY** val)
{
  HRESULT hr = S_OK;

  CComSafeArray<double> csaData;

  // Create array with 3 elements
  csaData.Create(3);

  // Set the values of the 3 elements
  csaData[0] = 0.0;
  csaData[1] = 1.0;
  csaData[2] = 2.0;

  // Assign the SAFEARRAY* while transfering ownership
  *val = csaData.Detach();

  return hr;
}

When you do NOT know in advance the size of the array that you are creating, the CComSafeArray can dynamically resize itself as you append items to it.

C++
Copy
HRESULT Acme4321::IAcme1234Table_GetData(SAFEARRAY** val)
{
  HRESULT hr = S_OK;

  CComSafeArray<double> csaData;

  // Create array with no elements
  csaData.Create();

  // Add elements
  csaData.Add(0.0);
  csaData.Add(1.0);
  csaData.Add(2.0);

  // Assign the SAFEARRAY* while transfering ownership
  *val = csaData.Detach();

  return hr;
}

When you want to return an array with no elements, you have to call Create otherwise the internal SAFEARRAY* will be NULL.

C++
Copy
HRESULT Acme4321::IAcme1234Table_GetData(SAFEARRAY** val)
{
  HRESULT hr = S_OK;

  CComSafeArray<double> csaData;

  // Create array with no elements
  csaData.Create();

  // Assign the SAFEARRAY* while transfering ownership
  *val = csaData.Detach();

  return hr;
}

Although using Detach is preferred (it doesn't allocate a new SAFEARRAY unnecessarily), it is sometimes more appropriate to use CopyTo, as in the following example. Since the SAFEARRAY we want to return is kept in a member variable, we do not want the internal SAFEARRAY* ownership transferred to the caller.

C++
Copy
class Acme1234
{
...
  CComSafeArray<double> m_csaData;
};

HRESULT Acme1234::IAcme1234Table_GetData(BSTR* val)
{
  HRESULT hr = S_OK;

  // Copy the array, this assumes the array was initialized previously
  hr = m_csaData.CopyTo(val);

  return hr;
}
Receiving a SAFEARRAY

When a driver calls a server that returns a SAFEARRAY, the client must free the SAFEARRAY that is allocated by the driver.

C++
Copy
void main()
{
  // Initialize COM, create instance of object...

  SAFEARRAY* psaData;
  hr = pDriver->GetData(&psaData);
  if (SUCCEEDED(hr))
  {
    CComSafeArray<double> csaData;
    csaData.Attach(psaData);

    // Process the data
    for (long i = 0; i < (long)csaData.GetLength(); i++)
    {
      double val = csaData[i];
      // Do something with val...
    }

    // Array will be freed by the destructor
  }

  // Release instance of object, terminate COM...
}

When receiving a SAFEARRAY as a parameter, it is important to use the SAFEARRAY data type and then to wrap it with a CComSafeArray. You should not attempt to pass a pointer to the CComSafeArray's internal SAFEARRAY*. The following example describes the problem. The example will compile, but will fail with an assertion at run-time.

C++
Copy
// WARNING: DO NOT DO THIS!
// This will assert at run-time, you are not allowed to change the internal
// SAFEARRAY behind CComSafeArray's back.
CComSafeArray<double> csaData;
hr = pDriver->GetData(csaData.GetSafeArrayPtr());
if (SUCCEEDED(hr))
{
  // Process the data...
}

When receiving a SAFEARRAY* as a return value (this assumes using #import with wrapper interfaces), you have to be careful to not leak the SAFEARRAY when wrapping it with a CComSafeArray. CComSafeArray's constructor and assignment operator will make a COPY of the SAFEARRAY. The following example describes the problem. The SAFEARRAY will returned by the driver will leak, because owned by the CComSafeArray is a copy of that SAFEARRAY.

C++
Copy
// WARNING: DO NOT DO THIS!
// This will leak, the SAFEARRAY* returned by GetData is copied
// into the CComSafeArray, so the one returned by GetData will never
// be destroyed.
CComSafeArray<double> csaData = pDriver->GetData();

// Process the data...

The correct way to receive a SAFEARRAY* as a return value is to use Attach so that no copy of the SAFEARRAY is made.

C++
Copy
// This is the correct way to call a method that returns a SAFEARRAY* as a return value
SAFEARRAY* psaData = pDriver->GetData();
if (psaData != NULL)
{
  CComSafeArray<double> csaData;
  csaData.Attach(psaData);

  // Process the data...

  // Array will be freed by the destructor
}
Passing a SAFEARRAY as Input

When a client calls a driver that accepts a SAFEARRAY, the client must allocate and free the SAFEARRAY.

C++
Copy
void main()
{
  // Initialize COM, create instance of object...

  CComSafeArray<double> csaData;
  csaData.Create(3);
  csaData[0] = 0.0;
  csaData[1] = 1.0;
  csaData[2] = 2.0;

  // Even though it's an input parameter, the data type is SAFEARRAY**
  // which is why we use GetSafeArrayPtr() to get a pointer to the internal
  // SAFEARRAY*.
  hr = pDriver->SetData(csaData.GetSafeArrayPtr());
  if (SUCCEEDED(hr))
  {
  }

  // Array will be freed by the destructor

  // Release instance of object, terminate COM...
}

More information is available in the MSDN documentation for CComSafeArray.

See Also

Other Resources

CComSafeArray Class


String Converter Classes

This sections describes common usage of the string converter classes.

Converting from a BSTR

The converter class COLE2T can be used to convert from a BSTR to an LPCTSTR.

C++
Copy
void PrintMessage(LPCTSTR pszText)
{
  // Do something with the LPCTSTR
}

HRESULT Acme4321::IAcme4321Display_put_Text(BSTR val)
{
  HRESULT hr = S_OK;

  // Use COLE2T to pass in a LPCTSTR
  PrintMessage(COLE2T(val));

  return hr;
}

Do not attempt to use a LPCTSTR obtained from a COLE2T after the COLE2T goes out of scope as the memory will be deleted. For this reason, COLE2T is typically used to pass a BSTR to a function that accepts an LPCTSTR or to initialize a string data type that will make a copy of the LPCTSTR immediately.

C++
Copy
HRESULT Acme4321::IAcme4321Display_put_Text(BSTR val)
{
  HRESULT hr = S_OK;

  // CString will make a copy of the LPCTSTR, this is ok.
  CString strText = COLE2T(val);

  return hr;
}

It is important to cast the COLE2T object to LPCTSTR when calling a function with variable arguments, if the variable argument is expected to be of type LPCTSTR. The most common example is CString::Format when the argument type is specified as %s.

C++
Copy
HRESULT Acme4321::IAcme4321Display_put_Text(BSTR val)
{
  HRESULT hr = S_OK;

  // IMPORTANT: Must cast the COLE2T object to LPCTSTR in this case!
  CString strText;
  strText.Format(_T("\"%s\""), LPCTSTR(COLE2T(val)));

  return hr;
}


Communicating With Instruments

The Nimbus Template Library includes a wide variety of functions used to communicate with an instrument. These functions greatly simplify I/O programming by wrapping lower-level calls to the underlying I/O library. The low-level I/O library that is actually used depends upon the I/O selection made in the I/O Page of the Driver Settings Editor. In most cases, the underlying I/O library will either be standard C-based VISA (visa32.dll) or VISA-COM. However, Nimbus can support any arbitrary mechanism for I/O communication.

The topics in this section explain the various options for communicating with an instrument using Nimbus.

In This Section

Automatic Command Formatting

Using the I/O Object

Understanding Buffered I/O

Setting the Trailing Character for Read and Write Operations

See Also

Other Resources

Instrument Command Syntax
Using the Instrument Command Editor


Automatic Command Formatting

By far, the simplest way to deal with instrument communication when implementing methods and properties is to rely upon the built-in command formatting features provided by Nimbus. Nimbus generates all of the required method implementation coe when using automatic command formatting.

Using Automatic Command Formatting

To use automatic command formatting, you must first associate an instrument command with the method or property by choosing the Instrument Command implementation type in the Method General Editor. Nimbus will generate code in the ForwardingShims.nimbus.cpp file to format the command and store it an internally managed command buffer. Within the method implementation, Nimbus will generate a call to a function such as InstrPrintCommand or InstrQueryResponse. These functions send the command stored in the command buffer to the instrument and possibly retrieve results from the instrument. This makes the actual implementation code appearing in the implementation file very simple. The code below is an example of the complete implementation of a method that uses automatic command formatting.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_Configure()
{
    HRESULT hr = S_OK;

    // Send command that is formatted by the auto-geneated code in the ForwardingShims.nimbus.cpp file.
    hr = InstrPrintCommand();

    return hr;
}


Using the I/O Object

All of the built-in instrument communication features of Nimbus are built on top of an I/O object. The I/O object supplies a wide variety of functions for reading and writing data to and from an instrument. The I/O object is an instance of a special class known as an I/O provider. Nimbus ships with two pre-built I/O providers -- the VISA-COM I/O provider and the VISA-C I/O provider.

For detailed information on the functions available on the I/O object, see the Nimbus Template Library topics on the I/O object.

Accessing the I/O Object

When the driver's Initialize function is called, Nimbus automatically creates the I/O object and associates it with the instrument session. The type of I/O object created depends upon the selection made in the I/O Page of the Driver Settings Editor. Often, the I/O object created will be an instance of CVisaComSession (the VISA-COM I/O provider) or an instance of CVisaCSession (the VISA-C I/O provider). In either case, the I/O object functions are accessed within a driver function by simply using the io property, as shown below.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_Configure()
{
    HRESULT hr = S_OK;

    hr = io.Printf(_T("SENS:OUTP:ENAB ON"));

    return hr;
}

When the user types "io" and then a ".", IntelliSense presents a list of all of the functions available for the type of I/O provider in use. The functions available for the VISA-COM and VISA-C I/O providers will be very similar, while those available for a custom I/O provider would include any specialized functions specific to that provider.

Best Practices for Using the I/O Object

One of the key advantages of using the I/O object is that the driver implementation code can be largely independent of the underyling I/O library in use -- be it VISA-COM, VISA-C, or a custom I/O library. The Nimbus Template Library provides a uniform set of functions for instrument I/O that can operate on top of any arbitrary I/O library. By using these common I/O functions instead of provider-specific functions or direct calls into a custom library, the driver code can remain unchanged when a new I/O library is introduced or other I/O requirements change.

The Nimbus Template Library documentation for the I/O object is divided into sections that are general to all I/O providers and those that are specific to the VISA-COM or VISA-C I/O providers. All of the functions in the Nimbus Template Library topic I/O Object and its subtopics, can be used with any I/O provider, with the exception of those in the topic VISA-Specific Functions.

See Also

Other Resources

The I/O Object


Understanding Buffered I/O

Most of the I/O functions exposed via the I/O object send data to or read data from an in-memory buffer managed by Nimbus. Rather than sending data directly to the device, write operations format the data and send it to an internal buffer where data accumulates until it is ready to be sent. A similar operation takes place with read functions -- data is read from the device in "chunks" and stored in a read buffer from which the various Nimbus Template Library read functions obtain their data. Buffering data in this way can improve overall performance by minimizing the total number of I/O roundtrips between the control computer and the instrument.

Buffered I/O Write Operations

With the exception of the four low-level write operations, data sent to the device using any of the I/O object functions first passes into the I/O write buffer. The four low-level write operations that send data directly to the device without passing through the write buffer are:

  • LowLevelWrite

  • LowLevelWriteNoPoll

  • LowLevelWriteString

  • LowLevelWriteStringNoPoll

Functions such as Printf format the data and then copy it into the write buffer. Data accumulates in the write buffer for all successive write operations. The data in the write buffer is sent to the device when the write buffer is flushed. The write buffer will be flushed in the following circumstances:

  • When an explicit call to FlushWrite is made.

  • When the bFlush parameter of a write function is set to true.

  • When the write buffer is full.

The size of the write buffer can be controlled via the SetBufferSize function. The default size of the write buffer is 4096 bytes.

Buffered I/O Read Operations

With the exception of the four low-level read operations, data read from the device using any of the I/O object functions first passes into the I/O read buffer. The four low-level read operations that read data directly from the device without passing through the read buffer are:

  • LowLevelRead

  • LowLevelReadNoPoll

  • LowLevelReadString

  • LowLevelReadStringNoPoll

Functions such as Scanf read data from the device in "chunks" of data (4096 bytes, by default) and store the data in the read buffer. Data is only read from the device when the read buffer is empty and a call to a read function requires more data.

Often, a device will send more data in response to a query than is needed. For example, only the first 100 bytes of a lengthy device response block might be needed for processing in the driver. In such cases, the read buffer can be flushed -- either by an explicit call to the FlushRead function or by setting the bFlush parameter of a read function to true. It is important to note that flushing the read buffer also involves reading any pending data from the device itself. This ensures that both the read buffer and the instrument's internal buffer are empty and free of spurious data for the next read operation.

The size of the read buffer can be controlled via the SetBufferSize function. The default size of the read buffer is 4096 bytes.

See Also

Other Resources

Printf-Style Functions
Basic I/O Functions


Setting the Trailing Character for Read and Write Operations

Many instruments require special termination characters when reading and writing data. For instance, a line-feed character is often used by instruments to detect the end of a particular command sequence. Correspondingly, instruments often return data that includes extra termination characters in the response string. Manually inserting these termination characters when data is written to an instrument is tedious and error-prone, as is manually stripping these termination characters from response data read from the instrument.

To simplify driver I/O programming in the face of instruments that use termination characters, Nimbus provides two special functions: SetTrailingForReads and SetTrailingForWrites. Calls to I/O write functions, such as WriteString, will have the trailing characters appended to the string specified in the write call. Similarly, the string specified in a call to SetTrailingForReads function will automatically be stripped from the instrument response when using I/O read functions, such as ReadString.

See Also

Other Resources

Communicating With Instruments


Calling Driver Methods and Properties

It is common to invoke driver methods and properties within the implementation of other methods and properties. For example, high-level configuration functions, such as the IIviRFSigGenFM::Configure defined in the IviRFSigGen class specification, often rely upon lower-level driver properties for their implementation. When such properties are called from another driver method, it is very important that the properties are called using the syntax described below.

Important note Important

If driver methods and properties are invoked from within the driver in any fashion other than that described in this topic, a wide variety of unpredictable results may be observed. These errors will not be detectable at compile time.

The format for properly invoking a driver method or property from another driver method or property is as follows (note the leading underscore is required):

_<interface>::<method>

or, for a property put operation

_<interface>::<put_property>

or, for a property get operation

_<interface>::<get_property>

The reason it is so important to invoke methods and properties in this way is that the above syntax ensures the method call goes through the Nimbus generated pre-processing and post-processing code in the ForwardingShims.nimbus.cpp file. The code in this file provides a wide variety of important services, such as parameter validation, thread safety, range checking, state caching, and more. Directly calling a driver method or property in any other fashion completely bypasses all of this important logic.

The code sample below demonstrates the proper way to invoke driver methods from within the driver implementation.

C++
Copy
HRESULT Acme4321::IIviRFSigGenFM_Configure(BSTR Source, double Deviation)
{
   HRESULT hr = S_OK;

   hr = _IIviRFSigGenFM::put_Source(Source);
   if (SUCCEEDED(hr))
   {
      hr = _IIviRFSigGenFM::put_Deviation(Deviation);
   }

   return hr;
}

The code sample belows shows some INCORRECT ways to invoke driver methods from within the driver implementation.

C++
Copy
HRESULT Acme4321::IIviRFSigGenFM_Configure(BSTR Source, double Deviation)
{
   HRESULT hr = S_OK;

   /// WRONG!! WRONG!!! WRONG!!!
   /// This will compile, but may not behave as expected.
   hr = put_Source(Source);

   if (SUCCEEDED(hr))
   {
      /// WRONG!! WRONG!!! WRONG!!!
      /// This will also compile, but may not behave as expected.
      hr = Acme4321::put_Deviation(Deviation);
   }

   return hr;
}


Returning Errors from IVI-COM Drivers

The IVI specifications place special requirements on IVI-COM drivers with respect to error reporting. IVI defines a number of standard errors that drivers should use for common situations. These standard errors include COM HRESULT error code values as well as formatted error messages that need to be exposed via the COM error object.

Error Reporting Basics

Consider a situation where a method in an IVI-COM driver receives a bad input parameter value. The IVI specifications say that the driver is supposed to return the IVI-defined error HRESULTE_IVI_INVALID_VALUE. In addition, the driver method is supposed to compose an error message of the following form:

Invalid value (%1) for method %2, parameter %3.

The %1, %2, and %3 replacement tags are supposed to be filled in with the invalid value itself (for %1), the name of the method that generated the error (for %2) and the name of the parameter (for %3). A properly formatted error message might look something like the following:

Invalid value (-2) for method ConfigureRamp, parameter Time.

In addition to returning a valid HRESULT value and a properly formatted error message, IVI-COM drivers are required to populate the COM error object with error code, error message, and other information. This is typically done by first creating a COM error object using the Windows API function CreateErrorInfo. Then, the SetErrorInfo API is used to populate the error object with the desired information. The COM error object is then used by any COM compatible IDE to present the error information to the client program. In C# applications for instance, the .NET runtime interprets the contents of the COM error object and presents it as a .NET exception with the expected exception fields populated.

All of the tedious operations related to message formatting and COM error object management are handled by the Error Reporter object. This object is managed by Nimbus and contains error definitions for IVI-defined errors as well as for custom driver-defined errors. See the discussion of the Error Reporter object in the Nimbus Template Library section for detailed information.

Using the EnumToName Function for Better Error Reporting

Enums are very commonly used as parameters in IVI drivers. When the user passes in an unsupported enum value or when an error related to an enum value is otherwise generated, it is very helpful to the end user to have the name of the enum value reported. Since the driver implementation receives enum values as numeric constants and since the C++ language provides no mechanism for translating between an enum numeric constant and its symbolic name, the driver developer is often left with the choice of returning a poor error message containing only the enum numeric value or writing tedious code to explicitly translate numeric values to symbolic names. The following example code shows the kind of code that would be necessary to include the symbolic name of an enum member in a driver error message:

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::ConfigureTrigger(Acme4321TriggerSourceEnum eSource)
{
  HRESULT hr = S_OK;

  // Only internal and external triggering are supported
  switch (eSource)
  {
    case Acme4321TriggerSourceInternal:
    case Acme4321TriggerSourceExternal:
      hr = InstrPrintCommand();
      break;
    case Acme4321TriggerSourceSoftware:
      hr = err.InvalidValue(_T("eSource"), _T("Acme4321TriggerSourceSoftware"));
      break;
    case Acme4321TriggerSourceTTL0:
      hr = err.InvalidValue(_T("eSource"), _T("Acme4321TriggerSourceTTL0"));
      break;
    case Acme4321TriggerSourceTTL1:
      hr = err.InvalidValue(_T("eSource"), _T("Acme4321TriggerSourceTTL1"));
      break;
    case Acme4321TriggerSourceTTL2:
      hr = err.InvalidValue(_T("eSource"), _T("Acme4321TriggerSourceTTL2"));
      break;
    case Acme4321TriggerSourceTTL3:
      hr = err.InvalidValue(_T("eSource"), _T("Acme4321TriggerSourceTTL3"));
      break;
    case Acme4321TriggerSourceRTSI1:
      hr = err.InvalidValue(_T("eSource"), _T("Acme4321TriggerSourceRTSI1"));
      break;
    case Acme4321TriggerSourceRTSI2:
      hr = err.InvalidValue(_T("eSource"), _T("Acme4321TriggerSourceRTSI2"));
      break;
    case Acme4321TriggerSourceRTSI3:
      hr = err.InvalidValue(_T("eSource"), _T("Acme4321TriggerSourceRTSI3"));
      break;
    case Acme4321TriggerSourceRTSI4:
      hr = err.InvalidValue(_T("eSource"), _T("Acme4321TriggerSourceRTSI4"));
      break;
    case Acme4321TriggerSourceRTSI5:
      hr = err.InvalidValue(_T("eSource"), _T("Acme4321TriggerSourceRTSI5"));
      break;
    case Acme4321TriggerSourceRTSI6:
      hr = err.InvalidValue(_T("eSource"), _T("Acme4321TriggerSourceRTSI6"));
      break;
    // ... more cases for all possible enum values
  };

  return hr;
}

The code above can be greatly simplified by the use of the Nimbus Template Library function EnumToName. This function automatically converts a driver enum value into its symbolic name. The code below demonstrates use of EnumToName.

For more information, see the description of EnumToName in the Nimbus Template Library.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::ConfigureTrigger(Acme4321TriggerSourceEnum eSource)
{
  HRESULT hr = S_OK;

  // Only internal and external triggering are supported
  switch (eSource)
  {
    case Acme4321TriggerSourceInternal:
    case Acme4321TriggerSourceExternal:
      hr = InstrPrintCommand();
      break;
    default:
      CString strEnum;
      EnumToName<Acme4321TriggerSourceEnum>(eSource, strEnum);

      hr = err.InvalidValue(_T("eSource"), strEnum);
      break;
  };

  return hr;
}
See Also

Other Resources

Adding an Error
Adding a Warning
The Error Reporter Object


Using Object Parameters

Some instrument operations produce several related results. Consider, for instance, an operation that performs a CDMA measurement and returns IQ data. Each operation yields four pieces of information:

  • The data type (as a string).

  • The spread factor (as an integer).

  • The code number (as an integer).

  • The channel amplitude (as a floating point number).

Since all of these items are returned from a single operation, the driver needs to expose a single method that returns all of these items. A naive design might simply add a method that returns each result as an [out] parameter. Client programmers working in C#, for instance, would be left to contend with a method signature such as the following:

C++
Copy
void MeasureIQ(out string DataType, out int SpreadFactor, out int CodeNumber, out double Amplitude);

Designing methods with multiple output parameters is generally bad form. Client applications are forced to set up multiple local variables just to retrieve the data (even if they are only interested in one piece of data). In addition, if an instrument happens to return a series of related results, then each of the [out] parameters above would be arrays of results and the client code would be even more cumbersome.

A better design for methods that return multiple results would be to consolidate all of the result items into a single results object and provide that object as the method's return value. In the C programming language, the struct data type would work nicely. In COM, we can model a struct by creating an interface with read-only properties that return each of the result items. For the example above, the interface that we would need would look like the following to a C# client:

C++
Copy
interface IAcme4321IQResults
{
   string DataType { get; }     // NOTE: Each property is read-only
   int Spreadfactor { get; }
   int CodeNumber { get; }
   double Amplitude { get; }
}

With the IAcme4321IQResults interface in hand, we can now define a much more client-friendly MeasureIQ method:

C++
Copy
IAcme4321IQResults MeasureIQ();
Adding an Object Parameter to a Driver Method

Adding an object parameter to a method is considerably more complex than adding simple data type parameters. The process consists of the following steps, described in detail in this topic:

  1. Adding an interface that contains the result items.

  2. Adding a COM coclass to implement the results interface.

  3. Adding a C++ class to implement the COM coclass.

  4. Coding the driver method to return an instance of the COM class.

  5. Updating the driver installer to register the COM class.

Step 1 -- Adding an interface that contains the result items

The first step in adding a method that returns multiple results as a single unit, is to add an interface that contains each of the results. Note that since this interface will be implemented on a non-Nimbus-managed class, it must be added as a "free-standing" interface from the IVI-COM Designer flat tree view (not from the hierarchical tree view).

To add an interface for returning multiple method results

  1. From the IVI-COM Designer, right click on the Interfaces and choose Add Interface.

  2. The interface node enters edit mode. Enter the desired name of the interface.

  3. The interface is added to the driver project.

  4. From the flat tree view of the IVI-COM Designer, add the following four properties of the indicated type:

    • DataType : String

    • Spreadfactor : int

    • CodeNumber : int

    • Amplitude : double

  5. Change each of the above properties to be read-only.

Step 2 -- Adding a COM coclass to implement the results interface

COM interfaces returned from methods must be implemented by a special COM class, known as a coclass. The coclass for our results object must be defined in IDL. Since Nimbus automatically manages the IDL file for driver projects, special steps must be performed to "inject" custom IDL into the driver to support our custom results object.

To add a COM coclass that implements the results interface

  1. Add the following IDL files to your driver project:

    • CustomClasses.idl

    • CustomEnums.idl

    • CustomInterfaceDeclarations.idl

    • CustomInterfaceDefinitions.idl

    Each file can be added to your driver project from Solution Explorer by right-clicking the Source Files folder and choosing Add and then selecting New Item.... The Add New Item Dialog Box appears.

    From the tree view on the left, choose Code and then select Midl File (.idl) from the file types on the left.

    Enter the appropriate file name (CustomClasses, for example) and click Add. An empty IDL file is added to the driver project.

  2. From Solution Explorer, select all four of the above files and choose Properties. The Properties Page Dialog for the files appears.

    From the Configuration combo box, choose All Configurations.

    From the Platform combo box, choose All Platforms.

    From the tree view on the left, choose the General page.

    Set Excluded From Build to Yes.

  3. Copy the following code into CustomClasses.idl.

    C++
    Copy
    [
    uuid(COCLASSG-UIDC-OCLA-SSGU-IDCOCLASSGUI),
    helpstring(""),
    helpcontext(0)
]
coclass Acme4321IQResults
{
    [default] interface IAcme4321IQResults;
};

  4. The uuid attribute in the above code needs to have a unique value. Unique GUIDs can be generated from within Visual Studio by choosing Create GUID from the Tools. Replace the uuid attribute value COCLASSG-UIDC-OCLA-SSGU-IDCOCLASSGUI with a newly generated GUID.

  5. The other three IDL files added previously are generally only needed in advanced scenarios. In most instances, they can remain empty (though they must be present in the project for the driver to compile).

  6. In order to instruct Nimbus to merge the contents of the above IDL files with the Nimbus managed driver IDL file, a special MIDL preprocessor symbol must be defined.

    From Solution Explorer, right-click on the driver project, and choose Properties.

    From the Configuration combo box, choose All Configurations.

    From the Platform combo box, choose All Platforms.

    From the tree view on the left, choose the MIDL page.

    Add CUSTOM_IDL to the list of Preprocessor Definitions.

  7. The COM class that will hold our results needs to be registered with COM. This is done via a registration script (.rgs) file.

    From Solution Explorer, right-click on the Resources Files folder and choose Add New Item.... The Add New Item Dialog Box appears.

  8. From the tree view on the left, choose Resource and then select Registration Script (.rgs) from the file types on the right.

  9. Enter the name CoAcme4321IQResults and click Add. The file CoAcme4321IQResults.rgs is added to the driver project.

  10. Copy the following code into the CoAcme4321IQResults.rgs file.

    C++
    Copy
    HKCR
{
    Acme4321.Acme4321IQResults.1 = s 'Acme4321IQResults Class'
    {
        CLSID = s '{COCLASSG-UIDC-OCLA-SSGU-IDCOCLASSGUI}'
    }
    Acme4321.Acme4321IQResults = s 'Acme4321IQResults Class'
    {
        CLSID = s '{COCLASSG-UIDC-OCLA-SSGU-IDCOCLASSGUI}'
        CurVer = s 'Acme4321.Acme4321IQResults.1'
    }
    NoRemove CLSID
    {
        ForceRemove {COCLASSG-UIDC-OCLA-SSGU-IDCOCLASSGUI} = s 'Acme4321IQResults Class'
        {
            ProgID = s 'Acme4321.Acme4321IQResults.1'
            VersionIndependentProgID = s 'Acme4321.Acme4321IQResults'
            InprocServer32 = s '%MODULE%'
            {
                val ThreadingModel = s 'Both'
            }
            val AppID = s '%APPID%'
            'TypeLib' = s '{LIBIDLIB-IDLI-BIDL-IBID-LIBIDLIBIDLI}'
        }
    }
}

    Replace the {COCLASSG-UIDC-OCLA-SSGU-IDCOCLASSGUI} with the same GUID you assigned to the coclass definition in the CustomClasses.idl file value. Unique GUIDs can be generated from within Visual Studio by choosing Create GUID from the Tools.

    Replace the {LIBIDLIB-IDLI-BIDL-IBID-LIBIDLIBIDLI} with the driver's type library GUID (referred to as the LIBID). The LIBID can be found in the Nimbus-generated IDL file -- Acme4321.nimbus.idl. The LIBID is the value of the uuid attribute assigned to the library block, as shown in the following IDL code snippet:

    C++
    Copy
    #ifdef CUSTOM_IDL
#include "CustomInterfaceDeclarations.idl"
#endif

[
    uuid(LIBIDLIB-IDLI-BIDL-IBID-LIBIDLIBIDLI),
    version(0.1),
    helpstring(""),
    helpcontext(0)
]
library Acme4321
{
    importlib("stdole2.tlb");
    importlib("IviDriverTypeLib.dll");

  11. Add the following line of code to the driver project's Resource.h file, using a value of at least 200.

    C++
    Copy
    #define IDR_COACME4321IQRESULTS    201

  12. Right click on the driver project's .rc file (Acme4321.rc) and choose View Code. Add the following line of code to the bottom of the file:

    C++
    Copy
    IDR_COACME4321IQRESULTS          REGISTRY               "CoAcme4321IQResults.rgs"

Step 3 -- Adding a C++ class to implement the COM coclass

The COM coclass defined in the previous steps exists mostly to register the COM object. The code that will implement the methods and properties of our IAcme4321IQResults interface will be supplied by a C++ class.

To add a C++ class for implementing the COM coclass

  1. From Solution Explorer, right-click on the driver project and choose Add and then select New Item.... The Add New Item Dialog Box appears.

  2. From the tree view on the left, choose Code and then select Header File (.h) from the file types on the left.

  3. Enter a file name of CoAcme4321IQResults and click Add. The file CoAcme4321IQResults.h is added to the driver project.

  4. Replace the contents of the CoAcme4321IQResults.h file with the following code:

    C++
    Copy
    #pragma once
#include "resource.h"
#include "_Acme4321.h"

class ATL_NO_VTABLE Acme4321IQResults :
    public CComObjectRootEx<CComMultiThreadModel>,
    public CComCoClass<Acme4321IQResults, &__uuidof(Acme4321IQResults)>,
    public IAcme4321IQResults
{
public:
DECLARE_REGISTRY_RESOURCEID(IDR_ACME4321IQDATA)

BEGIN_COM_MAP(Acme4321IQResults)
    COM_INTERFACE_ENTRY(IAcme4321IQResults)
END_COM_MAP()

    DECLARE_PROTECT_FINAL_CONSTRUCT()

private:
   CString m_strDataType;
   long m_lSpreadFactor;
   long m_lCodeNumber;
   double m_dChannelAmplitude;

public:
   void Configure(const CString& strDataType, long lSpreadFactor, long lCodeNumber, double dChannelAmplitude);

public:
    STDMETHOD(get_DataType)(BSTR* val);
    STDMETHOD(get_SpreadFactor)(long* val);
    STDMETHOD(get_CodeNumber)(long* val);
    STDMETHOD(get_ChannelAmplitude)(double* val);
};

OBJECT_ENTRY_AUTO(__uuidof(Acme4321IQResults), Acme4321IQResults)

  5. From Solution Explorer, right-click on the driver project and choose Add and then select New Item.... The Add New Item Dialog Box appears.

  6. From the tree view on the left, choose Code and then select C++ File (.cpp) from the file types on the left.

  7. Enter a file name of CoAcme4321IQResults and click Add. The file CoAcme4321IQResults.cpp is added to the driver project.

  8. Replace the contents of the CoAcme4321IQResults.cpp file with the following code:

    C++
    Copy
    #include "stdafx.h"
#include "CoAcme4321IQResults.h"

void Acme4321IQResults::Configure(const CString& strDataType, long lSpreadFactor, long lCodeNumber, double dChannelAmplitude)
{
   m_strDataType = strDataType;
   m_lSpreadFactor = lSpreadFactor;
   m_lCodeNumber = lCodeNumber;
   m_dChannelAmplitude = dChannelAmplitude;
}

STDMETHODIMP Acme4321IQResults::get_DataType(BSTR* val)
{
   if (val == NULL)
      return E_POINTER;

   *val = m_strDataType.AllocSysString();

   return S_OK;
}

STDMETHODIMP Acme4321IQResults::get_SpreadFactor(long* val)
{
   if (val == NULL)
      return E_POINTER;

   *val = m_lSpreadFactor;

   return S_OK;
}

STDMETHODIMP Acme4321IQResults::get_CodeNumber(long* val)
{
   if (val == NULL)
      return E_POINTER;

   *val = m_lCodeNumber;

   return S_OK;
}

STDMETHODIMP Acme4321IQResults::get_ChannelAmplitude(double* val)
{
   if (val == NULL)
      return E_POINTER;

   *val = m_dChannelAmplitude;

   return S_OK;
}

Step 4 -- Coding the driver method to return an instance of the COM class

Once the COM class for the results object has been defined and implemented, the next step is to implement the driver method that packages up the results of the method and returns an instance of the class. Following with the current example, the MeasureIQ method below demonstrates the code necessary to return a results object from a driver method.

C++
Copy
// CoAcme4321.cpp

HRESULT Acme4321::MeasureIQ(IAcme4321IQResults** ppResults)
{
   HRESULT hr = S_OK;

   // Send a query command to the instrument.  Response is a comma-separated list of four values.
   CString strDataType;
   long lSpreadFactor;
   long lCodeNumber;
   double dChannelAmplitude;
   hr = io.Queryf(_T("SENS:IQ:DATA?"), _T("%$Cs,%d,%d,%le"), &strDataType, &lSpreadFactor,  &lCodeNumber, &dChannelAmplitude);
   if (SUCCEEDED(hr))
   {
      // Create an instance of the Acme4321IQResults COM class to hold the method results
      CComObject<Acme4321IQResults>* pResults = NULL;
      hr = CComObject<Acme4321IQResults>::CreateInstance(&pResults);
      if (SUCCEEDED(hr))
      {
         // Initialize the properties on the results object
         pResults->Configure(strDataType, lSpreadFactor, lCodeNumber, dChannelAmplitude);

         // Get the right interface pointer type
         pResults->QueryInterface(ppResults);
      }
   }

   return hr;
}

Step 5 -- Updating the driver installer to register the COM class

The code above to create an instances of our Acme4321IQResults class will only work if the COM class is properly registered. On a Nimbus developer machine, this registration happens automatically as part of the build. But, when the driver is deployed to an end-user machine, then the registration for this class must be performed by the driver installer. For the main driver class and repeated capability classes, Nimbus automatically updates the driver installer to create the appropriate entries. Also, since the IAcme4321IQResults interface was added via the Nimbus designer, Nimbus automatically updates the installer to register this interface on the end-user machine. However, the COM class definition was added manually, so the installer must be manually updated to register the COM class on the end-user machine during the driver installation process.

To add a COM class registration to the driver installer:

  1. From Solution Explorer, right-click on the Setup.wxs file in the driver setup project, and choose View Code.

  2. Locate the two Class elements for the main driver class. There will be two elements -- one in the 32-bit section of the Setup.wxs file and one in the 64-bit section of the Setup.wxs file. The existing entry for the main driver class will look something like the following:

    XML
    Copy
     <!-- Setup.wxs -->

<Class Id="{XXXXXXXG-XXXX-XXXX-XXXX-XXXXXXXXXXXX}" Advertise="no" Context="InprocServer32" Description="Acme4321 Object" ... >
   <ProgId Id="Acme4321.Acme4321.1">
      <ProgId Id="Acme4321.Acme4321" />
   </ProgId>
</Class>

  3. Copy the Class element for the main driver class and paste it just beneath the existing entry. Update the Id and Description attributes on the Class element as well as the Id attributes on the ProgId elements. The values must match those used in the .rgs and .idl files in previous steps. The result should look something like the following:

    XML
    Copy
     <!-- Setup.wxs -->

<Class Id="{XXXXXXXG-XXXX-XXXX-XXXX-XXXXXXXXXXXX}" Advertise="no" Description="Acme4321 Object" Context="InprocServer32" ... >
   <ProgId Id="Acme4321.Acme4321.1">
      <ProgId Id="Acme4321.Acme4321" />
   </ProgId>
</Class>
<Class Id="{COCLASSG-UIDC-OCLA-SSGU-IDCOCLASSGUI}" Advertise="no" Description="Acme4321IQResults Object" Context="InprocServer32" ... >
   <ProgId Id="Acme4321.Acme4321IQResults.1">
      <ProgId Id="Acme4321.Acme4321IQResults" />
   </ProgId>
</Class>

  4. Repeat the above process for the Class element in the 32-bit and 64-bit sections of the Setup.wxs file.

Using Arrays of Object Parameters in Driver Methods

Some driver methods may need to return an array of object parameters. The process for doing this is very similar to the process above for returning a single object parameter. The only difference is in the final step -- the implementation of the driver method itself.

With the COM class defined and implemented according to the steps above, the driver method for returning an array of our example Acme4321IQResults object would look like the following:

C++
Copy
// CoAcme4321.cpp

HRESULT Acme4321::MeasureIQMultiple(SAFEARRAY** ppsaResults)
{
   HRESULT hr = S_OK;

   // Send a query command to the instrument
   CString strResponse;
   hr = io.Queryf(_T("SENS:IQ:DATA:ALL?"), _T("%$Cs"), strResponse);
   if (SUCCEEDED(hr))
   {
      CAtlArray<CString> rgstrDataType;
      CAtlArray<long> rglSpreadFactor;
      CAtlArray<long> rglCodeNumber;
      CAtlArray<double> rgdChannelAmplitude;

      int nNumResults = (int)rgstrDataType.GetCount();

      // Parse the strResponse string into the local variables above.
      // This code is not shown for clarity.
      // ...

      // Declare an array of objects to store the results
      CComSafeArray<IUnknown*> saResults;

      // Create the correct number of elements in the results array
      saResults.Create(nNumResults);

      for (int i = 0; i < nNumResults && SUCCEEDED(hr); i++)
      {
         // Create a single results object
         CComObject<Acme4321IQResults>* pResult = NULL;
         hr = CComObject<Acme4321IQResults>::CreateInstance(&pResult);
         if (SUCCEEDED(hr))
         {
            CString strDataType = rgstrDataType.GetAt(i);
            long lSpreadFactor = rglSpreadFactor.GetAt(i);
            long lCodeNumber = rglCodeNumber.GetAt(i);
            double dChannelAmplitude = rgdChannelAmplitude.GetAt(i);

            // Initialize the properties on the results object
            pResult->Configure(strDataType, lSpreadFactor, lCodeNumber, dChannelAmplitude);

            // Get right interface pointer type
            IUnknown* pUnk = NULL;
            pResult->QueryInterface(&pUnk);

            // Add the result object to the array of result objects
            saResults.SetAt(i, pUnk);
         }
      }

      if (SUCCEEDED(hr))
      {
         *ppsaResults = saResults.Detach();
      }
   }

   return hr;
}


Retrieving the Intrument Model

When a client application initializes a driver via the IIviDriver::Initialize method, the standard Nimbus implementation of that method executes the InitializeIdentification function to query the instrument for identification information, such as the manufacturer, the firmware revision, and the specific instrument model. Nimbus caches the results of this process so that the driver developer (and the Nimbus-generated code) can use functions within the Nimbus Template Library to retrieve the identification information at any time during the driver session.

The GetModel function is provided to allow driver code to retrieve the specific instrument model with which the driver is currently communicating. The driver developer can use the GetModel function in a multi-model driver project to implement conditional logic. For instance, in the code example below, the GetModel function is used to determine the exact SCPI command that should be sent to the instrument to program the voltage range.

C++
Copy
HRESULT Acme43XX::IAcme43XXFrequency_put_Range(double Range)
{
   HRESULT hr = S_OK;

   CString strModel = GetModel();

   if (strModel == _T("4301"))
   {
      hr = InstrPrintf(_T("SENS:FREQ:VOLT:RANGE %.15g"), Range);
   }
   else if (strModel == _T("4302"))
   {
      hr = InstrPrintf(_T("FREQ:RANGE %.15g"), Range);
   }
   else if (strModel == _T("4303"))
   {
      hr = InstrPrintf(_T("FREQ:VOLT:RANGE %.15g"), Range);
   }
   else
   {
      hr = err.ModelNotSupported();
   }

   return hr;
}
Retrieving the Instrument Model in Simulation Mode

When a driver is initialized in simulation mode, the IIviDriver::Initialize method obviously cannot use the InitializeIdentification function to query the instrument for its identification information, such as the instrument model. Rather, the instrument model must be provided to the driver so that all of the model-based logic (both developer-written and Nimbus-generated) will operate properly. The model that is provided during simulation is referred to as the simulated model. When the driver is running in simulation mode, the GetModel function can be used in exactly the same fashion as with a live session.

The simulated model can be specified in one of two ways:

  • By using the Models Page of the Driver Settings Editor to specify a default model. The default model is stored by the driver installer in the IVI Configuration Store and is automatically retrieved by the Nimbus implementation IIviDriver::Initialize.

  • By passing in a DriverSetup string to the IIviDriver::Initialize method. The client application includes in the DriverSetup string a name-value pair of the form "Model=<model>". A simulated model provided in this way overrides the default model specified by the driver developer in the Driver Settings Editor.

The code below demonsrates how a client application can specify a simulated model when calling the driver's Initialize method.

C#
Copy
// Client.cs
IIviDriver driver = new Acme43XX();

driver.Initialize("GPIB::14", false, false, "Simulate=true, DriverSetup=Model=4302");
See Also

Other Resources

Adding Support for Multiple Instrument Models
GetModel
InstrumentInFamily
InstrumentIsModel
ModelInFamily


Retrieving Initialization Options

When client applications initialize an IVI driver via the Initialize method, they may provide a series of initialization options in the form of name-value pairs. Two types of initialization options may be passed to a driver's Initialize method - inherent options and driver setup options.

The inherent options are specific name-value pairs defined by the IVI Foundation. These include options such as Cache to turn on/off state caching and Simulation to indicate whether simulation should be enabled or not. The driver setup options are custom name-value pairs defined by the driver developer. Driver setup options may be used to control driver-specific features or to perform any custom setup. They are delineated from the inherent options by the IVI-defined DriverSetup keyword.

The example below shows a typical client application instantiating and then initializing a driver.

C#
Copy
// Client.cs
Acme4321 driver = new Acme4321();

driver.Initialize("GPIB::10", true, true, "InterchangeCheck=False, Simulate=True, DriverSetup=OptionA=Foo,OptionB=True");

InterchangeCheck option is an inherent option being passed in with a value of False. Simulation is also an inherent option specified with a value of True in the code above. Two driver setup options, OptionA and OptionB are being passed in with values of Foo and True, respectively.

The Nimbus implementation of the Initialize function automatically saves the values of all inherent and driver setup options. If some of the IVI-defined inherent options are not specified, Nimbus caches IVI-defined default values for those options.

Nimbus provides several functions for retrieving the values of the IVI-defined inherent options. These functions are fully documented in the Driver State Functions section of the Nimbus Template Library documentation. The table below shows each inherent option and the Nimbus function available to retrieve its value. The IVI-defined default value of each option is also shown.

Inherent Options | Accessor Function | Default Value
Cache | GetCache | True
InterchangeCheck | GetInterchangeCheck | False
QueryInstrStatus | GetQueryInstrStatus | False
RangeCheck | GetRangeCheck | True
RecordCoercions | GetRecordCoercions | False
Simulate | GetSimulate | False

The Nimbus Template Library also provides the GetDriverSetupOptionValue function for retrieving the value of driver setup options passed to the Initialize function. A simple example of using the GetDriverSetupOptionValue function is shown below. For more details, see the documentation for this function in the Nimbus Template Library.

C++
Copy
// IAcme4321.cpp
HRESULT Acme4321::IAcme4321_put_Frequency(double Frequency)
{
   HRESULT hr = S_OK;

   CString strOption = GetDriverSetupOptionValue("OptionA");

   if (strOption == "Foo")
   {
      // ...
   }

   return hr;
}


Implementing IVI-C-Only Functions and Attributes

Nimbus allows any IVI-C function or attribute to be implemented manually. In general, there are two reasons one might implement an IVI-C function or attribute manually:

  1. To override the Nimbus auto-generated implementation.

  2. To implement an IVI-C-only function or attribute.

The techniques presented in this section apply equally well to both scenarios.

File Locations of IVI-C Functions and Attributes

By default, when an IVI-C function or attribute is associated with an IVI-COM method or property, Nimbus generates an implementation of the IVI-C function or attribute in the following file:

<prefix>.nimbus.cpp

The auto-generated implementation delegates to the associated IVI-COM method or property, automatically performing the requisite data type conversions, error translations, and other tasks. If the Implementation type of the IVI-C function or attribute is changed to Manual, then the implementation of the function or attribute is removed from the Nimbus-managed <prefix>.nimbus.cpp file. A stub implementation of the IVI-C function or attribute is then added to the following user-managed file:

<prefix>.cpp

Similarly, if an IVI-C-only function or attribute is added to the driver via the IVI-C Designer, then it is always placed in the user <prefix>.cpp file. Manual implementation is the only option for IVI-C-only functions and attributes.

All of the code for manually implementing an IVI-C function or attribute is always placed in the user <prefix>.cpp file.

Tip Tip

The best way to begin manually implementing an IVI-C function or attribute is to refer to the auto-generated code in the Nimbus-managed <prefix>.nimbus.cpp file. This code demonstrates many techniques that may be needed in your manual IVI-C implementation.

Manually Implementing an IVI-C Function

Though an IVI-C function implementation can use a multitude of techniques to fulfill its purpose, the two most common scenarios in Nimbus drivers involve using IVI-C attributes and delegating to IVI-COM methods. This section discusses both scenarios.

Implementing IVI-C Functions Using IVI-C Attributes

One of the most common scenarios for manually implementing IVI-C functions is high-level "configure" functions. By convention, IVI drivers typically define a Configure function to set the values of attributes. The syntax for directly reading and writing IVI-C attributes via attribute accessors is somewhat cumbersome for end users, so IVI recommends that Configure functions be made available as well.

The following example demonstrates how to implement an IVI-C function in terms of an IVI-C attribute:

C++
Copy
ViStatus _VI_FUNC acme4321_ConfigureAcquisitionType ( ViSession Vi, ViInt32 AcquisitionType )
{
    ViStatus status = VI_SUCCESS;

  status = acme4321_SetAttributeViInt32(vi, VI_NULL, ACME4321_ATTR_ACQUISITION_TYPE, AcquisitionType);

    return status;
}

Implementing IVI-C Functions Using IVI-COM Methods and Properties

As mentioned previously, the default mode for Nimbus is to implement IVI-C functions in terms of the associated IVI-COM method or property (except, of course, in the case of IVI-C-only functions). The best way to understand how to manually implement an IVI-C function in terms of IVI-COM methods and properties is by examining a Nimbus-generated implementation from the <prefix>.nimbus.cpp file.

The following code demonstrates how to implement the IVI-C function ConfigureEdgeTriggerSource in terms of the IVI-COM method IIviScopeTriggerEdge.Configure:

C++
Copy
ViStatus _VI_FUNC acme4321_ConfigureEdgeTriggerSource ( ViSession Vi, ViConstString Source, ViReal64 Level, ViInt32 Slope )
{
    ViStatus status = VI_SUCCESS;
    CComPtr<IIviScopeTriggerEdge> spTriggerEdge;
    status = GetDriverInterface(Vi, &spTriggerEdge);
    if (status == VI_SUCCESS)
    {
        CParam<ViConstString> _Source(Source);
        CParam<ViReal64> _Level(Level);
        CParam<ViInt32> _Slope(Slope);
        HRESULT hr = spTriggerEdge->Configure(_Source, _Level, (IviScopeTriggerSlopeEnum)(long)_Slope);
        status = TranslateHRESULT(Vi, hr);
    }

    return status;
}

The first task performed by the above code is to obtain a pointer to the appropriate interface on the IVI-COM driver. In this case, the Configure method we are after resides on the IIviScopeTriggerEdge interface. This interface is accessed by calling the GetDriverInterface helper function provided by Nimbus. The interface pointer is returned from this function and stored in a CComPtr smart pointer variable named spTriggerEdge. Using CComPtr ensures that the reference to the interface is automatically released when the function exits.

The code then checks the status returned from GetDriverInterface, and, if successful, it sets up the three temporary input parameters (_Source, _Level, and _Slope) that will be passed to the IVI-COM Configure method.

The three temporary parameters (declared as CParam objects) are templatized based on the IVI-C parameter type and serve a very important role -- they automatically perform the data type conversions from the IVI-C input parameters to their COM equivalents. For instance, the Source parameter passed to the acme4321_ConfigureEdgeTriggerSource function is of type ViConstString. However, the corresonding IVI-COM method accepts the COM BSTR data type for its Source parameter. The IVI-C parameter cannot simply be passed directly to the IVI-COM method -- it must be converted from ViConstString to BSTR. This task is performed by the CParam helper classes provided by Nimbus. The CParam class can be used to convert between any two compatible IVI-C and IVI-COM data types.

With the appropriate CParam objects declared, the IVI-COM Configure method is invoked using the spTriggerEdge smart pointer. IVI-COM methods always return an HRESULT to indicate success or failure. They also populate a "hidden" COM error object that contains additional error information, such as a string description of the error that occurred. This information must be translated into a form that IVI-C clients can consume. This is the role of the TranslateHRESULT helper function provided by Nimbus. This function converts the HRESULT into a corresponding IVI-C ViStatus value. It also harvests the error description from the COM error object and stores it in the IVI-C session so that client calls to the IVI-C GetError function will return the appropriate message.

Returning Errors from IVI-C Functions

There are two techniques used for returning errors from IVI-C functions. The TranslateHRESULT function described above is always used when the IVI-C function is implemented by delegating to an IVI-COM method or property. The other option is to use the ReportError function with an explicit IVI-C error name and description.

The following code demonstrates use of the ReportError function to validate parameters passed to an IVI-C function.

C++
Copy
ViStatus _VI_FUNC acme4321_FetchWaveformMeasurement ( ViSession Vi, ViConstString Channel, ViInt32 MeasFunction, ViReal64* Measurement )
{
    if (Measurement == VI_NULL) return ReportError(Vi, ACME_ERROR_NULL_POINTER, _T("Parameter Measurement is VI_NULL."));

    ViStatus status = VI_SUCCESS;

    // ...

    return status;
}

The code in the above example uses ReportError to report a NULL-pointer error for the Measurement output parameter.

Manually Implementing an IVI-C Attribute

IVI-C attributes are implemented using the same techniques as IVI-C functions. The additional requirement for IVI-C attributes is that their implementation functions follow a precise naming convention. IVI-C attributes must be implemented using two functions (a getter and a setter) if they are read-write attributes. Only a single function is supplied for read-only or write-only attributes.

An IVI-C attribute getter must be implemented with a function declaration of the following form:

ViStatus _VI_FUNC <prefix>_get_<ATTR_NAME> ( ViSession Vi, ViConstString RepCapIdentifier, <AttrType>* AttributeValue)

An IVI-C attribute setter must be implemented with a function declaration of the following form:

ViStatus _VI_FUNC <prefix>_set_<ATTR_NAME> ( ViSession Vi, ViConstString RepCapIdentifier, <AttrType> AttributeValue)

For example, the following code shows stub implementations for the getter and setter functions for the IVI-C attribute TRIGGER_SLOPE. Note that the full attribute name as declared in the #define statement in the <prefix>.h file is ACME4321_ATTR_TRIGGER_SLOPE. However, only the TRIGGER_SLOPE portion of the full attribute name is used in the getter and setter implementation declarations.

C++
Copy
ViStatus _VI_FUNC acme4321_get_TRIGGER_SLOPE ( ViSession Vi, ViConstString RepCapIdentifier, ViInt32* AttributeValue )
{
  // ...
}

ViStatus _VI_FUNC acme4321_set_TRIGGER_SLOPE ( ViSession Vi, ViConstString RepCapIdentifier, ViInt32 AttributeValue )
{
  // ...
}
Session Locking in IVI-C Functions and Attributes

IVI-C drivers support a feature called session locking. Session locking allows a client program to call the <prefix>_LockSession function to gain exclusive access to the instrument session. No calls from other threads should execute on that instrument session until the client calls <prefix>_UnlockSession.

Note Note

Session locking does not prevent multiple threads from accessing different sessions connected to the device over different communication ports. For instance, if two sessions are created using the same driver by calling <prefix>_init with different resource descriptors, then session locking will not prevent multiple threads from executing on the two sessions, even if they refer to the same physical instrument.

Since sessions cannot be shared across processes, this also means that session locking does not protect against simultaneous instrument access from multiple applications.

When manually implementing IVI-C functions and attributes, session locking is automatically implemented within the Nimbus Template Library if the manual implementation delegates to the underlying IVI-COM driver. As demonstrated above, delegating to any IVI-COM driver method involves calling the GetDriverInterface helper function, and this function calls the appropriate session locking functions. However, if your manual IVI-C function or attribute implementation does not rely upon the IVI-COM driver (it does not call GetDriverInterface as one of its first actions), then you must use the CSessionLock utility class to properly implement session locking.

The example below demonstrates how to use the CSessionLock class to implement session locking in an IVI-C function that does not rely upon the IVI-COM core driver.

C++
Copy
ViStatus _VI_FUNC acme4321_FetchWaveformMeasurement ( ViSession Vi, ViConstString Channel, ViInt32 MeasFunction, ViReal64* Measurement )
{
    CSessionLock lock(Vi);  // The ctor obtains the lock and the dtor releases the lock.
                          // If the calling thread is not the lock owner, then the calling
                          // thread will block until the lock owner released the lock.

    if (Measurement == VI_NULL) return ReportError(Vi, ACME_ERROR_NULL_POINTER, _T("Parameter Measurement is VI_NULL."));

    ViStatus status = VI_SUCCESS;

    // ...

    return status;
}
See Also

Other Resources

Managing IVI-C Driver Functionality


Implementing Dynamic Repeated Capabilities

Nimbus supports two types of repeated capabilities -- static repeated capabilities and dynamic repeated capabilities. Static repeated capabilities represent the fixed functionality of the instrument -- such as physical channels on an oscilloscope. These repeated capabilities must be configured at driver development time using the Driver Settings Editor.

Dynamic repeated capabilities are those that cannot be determined at driver development time. Rather, the driver must "discover" by communicating with the instrument what repeated capabilities are present. For example, a driver for a multi-slot digital I/O mainframe has no way to know at driver development time what type and number of digital I/O cards will be plugged into the available mainframe slots.

In order to support dynamic repeated capabilities, Nimbus provides the GetDynamicRepCapNames function. One may accurately think of GetDynamicRepCapNames as the programmatic equivalent of the repeated capabilities Driver Settings Editor. The driver developer overrides this function in the main driver class header file and provides whatever logic necessary to return a list of repeated capability names. Nimbus automatically invokes the overridden GetDynamicRepCapNames function during driver initialization.

The signature of the GetDynamicRepCapNames function is as follows:

C++
Copy
virtual HRESULT GetDynamicRepCapNames(const CString& repCapClassName, CAtlArray<CString>& rgRepCapNames);

The repCapClassName parameter is passed to the function by Nimbus and represents the repeated capability class for which you should return the associated repeated capability names.

The rgRepCapNames parameter is an array that the function implementation should use to return the dynamic repeated capability names to Nimbus. Nimbus will create one instance of the repeated capability class identified by the repCapClassName parameter for each element added to the rgRepCapNames array.

The code below demonstrates how to implement GetDynamicRepCapNames in the main driver class header file.

C++
Copy
// CoAcme4321.h
class ATL_NO_VTABLE Acme4321 :
{
   // ...

   virtual HRESULT GetDynamicRepCapNames(const CString& repCapClassName, CAtlArray<CString>& rgRepCapNames)
   {
      if (repCapClassName == _T("Acme4321InputChannel"))
      {
         // Query the instrument for the number of digital input cards plugged into the mainframe
         long lNumCards;
         hr = InstrQueryf(_T("SYST:CTYP:COUN?", &lNumCards));
         if (FAILED(hr)) return hr;

         // Each card has 32 input channels
         for (int lSlot = 0; lSlot < lNumCards; lSlot++)
         {
            for (int lChannel = 0; lChannel < 32; lChannel++)
            {
               // Each channel name will be of the form: "Channel-[slot]-[channel]"
               CString strName;
               strName.Format(_T("Channel-%d-%d"), lSlot, lChannel);

               // Add the name to the collection of repeated capability names
               rgRepCapNames.Add(strName);
            }
         }
      }
      else if (repCapClassName == _T("Acme4321OutputChannel"))
      {
         // ... query instrument for the number of dynamic trace repeated capabilities
      }
   }

   // ...
}
See Also

Other Resources

Repeated Capabilities
Adding a Repeated Capability


State Caching Overview

Nimbus provides powerful state caching features that allow driver developers to maximize the performance of their driver by minimizing the number of expensive instrument I/O operations. A special State Caching Editor provides a simple declarative mechanism for expressing couplings between instrument properties, and state caching API functions provide programmatic access to caching operations as well.

In This Section

Understanding Nimbus State Caching

Property Identifiers

Manually Controlling State Caching

See Also

Other Resources

State Caching Functions


Understanding Nimbus State Caching

State caching is a feature of IVI drivers that can improve performance by minimizing the number of I/O calls to an instrument. For instance, if a driver property value is set and the driver sends the programmed value to the instrument, subsequent calls to the same property need not communicate with the instrument if the value being set is the same as the previous value. Correspondingly, reading a driver property need not result in instrument communication if the driver can somehow "remember" the last value that was sent to the instrument. When a client application invokes a driver property, the driver caches the value specified in memory so that subsequently the driver can simply retrieve the value from the driver's cache when the property is read or avoid making a redundant call to the instrument when the property is written. In this way, the instrument I/O traffic is minimized and the overall client application performance can be improved.

Understanding Cache Couplings

When a driver caches the value of a property, it should ideally return the cached value when the property is later read, rather than incurring the performance hit of querying the instrument for the property value. This will work so long as nothing takes place within the instrument that would invalidate the value cached in the driver. If, after caching the value of a property, the driver performs a different instrument operation that directly or indirectly changes the value of the property within the instrument, then the driver's cache and the "real" setting in the instrument are inconsistent. This is one form of what is termed a cache coherency problem.

If setting some driver property produces a change in an instrument setting represented by another property, the two properties are said to be coupled. For state caching to work properly, these cache couplings must be programmed into the driver, so that the driver knows when to invalidate specific cached values. For instance, if the driver is caching a Frequency property, then setting the Bandwidth property may also change the frequency setting within the instrument. This means that the driver must know to invalidate the cached value for the Frequency property whenever the Bandwidth is set.

State Caching Features in Nimbus

Nimbus provides two mechanisms for controlling state caching -- automatic state caching and manual state caching. The automatic state caching feature of Nimbus is the simplest to use and will suffice in mostcircumstances. With this technique, Nimbus automatically creates and manages a cache entry for every driver property for which state caching has been enabled. The State Caching Editor is used to turn state caching on and off on a property-by-property basis. The other bit of information that the driver developer must provide via the State Caching Editor is the list of properties to which the cached property is coupled. In other words, the driver developer must specify which driver properties, when changed, will cause the value of the cached property to become invalid. This allows Nimbus to keep its in-memory cache consistent with the settings in the instrument.

In addition to the automatic state caching features of Nimbus exposed by the State Caching Editor, Nimbus also supplies a series of state caching functions that can be used to manually control the state caching engine. Manual state caching can be useful if the couplings between properties cannot easily be expressed in the State Caching Editor.

When To Enable State Caching

State caching is a feature that certainly must be used with care. Cache coherency problems can easily arise if the driver developer is not keenly aware of the details of the instrument behavior and/or does not accurately and thorougly represent instrument couplings in the driver. Thus, in general, it is advisable to consider enabling state caching for those properties that have the following characteristics:

  1. They require considerable time to execute (and, hence, stand to improve performance the most when cached).

  2. They have a modest and easily expressed set of couplings to other properties.

Enabling state caching broadly across all properties in a driver is almost never feasible, as correctly implementing the driver code would involve effectively replicating much of the instrument firmware logic itself. Consequently, Nimbus disables state caching by default for all properties.

See Also

Other Resources

State Caching Functions


Property Identifiers

Several Nimbus features rely upon the ability to reference a driver property from the driver implemenation code itself. For instance, Nimbus state caching allows couplings between properties to be expressed using string identifiers. These identifiers are known as property identifiers.

Property identifiers have two forms:

  • Simple property identifiers

  • Extended property identifiers

Simple Property Identifiers

Simple property identifers are the most common form of property identifiers and are used to reference properties that are defined on the same class. Drivers that contain no repeated capabilities use a single class to implement all properties, so these drivers need only use this form of property identifiers. More complex drivers may need to use extended property identifers to reference properties implemented on different classes.

Simple property identifiers have the following form:

<interface>.<property>`

Since only the interface name and property name are specified, it is implied that the referenced property exists on the same class. When Nimbus attempts to resolve a simple property identifier, it will only look on the class of the calling function to locate the specified interface and property.

The following example shows use of the InvalidateCacheEntry with a simple property identifier to manually implement a coupling between the Bandwidth property and the Frequency property.

C++
Copy
STDMETHODIMP Acme4321::IAcme4321_put_Bandwidth(double dVal)
{
   HRESULT hr = S_OK;

   InvalidateCacheEntry("IAcme4321.Frequency");

   return S_OK;
};
Extended Property Identifiers

In some instances, it may be necessary for implementation code in one class to reference a property that resides on a completely different class. Typically this situation arises when the driver contains repeated capabilities, such as the channels repeated capability of the IviScope instrument class. Nimbus supports a special syntax called extended property identifiers to deal with precisely this situation.

Extended property identifers prepend the simple property identifier with a repeated capability identifier to denote the class on which the property exists.

<repeated capability identifier>.<interface>.<property>

The repeated capability identifier includes the name of the repeated capability class as well as the index of the specific instance of that class. For example, the repeated capability identifier Acme4321Channel[2] identifies the third instance of the Acme4321Channel repeated capability class.

In the case of nested repeated capabilities, the repeated capability identifier may include more than one class name. For instance, if the channel repeated capability contained a child Trace repeated capability, then a valid repeated capability identifier to reference properties on a trace class might look like Acme4321Channel[1].Acme4321Trace[0].

Note Note

Repeated capability identifiers are always interpreted as being relative to the class from which it is used. The first class listed in the repeated capability identifier is understood to be an immediate child repeated capability of the calling class. If it is necessary to reference a property on a repeated capabilility that is not a direct descendant of the calling class, then the repeated capability identifier must start with the class name "Driver" (representing the main driver class) and explicitly list all parent classes of the referenced property. The last example below demonstrates this particular situation.

The following example shows use of the InvalidateCacheEntry with an extended property identifier to manually implement a coupling between the Bandwidth property of the Acme4321Channel repeated capability and the Span property on the second instance of the Acme54600Trace repeated capability.

C++
Copy
STDMETHODIMP Acme4321::IAcme4321_put_Bandwidth(double dVal)
{
   HRESULT hr = S_OK;

   InvalidateCacheEntry("Acme4321Trace[1].IAcme4321.Span");

   return S_OK;
};

This example demonstrates referencing a property on a nested repeated capability. The implemenation of the put_Frequency method on the main driver class uses the InvalidateCacheEntry function to invalidate the cache entry for the Amplitude property on the fourth instance of the Trace child repeated capability on the third instance of the Measurement repeated capability.

C++
Copy
STDMETHODIMP Acme4321::IAcme4321_put_Frequency(double dVal)
{
   HRESULT hr = S_OK;

   InvalidateCacheEntry("Acme4321Measurement[2].Acme4321Trace[3].IAcme4321Trace.Amplitude");

   return S_OK;
};

In the final example below, the Amplitude property is implemented on a Trace repeated capability that is a direct child repeated capability of the main driver class. This Amplitude property references the Frequency property on a channel repeated capability that is also a direct child repeated capability of the main driver class. Hence, the "Driver" prefix must be used to access the Channel repeated capability since that repeated capability is not a child of the Trace repeated capability.

C++
Copy
STDMETHODIMP Acme4321::IAcme4321Trace_put_Amplitude(double dVal)
{
   HRESULT hr = S_OK;

   InvalidateCacheEntry("Driver.Acme4321Channel[2].IAcme4321Channel.Frequency");

   return S_OK;
};
See Also

Other Resources

Understanding Nimbus State Caching
Manually Controlling State Caching


Manually Controlling State Caching

The code that Nimbus generates in response to settings on the State Caching Editor relies upon a series of state caching functions in the Nimbus Template Library. These functions interact with the state caching engine to check for the presence of a cached value, retrieve a cached value, or update a cached value. In some circumstances, the logic required to represent couplings between some driver properties is more complex than can be represented with the simple settings in the State Caching Editor. In such cases, the state caching functions can be used directly in method and property implementations to manually implement state caching.

Another reason manual state caching may be useful is in the implementation of high-level configuration functions. Often these functions accept multiple parameters and each parameter may correspond to a driver property that you would like to have cached. If the configuration function does not delegate to a property setter, then the manual state caching functions may have to be used to invalidate or update cache entries. For instance, a high-level configuration function may use semi-colon-separated SCPI commands to send multiple instrument settings at once, rather than calling driver property setters individually. Thus, the state caching logic in the property setters is bypassed and must be placed in the configure function manually.

Note Note

Some driver properties can use the built-in state caching mechanism programmed through the State Caching Editor while other properties can use manual state caching. However, it is important to turn off state caching in the State Caching Editor for any property that uses manual state caching. Otherwise, Nimbus will generate redundant (and incorrect) state caching code and the results will be unpredictable.

The logic used to manually implement state caching is, of course, user-defined. However, the basic steps in all manual state caching scenarios is the same. The steps can be summarized as follows:

  1. Use the GetOrCreateCacheEntry function to create an entry in the cache that is associated with a driver property. This function returns a CCacheEntry object that exposes methods that can be used to retrieve and update the value of the cache entry.

  2. Use the InvalidateCacheEntry function or the CCacheEntry::Invalidate function to implement user-defined couplings between properties. For instance, you may create a cache entry for the Bandwidth property and couple it to the Frequency property by calling InvalidateCacheEntry on the Bandwidth property inside the Frequency property setter. This would ensure that any time the frequency is set, the subsequent queries of the Bandwidth property retrieve the actual value from the instrument rather than the cached value.

  3. In the property getter for a cached property, use the CCacheEntry::GetValue function to retrieve the value from the cache if the value is valid.

  4. In the property setter for a cached property, use the CCacheEntry::ContainsValue function to first check if the cache already contains the same value as the one being set. If so, then the property setter implementation need do nothing further. If the new value is different from the cached value, then the implementation should send the new value to the instrument and subsequently call the CCacheEntry::UpdateValue function to update the property's cached value.

Manually Implementing State Caching in a Property Getter

The example code below shows how to manually implement the getter for a property that is being cached:

C++
Copy
HRESULT Acme4321::IAcme4321_get_Bandwidth(double* val)
{
   // Retrieve the cache entry for the Bandwidth property
   CCacheEntry<double>* pEntry = GetOrCreateCacheEntry<double>("IAcme4321.Bandwidth");

   // If the value is in the cache AND is valid, retrieve the value and return
   if (pEntry->GetValue(val))
      return S_OK;

   // If we get this far, then the cached value is not valid, so we
   // must communicate with the instrument to retrieve the value
   HRESULT hr = InstrQueryResponse(val);

   return hr;
}
Manually Implementing State Caching in a Property Setter

The example code below shows how to manually implement the setter for a property that is being cached:

C++
Copy
HRESULT Acme4321::IAcme4321_put_Bandwidth(double val)
{
   // Retrieve the cache entry for the Bandwidth property
   CCacheEntry<double>* pEntry = GetOrCreateCacheEntry<double>("IAcme4321.Bandwidth");

   // If the value is in the cache AND is valid, simply return since we don't need to send the instrument command
   if (pEntry->ContainsValue(val, GetModel()))
      return S_OK;

   // If we get this far, then the new value is not in the cache, so we
   // must communicate with the instrument to set the value
   HRESULT hr = InstrPrintCommand(val);

   if (SUCCEEDED(hr))
   {
      // The new value was successfully sent to the instrument, so update the cache
      pEntry->UpdateValue(val);
   }

   return hr;
}
Manually Implementing a Cache Coupling

The example code below shows how to manually implement a coupling between two properties. In this example, the Bandwidth property is being cached and is coupled to the Frequency property. The coupling is such that any new value set for the Frequency property that is greater than 10 MHz invalidates the cached value of the Bandwidth property. Thus, the invalidation logic appears in the Frequency property setter.

C++
Copy
HRESULT Acme4321::IAcme4321_put_Frequency(double val)
{
   // Only couple the properties if the frequency is greater than 10 MHz
   if (val > 10E6)
   {
      InvalidateCacheEntry("IAcme4321.Bandwidth");
   }

   HRESULT hr = InstrPrintCommand(val);

   return hr;
}
See Also

Other Resources

State Caching Overview
State Caching Functions


Implementing Class-Compliant Interfaces

Class-Compliant Implementation Basics
Note Note

If you are implementing the IviFgen instrument class specification, please see the topic Special Notes on Implementing IviFgen.

Unsupported Methods and Properties

By default, Nimbus generates code that returns an IVI-defined error (E_IVI_METHOD_NOT_SUPPORTED or E_IVI_PROPERTY_NOT_SUPPORTED) indicating that the method or property is not supported. If the driver does not support a particular class-compliant feature, then you may simply leave the auto-generated implementation of the associated method or property as is.

Note Note

If the driver has enabled IVI-C wrapper generation and a class-compliant method or property is not supported, then you must prevent the method or property from being exported in the IVI-C driver by deleting the associated IVI-C function or attribute. See the topic Linking IVI-COM and IVI-C Methods and Properties.

Repeated Capability Interfaces and Interface Reference Properties

repeated capability interfaces are exposed from both the class-compliant and instrument-specific interfaces. Both implementations must expose the same set of repeated capability instances. Nimbus automatically generates a suitable implementation of the Count, Item, and Name properties to accomplish this. There generally is no need to modify the implementation of these properties.

Nimbus also generates a suitable implementation for interface reference properties in class-compliant interfaces. Generally, these property implementations can be left as is.

Leveraging the Instrument-Specific Code

Most IVI-COM drivers are designed such that the full functionality of the instrument is exposed in the instrument-specific interfaces. This means that the functionality in the class-compliant interfaces is necessarily a subset of that in the instrument-specific interfaces. Thus, the best strategy for implementing class-compliant methods and properties is to use the code in the instrument-specific methods and properties. This allows all of the real driver logic to be consolidated in one set of methods and properties.

Delegating a class-compliant method call to an instrument-specific method call is generally a simple matter. There are two specific areas that do require particular attention:

  1. The syntax used to invoke the instrument-specific method or property

  2. Translating IVI-defined enum values to instrument-specific enum values

Syntax for Invoking Instrument-Specific Methods

The proper syntax for invoking an instrument-specific method from a class-compliant method is as follows:

_<interfaceName>::<methodName>(...)

Note that the leading underscore is required in the syntax above. Also, note that the above syntax is required for both instrument-specific and class-compliant methods calls made from any location within the driver code -- not just from within class-compliant code.

The reason it is so important to invoke methods and properties in this way is that the above syntax ensures the method call goes through the Nimbus generated pre-processing and post-processing code in the ForwardingShims.nimbus.cpp file. The code in this file provides a wide variety of important services, such as parameter validation, thread safety, range checking, state caching, and more.

Caution note Caution

Directly calling a driver method or property in any other fashion than that described above completely bypasses important logic.

For more details on the proper syntax for calling methods and properties from within the driver, see the topic Calling Driver Methods and Properties.

The example below demonstrates how to implement the class-compliant IIviRFSigGenFM.Deviation property setter by delegating to the Deviation property setter on the instrument-specific IAcme4321FM interface.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::IIviRFSigGenFM_put_Deviation(double Deviation)
{
   HRESULT hr = S_OK;

   hr = _IAcme4321FM::put_Deviation(Deviation);

   return hr;
}

Translating Class-Compliant Enum Values to Instrument-Specific Enum Values

For methods and properties that accept enum parameters, the IVI-defined enum value passed in through the class-compliant method must be translated to the corresponding instrument-specific enum value. In addition, the class-compliant implementation must return a specific IVI-defined error (E_IVI_VALUE_NOT_SUPPORTED) if one of the enum values defined by IVI is not supported by the driver.

The example below demonstrates how to translate IVI-defined enum values before delegating to the instrument-specific method. Note that this particular instrument does not support frequency stepped sweeps or power stepped sweeps, so the implementation returns E_IVI_VALUE_NOT_SUPPORTED if the user attempts to set the mode to frequency step or power step.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::IIviRFSigGenSweep_put_Mode(IviRFSigGenSweepModeEnum val)
{
   HRESULT hr = S_OK;

   switch (val)
   {
      case IviRFSigGenSweepModeNode:
         hr = _IAcme4321Sweep::put_SweepMode(Acme4321SweepModeOff);
         break;
      case IviRFSigGenSweepModeFrequencySweep:
         hr = _IAcme4321Sweep::put_SweepMode(Acme4321SweepModeFrequency);
         break;
      case IviRFSigGenSweepModePowerSweep:
         hr = _IAcme4321Sweep::put_SweepMode(Acme4321SweepModePower);
         break;
      case IviRFSigGenSweepModeFrequencyStep:
         hr = ReportError(IDS_E_IVI_VALUE_NOT_SUPPORTED, _T("IviRFSigGenSweepModeFrequencyStep"), _T("val"), _T("put_Mode"));
         break;
      case IviRFSigGenSweepModePowerStep:
         hr = ReportError(IDS_E_IVI_VALUE_NOT_SUPPORTED, _T("IviRFSigGenSweepModePowerStep"), _T("val"), _T("put_Mode"));
         break;
      case IviRFSigGenSweepModeList:
         hr = _IAcme4321Sweep::put_SweepMode(Acme4321SweepModeList);
         break;
   }

   return hr;
}

Translating Instrument-Specific Enum Values to Class-Compliant Enum Values

When a read operation is performed on an enum property, the instrument-specific implementation will return an instrument-specific enum value. There may not be an IVI-defined enum value that maps to the value returned from the instrument-specific property. In this case, IVI requires that the class-compliant implementation return the well-known error E_IVI_UNEXPECTED_RESPONSE.

The example below demonstrates how to map instrument-specific enum values to class-compliant enum values. Note that if the instrument-specific call returns a mode value of Acme4321SweepModeDualSweep, the class-compliant implementation returns the error E_IVI_UNEXPECTED_RESPONSE.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::IIviRFSigGenSweep_get_Mode(IviRFSigGenSweepModeEnum* val)
{
   HRESULT hr = S_OK;

   Acme4321SweepModeEnum eMode;
   hr = _IAcme4321Sweep::get_SweepMode(&eMode);
   if (SUCCEEDED(hr))
   {
      switch (val)
      {
         case Acme4321SweepModeOff:
            *val = IviRFSigGenSweepModeNode;
            break;
         case Acme4321SweepModeFrequency:
            *val = IviRFSigGenSweepModeFrequencySweep;
            break;
         case Acme4321SweepModePower:
            *val = IviRFSigGenSweepModePowerSweep;
            break;
         case Acme4321SweepModeDual:
            // IVI does not define a "Dual" sweep type
            hr = ReportError(IDS_E_IVI_UNEXPECTED_RESPONSE);
            break;
         case Acme4321SweepModeList:
            *val = IviRFSigGenSweepModeList;
            break;
         default:
            hr = ReportError(IDS_E_IVI_UNEXPECTED_RESPONSE);
            break;
      }
   }

   return hr;
}
See Also

Other Resources

How IVI Drivers Provide Interchangeability
Adding Support for an Instrument Class
Special Notes on Implementing IviFgen


Special Notes on Implementing IviFgen

In February of 2016, the IVI Foundation released version 5.1 of the IviFgen instrument class specification. This version of the IviFgen class specification includes the final set of changes required to enable developers to build IviFgen-compliant IVI-COM drivers that support new interfaces for advanced arbitrary waveform generation. At the same time, the IVI Foundation released a revised IVI-COM type library that defined these new interfaces. These new interfaces are commonly referred to as the "IviFgen2" interfaces because the new root interface is named "IviFgen2". This new IviFgen type library (version 5.1) ships as part of the IVI Shared Components version 2.4 and higher.

Important note Important

In order to create IVI-COM drivers that comply with the IviFgen 5.1 instrument class specification, you must have IVI Shared Components 2.4 or higher installed. Correspondingly, in order to create applications that use drivers that support IviFgen 5.1, you must have IVI Shared Components 2.4 or higher installed.

Because the IviFgen instrument class specification represents the only class specification for which the actual interface defintions have been revised, there are some special considerations that must be taken into account when working with IviFgen-compliant drivers.

Creating New IviFgen-Compliant IVI-COM Drivers

When Nimbus 4.2 or greater is installed, creating a new IviFgen-compliant IVI-COM driver always yields an IviFgen 5.1-compliant driver. The full set of interfaces defined by IviFgen 5.1 are automatically included in the driver. There is no means to create an IviFgen 3.0-compliant IVI-COM driver with Nimbus 4.2 or greater.

Caution note Caution

Whenever you create an IviFgen 5.1-compliant IVI-COM driver, you are imposing a requirement on all end users of that driver such that they must also have IVI Shared Components 2.4 or greater installed in order to use the driver.

In practice, there should be few, if any, reasons to create a new IVI-COM driver that complies with the earlier version of the IviFgen class specification -- IviFgen 3.0. However, if you wish to create a new IviFgen 3.0-compliant IVI-COM driver, then you must install Nimbus 4.1 or earlier. An IviFgen 3.0-compliant driver may be created with IVI Shared Components 2.3 or 2.4 (or greater). However, if creating the IviFgen 3.0-compliant driver with IVI Shared Components 2.4 (or later), then any references to the IviFgen 3.0 type library will need to be manually updated to point to the IviFgen 5.1 type library. All of the IviFgen 3.0 interfaces are fully defined and shipped with IVI Shared Components 2.4, but the containing type library version was changed from 3.0 to 5.1.

To update a C# or Visual Basic project to use the IviFgen 5.1 type library:

  1. Expand the References node in Solution Explorer for the project in question and locate the IviFgenLib reference.

  2. Delete the reference.

  3. Right-click on the References node and choose Add Reference. The Reference Manager appears.

  4. Select the COM tab and then choose Type Libraries.

  5. Check the entry titled "IviFgen 5.1 Type Library" and click OK.

To update a C++ project to use the IviFgen 5.1 type library:

  1. Locate any #import statements in the project source files that refer to the IviFgen type library. Nimbus automatically creates statements that look like the following:

    C++
    Copy
    #import IviFgenLib_LIBID version("3.0") no_namespace

  2. Change the arguments to the version attribute from 3.0 to 5.1.

Working with Existing IviFgen 3.0-Compliant IVI-COM Drivers

As noted above, when Nimbus 4.2 or greater is installed, you cannot create new IviFgen 3.0-compliant IVI-COM drivers. However, you can open, edit, and run existing IviFgen 3.0-compliant IVI-COM drivers. The driver will remain an IviFgen 3.0-compliant driver. No additional dependencies will be incorporated into the driver by virtue of compiling it on a machine with IVI Shared Components 2.4 installed. The driver will run on end user machines with much earlier versions of the IVI Shared Components than version 2.4.

Note Note

Nimbus does not have a mechanism for automatically upgrading an existing IviFgen 3.0-compliant IVI-COM driver to IviFgen 5.1 compliance. Such a conversion requires extensive and detailed manual modifications to the driver and to internal Nimbus structures. A for-fee conversion service is provided by Pacific MindWorks. Please contact us at support@pacificmindworks.com for details on this program.

See Also

Other Resources

Implementing Class-Compliant Interfaces


Implementing Simulation

Implementing Methods and Properties to Support Simulation

Simulation is a required feature for IVI drivers. To support simulation, the developer must take explicit steps in the driver implementation. Specifically, the driver must ensure that when simulation is turned on, no instrument I/O communication is attempted, since the I/O infrastructure in Nimbus is not initialized when simulation is on. Consequently, functions such as Printf will not work at all in simulation mode.

Simulation is enabled by the client application by either passing in "Simulate=True" in the OptionString parameter to IIviDriver::Initialize or by setting the IIviDriverOperation::Simulate property to true. In either case, Nimbus maintains the current state of the simulate option and makes it available via the GetSimulate function. Thus, the primary tactic for driver developers implementing simulation in a Nimbus driver is to use the GetSimulate function to "synthesize" special simulated results and to avoid calling any of the instrument I/O functions.

In the example below, a configure method is modified to support simulation. Since this function performs only setup operations on the instrument (i.e. no data is read back from the instrument), the implementation need only check for simulation and then return immediately if it is enabled.

C++
Copy
HRESULT Acme4321::IAcme4321_Configure(DOUBLE Frequency, DOUBLE Bandwidth)
{
   // Check for simulation enabled and return immediately if true
   if (GetSimulate())
      return S_OK;

   // If we get to here, simulation is not on, so instrument I/O is performed
   HRESULT hr = io.Printf(_T("SENS:CONF %f, %f"), Frequency, Bandwidth);

   return S_OK;
}

For query methods or property read operations, the driver implementation must return a simulated value for any of the output parameters. The example below demonstrates how to use GetSimulate with a property getter.

C++
Copy
HRESULT Acme4321::IAcme4321_get_Bandwidth(DOUBLE* Frequency)
{
   if (GetSimulate())
   {
      *Frequency = 1.5E7;
      return S_OK;
   }

   HRESULT hr = io.Queryf(_T("SENS:BAND?"), Frequency);

   return hr;
}
Multi-Model Drivers and Simulation

When an IVI driver is operating in connected mode (i.e. not in simulation mode), the instrument model is determined by communicating with the instrument. See the topic InitializeIdentification for details on how this is accomplished. However, when a driver is operating in simulation mode, the instrument model obviously cannot be determined by communicating with the instrument. Instead, the user can specify which instrument model to simulate by passing in a value for a special "Model" initialization option.

The example code below demonstrates how a user would specify the simulated model.

C++
Copy
// Client.cs
IAcme4321 driver = new Acme4321();

// Turn on simulation and specify a simulated model of "4321"
driver.Initialize("GPIB::3", true, true, "Simulate=True, DefaultSetup=Model=4321");

Given the client program above, any model-specific code in the driver implementation would use an instrument model value of "4321". This is the value that would be returned from the GetModel function.

If the "Model" initialization option is not specified when simulation is enabled, then the default model established by the driver developer would be used as the simulated model. The default model is set using the Models Page of the Driver Settings Editor.


Using Code from External DLLs

Since a Nimbus driver is a standard Visual C++ project, it can use code from an external DLL in very much the same fashion as any other Visual C++ project. It may be that an external DLL includes logic for performing register-based I/O or a previous-generation VXI Plug-n-Play driver may exist and the developer wishes to use it directly rather than replicating the logic from scratch in the Nimbus driver code.

The procedure for accessing an external DLL from a Nimbus driver project is essentially the same as for any other Visual C++ project. One item that must be considered is how the external DLL is initialized and closed down, and how it uses instrument I/O. The section below gives a brief example of how the initialization and shutdown of a external DLL may be incorporated into a Nimbus driver.

Initializing and Closing the External DLL

There are several possibilities on where to place the initialization code, but the best place is to override the InitializeIO and CloseIO functions. A simple example of this is shown in the code below.

C++
Copy
HRESULT Acme4321::InitializeIO()
{
  HRESULT hr = __super::InitializeIO();
  if (SUCCEEDED(hr))
  {
    // Initialize the session
    ViStatus status = mydll_initWithOptions(GetResourceDescriptor(), ..., &m_session);
    if (status != VI_SUCCESS)
    {
      // TODO: Report appropriate error based on status code
    }
  }
  return hr;
}

HRESULT Acme4321::CloseIO()
{
  HRESULT hr = __super::CloseIO();
  if (SUCCEEDED(hr))
  {
    // Close the session
    ViStatus status = mydll_close(m_session);
    m_session = VI_NULL;
  }
  return hr;
}
See Also

Other Resources

InitializeIO Method
CloseIO Method
Customizing Driver Initialization


Customizing Config Store Registration

When an IVI driver is installed on an end user system, a number of entries for the driver must be created in the IVI Configuration Store. Information such as the driver's repeated capability physical names, supported IVI instrument classes, and IVI-C prefix is all required by the IVI specifications to be placed in the IVI Configuration Store by the IVI driver installer.

Nimbus maintains the IVI Configuration Store entries for a driver in a special XML file with the following name:

<project>.xml

This file (referred to simply as the Config Store XML file) contains all of the information that the Nimbus driver installer will use when the IVI driver is deployed on the end user system. This Config Store XML file is actually a complete "mini" IVI Configuration Store, with all of the requisite formatting and entries. The driver installer merges the contents of this file with the end-user's IVI Configuration Store file.

Customizing IVI Configuration Store registration for a Nimbus driver consists only of editing the Config Store XML file (<project>.xml) to add the desired entries. Editing the Config Store XML file can be performed in two ways:

  1. Directly editing the Config Store XML with a text editor.

    Caution note Caution

    If you customize the Config Store XML file by directly editing it, you must take great care not to invalidate the file. Nimbus roundtrips this file automatically as the driver project is edited, so it must always be a valid XML file. It must also always comply with the IVI Configuration Store schema. Make certain that any edits performed directly on this file maintain its validity.

  2. Using a 3rd-party IVI Configuration Store editor.

    One of the chief benefits of the Nimbus Config Store XML file being a complete IVI Configuration Store is that it can be edited using any available IVI Configuration Store editor, such as NI-MAX® from National Instruments®. The advantages of this approach are that there is no danger of corrupting the format of the Config Store XML file and that the customization can be performed without having to understand the details of the IVI Configuration Store file format.

See Also

Other Resources

IVI Shared Components


Customizing the Driver Inherent Capabilities

All IVI drivers implement a standard set of IVI-defined methods and properties, irrespective of whether or not an instrument class is supported. This base set of functionality is referred to as the inherent capabilities. For a complete listing of the IVI inherent capabilities, see the IVI specification IVI-3.2: Inherent Capabilities Specification.

Nimbus provides complete implementations for all inherent capability methods and properties. In most cases, the Nimbus-supplied implementations fulfill the requirements of the driver developer. However, the implementation of the inherent capability methods and properties and be customized. Two techniques are available for customizing the behavior of the inherent capabilities:

  1. Using the Driver Info Object to specify basic function behavior.

  2. Overriding the Nimbus-supplied implementation completely.

Customizing the Inherent Capabilities with the Driver Info Object

The Nimbus-supplied implementation of many of the inherent capabilities relies upon a special called the Driver Info object. This object is an instance of a Nimbus-generated class named CDriverInfo and is accessible from any driver method via the GetDriverInfo method. The member variables exposed from this object control the implementation of the inherent capabilities. For example, setting the m_strDriverDescription member controls what is returned from the implementation of the IIviComponentIdentity::Description property.

The Nimbus Template Library documentation for the Driver Info object lists all members available and how they relate to the various inherent capability methods and properties.

Typically, the best place to access the Driver Info object is from the OnFinalConstruct method in the main driver implementation file. The example below demonstrates how to use the Driver Info object to set the timeouts used for the IIviDriverUtility::Reset and IIviDriverUtility::Disable functions.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::OnFinalConstruct()
{
  HRESULT hr = S_OK;

    GetDriverInfo().m_lSelfTestTimeout = 5000;
    GetDriverInfo().m_lDisableTimeout = 5000;

  return hr;
}
Customizing the Inherent Capabilities by Overriding the Default Implementation

In scenarios where there is a need for more control over the inherent capability implementation, the driver developer can simply override the NTL-based implementation. The main driver class implementation file (Co<driverName>.cpp) contains the implementation of all of the inherent capability methods and properties. Most contain a single line of code that delegates to a function in the driver bases classes. This delegation code can simply be replaced with custom logic.

Customizing the Initialize and Close Methods

Two of the IVI inherent capability methods bear special consideration when considering how to customize driver behavior. These are the IIviDriver::Initialize and IIviDriver::Close methods. Unlike the other Nimbus-supplied implementations of inherent capabilities, the implementations of Initialize and Close contain essential code for properly initializing and shutting down core driver features. As such, the implementation of these functions must ALWAYS delegate to the NTL base classes, via calls to DriverBase::Initialize and DriverBase::Close.

Caution note Caution

Never remove the calls to DriverBase::Initialize or DriverBase::Close from the Initialize and Close implementations.

Rather than allowing you to override the Initialize and Close implementations entirely, Nimbus provides a structured way to take control of various stages of driver initialization and shutdown, while still allowing the core Nimbus code to execute. These customization techniques are discussed in detail in the topic Customizing Driver Initialization and Shutdown.

See Also

Other Resources

The Driver Info Object


Customizing Driver Initialization And Shutdown

A Nimbus IVI-COM driver passes through a number of phases after the user code invokes the driver's Initialize method. Many of these tasks are imposed by the IVI specifications themselves, while others initialize special Nimbus driver features. Depending upon the specific driver initialization and shutdown requirements, these steps might need to be augmented or overridden altogether with custom code. The topics in this section explain the customization points that Nimbus provides for injecting custom logic into the intialization and shutdown sequence.

In This Section

Customizing Driver Initialization

Customizing Driver Shutdown


Customizing Driver Initialization

Properly initializing an IVI-COM driver involves a number of tasks that may need to be customized for specific driver requirements. Understanding the order in which Nimbus drivers execute their initialization functions is critical if a driver developer is to successfully control driver initialization. The topics in this section first explain the initialization sequence and then discuss each of the functions that can be used to intercept driver initialization and inject custom logic.

In This Section

Understanding the Initialization Sequence

Initialize Method

InitializeIdentification Method

InitializeIO Method

OnFinalConstruct Method

ResetObjectState Method

OnFinalInitialize Method


Understanding the Initialization Sequence

The instantiation and initialization of an IVI-COM driver follows a series of well-defined steps. At each stage in the process, Nimbus provides customization functions for taking control of some aspect of the driver initialization. The first step in understanding how to customize this process is to understand the sequence in which code executes during the lifetime of an IVI-COM driver instance. Consider the simple C# client code used to instantiate and initialize the Acme4321 IVI-COM driver.

C#
Copy
// Create an instance of the driver
IAcme4321 driver = new Acme4321();

// Initialize the driver
driver.Initialize("GPIB::15", true, true, "");

When the code above executes, the following sequence occurs within the IVI-COM driver:

Step | Function Called | Description
1 | new Acme4321() runs | In another language, this would correspond to another function call, such as CoCreateInstance if a C++ client were in use.
2 | OnFinalConstruct | This method executes on the main driver class only. The repeated capability instances have not been created at this point in the initialization process. This method is called only once over the lifetime of the driver instance, irrespective of the number of times the client application invokes the driver's Initialize method.
3 | driver.Initialize(...) |
4 | IIviDriver::Initialize execution begins | This method executes on the main driver class after each client call to the Initialize method. The NTL implementation of this method (which must ALWAYS be called by the driver implementation) calls several customizable functions on the main driver class and on any repeated capability classes before it finishes.
5 | InitializeIO | By default, Nimbus initializes the selected I/O provider (typically the VISA-COM or VISA-C I/O provider). Drivers using a custom I/O library would override this method to perform custom I/O initialization.
6 | InitializeIdentification | This method is used to set the instrument model, as well as other identification information. By default, Nimbus issues a "*IDN?" query and expects a standard 488.2 response. Drivers that need to use an alternate mechanism for identifying the connected instrument must override this method.
7 | InstrumentSupported | This method checks if the connected instrument is supported by the driver. By default, this function checks that the model detected by the InitializeIdentification method in the previous step is in the list of supported models. This function can be overridden to implement more advanced logic, such as cases where the number of instrument models supported is prohibitively large and/or not precisely enumerable by the driver.
8 | ResetObjectState | This method first executes on the main driver class and then on any repeated capability instances.
9 | OnFinalInitialize | This method first executes on the main driver class and then on any repeated capability instances.
10 | IIviDriver::Initialize execution completes |


Initialize Method

Called be client applications to initialize the driver and establish an I/O connection to the device.

HRESULT Initialize(BSTR ResourceName, VARIANT_BOOL IdQuery, VARIANT_BOOL Reset, VARIANT_BOOL OptionString);
Parameters
ResourceName

[in] String identifier specifying how to connect to the device. Usually a VISA resource descriptor.

IdQuery

[in] Indicates whether the driver should perform an ID query check during initialization.

Reset

[in] Specifies whether the driver should execute the Reset function during initialization.

OptionString

[in] Option string specifying various IVI-defined and driver-specific initialization options.

File

Co<MainClass>.cpp

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

The IIviDriver::Initialize method executes in response to each client program call to Initialize. The default implementation simply delegates to an internal Nimbus implementation that performs a wide variety of tasks. It is critical that any customization of the Initialize function ultimately call the internal Nimbus implementation using the following syntax:

hr = DriverBase::Initialize(ResourceName, IdQuery, Reset, OptionString);

Caution note Caution

If you customize the implementation of IIviDriver::Initialize and do not call the internal Nimbus implementation, the driver will almost certainly not operate correctly. Nimbus relies heavily upon the code inside this internal implementation.

The most common reason to customize the implementation of Initialize is to perform pre-processing or post-processing of the Nimbus implementation. Post-processing is arguably more useful since the driver is not in a fully initialized state before the call to the internal Nimbus implementation.

See Also

Other Resources

Customizing Driver Initialization
Customizing Driver Shutdown


InitializeIdentification Method

Queries the instrument for its identification string and initializes the corresponding driver settings.

virtual HRESULT InitializeIdentification();
Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

When to Override

Override this function when you need to perform custom parsing of the instrument identification string. The default implementation of this function issues a "*IDN?" query and expects a response in the following format:

<manufacturer>,<model>,<serialNumber>,<firmwareRevision>

Remarks

This function is used in the implementation of the IIviDriver::Initialize method. When the driver is initialized, the InitializeIdentification function sends a "*IDN?" query. The instrument responds by returning its identification string, which is parsed to retrieve the instrument manufacturer, the instrument model, the serial number, and the firmware revision. If the instrument does not response to "*IDN?" in the form shown above, then the InitializeIdentification function must be overridden to properly parse and store the instrument identification information.

Note Note

Within the implementation of InitializeIdentification, it is important to ultimately call the SetIdentificationInformation function to properly cache the information parsed from the indentification string. See the example below.

Example
C++
Copy
// CoAcme4321.h
class ATL_NO_VTABLE Acme4321 :
{
   // ...

   virtual HRESULT InitializeIdentification()
   {
      // Query the instrument for its ID string using the command "SYST:ID?"
      // The instrument returns an ID string in the following form:
      //   <manufacturer>;<serialNumber>;<firmwareRevision>;<model>

      CString strManufacturer, strModel, strSerialNumber, strFirmwareRevision;
      HRESULT hr = io.Queryf(_T("SYST:ID?", _T("%s,%s,%s,%s"), &strManufacturer, &strSerialNumber, &strFirmwareRevision, &strModel);
      if (SUCCEEDED(hr))
      {
         // Cache the identification information in the driver
         SetIdentificationInfo(strIdentification, strManufacturer, strModel, strSerialNumber, strFirmwareRevision);
      }

      return hr;
   }

   // ...
}
See Also

Other Resources

Initialize Method
Customizing Driver Initialization


InitializeIO Method

Initializes the instrument I/O communication layer (often VISA or VISA-COM).

virtual HRESULT InitializeIO();
File

Co<MainClass>.cpp

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

When to Override

Override this function when you want to do additional initialization at the same time as when the I/O is initialized. A common case is if you want to implement your driver by delegating to an external DLL for the I/O. You would want to initialize the external DLL here.

Remarks

This function is used in the Nimbus implementation of the IIviDriver::Initialize method.

An alternative is to put the additional initialization code in OnFinalInitialize. One important difference is that InitializeIO is called before GetDynamicRepCapNames, but OnFinalInitialize is called after it. Thus, if the dynamic repeated capability discovery code requires custom I/O initialization, that initialization has to be done in InitializeIO.

Example
C++
Copy
// CoAcme4321.h
class ATL_NO_VTABLE Acme4321 :
{
   // ...

   virtual HRESULT InitializeIO()
   {
      // Call the base class implementation
      HRESULT hr = __super::InitializeIO();
      if (SUCCEEDED(hr))
      {
         CString strResourceDesc = GetResourceDescriptor();

         // TODO: additional I/O initialization here, such as initializing an external DLL
      }

      return hr;
   }

   // ...
}
See Also

Other Resources

Initialize Method
Customizing Driver Initialization


OnFinalConstruct Method

Called during instantiation of a driver.

virtual HRESULT OnFinalConstruct();
File

Co<MainClass>.cpp

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

The OnFinalConstruct method can be used to perform any driver-specific initialization just after object construction. The OnFinalConstruct method executes only once on the main driver classover the lifetime of the driver, irrespective of the number of times a client application calls IIviDriver::Initialize and IIviDriver::Close.

Since OnFinalConstruct executes before IIviDriver::Initialize, this function can be used to initialize data for driver methods that can themselves execute before the client calls IIviDriver::Initialize. In practice, this situation is quite rare, since most driver methods require Initialize to be called. For this reason, OnFinalConstruct is not often used in IVI-COM drivers. Rather, the ResetObjectState method, which is called with each invocation of Initialize, is used. See the description of ResetObjectState for more information.

Note Note

When this function executes, the instrument I/O infrastructure has not yet been initialized. Thus, none of the instrument I/O functions can be used within this function.

See Also

Other Resources

Customizing Driver Initialization


ResetObjectState Method

void ResetObjectState();
File

Co<MainClass>.cpp

Co<RepCapClass>.cpp

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

Drivers often need to cache data of various forms. Typically, cached data is stored as member variables of the main driver class or on repeated capability classes if the data is specific to a repeated capability instance. This cached data is referred to generically as object state. One use of object state in drivers is to store settings that represent the default state of the instrument.

The ResetObjectState method is provided by Nimbus as a single location to place initialization code for cached data. ResetObjectState is called after the IIviDriver:Initialize method but before the call to OnFinalInitialize. ResetObjectState is also called by the Nimbus implementation of IIviDriverUtility::Reset and IIviDriverUtility::ResetWithDefaults.

The ResetObjectState method is called on the main driver class as well as on each repeated capability instance.

Example

The code below demonstrates how to use the ResetObjectState method to initialize member variables on the main driver class.

C++
Copy
// CoAcme4321.cpp
void Acme4321::ResetObjectState()
{
   // Use this function to initialize member variables and any cached data.
   // This function is automatically called in the following circumstances.
   //   1) After IIviDriver::Initialize, just BEFORE FinalInitialize is called
   //   2) After IIviDriverUtility::Reset
   //   3) After IIviDriverUtility::ResetWithDefaults

   // Set the initial active trace window to the first window
   m_lActiveWindow = 1;
}
See Also

Other Resources

Customizing Driver Initialization


OnFinalInitialize Method

Called during initialization of a driver.

virtual HRESULT OnFinalInitialize();
File

Co<MainClass>.cpp

Co<RepCapClass>.cpp

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

The OnFinalInitialize method can be used to perform driver-specific actions immediately after each client call to IIviDriver::Initialize. The OnFinalInitialize method executes on the main driver class and on any repeated capability classes. This function is called after the call to the IIviDriver::Initialize implementation.

When the OnFinalInitialize method executes, Nimbus has performed all of its required internal initialization of the driver. All of the repeated capabilities have been initialized and the ResetObjectState method has run. In addition, the instrument I/O infrastructure has been fully initialized by this point, so any of the instrument I/O functions may be used within this method.

Some common tasks that a driver may wish to perform in OnFinalInitialize include:

  • Validating any custom initialization option string values (via the OptionString parameter) and returning an IVI-defined error, such as E_IVI_BAD_OPTION_VALUE or E_IVI_BAD_OPTION_NAME.

  • Setting the trailing characters to be used when reading and writing data to the instruments with the Nimbus Template Library instrument I/O functions.

  • Querying special instrument capabilities (e.g. firmware options installed) and caching the results.

Example

The example code below shows how to use the OnFinalInitialize method to set the trailing character for instrument reads and writes.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::OnFinalInitialize()
{
   // Use this function to perform any driver-specific actions immediately after each call to IIviDriver::Initialize

   HRESULT hr = S_OK;

   // This will automatically remove the trailing characters
   // when reading strings from the instrument.
   io.SetTrailingForReads(_T("\r\n"));

   // This will automatically add the trailing characters
   // when writing strings to the instrument (if the trailing characters
   // are not already present).
   io.SetTrailingForWrites(_T("\r\n"));

   return hr;
}
See Also

Other Resources

Customizing Driver Initialization


Customizing Driver Shutdown

The shutdown sequence of a Nimbus IVI-COM driver proceeds in an orderly fashion to ensure that driver resources, such as repeated capability pointers or I/O session pointers, are properly released. If the driver developer customized the intialization sequence of the driver, then it may very well be the case that resources were acquired by this custom initialization logic. Those resources would need to be freed during the shutdown sequence of the driver. Alternatively, other cusotm logic might need to be performed at some point after the end user code invokes the driver's Close method.

The topics in this section first explain the initialization sequence and then discuss each of the functions that can be used to intercept driver initialization and inject custom logic.

In This Section

Understanding the Shutdown Sequence

CloseIO Method

OnFinalClose Method

OnFinalRelease Method


Understanding the Shutdown Sequence

Just as the initialization of an IVI-COM driver proceeds in distinct steps, so does the the shutdown process proceed in an orderly fashion. Nimbus provides two functions that can be used to customize the driver shutdown process.

To understand how to customize the driver shutdown process, consider the simple C# client code used to instantiate, initialize, and finally close the Acme4321 IVI-COM driver.

C#
Copy
// Create an instance of the driver
IAcme4321 driver = new Acme4321();

// Initialize the driver
driver.Initialize("GPIB::15", true, true, "");

// ... call various methods/properties on the driver

// Close the driver
driver.Close();

When the code above executes, the first two lines of code first instantiate and then initialize the driver. The sequence of actions that occurs during this initialization process is discussed in the topic Customizing Driver Intialization. After the client application is finished using the driver, a call to IIviDriver::Close triggers the shutdown sequence that is detailed in the table below:

Step | Function Called | Description
1 | driver.Close() runs |
2 | IIviDriver::Close() | This method executes on the main driver class after each client call to the Close method.
3 | CloseIO | By default, Nimbus closes the selected I/O provider (typically the VISA-COM or VISA-C I/O provider). Drivers using a custom I/O library would override this method to perform custom I/O shutdown and to release any custom I/O resources.
4 | OnFinalClose | This method executes on the main driver class and on the repeated capability classes. The OnFinalClose method is called on the repeated capabilities before it is called on the main driver class.
5 | OnFinalRelease | This method executes only on the main driver class. This method is called only once on the main driver class over the lifetime of the driver instance, irrespective of the number of times the client application invokes the driver's Close method.
6 | Main driver class destructor | This code is tightly integrated into the ATL plumbing and is never directly modified in a driver.


CloseIO Method

Closes the instrument I/O communication layer (often VISA or VISA-COM).

virtual HRESULT CloseIO();
File

Co<MainClass>.cpp

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

When to Override

Override this function when you want to perform additional closing at the same time as when the I/O is closed. A common case is if an external DLL library is being used for instrument I/O. You would want to close the external DLL here and release any I/O related resources.

Remarks

This function is used in the implementation of the IIviDriver::Close method.

Example
C++
Copy
// CoAcme4321.cpp
class ATL_NO_VTABLE Acme4321 :
{
   // ...

   virtual HRESULT CloseIO()
   {
      // Call the base class implementation
      HRESULT hr = __super::CloseIO();
      if (SUCCEEDED(hr))
      {
         // TODO: additional I/O shutdown here, such as closing an external DLL
      }

      return hr;
   }

   // ...
}


OnFinalClose Method

Called during the execution of the Close method of a driver.

virtual HRESULT OnFinalClose();
File

Co<MainClass>.cpp

Co<RepCapClass>.cpp

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

The OnFinalClose method can be used to perform driver-specific actions immediately after each client call to IIviDriver::Close. This function is called after the call to the IIviDriver::Close implementation. Repeated capability classes also have an OnFinalClose method that is called before the OnFinalClose of the main driver class.

Note Note

By the time this function executes, the instrument I/O infrastructure has already been torn down. Thus, none of the instrument I/O functions can be used within this function.

See Also

Other Resources

Customizing Driver Shutdown


OnFinalRelease Method

Called during destruction of a driver instance.

virtual HRESULT OnFinalRelease();
File

Co<MainClass>.cpp

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

The OnFinalRelease method executes only once on the main driver class over the lifetime of the driver, irrespective of the number of times a client application calls IIviDriver::Initialize and IIviDriver::Close.

The OnFinalRelease is generally used to cleanup resources allocated in OnFinalConstruct.

Note Note

By the time this function executes, the instrument I/O infrastructure has already been torn down. Thus, none of the instrument I/O functions can be used within this function.

See Also

Other Resources

Customizing Driver Shutdown


Supporting .NET Client Applications

IVI-COM drivers provide seamless support for .NET applications through the use of special "wrapper" DLLs known as interop assemblies. These interop assemblies present a .NET interface to client applications built in languages such as C# and VB.NET. From the perspective of the .NET client, the experience is very much like using a native .NET component. Under the covers, the interop assembly simply delegates to the underlying IVI-COM driver. Nimbus automatically creates an interop assembly for every IVI driver and integrates it into the installer. The interop assembly name has the following form:

<driverVendor>.<driverName>.Interop.dll

This interop assembly is created as part of the driver build sequence and complies with the IVI interop assembly requirements laid out in IVI-3.14: Primary Interop Assembly Specification. The .NET Page of the Driver Settings Editor can be used to control the interop assembly name. In addition, two other critical aspects of .NET interoperability must be considered by the driver developer -- applying a digital signature to the interop assembly and versioning the interop assembly. This topic discusses digital signatures while the topic Understanding .NET Versioning explains how driver version numbers must be managed for .NET.

Interop Assemblies and Digital Signatures

All .NET assemblies can be signed with a digital signature by using a command line tool known as the strong name utility (sn.exe).

There are three main reasons for signing a .NET assembly:

  1. The digital signature allows clients to associate the assembly with a specific software publisher. This assures the end user that the assembly they have really came from the source they expect.

  2. Signing an assembly provides a security assurance to the client application that the assembly has not been tampered with or altered since it was built by the person performing the signing.

  3. Signing an assembly allows the assembly to be deployed in a special shared location on the client machine known as the global assembly cache (GAC). Deploying an assembly in the GAC ensures that .NET client applications will be able to locate and load the assembly at runtime.

For the reasons outlined above, the IVI Foundation requires that IVI-COM driver interop assemblies be signed with a digital signature. See IVI-3.14: Primary Interop Assembly Specification for details. The sections that follow provide basic information on how digital signatures can be applied to an IVI-COM driver.

Basics of Assembly Signing

To sign an interop assembly, you must have a public-private key pair. This public-private key pair is supplied to the strong name utility (sn.exe) to produce the digitally signed interop assembly. Public-private key pairs are extremely sensitive pieces of information. They represent the identity of your company as a software publisher, and, if compromised, could allow malicious users to impersonate your software. Thus, public-private key pairs must be securely stored.

Caution note Caution

Never store a public-private key pair on computer hard drive. A variety of simple, inexpensive devices are available for safely controlling access to the public-private key pair.

Obtaining a Public-Private Key Pair

Most organizations developing IVI-COM drivers are likely to have already dealt with the issue of assembly signing for other .NET products they may have produced. Thus, it is important for the driver developer to check within their own company to determine if a public-private key pair has already been established for the company or organization.

Caution note Caution

Because the public-private key pair represents the digital identity of the company or organization, you should never simply create a new key pair just for the purpose of shipping a single IVI-COM driver. If the IVI-COM driver is, in fact, the first project that requires a public-private key pair, then it is highly recommended that the organization take the appropriate steps to create a standard, secure public-private key pair.

Delay Signing

Since the public-private key pair is a sensitive piece of information and must be maintained in a secure location, driver developers will (hopefully) not have direct access to the key pair from their development machine. Yet, it is the driver developer who must apply the digital signature to the interop assembly when compiling the IVI-COM driver. To deal with this inherent dichotomy, the .NET Framework supports a feature called delay signing.

Delay signing allows a developer to create an interop assembly using only the public key portion of the public-private key pair. Only the private key portion of the key pair is sensitive, so it is perfectly safe to distribute the public key portion to driver developers.

The strong name utility (sn.exe) is used to extract the public key. From a Visual Studio command prompt, the trusted individual maintaining the secure public-private key pair would need to execute the following command:

sn -p keypair.snk public.snk

The above command will extract the public key from the key pair stored in the file keypair.snk and place it in a file called public.snk. The public.snk file is then distributed to the driver developers and other individuals needing to produce .NET components.

With the public key in hand, the driver developer instructs Nimbus to use that public key when building the IVI-COM driver interop assembly. This is done via the .NET Page of the Driver Settings Editor. Since, by definition, the delay-signed interop assembly does not contain a digital signature, it cannot be deployed in the GAC, nor can it be used in .NET applications that expect a full digital signature. Thus, before the driver can be shipped, it must be re-signed using the strong-name utility.

To re-sign an interop assembly, the trusted individual managing the public-private key pair would execute the following command from a Visual Studio command prompt:

sn -R MyCompany.MyDriver.Interop.dll keypair.snk

The above command will apply a full digital signature using keypair.snk to the IVI-COM driver interop assembly MyCompany.MyDriver.Interop.dll. (Note the somewhat verbose format for the interop assembly name follows the IVI-COM interop assembly naming convention presented in IVI-3.14: Primary Interop Assembly Specification).

Caution note Caution

You must never ship an IVI-COM driver interop assembly that has been delay-signed. The driver installer will fail to install the interop assembly in the GAC, and the driver will not be accessible from .NET client applications.

Working with a Delay Signed Assembly

The re-signing procedure described above is typically only done just before an IVI-COM driver is ready to ship. During development, however, it is important to be able to use the interop assembly, particularly for the purposes of unit testing, since NUnit is based on .NET. For a delay-signed interop assembly to work, you must take an explicit step to instruct the .NET Framework not to try to validate the signature on the interop assembly, since it has been delay signed. If you do not perform this step, the delay-signed interop assembly will not deploy into the GAC, nor will it be usable from .NET client applications. This process is called verification skipping.

To register a driver interop assembly for verification skipping, execute the following command from a Visual Studio command prompt. Note that this command requires administrator privileges.

sn -Vr MyCompany.MyDriver.Interop.dll

The above command instructs the .NET Framework to skip verification of the interop assembly, allowing it to be used while it is delay-signed. Note that the command does not modify the interop assembly itself in any way, and the verification skipping only applies to the local machine. Thus, if the interop assembly is placed on a different machine, then it must again be registered for verification skipping by an administrator user on that machine. You can remove the verification skipping registration by executing the following command:

sn -Vu MyCompany.MyDriver.Interop

After executing the above command, the .NET Framework will once again go back to its normal mode of operation when loading the interop assembly, and attempt to verify the digital signature. If the assembly is still delay-signed, then it will not be usable or deployable in the GAC after executing the sn -Vu command.

See Also

Other Resources

public-private key pair
Global Assembly Cache
strong name utility (sn.exe)


Tracing the Execution of an IVI-COM Driver

All IVI-COM drivers produced with Nimbus are instrumented with special code that can trace the execution of the driver when used in an application. Tracing is controlled via special Nimbus-defined tracing parameters passed to the driver in the DriverSetup parameter of the Initialize method. Because tracing is controlled via the Initialize method, this feature is available to end users working with a deployed driver as well as driver developers authoring a driver.

When tracing is enabled, the following information is recorded by the Nimbus-generated code and stored in a trace log file:

  • The method or property name.

  • The value of each [in] and [in, out] parameter passed from the application to the driver.

  • The value of each [out] and [in, out] parameter returned from the driver to the application.

  • The local system date and time at which the driver method or property began executing.

  • The total execution time for the method or property.

Important note Important

Enabling tracing adds overhead to driver execution. Typically, tracing should only be enabled for diagnostic purposes.

Controlling Tracing with the Initialize Method

By default tracing is not enabled in an IVI-COM driver. The end user must explicitly enable tracing by passing Trace=True as part of the DriverSetup parameter in the driver's Initialize method. This is demonstrated in the following C# code:

C#
Copy
driver.Initialize("GPIB::15", true, true, "DriverSetup= Trace=True");

Several other DriverSetup parameters are available for controlling the tracing features of Nimbus IVI-COM drivers. These options are presented in the table below:

DriverSetup Option

Description

Values

Trace

Enable or disable tracing.

true,false

TraceName

If specified, an XML trace file of the specified name is created each time the driver is initialized with tracing enabled.

If not specified, tracing generates a unique XML trace file name based on the date and time. A new file is created each time the driver is initialized with tracing enabled.

If TraceName is a fully qualified path, then the trace log is written to the specified path. If TraceName includes no path information then the file is stored in the current working directory of the calling application. See the section below on The Trace Log File for details.

String name

TraceArray

Specifies if array parameters should be traced.

true,false

TraceArraySizeMax

Specifies the maximum number of elements to trace for array parameters. The default value is 10.

Numeric value in elements

TraceSizeMax

Specifies the maximum size of the trace log file in bytes. Once the file reaches this size, tracing will be turned off automatically by the driver. The default value is 1000000.

Numeric value in bytes

TraceSaveInterval

Specifies how often the driver should save trace data to the trace log file. The value is specified in minutes. The default value is 1.

Numeric value in minutes

The Trace Log File

The trace data collected by the driver during execution is periodically saved to an XML log file. When the driver is closed, the trace log file is closed. If the TraceName option is not specified, Nimbus creates a new trace log file each time the driver is initialized. The trace log file has a name of the following form:

<driverIdentifier>_<timeStamp>.xml

where <timeStamp> is of the form:

yyyy-mm-dd_hr-min-sec

It is important to understand where the trace log file is stored when tracing is enabled. The folder can be controlled by including a fully qualified path in the TraceName option passed to the Intialize method. If the TraceName option does not include path information, then the trace log is written to the current working directory. This folder is determined by the calling application. The trace log file is written to the same folder where the calling application executable (.exe) resides.

Important note Important

When running the IVI-COM driver unit test, the calling "application" is the Nimbus unit test execution engine (MindWorks.IviDriverUnitTestHost.exe). This file is located in the Nimbus installation folder (typically a folder such as C:\Program Files\Pacific MindWorks\Nimbus 2.1). Thus, Nimbus will attempt to write the trace log file to that folder. If User Account Control (UAC) is enabled, then the Program Files folder under which Nimbus is installed may not accessible, in which case the trace log file may not be written. For this reason, it is typically best to specify a full path with the TraceName option when tracing IVI-COM driver unit tests.


Testing an IVI-COM Driver

One of the most important aspects of IVI driver development is authoring and maintaining a suite of driver tests. Nimbus provides integrated unit testing support for IVI-COM drivers and IVI-C wrappers. This topic discusses the IVI-COM driver unit testing features while the topic Testing an IVI-C Wrapper explains how to perform similar tasks with IVI-C wrappers.

Important note Important

When testing an IVI-COM driver using the Visual Studio debugger, whether it be inside a unit test or in a standalone application, there is a debugger setting that should be changed from its default value. From the Tools menu, choose Options to bring up the Options Dialog.

From the tree view on the left, choose Debugging. Uncheck the box labeled Enable property evaluation and other implicit function calls.

If this option is left at its default enabled setting, then the Visual Studio debugger will sporadically execute properties on the driver as you are debugging. This will trigger unexpected and undesired instrument communication and produce confusing results.

Creating an IVI-COM Driver Unit Test

All of the unit test code for an IVI-COM driver is housed in a single Visual C# project created by Nimbus. Typically, this project is created upfront with the other driver projects after the New IVI-COM Driver Wizard runs. This is controlled by the Create IVI-COM unit test check box on the Projects page of the New IVI-COM Driver Wizard.

If the unit test project is not created by the wizard, then it can always be generated at any stage of driver development by right-clicking on the solution node in Solution Explorer and choosing Add New Project....

Structure of an IVI-COM Driver Unit Test

The IVI-COM driver unit tests are contained within the unit test project, named as follows:

<driverName>UnitTest

This Visual C# project contains one source file per IVI-COM interface. Each source file contains one test class for the interface, and the test class contains one test method per driver method or property in that interface.

The code below shows an example of a test class.

C#
Copy
// IIviScopeTriggerEdgeTest.cs
[TestClass]
public class IIviScopeTriggerEdgeTest : BaseTest
{
    protected IIviScopeTriggerEdge Interface { get; private set; }

    public override void _Init()
    {
        base._Init();

        m_interface = m_host as IIviScopeTriggerEdge;
    }

    [TestMethod]
    public void Configure()
    {
        string Source = "Internal";
        double Level = 0.1;
        IviScopeTriggerSlopeEnum Slope = IviScopeTriggerSlopeEnum.IviScopeTriggerSlopePositive;
        this.Interface.Configure(Source, Level, Slope);
    }

    [TestMethod]
    public void Slope()
    {`
        IviScopeTriggerSlopeEnum inVal;
        IviScopeTriggerSlopeEnum outVal;

        inVal = IviScopeTriggerSlopeEnum.IviScopeTriggerSlopePositive;
        this.Interface.Slope = inVal;
        outVal = this.Interface.Slope;
        Assert.AreEqual(inVal, outVal);

        inVal = IviScopeTriggerSlopeEnum.IviScopeTriggerSlopeNegative;
        this.Interface.Slope = inVal;
        outVal = this.Interface.Slope;
        Assert.AreEqual(inVal, outVal);
    }
}

The above test shows the IIviScopeTriggerEdgeTest class that is used to test the methods and properties in the IIviScopeTriggerEdge interface. The class is adorned with a [TestClass] attribute to indicate that the class contains unit test methods. Similarly, each test method within the class is adorned with a [Test] attribute to indicate that it is a test method.

The Slope test method in the example above is used to exercise the IIviScopeTriggerEdge::Slope property in the driver. Note that a single test method is used to test both the property getter and the property setter. In this example, the test method sets the Slope property to the enum value IviScopeTriggerSlopePositive and then immediately reads back the value of the property. The m_interface member variable is used to access driver methods and properties on the IIviScopeTriggerEdge interface. The Assert class is used to compare the value written with the value read back. If the comparison fails, then an exception is thrown and a test failure is reported in the Test Results window. The process is repeated for the IviScopeTriggerSlopeNegative enum value.

Test Initialization and Shutdown

Each test class in a unit test project derives from a BaseTest class. The BaseTest class is defined in the BaseTest.cs file of the unit test project. It serves two purposes in driver unit testing:

  • It provides a place to define common member variables that many test classes might need, such as the Driver property that can be used by any test method to access any driver method or property.

  • It defines the _Init and _Close methods that are executed before and after each test method in the unit test project.

The key methods of interest in the BaseTest class are the _Init and _Close. and is marked with the [Setup] attribute. This method is executed before each test method. The _Init method is responsible for instantiating the driver performing any other driver-specific setup the test methods may require. Since every test class derives from the BaseTest class, they all share the same _Init method. If a particular set of unit tests need interface-specific initialization, then the test class can override the definition of _Init in the BaseTest class.

The code below demonstrates how a test class overrides _Init in order to initialize the Driver property and to call the ConfigureWaveform methodh.

Important note Important

It is critical that any override of _Init call the base class _Init function, as shown in the example below. The driver will not be properly initialized if the base class implementation is not called.

C#
Copy
// IIviScopeTriggerEdgeTest.cs
[TestClass]
public class IIviScopeTriggerEdgeTest : BaseTest
{
    protected IIviScopeTriggerEdge Interface { get; private set; }

    public override void _Init()
    {
        base._Init();

        this.Interface = (this.Driver as IIviScopeTriggerEdge);

    this.Driver.Waveform.ConfigureWaveform(Waveform.Sine, 1000, 0.1);
    }

  // ... test methods
}

The _Close function on the BaseTest class is executed after each test method and is responsible for calling the Close method. As with the _Init function, the _Close function can also be customized on a per-test-class basis by overriding it in the test class.

Running Unit Tests

The unit tests generated by Nimbus integrate directly with Visual Studio's native unit testing features. The starting point for executing tests is to bring up the Visual Studio Test View, which is typically docked as a tab within Solution Explorer. To bring up Test View for executing unit tests, click on the Test menu, then choose Windows and select Test View.

Once the Test View window is shown, executing tests proceeds in the exact same fashion as any other Visual Studio unit test. For details on working with the Visual Studio unit testing features, see the MSDN topic Verifying Code by Using Unit Tests.

Tip Tip

Nimbus drivers typically contain a large number of unit tests. To work with the Test View effectively, use the Group By combo box, which offers a variety of choices for organizing the display of unit tests in the Test View. For Nimbus drivers, setting the Group By combo box to Class Name is often the most effective presentation of the unit test methods.

See Also

Other Resources

Verifying Code by Using Unit Tests


Testing an IVI-C Wrapper

One of the most important aspects of IVI driver development is authoring and maintaining a suite of driver tests. Nimbus provides integrated unit testing support for IVI-COM drivers and IVI-C wrappers. This topic discusses the IVI-C wrapper unit testing features while the topic Testing an IVI-COM Driver explains how to perform similar tasks with the underlying IVI-COM driver.

Creating an IVI-C Wrapper Unit Test

All of the unit test code for an IVI-C wrapper is housed in a single Visual C++ project created by Nimbus. Typically, this project is created upfront with the other driver projects after the New IVI-COM Driver Wizard runs. This is controlled by the Create IVI-C unit test check box on the Projects page of the New IVI-COM Driver Wizard.

If the IVI-C unit test project is not created by the wizard, then it can always be generated at any stage of driver development by right-clicking on the solution node in Solution Explorer and choosing Add New Project....

Structure of an IVI-C Wrapper Unit Test

The IVI-C wrapper unit tests are contained within the IVI-C unit test project, named as follows:

<driverName>CWrapperUnitTest

This Visual C++ project contains a single source file -- UnitTest.cpp. This source file contains one test function for each IVI-C wrapper function and attribute.

C++
Copy
// UnitTest.cpp
[TestMethod]
void ConfigureEdgeTriggerSource()
{
    ViStatus status = VI_SUCCESS;
    ViConstString Source = "External";
    ViReal64 Level = 0.1;
    ViInt32 Slope = ACME4321_VAL_NEGATIVE;
    status = acme4321_ConfigureEdgeTriggerSource(g_session, Source, Level, Slope);
    Assert::AreEqual(VI_SUCCESS, status);
}

The above code shows a test function for the ConfigureEdgeTriggerSource IVI-C wrapper function. The [TestMethod] attribute marks the function as being a unit test for the Visual Studio unit test execution engine.

The Assert::AreEqual method is used to check that the status returned from the ConfigureEdgeTriggerSource driver function is equal to VI_SUCCESS. If the comparison fails, then an exception is thrown and a test failure is reported in the Test Results window.

Test Initialization and Shutdown

The IVI-C unit test code includes two special functions known as the initialize and cleanup functions. These two functions appear at the top of the UnitTest.cpp file and are declared with two special attributes -- the [TestInitialize] attribute and the [TestCleanup] attribute. The code below shows two typical initialize and cleanup functions.

C++
Copy
// UnitTest.cpp
[TestInitialize]
void Initialize()
{
    ViStatus status = acm_InitWithOptions(g_resourceDesc, VI_TRUE, VI_TRUE, "QueryInstrStatus=True, Simulate=False, DriverSetup= ", &g_session);
    Assert::AreEqual(VI_SUCCESS, status);
};

[TestCleanup]
void Cleanup()
{
    if (g_session != VI_NULL)
    {
        ViStatus status = acm_close(g_session);
        Assert::AreEqual(VI_SUCCESS, status);
        g_session = VI_NULL;
    }
};

The initialize function executes before each test method in the project, while the cleanup function executes after each test method. The primary role of the initialize function is to initialze the driver by calling the InitWithOptions function. If the init call is successful, then the driver session is stored in the g_session global variable. All of the test functions use the g_session to execute driver functions. Correspondingly, the role of the cleanup function is to close the driver session by executing the driver's close function on the global g_session.

Drivers that require special configuration or setup prior to testing methods can add custom code to the setup function. Though less common, custom code can also be added to the teardown function.

Running Unit Tests

The unit tests generated by Nimbus integrate directly with Visual Studio's native unit testing features. The starting point for executing tests is to bring up the Visual Studio Test View, which is typically docked as a tab within Solution Explorer. To bring up Test View for executing unit tests, click on the Test menu, then choose Windows and select Test View.

Once the Test View window is shown, executing tests proceeds in the exact same fashion as any other Visual Studio unit test. For details on working with the Visual Studio unit testing features, see the MSDN topic Verifying Code by Using Unit Tests.

Tip Tip

Nimbus drivers typically contain a large number of unit tests. To work with the Test View effectively, use the Group By combo box, which offers a variety of choices for organizing the display of unit tests in the Test View. For Nimbus drivers, setting the Group By combo box to Class Name is often the most effective presentation of the unit test methods.

See Also

Other Resources

Verifying Code by Using Unit Tests


Creating a MATLAB Wrapper

With the release of MATLAB® classes in the R2009a release of MATLAB®, IVI-COM drivers can be represented in a very natural, hierarchical fashion in MATLAB. The MATLAB Instrument Control Toolbox allows MATLAB users to access both the instrument-specific and class-compliant interfaces exposed from any compliant IVI-COM driver. To fully integrate IVI-COM drivers with the MATLAB environment requires special MATLAB "wrapper" classes that encapsulate the COM programming details and expose a more natural and familiar interface to the MATLAB user. Nimbus can be instructed to automatically generate these wrapper classes for any IVI-COM driver by changing a single setting on the MATLAB Page of the IVI-COM driver Driver Settings Editor.

Requirements for Using MATLAB Wrapper Classes

In order to use the generated MATLAB classes, the end user system must meet the following requirements:

  1. MATLAB R2009a or later.

  2. MATLAB Instrument Control Toolbox

Note Note

The Nimbus driver developer does not need to have MATLAB installed in order to generate the MATLAB wrapper classes. Only end users developing with the wrappers need to meet the above requirements. Obviously, driver developers working without MATLAB have no way to test their MATLAB wrapper, so validation must be performed on a machine that also meets the above requirements.

Fundamentals of MATLAB Driver Wrappers

A MATLAB wrapper in Nimbus is a series of MATLAB M-files (.m) that define a set of MATLAB classes. These classes are arranged in a hierarchy that exactly matches the hierarchy of the underlying IVI-COM driver. One MATLAB class is generated in one .m file for each instrument-specific IVI-COM interface in the driver. MATLAB ships with pre-built classes for all of the IVI-defined instrument classes (e.g. IviDmm, IviSpecAn, IviScope, etc.), so Nimbus does not generate any .m files for IVI-defined interfaces. Rather, if a Nimbus driver supports an IVI-defined instrument class, the Nimbus-generated MATLAB wrapper will utilize object-oriented features in MATLAB to inherit from the appropriate pre-built IVI wrapper class. In this way, the MATLAB user has a consistent and natural way to access all of the functionality in a Nimbus IVI driver -- class-compliant and instrument-specific.

The hierarchy of methods and properties in a MATLAB wrapper is established by the hierarchy of .m files in special folders that MATLAB knows to search on an end-user system. When MATLAB wrapper generation is enabled via the MATLAB Page of the IVI-COM driver Driver Settings Editor, Nimbus not only generates the appropriate MATLAB classes and .m files, but it also modifies the driver installer so that the .m files are deployed on the end user system where MATLAB expects these classes to be. Specifically, the driver installer will deploy the .m files in the following folder:

<IviInstallDir>\Components\MATLAB\+instrument\+driver\+<driverName>

For example, a typical end user system would find the MATLAB wrapper files in the following folder:

C:\Program Files\IVI Foundation\IVI\Components\MATLAB\+instrument\+driver\+Acme4321


Versioning an IVI-COM Driver

Driver functionality must necessarily evolve over time, as new features are introduced into the associated instrument. Both the IVI Foundation and COM impose specific requirements on how new functionality is introduced in an IVI driver. These requirements are intended to preserve backwards compatibility and minimize the disruption to existing IVI-based application code.

The topics in this section explain the issues involved in versioning IVI drivers and the features provided by Nimbus to address those issues.

In This Section

Basics of IVI Driver Versioning

Understanding COM Versioning

Understanding .NET Versioning

Revise Interface Dialog


Basics of IVI Driver Versioning

Once a driver has been implemented, tested, and released, it should not be modified in ways that would break backwards compatibility with applications built against the released driver. Nimbus offers a Publish command that, when executed, locks down the driver such that it cannot be modified in ways that would make it incompatible with the released version. After publishing a driver via the Publish command, the driver interface definitions and other API elements can only be modified by explicitly versioning an interface via the Revise Interface command.

This topic explains how drivers are published after release and how published drivers are subsequently revised to accommodate new requirements.

Publishing an IVI Driver

The goal of IVI driver versioning is to enable end users to install a new version of a driver without invalidating existing applications built against against the previous version of the driver. Ideally, client applications should require no modification nor even a re-compile or re-link. This should be the case irrespective of the IDE in which the IVI driver is used. To accomplish this, a variety of rules must be obeyed once an IVI driver has been released (aka "published") to customers. These rules are summarized later in this section.

Nimbus offers a Publish command that helps enforce the rules for maintaining a driver that has been released to customers.

Caution note Caution

Before publishing a driver with the Publish command, be certain that the driver requires no further modification for release. Once the Publish command has been executed, the driver can only be modified using the Revise Interface command described below. There is "Unpublish" command.

To publish an IVI driver

  1. From Solution Explorer, right-click on the the Nimbus node, and choose Publish....

  2. A confirmation dialog is presented to confirm the command.

  3. When the command completes, the methods and properties appear in blue in the tree view, indicating that they are published and cannot be directly modified.

Rules for Maintain Backwards Compatibility with Released Drivers

Do not add or remove methods or properties from an IVI-COM interface

The fundamental rule for versioning IVI-COM interfaces is simple: interfaces are immutable. This means that methods and properties cannot be added or removed from an IVI-COM driver interface after the interface has been published. Doing so would break COM's binary compatibility model, and client applications will fail to compile or to run after installing an improperly versioned IVI-COM driver. Sometimes these runtime failures can be subtle indeed. Thus, it is critical that proper COM versioning techniques be used when adding or removing interfaces from an IVI-COM driver.

For a discussion of COM versioning, see the topic Understanding COM Versioning.

Do not change the signature of a method or property

As discussed in Rule 1, COM intefaces are immutable. It follows that the method and property definitions within an inteface are also immutable. This means that once you have published a driver, you cannot change the signature of any methods or properties in any interface. The signature includes the method or property name, return type, as well as the type and number of parameters. You cannot add or remove parameters, nor can you change the data type of any of the parameters or the return type.

Do not change the name or value of an IVI-C attribute identifier

IVI-C attributes are implemented as #define statements in the IVI-C header file (<prefix>.h). Neither the symbolic name nor the numeric value for the attribute can change after the driver has been published.

Do not change the name or numeric value of enum members

Enums in IVI-COM are part of the signature of the method (or property) in which they are used. Thus, with respect to IVI-COM, this rule is really just a specific case of Rule 2 above. For IVI-C, enum values are represented as #define statements in the IVI-C header file (<prefix>.h).

Do not change the name or numeric value of error codes

Error codes in both IVI-COM and IVI-C have symbolic names and error code values. Only the specific error field (bits 11-0 of the error value) portion of the error code value may be edited by the driver developer. The other portions of the error code are prescribed by IVI-3.1: Driver Architecture Specification. Since client applications will have direct references to the error code names and values, it is important not to change these either of these after publishing a driver.

Revising a Published IVI Driver Interface

Once an IVI driver interface has been published via the Publish command, the only way to make changes to the driver hierarchy is by revising the interface using the Revise Interface command. Nimbus offers two techniques for revising an interface, and it's important to understand the implications of choosing one technique over the other. See the topic Understanding COM Versioning for a discussion of the two IVI driver versioning techniques offered by Nimbus.

To revise a published IVI driver interface

  1. From Solution Explorer, double-click the Driver Designer node under the Nimbus node.

  2. The Driver Designer opens as a tabbed document window. Select the IVI-COM tab.

  3. Click the Hierarchical button beneath the tree view on the left side of the IVI-COM Designer.

  4. Locate the interface reference property for the interface you wish to version. If working from the flat view, locate the interface directly.

    Right-click and choose Revise Interface. The Revise Interface Dialog appears. See the help topic for the Revise Interface Dialog for details on the options available.


Understanding COM Versioning

The goal of COM's versioning scheme is to allow end users to install updated versions of COM components without breaking existing code. Indeed, if properly done, COM versioning allows existing client applications to dynamically load a new COM component without even recompiling the application.

For COM versioning to work, new versions of COM interfaces must maintain binary compatibility with previous versions. Although other techniques for achieving this exist, by far the most common and straightforward technique uses simple interface inheritance.

In addition to the traditional versioning approach of interface inheritance, Nimbus supports a second mode of versioning that allows methods and properties to be deleted. Or, it may simply be the case that after multiple versioning sequences have been performed on an IVI-COM driver, the interface becomes cluttered with outdated references. In these cases, it may be desirable to break backwards compatibility in favor of a more presentable interface. The important consequence of this versioning approach is that client applications built against the driver may need to be recompiled.

This topic presents both versioning techniques available with Nimbus.

Using Interface Inheritance for COM Versioning

The fundamental limitation of COM versioning and the interface inheritance technique is that methods and properties can only be added -- they cannot be removed. This makes sense in general, considering that existing client applications may reference a method or property that gets removed, and these client applications would not compile against a new version. This is obviously not a restriction that is specific to COM -- any versioning scheme that allows deletion of published functionality will break client code.

Adding new methods and properties is far more common, and interface inheritance fits the bill here very nicely. Consider the following definition of an interface ICalc that has been released to customers: (Note the syntax used here is a simplied form of the IDL-like definitions that can be found in a Nimbus project's interface definition file (<project>.nimbus.idl) file.

C++
Copy
// Acme4321.nimbus.idl
[
  object,
  uuid("79f6d7a2-bce6-4915-8906-8d5d8be61556"),    // This is the unique identifier for the ICalc interface ONLY
  // ...
]
interface ICalc : IUnknown
{
  HRESULT Add([in] int x, [in] int y, [out, retval] int* z);

  HRESULT Subtract([in] int x, [in] int y, [out, retval] int* z);
}

The ICalc interface defined above contains two methods -- Add and Subtract. If we wish to release a new version of a calculator component that adds new methods, then we define a new interface ICalc2 that derives from ICalc. Note that it is crucial to generate a new UUID for the ICalc2 interface, since it is distinct from ICalc.

C++
Copy
// Acme4321.nimbus.idl
[
  object,
  uuid("9C4AE307-B366-41d5-9BAD-BD4CF59CF19C"),    // This is the unique identifier for the ICalc2 interface ONLY
  // ...
]
interface ICalc2 : ICalc
{
  HRESULT Multiply([in] int x, [in] int y, [out, retval] int* z);

  HRESULT Divide([in] int x, [in] int y, [out, retval] int* z);
}

The ICalc2 interface as defined above actually contains 4 methods total -- the Multiply and Divide methods defined directly on ICalc2 as well as the Add and Subtract methods inherited from ICalc. The net result of this inheritance-based versioning scheme is two-fold:

  1. New client applications can access all of the functionality defined on ICalc and ICalc2 by using ICalc2.

  2. Existing client applications that upgrade to the new component can continue using ICalc and will work without recompiling. This is because ICalc2 can be used anywhere an ICalc reference can be used -- this is, after all, the whole point of inheritance.

Versioning By Creating a New Interface

As previously discussed, it is sometimes necessary to remove functionality from an IVI-COM driver. This cannot be accomplished with the interface inheritance technique discussed above. Because the versioned interface derives from the original interface, it has all of the original interface members, and these are visible to the user.

Nimbus offers an alternate technique for versioning whereby a "clone" of the original interface is made and exposed from the driver. There is no inheritance relationship between the new interface and the old interface, so methods and properties can be removed from the revised interface. Nimbus preserves the original interface definition so that the existing applications do not need to be rewritten. It should be noted, however, that some types of applications may need to be recompiled when this mode of versioning is employed.


Understanding .NET Versioning

Unlike COM versioning, the versioning mechanisms in .NET do not rely upon binary compatibility between interfaces. Rather, the entire .NET DLL (known as an assembly) is versioned as a unit. All interfaces, classes, enums, and other types within a single .NET assembly carry the same version number assigned to the assembly as a whole. Also unlike COM versioning which uses only a two-part version number, .NET version numbers contain four parts. These version numbers have the following form:

<major>.<minor>.<build>.<revision>

Since IVI-COM drivers are exposed to .NET client applications (such as C# and VB.NET applications) via a .NET interop assembly, the IVI driver must properly manage the .NET interop assembly version number to ensure client applications do not break when new driver versions are introduced.

.NET Assembly Versions and Client Applications

The key to understanding .NET versioning is realizing that the version number of an assembly is embedded into each client application that uses the assembly. When a C# client application adds a reference to an IVI-COM driver and compiles the code, the full four-part version number of the driver interop assembly is "baked" into the client DLL. Whenever that client application runs, the .NET runtime will verify that the version number of the loaded interop assembly matches the version number of the interop assembly against which the client application was originally built. If the two version numbers do not match EXACTLY (all four parts must match), then an exception is generated and the client application will not run.

At first glance, it might seem that distributing an updated version of an IVI driver would require all .NET applications to be recompiled, so that the new version number of the interop assembly would be embedded in the client application. This would be a most intrusive versioning scheme indeed. Fortunately, the .NET Framework provides a special mechanism that allows existing client applications to load newer versions of assemblies without being recompiled. This mechanism relies on special companion files known as policy files. These are discussed in the next section.

IVI Drivers and Policy Files

A .NET policy file is a specially formatted and specially named DLL companion file that ships alongside a .NET assembly, such as an IVI driver interop assembly. The policy file contains special statements known as binding re-direct statements. These binding re-directs tell the .NET runtime to load a designated version of an assembly (typically a newer version) instead of an existing version that a client application might be compiled against. This allows .NET client applications to be seamlessly upgraded to newer versions without having to be recompiled.

As an example, consider the following scenario. An end user builds a C# client application using version 1.0.0.0 of an IVI-COM driver. Several months later, the vendor of the IVI-COM driver ships version 2.0.0.0. If the end user installs version 2.0.0.0 of the driver and tries to run the application, it will fail to load because the application contains a reference to version 1.0.0.0 of the driver's interop assembly. What the driver vendor must do is create and distribute a policy file that contains the appropriate statements to say to the .NET runtime -- "for any client application that attempts to load version 1.0.0.0, load version 2.0.0.0 instead". With the policy file installed alongside the driver's interop assembly, any client applications using version 1.0.0.0 of the driver will automatically be "re-directed" to load version 2.0.0.0. In fact, version 1.0.0.0 of the driver need not even be installed anywhere on the client machine.

Managing Policy Files with Nimbus

Nimbus will automatically create the appropriate policy files for an IVI-COM driver given simple compatibility statements the driver developer makes about the driver. The General Page of the Driver Settings Editor contains a list of compatible versions. This allows the driver developer to express which previous versions of the driver are compatible with the current version. For each compatible version listed, Nimbus will create a policy file and integrate it with the driver installer. Each policy file contains the appropriate binding re-direct statements to upgrade .NET clients from that specific version to the latest version of the driver.

The .NET runtime requires a very specific name for policy files in order to properly mate them with their associated assemblies at runtime. The policy files must have the following form:

Policy.<major>.<minor>.<assembly>.dll

In the above name, the major and minor version numbers refer to the previous version to upgrade FROM. For example, for a driver named "Acme4321" shipped by a company called "Acme", the policy file for upgrading clients from version 1.0 to the latest version would be named as follows:

Policy.1.0.Acme.Acme4321.Interop.dll

Limitations of Policy Files

One fundamental limitation of .NET versioning is that policy files can only be used to re-direct versions based on the major and minor version numbers. Even though the .NET runtime uses all four parts of the version number in resolving assembly versions at runtime, the policy file mechanism can only discriminate assemblies based on the major and minor portions of the four-part version. This explains why the standard format policy file name above only contains a two-part version number. What this means is that you cannot upgrade version 1.0.1.0 to a different assembly than the one to which you upgrade version 1.0.2.0. Any client compiled against 1.0.X.X would be upgraded to the same assembly version. In practice, this is rarely an issue for IVI drivers.

Signing Policy Files

Policy files are DLLs that must be installed in the global assembly cache (GAC) just as the interop assemblies themselves. Thus, they must ultimately be signed with a digital signature just like the driver interop assemblies. Nimbus automatically manages the digital signature for policy files in the same way it manages them for interop assemblies.

For more information on digitial signatures for IVI drivers, see the topic Supporting .NET Client Applications.

See Also

Other Resources

Supporting .NET Client Applications
Supporting .NET Client Applications
How to: Create a Publisher Policy File
global assembly cache (GAC)


Revise Interface Dialog

The Revise Interface Dialog is used to perform versioning on an interface that has been published. The dialog offers two options for revising the interface.

For background information on versioning COM interfaces, see the topic Understanding COM Versioning

Add to existing interface

Selecting this mode of versioning uses traditional COM interface inheritance to revise the interface. Binary backwards compatibility is fully preserved. The primary limitation of this versioning mode is that methods and properties defined in the original interface cannot be deleted. The user will see the "union" of interfaces, methods, and properties.

Modify existing interface

This option is useful when methods and properties need to be removed from the interface. Nimbus preserves the original interface for existing applications and creates a cloned interface that will be the one visible in the driver hierarchy.

Update version

Choosing this option allows you to update the driver version number. This has the same effect as explicitly changing the driver version number via the General Page of the Driver Settings Editor.

Add current version to compatible versions

If checked, Nimbus will add the current driver version to the list of compatible driver version numbers. This information is used to create the driver's .NET versioning policy.

Checking this box has the same effect as explicitly adding a compatible version via the General Page of the Driver Settings Editor.

For more information on .NET policy files, see the IVI-COM driver topic Understanding .NET Versioning.


The Nimbus Template Library (NTL)

In This Section

The Driver Info Object

The I/O Object

Instrument Command Functions

The Error Reporter Object

Instrument Model Functions

Configuration Server Functions

Repeated Capability Functions

State Caching Functions

Driver State Functions

Miscellaneous Functions


The Driver Info Object

The Nimbus Template Library supplies a special object called the Driver Info object for controlling the standard Nimbus implementation of various IVI-defined functions. Previous versions of Nimbus relied upon virtual functions that the driver developer needed to override separately to customize the NTL default behavior. The Driver Info object simplifies this customization.

Driver Info Object Members

The Driver Info object is an instance of the CDriverInfo class defined in NtlDriver.h. A single instance of this class is created and managed by Nimbus. The table below explains each of the members and the role they play in controlling the Nimbus implementation of various functions. It is important to note that some of these members are controlled via various settings in the Driver Settings Editor, while other members can be directly set in the OnFinalConstruct or the OnFinalInitialize methods.

Member | Data Type | How to Set | Default | Description
m_strSoftwareModuleName | CString | Manual | <projectName> OR <prefix>, if IVI-C is enabled | Name of the software module in the IVI Configuration Store. This value should not be changed directly. Rather the project should be renamed or the IVI-C prefix should be modified.
m_strDriverIdentifier | CString | Manual | <projectName> | Used to implement the IIviDriver::Identity property.
m_strDriverVendor | CString | Driver Settings | Specified in wizard | Used to implement the IIviComponentIdentity::Vendor property.
m_strDriverDescription | CString | Driver Settings | Specified in wizard | Used to implement the IIviComponentIdentity::Description property.
m_strDriverRevision | CString | Driver Settings | 1.0 | Used to implement the IIviComponentIdentity::Revision property.
m_strGroupCapabilities | CString | Driver Settings | All groups in selected classes | Used to implement the IIviDriverIdentity::GroupCapabilities property.
m_strSupportedModels | CString | Driver Settings | <projectName> | Used to implement the IIviDriverIdentity::SupportedInstrumentModels property.
m_strDefaultSimulatedModel | CString | Driver Settings | First supported model | Used to determine which model is assumed when simulating and no Model option is passed to Initialize.
m_lSpecificationMajorVersion | long | Driver Settings | Major version of class spec | Used to implement the IIviDriverIdentity::SpecificationMajorVersion property.
m_lSpecificationMinorVersion | long | Driver Settings | Minor version of class spec | Used to implement the IIviDriverIdentity::SpecificationMinorVersion property.
m_bInterchangeCheckSupported | bool | Manual | false | Indicates if the driver supports interchangeability checking. A runtime error will be generated in Initialize if the user tries to enable interchangeability checking and this member is set to false.
m_bResetSupported | bool | Manual | true | Indicates if the driver supports the Reset function. A runtime error will be generated in Initialize if the user tries to reset the device and this member is set to false.
m_bSelfTestSupported | bool | Manual | true | Indicates if the driver supports the IIviDriverUtility::SelfTest function.
m_bRevisionQuerySupported | bool | Manual | true | Indicates if the driver supports querying for the driver version number.
m_bIdQuerySupported | bool | Manual | true | Indicates if the driver supports querying the instrument for its identification information.
m_lSelfTestTimeout | long | Manual | 2000 | Specifies the I/O timeout value (in milliseconds) to use when executing the IIviDriverUtility::SelfTest function.
m_lDisableTimeout | long | Manual | 2000 | Specifies the I/O timeout value (in milliseconds) to use when executing the IIviDriverUtility::Disable function.
m_lResetTimeout | long | Manual | 2000 | Specifies the I/O timeout value (in milliseconds) to use when executing the IIviDriverUtility::Disable function.
m_lCoercionLogSize | long | Manual | 1000 | Specifies the size of the internal buffer used to store coercion log entries. The size is indicated in terms of the number of entries. Once the coercion log is full, entries are overwritten starting with the oldest.
Accessing the Driver Info Object

The Driver Info object is accessed via the GetDriverInfo function. Typically settings that need to be overridden are set in the OnFinalConstruct function. This function executes only once over the lifetime of the driver (NOT once per Initialize call) and since the settings available on the Driver Info object typically do not depend upon the specific instrument connection (for instance, the specific model connected), the OnFinalConstruct function is the typical choice for customizing the Driver Info object settings.

If the desired Driver Info object settings depend upon some aspect of the specific instrument connected (such as the specific model), then the OnFinalInitialize function can be used to customize the Driver Info object settings. This function executes at the last stage of driver initialization so all of the model identification information is available.

The example code below demonstrates changing the timeout values used for the Reset and Disable functions.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::OnFinalConstruct()
{
  HRESULT hr = S_OK;

    GetDriverInfo().m_lSelfTestTimeout = 5000;
    GetDriverInfo().m_lDisableTimeout = 5000;

  return hr;
}


The I/O Object

The I/O object is the primary means for instrument communication in Nimbus. The I/O object exposes a wide variety of functions for performing instrument communication, including buffered and non-buffered I/O.

Most functions exposed from the I/O object are available independent of the underlying I/O provider. However, some functions are specific to VISA-C while others are specific to VISA-COM. Separate sections highlighting these provider-specific functions are provided.

In This Section

Session Management Functions

Printf-Style Functions

Basic I/O Functions

Low-Level I/O Functions

Buffer Management Functions

Instrument Error Functions

VISA-Specific Functions

See Also

Other Resources

Communicating With Instruments
Using the I/O Object


Session Management Functions

The functions in this section control a variety of settings that are global to the I/O session. The settings configured here are used by many Nimbus I/O functions.

In This Section

ReadStatusByte

Clear

SetTrailingForReads

GetTrailingForReads

SetTrailingForWrites

GetTrailingForWrites

SetInstrumentBigEndian

GetInstrumentBigEndian

SetTimeout

GetTimeout

SetTerminationCharacter

GetTerminationCharacter

SetTerminationCharacterEnabled

GetTerminationCharacterEnabled

Lock

Unlock

IoLockType Enumeration


ReadStatusByte

Reads a status byte from a device.

virtual HRESULT ReadStatusByte(short* psStatusByte) abstract;
Parameters
psStatusByte

[in] Status byte read from the device.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Example

The following example demonstrates use of the ReadStatusByte function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::Configure()
{
  HRESULT hr = S_OK;

  short sStatus;
  hr = io.ReadStatusByte(&sStatus);

  return hr;
}


Clear

This operation performs an IEEE 488.1-style clear of the device.

virtual HRESULT Clear() abstract;
Remarks

The exact operation performed depends upon the type of I/O session. For VISA I/O sessions, various operations make occur based on the specific VISA session type. For instance, for VXI INSTR sessions, the Word Serial Clear command is used. For GPIB INSTR sessions, the Selected Device Clear command is used. For Serial INSTR sessions, VISA flushes the I/O output buffer, sends a break, and then flushes the I/O input buffer. For TCP/IP SOCKET sessions, VISA flushes the I/O buffers. For USB INSTR sessions, VISA must send the INITIATE_CLEAR and CHECK_CLEAR_STATUS commands on the control pipe.

  • For VXI INSTR sessions, the Word Serial Clear command is used.

  • For GPIB INSTR sessions, the Selected Device Clear command is used.

  • For Serial INSTR sessions, VISA flushes the I/O output buffer, sends a break, and then flushes the I/O input buffer.

  • For TCP/IP SOCKET sessions, VISA flushes the I/O buffers.

  • For USB INSTR sessions, VISA must send the INITIATE_CLEAR and CHECK_CLEAR_STATUS commands on the control pipe.


SetTrailingForReads

Specifies the string that should be automatically stripped from the device response.

virtual void SetTrailingForReads(const CString& str) abstract;
Parameters
str

[in] String which should be automatically removed from the device response.

Remarks

Many instruments return trailing characters, such as "\n", in their response strings. This function is used to automatically have these trailing characters removed from device response strings. The trailing characters specified can be a single character or an entire string. If more than one character is specified in the str parameter, then the device response must be terminated with the entire string in order for it to be removed. No error is generated if a device response does not end in the specified trailing string.

The default trailing string is the line feed character "\n".

Example

The following example demonstrates use of the SetTrailingForReads function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::OnFinalInitialize()
{
  HRESULT hr = S_OK;

  // Response strings will be stripped of CR/LF combination, if present
  hr = io.SetTrailingForReads(_T("\r\n"));

  return hr;
}
See Also

Other Resources

GetTrailingForReads
GetTrailingForWrites
SetTrailingForWrites


GetTrailingForReads

Gets the string that is currently configured to be automatically removed from device response strings.

virtual CString GetTrailingForReads() const abstract;
Return Value

The string that is currently configured to be automatically removed from device response strings.

Remarks

See the description of the SetTrailingForReads function for more details.

Example

The following example demonstrates use of the GetTrailingForReads function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::OnFinalInitialize()
{
  HRESULT hr = S_OK;

  CString strTrailing = io.GetTrailingForReads();

  return hr;
}
See Also

Other Resources

SetTrailingForReads


SetTrailingForWrites

Specifies the string that should be automatically appended to strings sent to the instrument.

virtual void SetTrailingForWrites(const CString& str) abstract;
Parameters
str

[in] String which should be automatically appended to device command strings.

Remarks

Many instruments require that command strings be terminated with a special character sequence. Rather than explicitly inserting these trailing characters into each command sent to the instrument, the SetTrailingForWrites function can be used to specify a set of characters that will automatically be appended to each command string sent to the device.

The default trailing string is the line feed character "\n".

Example

The following example demonstrates use of the SetTrailingForWrites function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::OnFinalInitialize()
{
  HRESULT hr = S_OK;

  // Command strings will be automatically be appended with a CR/LF combination
  hr = io.SetTrailingForWrites(_T("\r\n"));

  return hr;
}
See Also

Other Resources

GetTrailingForWrites
GetTrailingForReads
SetTrailingForReads


GetTrailingForWrites

Gets the string that is currently configured to be automatically appended to device command strings.

virtual CString GetTrailingForWrites() const abstract;
Return Value

The string that is currently configured to be automatically appended to device command strings.

Remarks

See the description of the SetTrailingForWrites function for more details.

Example

The following example demonstrates use of the GetTrailingForWrites function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::OnFinalInitialize()
{
  HRESULT hr = S_OK;

  CString strTrailing = io.GetTrailingForWrites();

  return hr;
}
See Also

Other Resources

SetTrailingForWrites


SetInstrumentBigEndian

Specifies whether the device returns binary data in big endian or little endian format.

virtual void SetInstrumentBigEndian(bool bBigEndian) abstract;
Parameters
bBigEndian

[in] If true, the instrument returns binary data in big endian format. If false, the instrument returns binary data in little endian format.

Remarks

This function is used to indicate the byte ordering used by the connected device. The ReadBinaryBlock and WriteBinaryBlock functions use the byte order specified here to know when to perform byte swapping. Note that the printf-style functions, such as Printf and Scanf do not use the byte order specified with the SetInstrumentBigEndian function.

The default byte order is big endian.

Example

The following example demonstrates use of the SetInstrumentBigEndian function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::OnFinalInitialize()
{
  HRESULT hr = S_OK;

  // Little endian byte ordering
  io.SetInstrumentBigEndian(false);

  return hr;
}
See Also

Other Resources

GetInstrumentBigEndian


GetInstrumentBigEndian

Gets a value indicating whether the device returns binary data in big endian or little endian format.

virtual bool GetInstrumentBigEndian() const abstract;
Return Value

Returns true if the device uses big endian byte ordering or false if the device uses little endian byte ordering.

Remarks

This function returns the current setting for the device byte ordering. By default, the byte order is big endian. The setting can be controlled via the SetInstrumentBigEndian function.

Example

The following example demonstrates use of the GetInstrumentBigEndian function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::OnFinalInitialize()
{
  HRESULT hr = S_OK;

  bool bBigEndian = io.GetInstrumentBigEndian();

  return hr;
}
See Also

Other Resources

SetInstrumentBigEndian


SetTimeout

Sets the timeout value for the I/O session (in milliseconds).

virtual HRESULT SetTimeout(long lTimeout) abstract;
Parameters
str

[in] Sets the timeout value for the I/O session (in milliseconds).

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

The default timeout is 2000 ms.

Example

The following example demonstrates use of the SetTimeout function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::OnFinalInitialize()
{
  HRESULT hr = S_OK;

  // Set the I/O session timeout value to 5000 ms
  hr = io.SetTimeout(5000);

  return hr;
}
See Also

Other Resources

GetTimeout


GetTimeout

Gets the timeout value for the I/O session (in milliseconds).

virtual HRESULT GetTimeout(long* plTimeout) abstract;
Parameters
str

[out] The timeout value for the I/O session (in milliseconds).

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

The default timeout is 2000 ms.

Example

The following example demonstrates use of the SetTimeout function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::OnFinalInitialize()
{
  HRESULT hr = S_OK;

  // Set the I/O session timeout value to 5000 ms
  hr = io.SetTimeout(5000);

  return hr;
}
See Also

Other Resources

Communicating With Instruments


SetTerminationCharacter

Sets the termination character for read operations.

virtual HRESULT SetTerminationCharacter(UCHAR cTermChar) abstract;
Parameters
cTermChar

[in] A single character that, when read from the device, causes the read operation to terminate.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

When the termination character is read and it has been enabled via the SetTerminationCharacterEnabled function, the read operation terminates.

The default termination character is set to the newline character (\n) and it is enabled by default.

Example

The following example demonstrates use of the SetTerminationCharacter function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::OnFinalInitialize()
{
  HRESULT hr = S_OK;

  // Set the termination character to a carriage-return (\r)
  hr = io.SetTerminationCharacter('\r');

  return hr;
}
See Also

Other Resources

GetTerminationCharacter
SetTerminationCharacterEnabled


GetTerminationCharacter

Gets the termination character for read operations.

virtual HRESULT GetTerminationCharacter(UCHAR* pcTermChar) abstract;
Parameters
pcTermChar

[out] A single character that, when read from the device, causes the read operation to terminate.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

When the termination character is read and it has been enabled via the SetTerminationCharacterEnabled function, the read operation terminates.

The default termination character is set to the newline character (\n) and it is enabled by default.

Example

The following example demonstrates use of the GetTerminationCharacter function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::OnFinalInitialize()
{
  HRESULT hr = S_OK;

  // Get the current termination character)
  char ch;
  hr = io.GetTerminationCharacter(&ch);

  return hr;
}
See Also

Other Resources

Communicating With Instruments
GetTerminationCharacter
SetTerminationCharacterEnabled


SetTerminationCharacterEnabled

Enables for disables the I/O termination character for read operations.

virtual HRESULT SetTerminationCharacterEnabled(bool bEnabled) abstract;
Parameters
bEnabled

[in] When true, the termination character is used to determine when a read operation ends.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

When the termination character is enabled using this function, the termination character specified with the SetTerminationCharacter function determines when the read operation terminates.

The default termination character is set to the newline character (\n) and it is enabled by default.

Example

The following example demonstrates use of the SetTerminationCharacterEnabled function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::OnFinalInitialize()
{
  HRESULT hr = S_OK;

  // Set the termination character to a carriage-return (\r) and enable it
  hr = io.SetTerminationCharacter('\r');
  if (SUCCEEDED(hr))
  {
    hr = io.SetTerminationCharacterEnabled(true);
  }

  return hr;
}
See Also

Other Resources

GetTerminationCharacterEnabled
SetTerminationCharacter


GetTerminationCharacterEnabled

Indicates whether the I/O termination character for read operations is enabled or disabled.

virtual HRESULT GetTerminationCharacterEnabled(bool* pbEnabled) abstract;
Parameters
pbEnabled

[out] When true, the termination character is used to determine when a read operation ends.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

When the termination character is enabled, the termination character specified with the SetTerminationCharacter function determines when the read operation terminates.

The default termination character is set to the newline character (\n) and it is enabled by default.

Example

The following example demonstrates use of the GetTerminationCharacterEnabled function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::OnFinalInitialize()
{
  HRESULT hr = S_OK;

  bool bEnabled;
  hr = io.GetTerminationCharacterEnabled(&bEnabled);

  return hr;
}
See Also

Other Resources

Communicating With Instruments
GetTerminationCharacterEnabled
SetTerminationCharacter


Lock

Requests a device lock.

                virtual HRESULT Lock(IoLockType eLockType, long lLockTimeout, const CString& strRequestedKey, CString& strAccessKey) abstract;
Parameters
eLockType

[in] The desired IoLockType for the session.

lLockTimeout

[in] The amount of time (in milliseconds) to wait for the lock.

strRequestedKey

[in] The requested key to use when requesting a shared lock. Not applicable when eLockType is IoLockExclusive.

strAccessKey

[out] The access key returned by the I/O session. Not applicable when eLockType is IoLockExclusive.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

This function is used to obtain a lock on the device I/O session. The caller can specify the type of lock requested and the length of time the operation will suspend while waiting to acquire the lock before timing out.

The strRequestedKey and the strAccessKey parameters apply only to shared locks. These parameters are not applicable when the access mode is IoLockExclusive. The I/O session allows user applications to specify a key to be used for lock sharing, through the use of the requestedKey parameter. Alternatively, a you can pass an empty string for the strRequestedKey parameter when obtaining a shared lock, in which case a unique access key will be generated and returned in the strAccessKey parameter. If a user application does specify a strRequestedKey value, the I/O session will try to use this value for the strAccessKey. As long as the resource is not locked, the strRequestedKey will be used as the access key and the lock will be granted.

Example

The following example demonstrates use of the Lock function to obtain an exclusive lock. The example shows of the Printf and Scanf functions to retrieve the *IDN? response string from the device. A lock is used to ensure that no other thread or process attempts to access the device between the Printf and Scanf calls.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::Configure()
{
  HRESULT hr = S_OK;

  // Request an exclusive lock to block other sessions from interrupting the *IDN query
  hr = io.Lock(IoLockExclusive, 2000, _T(""), _T(""));
  if (SUCCEEDED(hr))
  {
    hr = io.Printf(_T("*IDN?"));
    if (SUCCEEDED(hr))
    {
      CString strId;
      hr = io.Scanf(_T("%$Cs"), strId);
    }

    // Unlock the session so other threads and processes can use it
    HRESULT hr2 = io.Unlock();
    hr = FAILED(hr) ? hr : hr2;
  }

  return hr;
}

The following example demonstrates use of the Lock function to obtain a shared lock with an access key. Other I/O sessions can use this access key in the requestedKey parameter of the Lock function to share access to the locked device.

The example then shows the original session acquiring an exclusive lock while maintaining its shared lock. When the session holding the exclusive lock unlocks the resource via the Unlock function, all sessions sharing the lock will again have the access privileges associated with the shared lock..

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::Configure()
{
  HRESULT hr = S_OK;

  // Request a shared lock so that only processes we "know" about can access the device
  CString strAccessKey;
  hr = io.Lock(IoLockShared, 2000, _T(""), strAccessKey);
  if (SUCCEEDED(hr))
  {
    // At this point, we "publish" the value of strAccessKey to other processes
    // to which we want to grant access privileges.  This can be done using
    // any desired interprocess communication mechanism

    hr = io.Printf(_T("*RST?;SENS:CONFIG DEF"));
    if (SUCCEEDED(hr))
    {
      // Now lock out all other threads (including those that share the key)
      // so that the *IDN? query doesn't get interrupted
      hr = io.Lock(IoLockExclusive, 2000, _T(""), _T(""));
      if (SUCCEEDED(hr))
      {
        hr = io.Printf(_T("*IDN?"));
        if (SUCCEEDED(hr))
        {
          CString strId;
          hr = io.Scanf(_T("%$Cs"), strId);
        }

        // Release the exclusive lock
        HRESULT hr2 = io.Unlock();
        hr = FAILED(hr) ? hr : hr2;
      }

      // Release the shared lock
      HRESULT hr2 = io.Unlock();
      hr = FAILED(hr) ? hr : hr2;
    }
  }

  return hr;
}
See Also

Other Resources

Unlock


Unlock

Relinquishes a device lock.

virtual HRESULT Unlock();
Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

This operation is used to relinquish the lock previously obtained using the Lock function.

Example

The following example demonstrates use of the Unlock function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::OnFinalInitialize()
{
  HRESULT hr = S_OK;

  // Release previously obtained lock
  hr = io.Unlock();

  return hr;
}
See Also

Other Resources

Lock


IoLockType Enumeration

Specifies the type of lock to obtain for the device session.

enum IoLockType
Members

Member name

Description

IoLockExclusive

Obtain an exclusive lock on the device.

A session can lock a device using this lock type to get exclusive access privileges to the device. This exclusive lock type excludes access to the device from all other sessions.

IoLockShared

Obtain a shared lock on the device.

A session can share a lock on a device with other sessions by using a shared lock. Shared locks are similar to exclusive locks in terms of access privileges, but they can be shared between multiple sessions.

A session that has obtained a shared lock can modify aspects of the device (unless it has been exclusively locked by another session). Sessions that do not have a shared lock on the device will not be able to access it.

Remarks

See the Lock function for details.

See Also

Other Resources

Lock
Unlock


Printf-Style Functions

The functions in this section provide an I/O programming interface very similar to that provided by the familiar printf function. These functions extend the standard ANSI syntax for printf to provide powerful constructs for performing such tasks as converting to and from COM data types, reading and writing IEEE binary blocks, and performing a wide variety of other formatting options.

These printf-style functions, as they are termed, are most useful in cases where several items need to be formatted within an instrument command (or response) at once. Simple commands that involve reading or writing only a single item, such as an integer or floating-point number, might be simpler to implement using the basic I/O functions.

In This Section

Printf

PrintfNoPoll

VPrintf

Scanf

ScanfNoPoll

ScanfWithTimeout

ScanfWithTimeoutNoPoll

VScanf

VScanfNoPoll

Queryf

QueryfNoPoll

QueryfWithTimeout

QueryfWithTimeoutNoPoll

VQueryf

VQueryfNoPoll

I/O Format Specifiers


Printf

Sends formatted output to a device.

virtual HRESULT Printf(const CString strFormat [, argument] ...) abstract;
Parameters
strFormat

[in] String describing the format for arguments. See the topic I/O Format Specifiers for Write Operations for details.

argument

[in] Optional arguments interpreted by the format string.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

The Printf function formats and sends a series of characters to a device. Any arguments passed to Printf are converted and formatted and the resulting string is sent to the formatted I/O buffer.

If the strFormat parameter ends in a newline character (\n), then the contents of the formatted I/O buffer are flushed to the device and an END indicator is sent with the last byte (the newline character).

If the I/O buffer is flushed, the instrument is polled for errors.

Example

The following example demonstrates use of the Printf function. Note that the topic I/O Format Specifiers for Write Operations has many more examples of format strings that can be used with Printf.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_Configure(double Range, double Resolution)
{
  HRESULT hr = S_OK;

  // Send command to device, flush I/O buffer
  hr = io.Printf(_T("SENS:MEAS %f, %6.2e"), Range, Resolution);

  return hr;
}
See Also

Other Resources

PrintfNoPoll
VPrintf


PrintfNoPoll

Sends formatted output to a device without polling for errors.

virtual HRESULT PrintfNoPoll(const CString strFormat [, argument] ...) abstract;
Parameters
strFormat

[in] String describing the format for arguments. See the topic I/O Format Specifiers for Write Operations for details.

argument

[in] Optional arguments interpreted by the format string.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

This function behaves identically to Printf except that the device is not polled for errors after the data is sent. This can be useful in cases where a query string is sent to the device and a separate function will be executed to read the results. Were Printf used in such a situation instead of PrintfNoPoll, the error polling command would attempt to write to the device again -- before the results of the initial query could be read.

Example

The following example demonstrates use of the PrintfNoPoll function. Note that the topic I/O Format Specifiers for Write Operations has many more examples of format strings that can be used with PrintfNoPoll.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_Configure(long Channel, long* Count)
{
  HRESULT hr = S_OK;

  // Send query command to device, without polling for errors
  hr = io.PrintfNoPoll(_T("TRIG:COUNT? %d"), Channel);
  if (SUCCEEDED(hr))
  {

    // ... other logic

    hr = io.ReadNumber(Count);
  }

  return hr;
}
See Also

Other Resources

Printf
VPrintf


VPrintf

Sends formatted output to a device.

virtual HRESULT VPrintf(const CString strFormat, va_list& argList, long lTimeout = CUR_TIMEOUT) abstract;
Parameters
strFormat

[in] String describing the format for arguments. See the topic I/O Format Specifiers for Write Operations for details.

argList

[in] Argument list interpreted by the format string.

lTimeout

[in] I/O timeout in milliseconds.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

This function behaves identically to Printf except that the argument list is supplied using a va_list argument list instead of separate argument parameters. This type of argument list function is typically used to implement higher-level functions that accept variable argument lists. Indeed, the implementation of Printf in NtlIo.inl is done in terms of VPrintf, as shown in the example later.

The lTimeout parameter allows the I/O timeout to be temporarily changed to the specified value for the duration of the VPrintf function call. The timeout is returned to its previous value after VPrintf returns. If lTimeout is not specified, then the I/O timeout is not modified.

Example

The following example demonstrates use of the VPrintf function.

C++
Copy
// NtlIo.inl
inline HRESULT CIoSession::Printf(const CString strFormat, ...)
{
    HRESULT hr = S_OK;

    va_list argList;
    va_start(argList, strFormat);

    hr = CFormattedIo::VPrintf(m_spBuf, m_pEnumFormatter, strFormat, argList);

    va_end(argList);

    if (SUCCEEDED(hr))
    {
        hr = PollInstrumentErrors();
    }

    return hr;
}
See Also

Other Resources

Printf
PrintfNoPoll


Scanf

Reads formatted input from a device.

virtual HRESULT Scanf(const CString strFormat [, argument] ...) abstract;
Parameters
strFormat

[in] String describing the format of the data to be read. See the topic I/O Format Specifiers for Read Operations for details.

argument

[in] Optional arguments interpreted by the format string.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

The Scanf function reads and formats data using the strFormat format specifier. The scanned data is stored in the argument passed to Scanf.

Example

The following example demonstrates use of the Printf function. Note that the topic I/O Format Specifiers for Write Operations has many more examples of format strings that can be used with Printf.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_Configure()
{
  HRESULT hr = S_OK;

  // Send ID query to device
  hr = io.PrintfNoPoll(_T("*IDN?"));
  if (SUCCEEDED(hr))
  {
    CString strManufacturer, strModel, strSerial, strRevision;

    hr = io.Scanf(_T("%$C[^,],%$C[^,],%$C[^,],%$C[^,]"), &strManufacturer, &strModel, &strSerial, &strRevision);
  }

  return hr;
}
See Also

Other Resources

ScanfNoPoll
ScanfWithTimeout
ScanfWithTimeoutNoPoll
VScanf
VScanfNoPoll


ScanfNoPoll

Reads formatted input from a device without polling for errors.

virtual HRESULT ScanfNoPoll(const CString strFormat [, argument] ...) abstract;
Parameters
strFormat

[in] String describing the format of the data to be read. See the topic I/O Format Specifiers for Read Operations for details.

argument

[in] Optional arguments interpreted by the format string.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

This function behaves identically to Scanf except that the device is not polled for errors after the data is read.

Example

The following example demonstrates use of the ScanfNoPoll function. Note that the topic I/O Format Specifiers for Read Operations has many more examples of format strings that can be used with ScanfNoPoll.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_Configure()
{
  HRESULT hr = S_OK;

  // Send ID query to device
  hr = io.PrintfNoPoll(_T("*IDN?"));
  if (SUCCEEDED(hr))
  {
    CString strManufacturer, strModel, strSerial, strRevision;

    hr = io.ScanfNoPoll(_T("%$C[^,],%$C[^,],%$C[^,],%$C[^,]"), &strManufacturer, &strModel, &strSerial, &strRevision);

    // ...
  }

  return hr;
}
See Also

Other Resources

Scanf
ScanfWithTimeout
ScanfWithTimeoutNoPoll
VScanf
VScanfNoPoll


ScanfWithTimeout

Reads formatted input from a device.

virtual HRESULT ScanfWithTimeout(const CString strFormat, long lTimeout, [, argument] ...) abstract;
Parameters
strFormat

[in] String describing the format of the data to be read. See the topic I/O Format Specifiers for Read Operations for details.

argument

[in] Optional arguments interpreted by the format string.

lTimeout

[in] I/O timeout value in milliseconds.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

The ScanfWithTimeout function behaves identically to the Scanf function except that an I/O timeout parameter is supplied. The lTimeout parameter allows the I/O timeout to be temporarily changed to the specified value for the duration of the ScanfWithTimeout function call. The timeout is returned to its previous value after ScanfWithTimeout returns.

Example

The following example demonstrates use of the ScanfWithTimeout function. Note that the topic I/O Format Specifiers for Write Operations has many more examples of format strings that can be used with ScanfWithTimeout.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_Configure()
{
  HRESULT hr = S_OK;

  // Start a measurement that will generate a lot of data
  hr = io.PrintfNoPoll(_T("MEAS:DATA?"));
  if (SUCCEEDED(hr))
  {
    // Read an IEEE 488.2 binary block, needs up to 10 seconds to complete
    SAFEARRAY* psaData = NULL;
    hr = io.ScanfWithTimeout(_T("%$Sb"), 10000, &psaData);

    // I/O timeout automatically changed back to previous value before ScanfWithTimeout call
  }

  return hr;
}
See Also

Other Resources

Scanf
ScanfNoPoll
ScanfWithTimeoutNoPoll
VScanf
VScanfNoPoll


ScanfWithTimeoutNoPoll

Reads formatted input from a device.

virtual HRESULT ScanfWithTimeoutNoPoll(const CString strFormat, long lTimeout, [, argument] ...) abstract;
Parameters
strFormat

[in] String describing the format of the data to be read. See the topic I/O Format Specifiers for Read Operations for details.

lTimeout

[in] I/O timeout value in milliseconds.

argument

[in] Optional arguments interpreted by the format string.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

The ScanfWithTimeoutNoPoll function behaves identically to the ScanfWithTimout function except that the device is not polled for errors after the data is read.

Example

The following example demonstrates use of the ScanfWithTimeoutNoPoll function. Note that the topic I/O Format Specifiers for Write Operations has many more examples of format strings that can be used with ScanfWithTimeoutNoPoll.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_Configure()
{
  HRESULT hr = S_OK;

  // Start a measurement that will generate a lot of data
  hr = io.PrintfNoPoll(_T("MEAS:DATA?"));
  if (SUCCEEDED(hr))
  {
    // Read an IEEE 488.2 binary block, needs up to 10 seconds to complete
    SAFEARRAY* psaData = NULL;
    hr = io.ScanfWithTimeoutNoPoll(_T("%$Sb"), 10000, &psaData);

    // I/O timeout automatically changed back to previous value before ScanfWithTimeout call
  }

  return hr;
}
See Also

Other Resources

Scanf
ScanfNoPoll
ScanfWithTimeout
VScanf
VScanfNoPoll


VScanf

Reads formatted input from a device.

virtual HRESULT VScanf(const CString strFormat, va_list& argList, long lTimeout = CUR_TIMEOUT) abstract;
Parameters
strFormat

[in] String describing the format for arguments. See the topic I/O Format Specifiers for Write Operations for details.

argList

[in] Argument list interpreted by the format string.

lTimeout

[in] I/O timeout in milliseconds.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

This function behaves identically to Scanf except that the arguments are supplied using a va_list argument list instead of separate argument parameters. This type of argument list function is typically used to implement higher-level functions that accept variable argument lists. Indeed, the implementation of Scanf in NtlIo.inl is done in terms of VScanf, as shown in the example later.

The lTimeout parameter allows the I/O timeout to be temporarily changed to the specified value for the duration of the VScanf function call. The timeout is returned to its previous value after VScanf returns. If lTimeout is not specified, then the I/O timeout is not modified.

Example

The following example demonstrates use of the VScanf function.

C++
Copy
// NtlIo.inl
inline HRESULT CIoSession::Scanf(const CString strFormat, ...)
{
    if (!Initialized()) return m_pErrReporter->NotInitialized();

    HRESULT hr = S_OK;

    va_list argList;
    va_start(argList, strFormat);

    hr = CFormattedIo::VScanf(m_spBuf, m_pEnumFormatter, strFormat, argList);

    va_end(argList);

    if (SUCCEEDED(hr))
    {
        hr = PollInstrumentErrors();
    }

    return hr;
}
See Also

Other Resources

VScanfNoPoll
Scanf
ScanfNoPoll
ScanfWithTimeout
ScanfWithTimeoutNoPoll


VScanfNoPoll

Reads formatted input from a device.

virtual HRESULT VScanfNoPoll(const CString strFormat, va_list& argList, long lTimeout = CUR_TIMEOUT) abstract;
Parameters
strFormat

[in] String describing the format for arguments. See the topic I/O Format Specifiers for Write Operations for details.

argList

[in] Argument list interpreted by the format string.

lTimeout

[in] I/O timeout in milliseconds.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

This function behaves identically to VScanf except that the device is not polled for errors after the data is read.

Example

The following example demonstrates use of the VScanfNoPoll function.

C++
Copy
// NtlIo.inl
inline HRESULT CIoSession::QueryfNoPoll(const CString strWriteFormat, const CString strReadFormat, ...)
{
    HRESULT hr = S_OK;

    va_list argList;
    va_start(argList, strReadFormat);

    hr = VQueryf(strWriteFormat, strReadFormat, argList);

    va_end(argList);

    return hr;
}
See Also

Other Resources

VScanf
Scanf
ScanfNoPoll
ScanfWithTimeout
ScanfWithTimeoutNoPoll


Queryf

Performs a formatted write and read through as a single operation.

virtual HRESULT Queryf(const CString strWriteFormat, const CString strReadFormat  [, argument] ...) abstract;
Parameters
strWriteFormat

[in] String describing the format of the write arguments. See the topic I/O Format Specifiers for Write Operations for details.

strReadFormat

[in] String describing the format of the read arguments. See the topic I/O Format Specifiers for Read Operations for details.

argument

[in] Optional arguments interpreted by the write and read format strings.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

The Queryf function provides a mechanism of "send, then receive" typical to a device command sequences. In this manner, the response generated from the command can be read immediately. The device is not polled for errors after the write portion of the sequence.

This Queryf function performs a PrintfNoPoll operation followed immediately by a Scanf operation. The first n arguments are formatted according to the strWriteFormat then sent to the device. The write buffer is flushed immediately after the write portion of the operation completes. After these actions, the response data is read from the device into the remaining arguments (starting from parameter n+1) using the strReadFormat string.

Example

The following example demonstrates use of the Querf function. Note that the topics I/O Format Specifiers for Write Operations and I/O Format Specifiers for Read Operations has many more examples of format strings that can be used with Queryf.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_Configure()
{
  HRESULT hr = S_OK;

  // Send ID query to device and read the response
  CString strManufacturer, strModel, strSerial, strRevision;

  hr = io.Queryf(_T("*IDN?"), _T("%$C[^,],%$C[^,],%$C[^,],%$C[^,]"), &strManufacturer, &strModel, &strSerial, &strRevision);

  return hr;
}
See Also

Other Resources

QueryfNoPoll
QueryfWithTimeout
QueryfWithTimeoutNoPoll
VQueryf
VQueryfNoPoll


QueryfNoPoll

Performs a formatted write and read through as a single operation without polling for instrument errors after the read.

virtual HRESULT QueryfNoPoll(const CString strWriteFormat, const CString strReadFormat  [, argument] ...) abstract;
Parameters
strWriteFormat

[in] String describing the format of the write arguments. See the topic I/O Format Specifiers for Write Operations for details.

strReadFormat

[in] String describing the format of the read arguments. See the topic I/O Format Specifiers for Read Operations for details.

argument

[in] Optional arguments interpreted by the write and read format strings.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

This function behaves identically to Queryf except that the device is not polled for errors after the data is read.

Example

The following example demonstrates use of the Queryf function. Note that the topics I/O Format Specifiers for Write Operations and I/O Format Specifiers for Read Operations has many more examples of format strings that can be used with QueryfNoPoll.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_Configure()
{
  HRESULT hr = S_OK;

  // Send ID query to device and read the response
  CString strManufacturer, strModel, strSerial, strRevision;

  hr = io.QueryfNoPoll(_T("*IDN?"), _T("%$C[^,],%$C[^,],%$C[^,],%$C[^,]"), &strManufacturer, &strModel, &strSerial, &strRevision);

  return hr;
}
See Also

Other Resources

Queryf
QueryfWithTimeout
QueryfWithTimeoutNoPoll
VQueryf
VQueryfNoPoll


QueryfWithTimeout

Performs a formatted write and read through as a single operation.

virtual HRESULT QueryfWithTimeout(const CString strWriteFormat, const CString strReadFormat, long lTimeout [, argument] ...) abstract;
Parameters
strWriteFormat

[in] String describing the format of the write arguments. See the topic I/O Format Specifiers for Write Operations for details.

strReadFormat

[in] String describing the format of the read arguments. See the topic I/O Format Specifiers for Read Operations for details.

argument

[in] Optional arguments interpreted by the write and read format strings.

lTimeout

[in] I/O timeout value in milliseconds.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

The QueryfWithTimeout function behaves identically to the Queryf function except that an I/O timeout parameter is supplied. The lTimeout parameter allows the I/O timeout to be temporarily changed to the specified value for the duration of the QueryfWithTimeout function call. The timeout is returned to its previous value after QueryfWithTimeout returns.

Example

The following example demonstrates use of the QueryfWithTimeout function. Note that the topics I/O Format Specifiers for Write Operations and I/O Format Specifiers for Read Operations has many more examples of format strings that can be used with QueryfWithTimeout.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_Configure()
{
  HRESULT hr = S_OK;

  // Start a measurement that will generate a lot of data and   {
  // read an IEEE 488.2 binary block as the response.
  // Needs up to 10 seconds to complete
  SAFEARRAY* psaData = NULL;
  hr = io.QueryfWithTimeout(_T("MEAS:DATA?"), _T("%$Sb"), 10000, &psaData);

    // I/O timeout automatically changed back to previous value before ScanfWithTimeout call

  return hr;
}
See Also

Other Resources

Queryf
QueryfNoPoll
QueryfWithTimeoutNoPoll
VQueryf
VQueryfNoPoll


QueryfWithTimeoutNoPoll

Performs a formatted write and read through as a single operation without polling for instrument errors after the read.

virtual HRESULT QueryfWithTimeoutNoPoll(const CString strWriteFormat, const CString strReadFormat, long lTimeout [, argument] ...) abstract;
Parameters
strWriteFormat

[in] String describing the format of the write arguments. See the topic I/O Format Specifiers for Write Operations for details.

strReadFormat

[in] String describing the format of the read arguments. See the topic I/O Format Specifiers for Read Operations for details.

argument

[in] Optional arguments interpreted by the write and read format strings.

lTimeout

[in] I/O timeout value in milliseconds.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

This function behaves identically to QueryfWithTimeout except that the device is not polled for errors after the data is read.

Example

The following example demonstrates use of the QueryfWithTimeoutNoPoll function. Note that the topics I/O Format Specifiers for Write Operations and I/O Format Specifiers for Read Operations has many more examples of format strings that can be used with QueryfWithTimeoutNoPoll.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_Configure()
{
  HRESULT hr = S_OK;

  // Start a measurement that will generate a lot of data and   {
  // read an IEEE 488.2 binary block as the response.
  // Needs up to 10 seconds to complete
  SAFEARRAY* psaData = NULL;
  hr = io.QueryfWithTimeoutNoPoll(_T("MEAS:DATA?"), _T("%$Sb"), 10000, &psaData);

    // I/O timeout automatically changed back to previous value before ScanfWithTimeout call

  return hr;
}
See Also

Other Resources

Queryf
QueryfNoPoll
QueryfWithTimeout
VQueryf
VQueryfNoPoll


VQueryf

Performs a formatted write and read through a single operation invocation.

virtual HRESULT VQueryf(const CString strWriteFormat, const CString strReadFormat, va_list& argList, long lTimeout = CUR_TIMEOUT) abstract;
Parameters
strFormat

[in] String describing the format for arguments. See the topic I/O Format Specifiers for Write Operations for details.

argList

[in] Argument list interpreted by the format string.

lTimeout

[in] I/O timeout in milliseconds.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

This function behaves identically to Queryf except that the arguments are supplied using a va_list argument list instead of separate argument parameters. This type of argument list function is typically used to implement higher-level functions that accept variable argument lists. This is Indeed, the implementation of Queryf in NtlIo.inl is done in terms of VQueryf, as shown in the example later.

The lTimeout parameter allows the I/O timeout to be temporarily changed to the specified value for the duration of the VQueryf function call. The timeout is returned to its previous value after VQueryf returns. If lTimeout is not specified, then the I/O timeout is not modified.

Example

The following example demonstrates use of the VScanf function.

C++
Copy
// NtlIo.h
inline HRESULT CIoSession::Queryf(const CString strWriteFormat, const CString strReadFormat, ...)
{
    HRESULT hr = S_OK;

    va_list argList;
    va_start(argList, strReadFormat);

    hr = VQueryf(strWriteFormat, strReadFormat, argList);

    va_end(argList);

    if (SUCCEEDED(hr))
    {
        hr = PollInstrumentErrors();
    }

    return hr;
}
See Also

Other Resources

VQueryfNoPoll
Queryf
QueryfNoPoll
QueryfWithTimeout
QueryfWithTimeoutNoPoll


VQueryfNoPoll

Performs a formatted write and read through a single operation invocation, without polling for errors after the read.

virtual HRESULT VQueryfNoPoll(const CString strWriteFormat, const CString strReadFormat, va_list& argList, long lTimeout = CUR_TIMEOUT) abstract;
Parameters
strFormat

[in] String describing the format for arguments. See the topic I/O Format Specifiers for Write Operations for details.

argList

[in] Argument list interpreted by the format string.

lTimeout

[in] I/O timeout in milliseconds.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

This function behaves identically to VQueryf except that the device is not polled for errors after the data is read.

Example

The following example demonstrates use of the VQueryf function.

C++
Copy
// NtlIo.h
inline HRESULT CIoSession::Queryf(const CString strWriteFormat, const CString strReadFormat, ...)
{
    HRESULT hr = S_OK;

    va_list argList;
    va_start(argList, strReadFormat);

    hr = VQueryf(strWriteFormat, strReadFormat, argList);

    va_end(argList);

    if (SUCCEEDED(hr))
    {
        hr = PollInstrumentErrors();
    }

    return hr;
}
See Also

Other Resources

VQueryf
Queryf
QueryfNoPoll
QueryfWithTimeout
QueryfWithTimeoutNoPoll


I/O Format Specifiers

This topic discusses the format specifier fields that may appear in the format control strings passed to the Printf-style I/O functions. Format specifiers differ for write operations (such as Printf) and read operations (such as Scanf).

In This Section

I/O Format Specifiers for Write Operations

Learn how to use the Printf function for sending formatted data to an instrument.

I/O Format Specifiers for Read Operations

Learn how to use the Scanf function for reading formatted data from an instrument.

See Also

Other Resources

Printf
Scanf


I/O Format Specifiers for Write Operations

This topic discusses the format specifier fields that may appear in the write format control strings passed to the Printf-style I/O functions. The format specifiers described here apply to the following functions:

  • Printf

  • PrintfNoPoll

  • VPrintf

  • Queryf

  • QueryfNoPoll

  • QueryfWithTimeout

  • QueryfWithTimeoutNoPoll

  • VQueryf

  • VQueryfNoPoll

Write Format Specifier Overview

The write format specifier for all Printf-style functions has the following general form:

%[modifiers]type

The type code is the only required field and appears after the optional modifiers. The type code determines whether the associated argument is interpreted as a character, string, number, or array. The type code also determines which modifiers are valid and how they are interpreted. The specific format of the format specifier is given in the various topics in this section for each supported type code.

The table below lists the type codes available along with links to the topics that discuss the format specifier for each data type.

Type of Data | Format Codes | Help Topic
Single characters | %c | Writing Characters
Strings | %s | Writing Strings
Integers | %d, %i, %o, %u, %x, %X | Writing Integers
Floating-point numbers | %f, %e, %E, %g, %G | Writing Floating-Point Numbers
IEEE 488.2 binary blocks | %b, %B | Writing IEEE 488.2 Binary Blocks
Raw binary data | %y | Writing Raw Binary Data
Special Formatting Characters

Special formatting character sequences send special characters. The following table lists the special characters and describes what they send to the device.

Formatting Character | Character Sent to Device
\n | Sends the ASCII linefeed character (LF). The END identifier will also be automatically sent.
\r | Sends the ASCII carriage return (CR) character.
\t | Sends the ASCII TAB character.
\### | Sends the ASCII character specified by the octal value.
\" | Sends the ASCII double-quote (") character.
\\ | Sends the ASCII backslash (\) character.
See Also

Other Resources

Printf


I/O Format Specifiers for Writing Characters

Character Data -- %c

A character argument has a format specifier of the following form:

%[flags] [width] [.precision] c

Modifier

Interpretation

Default Functionality

The argument is interpreted as a single-byte character. The character is sent to the device without change.

flags

-, 0

Controls justification and padding of the output, as follows:

  • - - left aligns the result with the given field width.

  • 0 - pads with zeros until the width is reached. If 0 and - appear together, the 0 is ignored.

width

Minimum field width of the output string.

An asterisk (*) may be present in lieu of an integer width modifier, in which case an extra int argument supplies the value.

precision

Maximum number of characters to send.

An asterisk (*) may be present in lieu of an integer precision modifier, in which case an extra int argument supplies the value.

Example -- Single-character output

C++
Copy
HRESULT hr = S_OK;

char ch = 'A';

hr = io.Printf(_T("%c"), ch);                 // Sends "A"

// Field width specifies minimum width, right justify and pad to the left
hr = io.Printf(_T("%5c"), ch);                // Sends "    A"

// Left justify and pad to the right, field width specified with a variable
int nWidth = 5;
hr = io.Printf(_T("%-*c"), nWidth, ch);       // Sends "A    "
See Also

Other Resources

Printf


I/O Format Specifiers for Writing Strings

String Data -- %s

A string argument has a format specifier of the following form:

%[{enum} | VARIANT_BOOL] [flags] [width] [.precision] [delimiter [array size] ] [$S] [$B | $C] [q | Q] s

Modifier

Interpretation

Default Functionality

The argument is interpreted as a null-terminated C-style string. The string is sent to the device without change.

enum

The argument is interpreted as an integer representing an allowed value for the specified enum. The integer value is converted to a string based upon the enum-to-string mappings specified int the Instrument Command Editor. A simplified version of the enum name can be used for the enum field. Specifically, the project name prefix and Enum suffix can be excluded.

VARIANT_BOOL

The argument is interpreted as a VARIANT_BOOL. The value is converted to a string based upon the enum-to-string mappings specified int the Instrument Command Editor.

flags

-, 0

Controls justification and padding of the output, as follows:

  • - - left aligns the result with the given field width.

  • 0 - pads with zeros until the width is reached. If 0 and - appear together, the 0 is ignored.

width

Minimum field width of the output string.

An asterisk (*) may be present in lieu of an integer width modifier, in which case an extra int argument supplies the value.

precision

Maximum number of characters to send.

An asterisk (*) may be present in lieu of an integer precision modifier, in which case an extra int argument supplies the value.

delimiter

[array size]

The argument is interpreted as an array of BSTR elements. Note that the $S modifier must be present. If the array size is not specified, then number of elements sent is determined from the size of the SAFEARRAY itself.

array size specifies the number of array elements to send.

An asterisk (*) may be present in lieu of an integer array size modifier, in which case an extra int argument supplies the value.

$B

The argument is interpreted as a BSTR or a SAFEARRAY of BSTR elements if paired with the $S modifier.

$C

The argument is interpreted as a CString. Note that the $C modifier cannot be combined with the $S modifier.

$S

The argument is interpreted as a SAFEARRAY of BSTR elements. This modifier can only appear if $B is also used, as SAFEARRAYs of CString or C-style strings are not supported.

q

The string is formatted with enclosing single quotes ('). If combined with the $S and $B modifiers to format a delimited list of strings, each element is enclosed in single quotes.

Q

The string is formatted with enclosing double quotes ("). If combined with the $S and $B modifiers to format a delimited list of strings, each element is enclosed in double quotes.

Example -- String literal output

C++
Copy
HRESULT hr = S_OK;

hr = io.Printf(_T("Hello World"));           // Sends "Hello World"

// Special formatting character -- linefeed
hr = io.Printf(_T("Hello World\\n"));        // Sends "Hello World" followed by a linefeed and END indicator

// Character specified using an octal value
hr = io.Printf(_T("\123"));                  // Sends "S"

Example -- String width and precision

C++
Copy
HRESULT hr = S_OK;

LPCSTR psz = "Hello World";

// Sends all characters up to the null terminator
hr = io.Printf(_T("%s"), psz);               // Sends "Hello World"

// Field width sets minimum width at 15, pad to the left
hr = io.Printf(_T("%15s"), psz);             // Sends "    Hello World"

// Field width set using a variable, left-justify and pad to the right
int nWidth = 15;
hr = io.Printf(_T("%-*s"), nWidth, psz);     // Sends "Hello World    "

// Precision specifies maximum width
hr = io.Printf(_T("%.5s"), psz);             // Sends "Hello"

Example -- Quoted strings

C++
Copy
HRESULT hr = S_OK;

LPCSTR psz = "Hello World";

// Enclose in single quotes
hr = io.Printf(_T("%qs"), psz);                 // Sends "'Hello World'"

// Padding is applied outside of the quotes
hr = io.Printf(_T("%15qs"), psz);               // Sends "  'Hello World'"

// Enclose in double quotes
hr = io.Printf(_T("%15Qs"), psz);               // Sends "  "Hello World""

Example -- BSTR and CString

C++
Copy
HRESULT hr = S_OK;

CComBSTR bstrName = OLESTR("Hello World");

hr = io.Printf(_T("%$Bs"), bstrName);      // Sends "Hello World"

CString strName = COLE2T(bstrName);

hr = io.Printf(_T("%$Cs"), strName);       // Sends "Hello World"

Example -- String arrays

Important note Important

The only type of string arrays supported are SAFEARRAYs of BSTR elements. Thus, $S$B will always appear in the format specifier for a string array. SAFEARRAY arguments that have CString or C-style strings as elements are not supported.

C++
Copy
HRESULT hr = S_OK;

CComBSTR bstr1 = OLESTR("one");
CComBSTR bstr2 = OLESTR("two");
CComBSTR bstr3 = OLESTR("three");

CComSafeArray<BSTR> saNames;
saNames.Add(bstr1);
saNames.Add(bstr2);
saNames.Add(bstr3);

hr = io.Printf(_T("%,$S$Bs"), saNames.m_psa);       // Sends "one,two,three"

// Enclose in single quotes
hr = io.Printf(_T("%,$S$Bqs"), saNames.m_psa);      // Sends "'one','two','three'"

Example -- Enum and boolean command strings

C++
Copy
HRESULT hr = S_OK;

// Convert eSource variable to a command string
// Note the enum format specifier excludes the "Acme4321" prefix and the "Enum" suffix
Acme4321TriggerSourceEnum eSource = Acme4321TriggerSourceExternal;
hr = io.Printf(_T("TRIG:SOUR %{TriggerSource}s"), eSource);

// Convert bEnabled variable to a command string
VARIANT_BOOL bEnabled = VARIANT_TRUE;
hr = io.Printf(_T("TRIG:SOUR:ENAB %{VARIANT_BOOL}s"), bEnabled);
See Also

Other Resources

Printf


I/O Format Specifiers for Writing Integers

Integer Data -- %d (and variants)

An integer argument has a format specifier of the following form:

%[flags] [488.2 type] [width] [.precision] [delimiter [array size] ] [$S] [b | h | l | I] [d | o | x]

Modifier

Interpretation

Default Functionality

The argument is formatted as an integer in NR1 format (an integer without a decimal point).

flags

+, -, 0

Controls justification and padding of the output, as follows:

  • - - left aligns the result with the given field width.

  • + - prefixes the output value with a sign (+ or –) if the output value is of a signed type. By default, a sign only appears for negative values.

  • 0 pads with zeros until the specified width is reached. If 0 and - appear together, the 0 is ignored.

488.2 type

The number is formatted in one of six standard IEEE 488.2 numeric formats. The supported formats are:

  • @1 - IEEE 488.2 NR1 format (integer without any decimal point). Example: 123

  • @2 - IEEE 488.2 NR2 format (number with at least one digit after the decimal point). Example: 123.45

  • @3 - IEEE 488.2 NR3 format (floating-point number in exponential form). Example: 1.2345E-67

  • @H - IEEE 488.2 hex format. Example: #HAF35B

  • @Q - IEEE 488.2 octal format. Example: #Q71234

  • @B - IEEE 488.2 binary format. Example: #B011101001

width

Minimum field width of the output number.

An asterisk (*) may be present in lieu of an integer width modifier, in which case an extra int argument supplies the value.

precision

Minimum number of digits to send.

An asterisk (*) may be present in lieu of an integer precision modifier, in which case an extra int argument supplies the value.

delimiter

[array size]

The argument is interpreted as an array of integers (or long or short integers, as specified by the length). If the $S modifier is present, the argument is interpreted as a SAFEARRAY of integers.

array size specifies the number of array elements to send.

An asterisk (*) may be present in lieu of an integer array size modifier, in which case an extra int argument supplies the value.

$S

The argument is interpreted as a SAFEARRAY of integers.

length modifier

If no length modifier is specified, then the argument is assumed to be a long integer (32-bits).

  • b - argument is a BYTE (8-bit) integer.

  • h - argument is a short (16-bit) integer.

  • l - argument is a long (32-bit) integer.

  • I - argument is a __int64 (64-bit) integer.

type

  • d - number is formatted as a decimal integer.

  • o - number is formatted as an octal integer.

  • x - number is formatted as a hex integer.

Example -- Field width control

C++
Copy
HRESULT hr = S_OK;

int nCount = 1234;

// Left justify
hr = io.Printf(_T("%-8d"), nCount);            // Sends "1234    "

// Right justify
hr = io.Printf(_T("%8d"), nCount);             // Sends "    1234"

// Right justify, pad with zeroes
hr = io.Printf(_T("%08d"), nCount);            // Sends "00001234"

// Supply field width using a variable
int nWidth = 5;
hr = io.Printf(_T("%0*d"), nWidth, lCount);    // Sends "00123";

Example -- Integer length modifiers

C++
Copy
HRESULT hr = S_OK;

int nCount = 1234;
hr = io.Printf(_T("%d"), nCount);      // Sends "1234"

long lCount = 1234;
hr = io.Printf(_T("%ld"), lCount);     // Sends "1234"

short sCount = 1234;
hr = io.Printf(_T("%hd"), sCount);     // Sends "1234"

Example -- Integer arrays

C++
Copy
HRESULT hr = S_OK;

int rgData[] = { 1, 2, 3, 4, 5 };

// Comma-separated list of 3 elements
hr = io.Printf(_T("%,3d"), rgData);                // Sends "1,2,3"

// Semi-colon separated, count supplied as a variable
int nCount = 4;
hr = io.Printf(_T("%(;)*d"), nCount, rgData);      // Sends "1;2;3;4"

// Field width specified applies to each element
hr = io.Printf(_T("%4,3d"), rgData);               // Sends "   1,   2,   3"

CComSafeArray<int> saData;
saData.Add(1);
saData.Add(3);
saData.Add(3);

// Comma-separated list.  Argument is a SAFEARRAY.
// No field width supplied, so count is determined from the SAFEARRAY itself.
hr = io.Printf(_T("%,$Sd"), saData.m_psa);         // Sends "1,2,3"

Example -- IEEE 488.2 format numbers

C++
Copy
HRESULT hr = S_OK;

// Format value as an IEEE-defined hex number
int nMask = 1234;
hr = io.Printf(_T("%@Hd"), nMask);         // Sends "#H7B"

// Format value as an IEEE-defined binary number
hr = io.Printf(_T("%@Hd"), nMask);         // Sends "#B1111011"

int rgData[] = { 1, 2, 3, 4, 5 };

// Field width of 5 includes the "#B", pad with zeros
hr = io.Printf(_T("%@B05,5d"), rgData);    // Sends "#B001,#B010,#B011,#B100,#B101"
See Also

Other Resources

Printf


I/O Format Specifiers for Writing Floating-Point Numbers

Floating-Point Data -- %f (and variants)

A floating point argument has a format specifier of the following form:

%[flags] [488.2 type] [width] [.precision] [delimiter [array size] ] [$S] [l | L] [f | e | E | g | G]

Modifier

Interpretation

Default Functionality

The argument is formatted as a floating point number in NR2 format (a number with at least one digit after the decimal point).

flags

+, -, 0

Controls justification and padding of the output, as follows:

  • - - left aligns the result with the given field width.

  • + - prefixes the output value with a sign (+ or –) if the output value is of a signed type. By default, a sign only appears for negative values.

  • 0 pads with zeros until the specified width is reached. If 0 and - appear together, the 0 is ignored.

488.2 type

The number is formatted in one of six standard IEEE 488.2 numeric formats. The supported formats are:

  • @1 - IEEE 488.2 NR1 format (integer without any decimal point). Example: 123

  • @2 - IEEE 488.2 NR2 format (number with at least one digit after the decimal point). Example: 123.45

  • @3 - IEEE 488.2 NR3 format (floating-point number in exponential form). Example: 1.2345E-67

  • @H - IEEE 488.2 hex format. Example: #HAF35B

  • @Q - IEEE 488.2 octal format. Example: #Q71234

  • @B - IEEE 488.2 binary format. Example: #B011101001

width

Minimum field width of the output number.

An asterisk (*) may be present in lieu of an integer width modifier, in which case an extra int argument supplies the value.

precision

Maximum number of digits after the decimal point for %f, %e, %E.

Maximum number of significant digits for %g, %G.

An asterisk (*) may be present in lieu of an integer precision modifier, in which case an extra int argument supplies the value.

delimiter

[array size]

The argument is interpreted as an array of floats (or double or long double, as specified by the length). If the $S modifier is present, the argument is interpreted as a SAFEARRAY of floating-point numbers.

array size specifies the number of array elements to send.

An asterisk (*) may be present in lieu of an integer array size modifier, in which case an extra int argument supplies the value.

$S

The argument is interpreted as a SAFEARRAY of floating-point numbers.

length modifier

  • l - argument is a double.

  • L - argument is a long double.

type

  • f - signed value having the form dddd.dddd

    where dddd is one or more digits.

    The number of digits before the decimal point depends on the magnitude of the number, and the number of digits after the decimal point depends on the requested precision.

    Example: 3.1415

  • e - signed value having the form d.dddde [+ | -]ddd

    where d is a single digit, dddd is one or more digits, ddd is exactly three digits.

    Example: 3.14e-123

  • E - identical to e format except that E rather than e introduces the exponent.

    Example: 3.14E-123

  • g - signed value in f or e format, whichever is more compact for the given value and precision.

    The e format is used only when the exponent of the value is less than –4 or greater than or equal to the precision.

    Trailing zeros are truncated, and the decimal point appears only if one or more digits follow it.

  • G - Identical to the g format, except that E, rather than e, introduces the exponent (where appropriate)..

Example -- Width and precision

C++
Copy
HRESULT hr = S_OK;

double dRange = 300;

// Default precision is 6, "l" modifier promotes to a double
hr = io.Printf(_T("%lf"), dRange);                        // Sends "300.000000"

// Specify width of 4, but required length is greater
hr = io.Printf(_T("%4.2lf"), dRange);                     // Sends "300.00"

// Width requires padding
hr = io.Printf(_T("%8.2lf"), dRange);                     // Sends "  300.00"

// Exponential notation
hr = io.Printf(_T("%8.2le"), dRange);                     // Sends "3.00e+02"

// Supply field width using a variable
int nWidth = 8;
hr = io.Printf(_T("%*.2le"), nWidth, dRange);             // Sends "3.00e+02"

// Supply field width and precision using variables
int nPrecision = 2;
hr = io.Printf(_T("%*.*le"), nWidth, nPrecision, dRange); // Sends "3.00e+02"

Example -- Floating-point arrays

C++
Copy
HRESULT hr = S_OK;

double rgData[] = { 1.1, 1.2, 1.3, 1.4, 1.5 };

// Comma-separated list of 3 elements
hr = io.Printf(_T("%4.2,3lf"), rgData);               // Sends "1.10,1.20,1.30"

// Semi-colon separated, count supplied as a variable
int nCount = 4;
hr = io.Printf(_T("%3.2(;)*le"), nCount, rgData);     // Sends "1.10e+00;1.20e+00;1.30e+00;1.40e+00"

CComSafeArray<double> saData;
saData.Add(1.1);
saData.Add(1.2);
saData.Add(1.3);

// Comma-separated list.  Argument is a SAFEARRAY.
// No field width supplied, so count is determined from the SAFEARRAY itself.
hr = io.Printf(_T("%4.2,$Slf"), rgData);              // Sends "1.10,1.20,1.30"
See Also

Other Resources

Printf


I/O Format Specifiers for Writing IEEE 488.2 Binary Blocks

IEEE Binary Block Data -- %b and $B

An array argument formatted as an IEEE binary block has a format specifier of the following form:

%[array size] [$S] [b | h | l | I | z | Z] [b | B]

Modifier

Interpretation

Default Functionality

The data block is sent as an IEEE 488.2 definite-length binary block. The array size field specifies the number of elements (by default, bytes) in the block.

array size

Specifies the number of elements in the associated array argument. If the argument is a SAFEARRAY, then the array size may be omitted, in which case the number of elements sent is determined from the size of the SAFEARRAY itself.

An asterisk (*) may be present in lieu of an integer array size modifier, in which case an extra int argument supplies the value.

$S

The argument is assumed to be a SAFEARRAY.

length modifier

If no length modifier is specified, then the argument is assumed to be an array (or SAFEARRAY if $S is used) of BYTE (8-bit) integer.

  • b - argument is an array of BYTE (8-bit) integer.

  • h - argument is an array of short (16-bit) integer.

    The array size indicates the number of 16-bit words, rather than the number of bytes.

    As per the 488.2 binary block standard, the data is sent with big-endian byte ordering. Byte-swapping is automatically performed on all elements in the array.

  • l - argument is an array of long (32-bit) integer.

    The array size indicates the number of 32-bit words, rather than the number of bytes.

    As per the 488.2 binary block standard, the data is sent with big-endian byte ordering. Byte-swapping is automatically performed on all elements in the array.

  • I - argument is an array of __int64 (64-bit) integer.

    The array size indicates the number of 64-bit words, rather than the number of bytes.

    As per the 488.2 binary block standard, the data is sent with big-endian byte ordering. Byte-swapping is automatically performed on all elements in the array.

  • z - argument is an array of float (32-bit) floating-point numbers.

    The numbers are sent in IEEE 754 format.

  • Z - argument is an array of double (64-bit) floating-point numbers.

    The numbers are sent in IEEE 754 format.

b

Data is sent as an IEEE 488.2 definite-length binary block.

B

Data is sent as an IEEE 488.2 indefinite-length binary block.

A linefeed character (\n) is sent after the last byte of the block.

Example -- Definite and indefinite-length blocks

C++
Copy
HRESULT hr = S_OK;

short rgShortData[] = { 1.1, 1.2, 1.3, 1.4, 1.5 };

// IEEE definite-length block of 3 16-bit words
hr = io.Printf(_T("%3hb"), rgShortData);

// IEEE indefinite-length block of all 5 16-bit words
// Number of elements specified as a variable
int nCount = 5;
hr = io.Printf(_T("%*hB"), nCount, rgShortData);

CComSafeArray<double> saData;
saData.Add(1.1);
saData.Add(1.2);
saData.Add(1.3);

// Definite-length block of 3 doubles.  Argument is a SAFEARRAY.
// No field width supplied, so count is determined from the SAFEARRAY itself.
hr = io.Printf(_T("%$Zb"), saData.m_psa);
See Also

Other Resources

Printf


I/O Format Specifiers for Writing Raw Binary Data

Raw Binary Data -- %y

An array argument formatted as raw binary data has a format specifier of the following form:

%[array size] [!ob | !ol] [$S] [b | h | l | I] y

Modifier

Interpretation

Default Functionality

The data block is sent as raw binary data. The array size field specifies the number of elements (by default, bytes) in the block.

array size

Specifies the number of elements in the associated array argument. If the argument is a SAFEARRAY, then the array size may be omitted, in which case the number of elements sent is determined from the size of the SAFEARRAY itself.

An asterisk (*) may be present in lieu of an integer array size modifier, in which case an extra int argument supplies the value.

$S

The argument is interpreted as a SAFEARRAY of integers, as dictated by the length modifier field.

!ob

Data is sent in standard IEEE 488.2 (big endian) format. This is the default behavior if neither !ob nor !ol is present. Byte-swapping is automatically performed on all elements in the array argument.

!ol

Data is sent in little endian format.

length modifier

If no length modifier is specified, then the argument is assumed to be an array of BYTE (8-bit) integer.

  • b - argument is an array of BYTE (8-bit) integer.

  • h - argument is an array of short (16-bit) integer.

    The array size indicates the number of 16-bit words, rather than the number of bytes.

  • l - argument is an array of long (32-bit) integer.

    The array size indicates the number of 32-bit words, rather than the number of bytes.

  • I - argument is an array of __int64 (64-bit) integer.

    The array size indicates the number of 64-bit words, rather than the number of bytes.

Example -- Raw binary data

C++
Copy
HRESULT hr = S_OK;

short rgShortData[] = { 100, 200, 300 };

// Raw binary block of 3 16-bit words, big endian byte ordering
hr = io.Printf(_T("%3hy"), rgShortData);

// Raw binary block of 5 16-bit words, little endian byte ordering
// Number of elements specified as a variable
int nCount = 3;
hr = io.Printf(_T("%*!olhy"), nCount, rgShortData);

CComSafeArray<long> saData;
saData.Add(100);
saData.Add(200);
saData.Add(300);
saData.Add(400);
saData.Add(500);

// Raw binary block of 5 32-bit long words. Argument is a SAFEARRAY.
// No field width supplied, so count is determined from the SAFEARRAY itself.
hr = io.Printf(_T("%$Sly"), saData.m_psa);
See Also

Other Resources

Printf


I/O Format Specifiers for Read Operations

This topic discusses the format specifier fields that may appear in the read format control strings passed to the Printf-style I/O functions. The format specifiers described here apply to the following functions:

  • Scanf

  • ScanfNoPoll

  • ScanfWithTimeout

  • ScanfWithTimeoutNoPoll

  • VScanf

  • VScanfNoPoll

  • Queryf

  • QueryfNoPoll

  • QueryfWithTimeout

  • QueryfWithTimeoutNoPoll

  • VQueryf

  • VQueryfNoPoll

Read Format Specifier Overview

The read format specifier for all Printf-style functions has the following general form:

%[modifiers]type

The type code is the only required field and appears after the optional modifiers. The type code determines whether the associated argument is interpreted as a character, string, number, or array. The type code also determines which modifiers are valid and how they are interpreted. The specific format of the format specifier is given in the various topics in this section for each supported type code.

The table below lists the type codes available along with links to the topics that discuss the format specifier for each data type.

Type of Data | Format Codes | Help Topic
Single characters | %c | Reading Characters
Strings | %s, %t, %T, %[] | Reading Strings
Integers | %d, %i, %o, %u, %x, %X | Reading Integers
Floating-point numbers | %f, %e, %E, %g, %G | Reading Floating-Point Numbers
IEEE 488.2 definite-length blocks | %b | Reading IEEE 488.2 Binary Blocks
Raw binary data | %y | Reading Raw Binary Data
Special Formatting Characters

Special formatting character sequences scan special characters. The following table lists the special characters and describes what they expect to receive from the device.

Formatting Character | Character Expected from Device
\n | Reads the ASCII linefeed character (LF).
\r | Reads the ASCII carriage return (CR) character.
\t | Reads the ASCII TAB character.
\### | Reads the ASCII character specified by the octal value.
\" | Reads the ASCII double-quote (") character.
\\ | Reads the ASCII backslash (\) character.
See Also

Other Resources

Scanf


I/O Format Specifiers for Readings Characters

Character Data -- %c

A character argument has a format specifier of the following form:

%[*] [width] c

Modifier

Interpretation

Default Functionality

A character is read from the device and stored in the argument.

* (asterisk)

An asterisk acts as the assignment suppression character. The input is scanned but not assigned to any parameters and is discarded.

width

Specifies the number of characters to read and store in the argument. The default is 1. A NULL terminator is not appended to the argument.

A # may be present in lieu of an integer width modifier, in which case an extra int argument supplies the value.

Example -- Single-character input

C++
Copy
HRESULT hr = S_OK;

char ch;

// Read a single character from the device and store in the argument
hr = io.Scanf(_T("%c"), ch);

// Field width specifies 5 characters should be read
char sz[5];
hr = io.Scanf(_T("%5c"), sz);               // sz is NOT NULL terminated

// Field width specified using a variable
int nWidth = 5;
hr = io.Scanf(_T("%#c"), nWidth, sz);       // sz is NOT NULL terminated

// Reads 5 characters from the device and discards
hr = io.Scanf(_T("%*5c"));
See Also

Other Resources

Scanf


I/O Format Specifiers for Readings Strings

String Data -- %s, %t, %T, and %[]

A string argument has a format specifier of the following form:

%[{enum} | VARIANT_BOOL] [*] [width] [delimiter [array size] ] [$S] [$B | $C] [q | Q] type

The type code indicates how the read operation is terminated and how whitespace is handled, as explained in the following table:

String Format Code

Whitespace Handling

Read Operation Termination

%s

Leading whitespace is ignored.

Characters are read until a whitespace character is received.

%t

Whitespace is preserved.

Characters are read until the first END indicator is received.

The character on which the END indicator was received is included in the user buffer.

%T

Whitespace is preserved.

Characters are read until a linefeed character (\n) is received.

The linefeed character is included in the user buffer.

%[]

Whitespace is preserved (unless explicitly excluded by the format code itself).

If the first character enclosed in brackets ([]) is not a caret (^), then characters are read up to the first character that does not appear in the bracketed character set.

If the first character in the set is a caret (^), the effect is reversed: characters are read up to the first character that does appear in the rest of the character set.

In either case, the character on which the read terminated is not included in the user buffer.

All four string format codes (%s, %t, %T, and %[]) have the same behavior with regard to the format modifiers, as given in the table below.

Modifier

Interpretation

enum

The argument is interpreted as an int pointer representing an allowed value for the specified enum. The string read from the device is converted to its associated integer value and stored in the int pointer argument supplied by the user. The string-to-integer conversion is performed according to the enum-to-string mappings specified in the Instrument Command Editor. A simplified version of the enum name can be used for the enum field. Specifically, the project name prefix and Enum suffix can be excluded.

VARIANT_BOOL

The argument is interpreted as a VARIANT_BOOL pointer. The string read from the device is converted to a value of VARIANT_TRUE or VARIANT_FALSE performed according to the bool-to-string mappings specified in the Instrument Command Editor.

* (asterisk)

An asterisk acts as the assignment suppression character. The input is scanned but not assigned to any parameters and is discarded.

width

Maximum string size.

A # may be present in lieu of an integer width modifier, in which case an extra int pointer argument supplies the value. Upon completion of the read operation, this width pointer argument is updated with the actual number of characters copied into the user array, not including the NULL terminator.

delimiter

[array size]

The argument is assumed to be a SAFEARRAY of BSTR elements. Note that the $S modifier must be present.

array size specifies the maximum number of array elements to store in the user array argument.

A # may be present in lieu of an integer array size modifier, in which case an extra int argument supplies the value.

$B

The argument is assumed to be a BSTR or a SAFEARRAY of BSTR elements if paired with the $S modifier.

$C

The argument is assumed to be a CString. Note that the $C modifier cannot be combined with the $S modifier.

$S

The argument is assumed to be a SAFEARRAY of BSTR elements. This modifier can only appear if $B is also used, as SAFEARRAYs of CString or C-style strings are not supported.

q

The string is expected to be read with surrounding single-quotes (') or double-quotes ("). Whitespace and delimiter characters enclosed in quotes are preserved and copied to the user argument.

Q

Same as q modifier except that the surrounding quotes are stripped before copying to the user argument.

Example -- String basics

C++
Copy
HRESULT hr = S_OK;

LPSTR sz[100];

// Instrument sends the following:
//    "Hello World"
hr = io.Scanf(_T("%100s"), sz);       // sz contains "Hello"
                                      // read stops at first whitespace

char szManufacturer[100];
char szModel[100];
char szSerial[100];
char szRevision[100];

// Send *IDN? query
// Instrument response is:
//   "Acme,Model4321,A53QWE,Rev1.2"
hr = io.Queryf(_T("*IDN?"), _T("%100[^,],%100[^,],%100[^,],%100[^,]"), szManufacturer, szModel, szSerial, szRevision);

// szManufacturer contains "Acme"
// szModel contains "Model4321"
// szSerial contains "A53QWE"
// szRevision contains "Rev1.2"

// Store only the model and serial number
// WARNING: Access violation occurs if instrument sends more than 99 characters for either model or serial number fields
hr = io.Queryf(_T("*IDN?"), _T("%*[^,],%[^,],%[^,],%*[^,]"), szModel, szSerial);

// Read until something OTHER than an "A", "B", or "C" is encountered
// Instrument sends the following:
//    "AB AC, aC"
hr = io.Scanf(_T("%100[ABC]"), sz);       // sz contains "AB AC, "
                                          // character set is case-sensitive, so read stops at "a"

// Read until a "D", "E", or "F" is encountered
// Instrument sends the following:
//    "AB EA"
hr = io.Scanf(_T("%100[^DEF]"), sz);      // sz contains "AB "

Example -- Quoted strings

C++
Copy
HRESULT hr = S_OK;

char szArg1[100];
char szArg2[100];
char szArg3[100];

// Response is expected in quotes
// Instruments sends the following:
//    'abc','def','hij'
hr = io.Scanf(_T("%100qs,%100qs,%100qs"), szArg1, szArg2, szArg3);      // szArg1 contains 'abc'
                                                                        // szArg2 contains 'def'
                                                                        // szArg3 contains 'hij'

// Response is expected in quotes, results stripped of quotes
// Instruments sends the following:
//    "abc","def","hij"
hr = io.Scanf(_T("%100Qs,%100Qs,%100Qs"), szArg1, szArg2, szArg3);      // szArg1 contains abc
                                                                        // szArg2 contains def
                                                                        // szArg3 contains hij

// Delimiters and whitespace enclosed in quotes are preserved
// Instruments sends the following:
//    "ab,c"," def ","h,i j"
hr = io.Scanf(_T("%100qs,%100qs,%100qs"), szArg1, szArg2, szArg3);      // szArg1 contains "ab,c"
                                                                        // szArg2 contains " def "
                                                                        // szArg3 contains "h,i j"

Example -- BSTR and CString

C++
Copy
HRESULT hr = S_OK;

// Queryf function will allocate memory within the CString objects
CString strManufacturer, strModel, strSerial, strRevision;

// Instrument response is:
//   "Acme,Model4321,A53QWE,Rev1.2"
hr = io.Queryf(_T("*IDN?"), _T("%$C[^,],%$C[^,],%$C[^,],%$C[^,]"), &strManufacturer, &strModel, &strSerial, &strRevision);

// strManufacturer contains "Acme"
// strModel contains "Model4321"
// strSerial contains "A53QWE"
// strRevision contains "Rev1.2"

// Queryf function will allocate memory within the CComBSTR objects
CComBSTR bstrManufacturer, bstrModel, bstrSerial, bstrRevision;

hr = io.Queryf(_T("*IDN?"), _T("%$B[^,],%$B[^,],%$B[^,],%$B[^,]"), &bstrManufacturer, &bstrModel, &bstrSerial, &bstrRevision);

// Memory allocated for CComBSTR and CString objects released upon existing the containing scope

Example -- String arrays

Important note Important

The only type of string arrays supported are SAFEARRAYs of BSTR elements. Thus, $S$B will always appear in the format specifier for a string array. SAFEARRAY arguments that have CString or C-style strings as elements are not supported.

C++
Copy
HRESULT hr = S_OK;

// Queryf will allocate memory for the SAFEARRAY AND for the BSTR elements within it
// Instrument response is:
//   "Acme,Model4321,A53QWE,Rev1.2"
SAFEARRAY* psaArg1 = NULL;
hr = io.Queryf(_T("*IDN?"), _T("%,$S$Bs"), &psaArg1);        // psaArg1[0] contains "Acme"
                                                             // psaArg1[1] contains "Model4321"
                                                             // psaArg1[2] contains "A53QWE"
                                                             // psaArg1[3] contains "Rev1.2"

// NOTE: Caller is responsible for freeing memory associated with SAFEARRAY
// AND the memory associated with each BSTR element.

// Scan using more than one possible delimiter -- colon, semicolon, and comma
// Instrument sends:
//   "abc;def,hij:klm"
SAFEARRAY* psaArg2 = NULL;
hr = io.Scanf(_T("%(:;,)$S$Bs"), &psaArg2);    // psaArg2[0] contains "abc"
                                               // psaArg2[1] contains "def"
                                               // psaArg2[2] contains "hij"
                                               // psaArg2[3] contains "klm"

Example -- Enum and boolean command strings

C++
Copy
HRESULT hr = S_OK;

// Convert string response of device into a valid enum value
// Note the enum format specifier excludes the "Acme4321" prefix and the "Enum" suffix
// Instrument response is:
//   "External"
Acme4321TriggerSourceEnum eSource;
hr = io.Queryf(_T("TRIG:SOUR?"), _T("%{TriggerSource}s"), &eSource);

// Acme4321TriggerSourceExternal is mapped to "External"
ATLASSERT(eSource == Acme4321TriggerSourceExternal);

// Convert string response of device into a VARIANT_BOOL
// Instrument response is "TRUE"
VARIANT_BOOL bEnabled;
hr = io.Queryf(_T("TRIG:ENAB?"), _T("%{VARIANT_BOOL}s"), &bEnabled);

// "TRUE" is mapped to VARIANT_TRUE
ATLASSERT(bEnabled == VARIANT_TRUE);
See Also

Other Resources

Scanf


I/O Format Specifiers for Readings Integers

Integer Data -- %d (and variants)

An integer argument has a format specifier of the following form:

%[*] [488.2 type] [width] [delimiter [array size] ] [$S] [b | h | l | I] [d | o | x]

Modifier

Interpretation

Default Functionality

Characters are read from the device until an entire number is read. The number read may be in either IEEE 488.2 formats <DECIMAL NUMERIC DATA>, also known as NRf; flexible numeric representation (NR1, NR2, NR3...); or <NON-DECIMAL NUMERIC DATA>(#H, #Q, and #B).

* (asterisk)

An asterisk acts as the assignment suppression character. The input is scanned but not assigned to any parameters and is discarded.

488.2 type

The number is expected to be in one of six standard IEEE 488.2 numeric formats. The supported formats are:

  • @1 - IEEE 488.2 NR1 format (integer without any decimal point). Example: 123

  • @2 - IEEE 488.2 NR2 format (number with at least one digit after the decimal point). Example: 123.45

  • @3 - IEEE 488.2 NR3 format (floating-point number in exponential form). Example: 1.2345E-67

  • @H - IEEE 488.2 hex format. Example: #HAF35B

  • @Q - IEEE 488.2 octal format. Example: #Q71234

  • @B - IEEE 488.2 binary format. Example: #B011101001

width

The input number will be stored in a field at least this wide.

A # may be present in lieu of an integer precision modifier, in which case an extra int argument supplies the value.

delimiter

[array size]

The argument is an array of int or short elements, as dictated by the length modifier field. If the $S modifier is present, the argument is assumed to be a pointer to a SAFEARRAY of integers.

array size specifies the maximum number of array elements to store in the user array argument.

A # may be present in lieu of an integer array size modifier, in which case an extra int argument supplies the value.

$S

The argument is interpreted as a pointer to a SAFEARRAY of integers.

length modifier

If no length modifier is specified, then the argument is assumed to be a pointer to a long integer (32-bits).

  • b - argument is a pointer to a BYTE (8-bit) integer.

  • h - argument is a pointer to a short (16-bit) integer.

  • l - argument is a pointer to a long (32-bit) integer.

  • I - argument is a pointer to a __int64 (64-bit) integer.

type

  • d - number is interpreted as a decimal integer.

  • o - number is interpreted as an octal integer.

  • x - number is interpreted as a hex integer.

Example -- Integer basics

C++
Copy
HRESULT hr = S_OK;

int nArg1;
int nArg2;
int nArg3;

// Instrument sends:
//   "8, 100, 42"
hr = io.Scanf(_T("%d,%d,%d"), &nArg1, &nArg2, &nArg3);         // nArg1 == 8
                                                               // nArg2 == 100
                                                               // nArg3 == 42

// Discard the second number in the list
// Instrument sends:
//   "8, 100, 42"
hr = io.Scanf(_T("%d,%*d,%d"), &nArg1, &nArg2);                // nArg1 == 8
                                                               // nArg2 == 42

Example -- Integer length modifiers

C++
Copy
HRESULT hr = S_OK;

long lArg1;
short sArg2;

// Instrument sends:
//   "8, 100"
hr = io.Scanf(_T("%ld,%hd"), &lArg1, &sArg2);         // nArg1 == 8
                                                      // nArg2 == 100

Example -- Integer field width

C++
Copy
HRESULT hr = S_OK;

int nArg1;
int nArg2;

// Field width controls how much is read for each argument
// Instrument sends:
//   "123456789"
hr = io.Scanf(_T("%3d%4d"), &lArg1, &sArg2);         // nArg1 == 123
                                                     // nArg2 == 4567

// Field width supplied using variables
// Instrument sends:
//   "123456789"
int nWidth1 = 3;
int nWidth2 = 4;
hr = io.Scanf(_T("%#d%#d"), &nWidth1, &lArg1, &nWidth2, &sArg2);         // nArg1 == 123
                                                                         // nArg2 == 4567

Example -- Integer arrays

C++
Copy
HRESULT hr = S_OK;

int rgData[5];

// Comma-separated list of 3 elements
// Instrument sends:
//     "123,456,789"
hr = io.Scanf(_T("%,3d"), rgData);                 // rgData[0] == 123
                                                   // rgData[1] == 456
                                                   // rgData[2] == 789

// Mixed delimiters, count supplied as a variable
// Instrument sends:
//     "123,456:789;321"
int nCount = 5;
hr = io.Scanf(_T("%(;,:)#d"), &nCount, rgData);    // rgData[0] == 123
                                                   // rgData[1] == 456
                                                   // rgData[2] == 789
                                                   // rgData[3] == 321

// nCount is updated with actual count
ATLASSERT(nCount == 4);

// Comma-separated list.  Argument is a SAFEARRAY.
// An array element count is not required since Scanf allocates the memory
// Instrument sends:
//     "123,456,789"
SAFEARRAY* psa = NULL;
hr = io.Scanf(_T("%,$Sd"), &psa);                  // psa[0] == 123
                                                   // psa[1] == 456
                                                   // psa[2] == 789

// ... use SAFEARRAY result

// IMPORTANT: SAFEARRAY must be destroyed
hr = ::SafeArrayDestory(psa);

Example -- IEEE 488.2 format numbers

C++
Copy
HRESULT hr = S_OK;

int nArg1;
int nArg2;
int nArg3;

// Read numbers in IEEE 488.2 hex format
// Instrument sends:
//   "#H34E8,#H12B,#HFE"
hr = io.Scanf(_T("%@Hd,%@Hd,%@Hd"), &nArg1, &nArg2, &nArg3);         // nArg1 == 0x34E8
                                                                     // nArg2 == 0x12B
                                                                     // nArg3 == 0xFE
See Also

Other Resources

Scanf


I/O Format Specifiers for Readings Floating-Point Numbers

Floating-Point Data -- %f (and variants)

A floating point argument has a format specifier of the following form:

%[*] [488.2 type] [width] [delimiter [array size] ] [$S] [l | L] [f | e | E | g | G]

Modifier

Interpretation

Default Functionality

Characters are read from the device until an entire number is read. The number read may be in either IEEE 488.2 formats <DECIMAL NUMERIC DATA>, also known as NRf; flexible numeric representation (NR1, NR2, NR3...); or <NON-DECIMAL NUMERIC DATA>(#H, #Q, and #B).

* (asterisk)

An asterisk acts as the assignment suppression character. The input is scanned but not assigned to any parameters and is discarded.

488.2 type

The number is formatted in one of six standard IEEE 488.2 numeric formats. The supported formats are:

  • @1 - IEEE 488.2 NR1 format (integer without any decimal point). Example: 123

  • @2 - IEEE 488.2 NR2 format (number with at least one digit after the decimal point). Example: 123.45

  • @3 - IEEE 488.2 NR3 format (floating-point number in exponential form). Example: 1.2345E-67

  • @H - IEEE 488.2 hex format. Example: #HAF35B

  • @Q - IEEE 488.2 octal format. Example: #Q71234

  • @B - IEEE 488.2 binary format. Example: #B011101001

width

The input number will be stored in a field at least this wide.

A # may be present in lieu of an integer precision modifier, in which case an extra int argument supplies the value.

delimiter [array size]

The argument is an array of float, double, or long double element as dictated by the length modifier field. If the $S modifier is present, the argument is assumed to be a pointer to a SAFEARRAY of floating-point elements.

array size specifies the maximum number of array elements to store in the user array argument.

A # may be present in lieu of an integer array size modifier, in which case an extra int argument supplies the value.

$S

The argument is a pointer to a SAFEARRAY of floating-point numbers.

length modifier

  • l - argument is a pointer to a double.

  • L - argument is a pointer to a long double.

Example -- Floating-point basics

C++
Copy
HRESULT hr = S_OK;

double dArg1;
double dArg2;
double dArg3;

// Instrument sends:
//   "3.2, 1.53E-12, 0.021"
hr = io.Scanf(_T("%le,%le,%le"), &dArg1, &dArg2, &dArg3);      // dArg1 == 3.2
                                                               // dArg2 == 1.53E-12
                                                               // dArg3 == 0.021

// Instrument sends:
//   "3.2, 1.53E-12, 0.021"
hr = io.Scanf(_T("%le,%*le,%le"), &dArg1, &dArg2);             // dArg1 == 3.2
                                                               // dArg2 == 0.21

Example -- Floating-point length modifiers

C++
Copy
HRESULT hr = S_OK;

double dArg1;
float fArg2;

// Instrument sends:
//   "3.14, 3E-4"
hr = io.Scanf(_T("%lf,%f"), &dArg1, &fArg2);         // dArg1 == 3.14
                                                     // fArg2 == 3E-4

Example -- Floating-point field width

C++
Copy
HRESULT hr = S_OK;

double dArg;

// Field width controls how much is read for each argument
// Instrument sends:
//   "12.3456"
hr = io.Scanf(_T("%5le"), &dArg);              // dArg == 12.34

// Field width supplied using variables
// Instrument sends:
//   "12.3456"
int nWidth = 5;
hr = io.Scanf(_T("%#le"), &nWidth, &dArg);     // dArg == 12.34

Example -- Floating-point arrays

C++
Copy
HRESULT hr = S_OK;

double rgData[5];

// Comma-separated list of 3 elements
// Instrument sends:
//   "1.23,4.0E-56,0.789"
hr = io.Scanf(_T("%,3le"), rgData);                // rgData[0] == 1.23
                                                   // rgData[1] == 4E-56
                                                   // rgData[2] == 0.789

// Mixed delimiters, count supplied as a variable
// Instrument sends:
//   "1.23;4.0E-56:0.789,-2"
int nCount = 5;
hr = io.Scanf(_T("%(;,:)#d"), &nCount, rgData);    // rgData[0] == 1.23
                                                   // rgData[1] == 4E-56
                                                   // rgData[2] == 0.789
                                                   // rgData[3] == -2

// nCount is updated with actual count
ATLASSERT(nCount == 4);

// Comma-separated list.  Argument is a SAFEARRAY.
// An array element count is not required since Scanf allocates the memory
// Instrument sends:
//   "1.23,4.0E-56,0.789"
SAFEARRAY* psa = NULL;
hr = io.Scanf(_T("%,$Sle"), &psa);                 // psa[0] == 1.23
                                                   // psa[1] == 4E-56
                                                   // psa[2] == 0.789

// ... use SAFEARRAY result

// IMPORTANT: SAFEARRAY must be destroyed
hr = ::SafeArrayDestory(psa);
See Also

Other Resources

Scanf


I/O Format Specifiers for Readings IEEE 488.2 Binary Blocks

IEEE Binary Block Data -- %b

An array argument formatted as an IEEE definite-length binary block has a format specifier of the following form:

%[*] [array size] [$S] [b | h | l | I | z | Z] b

Modifier

Interpretation

Default Functionality

The data block received must be in IEEE 488.2 definite-length binary block form.

* (asterisk)

An asterisk acts as the assignment suppression character. The input is scanned but not assigned to any parameters and is discarded.

array size

Specifies the maximum number of elements to read from the device. If the argument is a SAFEARRAY, then the array size may be omitted.

A # may be present in lieu of an integer array size modifier, in which case an extra int argument supplies the value.

$S

The argument is assumed to be a SAFEARRAY.

length modifier

If no length modifier is specified, then the argument is assumed to be an array (or SAFEARRAY if $S is used) of BYTE (8-bit) integer.

  • b - argument is an array of BYTE (8-bit) integer.

  • h - argument is an array of short (16-bit) integer.

    The array size indicates the number of 16-bit words, rather than the number of bytes.

    As per the 488.2 binary block standard, the data is assumed to have big-endian byte ordering. Byte-swapping is automatically performed on all elements in the array.

  • l - argument is an array of long (32-bit) integer.

    The array size indicates the number of 32-bit words, rather than the number of bytes.

    As per the 488.2 binary block standard, the data is assumed to have big-endian byte ordering. Byte-swapping is automatically performed on all elements in the array.

  • I - argument is an array of __int64 (64-bit) integer.

    The array size indicates the number of 64-bit words, rather than the number of bytes.

    As per the 488.2 binary block standard, the data is assumed to have big-endian byte ordering. Byte-swapping is automatically performed on all elements in the array.

  • z - argument is an array of float (32-bit) floating-point numbers.

    The numbers are assumed to be in IEEE 754 format.

  • Z - argument is an array of double (64-bit) floating-point numbers.

    The numbers assumed to be in IEEE 754 format.

Example -- Definite-length blocks

C++
Copy
HRESULT hr = S_OK;

short rgData[100];

// IEEE definite-length block of 100 16-bit words
hr = io.Scanf(_T("%100hb"), rgData);

SAFEARRAY* psa = NULL;

// Definite-length block of doubles.  Argument is a SAFEARRAY.
// No field width is needed as Scanf allocates the SAFEARRAY memory
hr = io.Scanf(_T("%$Zb"), &psa);

// ... use SAFEARRAY result

// IMPORTANT: SAFEARRAY must be destroyed
hr = ::SafeArrayDestory(psa);
See Also

Other Resources

Scanf


I/O Format Specifiers for Readings Raw Binary Data

Raw Binary Data -- %y

An array argument formatted as raw binary data has a format specifier of the following form:

%[*] [array size] [!ob | !ol] [$S] [b | h | l | I] y

Modifier

Interpretation

Default Functionality

The data block is received as raw binary data.

* (asterisk)

An asterisk acts as the assignment suppression character. The input is scanned but not assigned to any parameters and is discarded.

array size

Specifies the maximum number of elements to read from the device. If the argument is a SAFEARRAY, then the array size may be omitted.

A # may be present in lieu of an integer array size modifier, in which case an extra int argument supplies the value.

$S

The argument is assumed to be a SAFEARRAY.

!ob

Data is expected to be in standard IEEE 488.2 (big endian) format. This is the default behavior if neither !ob nor !ol is present. Byte-swapping is automatically performed on all elements in the array argument.

!ol

Data is expected to be in little endian format.

length modifier

If no length modifier is specified, then the argument is assumed to be an array (or SAFEARRAY if $S is used) of BYTE (8-bit) integer.

  • b - argument is an array of BYTE (8-bit) integer.

  • h - argument is an array of short (16-bit) integer.

    The array size indicates the number of 16-bit words, rather than the number of bytes.

  • l - argument is an array of long (32-bit) integer.

    The array size indicates the number of 32-bit words, rather than the number of bytes.

  • I - argument is an array of __int64 (64-bit) integer.

    The array size indicates the number of 64-bit words, rather than the number of bytes.

Example -- Raw binary data

C++
Copy
HRESULT hr = S_OK;

short rgData[100];

// Raw binary block of 100 16-bit words, big endian byte ordering
hr = io.Scanf(_T("%100hy"), rgData);

// Raw binary block of 100 16-bit words, little endian byte ordering
// Number of elements specified as a variable
int nCount = 100;
hr = io.Scanf(_T("%#!olhy"), &nCount, rgData);

// nCount updated with actual number of 16-bit words read

SAFEARRAY* psa = NULL;

// Raw binary block of 100 32-bit long words. Argument is a SAFEARRAY.
// No field width is needed as Scanf allocates the SAFEARRAY memory
hr = io.Scanf(_T("%$Sly"), &psa);

// ... use SAFEARRAY result

// IMPORTANT: SAFEARRAY must be destroyed
hr = ::SafeArrayDestory(psa);
See Also

Other Resources

Scanf


Basic I/O Functions

The functions in this section are typically the most commonly used functions for communicating with instruments in a Nimbus IVI-COM driver. Functions are available for reading and writing single numbers or strings, as well as comma-separated lists and IEEE binary block data. If only a single item needs to be formatted with a command (or response), these functions are typically the preferred approach. For situations where multiple values must be formatted together or the formatting requirements are otherwise more complex, the Nimbus Template Library provides a powerful set of printf-style I/O functions.

In This Section

QueryString

QueryStringNoPoll

QueryNumber

QueryNumberNoPoll

QueryList

QueryListNoPoll

Write

WriteNoPoll

WriteString

WriteStringNoPoll

WriteNumber

WriteNumberNoPoll

WriteList

WriteListNoPoll

WriteBinaryBlock

WriteBinaryBlockNoPoll

Read

ReadNoPoll

ReadString

ReadStringNoPoll

ReadNumber

ReadNumberNoPoll

ReadList

ReadListNoPoll

ReadBinaryBlock

ReadBinaryBlockNoPoll

IoDataType Enumeration


QueryString

Performs a write and read of a string result through as a single operation.

virtual HRESULT QueryString(const CString& strCommand, CString& pResult, long lTimeout = CUR_TIMEOUT) abstract;

virtual HRESULT QueryString(const CString& strCommand, BSTR* pResult, long lTimeout = CUR_TIMEOUT) abstract;
Parameters
strCommand

[in] Command string to send to the device.

pResult

[out] Response string read from the device.

lTimeout

[in] I/O timeout value in milliseconds.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

The QueryString function provides a mechanism of "send, then receive" typical to a device command sequences. In this manner, the response generated from the command can be read immediately. The device is not polled for errors after the write portion of the sequence.

The QueryString function performs a WriteStringNoPoll operation followed immediately by a ReadString operation.

Example

The following example demonstrates use of the QueryString function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_GetIdentification(BSTR* pbstrId)
{
  HRESULT hr = S_OK;

  // Send ID query to device and read the response as a BSTR string
  hr = io.QueryString(_T("*IDN?"), pbstrId);

  return hr;
}
See Also

Other Resources

QueryStringNoPoll
QueryNumber
QueryNumberNoPoll
QueryList
QueryListNoPoll


QueryStringNoPoll

Performs a write and read of a string result through as a single operation without polling for instrument errors after the read.

virtual HRESULT QueryStringNoPoll(const CString& strCommand, CString& strResult, long lTimeout = CUR_TIMEOUT) abstract;

virtual HRESULT QueryStringNoPoll(const CString& strCommand, BSTR* pbstrResult, long lTimeout = CUR_TIMEOUT) abstract;
Parameters
strCommand

[in] Command string to send to the device.

strResult

[out] Response string read from the device.

pbstrResult

[out] Response string read from the device.

lTimeout

[in] I/O timeout value in milliseconds.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

This function behaves identically to QueryString except that the device is not polled for errors after the data is read.

Example

The following example demonstrates use of the QueryStringNoPoll function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_GetIdentification(BSTR* pbstrId)
{
  HRESULT hr = S_OK;

  // Send ID query to device and read the response as a BSTR string
  hr = io.QueryStringNoPoll(_T("*IDN?"), pbstrId);

  return hr;
}
See Also

Other Resources

QueryString
QueryNumber
QueryNumberNoPoll
QueryList
QueryListNoPoll


QueryNumber

Performs a write and read of a numeric result through as a single operation.

virtual HRESULT QueryNumber(const CString& strCommand, double* pResult, bool bFlush = true, long lTimeout = CUR_TIMEOUT)  abstract;

virtual HRESULT QueryNumber(const CString& strCommand, float* pResult, bool bFlush = true, long lTimeout = CUR_TIMEOUT) abstract;

virtual HRESULT QueryNumber(const CString& strCommand, long* pResult, bool bFlush = true, long lTimeout = CUR_TIMEOUT) abstract;

virtual HRESULT QueryNumber(const CString& strCommand, short* pResult, bool bFlush = true, long lTimeout = CUR_TIMEOUT) abstract;

virtual HRESULT QueryNumber(const CString& strCommand, BYTE* pResult, bool bFlush = true, long lTimeout = CUR_TIMEOUT) abstract;
Parameters
strCommand

[in] Command string to send to the device.

pResult

[out] Numeric response read from the device.

bFlush

[in] true to flush the formatted I/O read buffer.

lTimeout

[in] I/O timeout value in milliseconds.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

The QueryNumber function provides a mechanism of "send, then receive" typical to a device command sequences. In this manner, the response generated from the command can be read immediately. The device is not polled for errors after the write portion of the sequence.

The QueryNumber function performs a WriteStringNoPoll operation followed immediately by a ReadNumber operation.

If the device response could not be parsed into the type of number requested, this function returns an error.

For more precise control of the response formatting and conversion, use the Scanf function.

Example

The following example demonstrates use of the QueryNumber function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_get_TriggerCount(long* plCount)
{
  HRESULT hr = S_OK;

  hr = io.QueryNumber(_T("TRIG:COUNT?"), plCount);

  return hr;
}
See Also

Other Resources

QueryNumberNoPoll
QueryString
QueryStringNoPoll
QueryList
QueryListNoPoll


QueryNumberNoPoll

Performs a write and read of a numeric result through as a single operation without polling for instrument errors after the read.

virtual HRESULT QueryNumberNoPoll(const CString& strCommand, double* pResult, bool bFlush = true, long lTimeout = CUR_TIMEOUT)  abstract;

virtual HRESULT QueryNumberNoPoll(const CString& strCommand, float* pResult, bool bFlush = true, long lTimeout = CUR_TIMEOUT) abstract;

virtual HRESULT QueryNumberNoPoll(const CString& strCommand, long* pResult, bool bFlush = true, long lTimeout = CUR_TIMEOUT) abstract;

virtual HRESULT QueryNumberNoPoll(const CString& strCommand, short* pResult, bool bFlush = true, long lTimeout = CUR_TIMEOUT) abstract;

virtual HRESULT QueryNumberNoPoll(const CString& strCommand, BYTE* pResult, bool bFlush = true, long lTimeout = CUR_TIMEOUT) abstract;
Parameters
strCommand

[in] Command string to send to the device.

pResult

[out] Numeric response read from the device.

bFlush

[in] true to flush the formatted I/O read buffer.

lTimeout

[in] I/O timeout value in milliseconds.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

This function behaves identically to QueryNumber except that the device is not polled for errors after the data is read.

Example

The following example demonstrates use of the QueryNumberNoPoll function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_get_TriggerCount(long* plCount)
{
  HRESULT hr = S_OK;

  hr = io.QueryNumberNoPoll(_T("TRIG:COUNT?"), plCount);

  return hr;
}
See Also

Other Resources

QueryNumber
QueryString
QueryStringNoPoll
QueryList
QueryListNoPoll


QueryList

Performs a write and read of a delimited list of results through as a single operation.

                virtual HRESULT QueryList(const CString& strCommand, double* pValues, long lMaxLength, long* plActualLength, const CString& strListSeparator = _T(","), long lTimeout = CUR_TIMEOUT) abstract;

                virtual HRESULT QueryList(const CString& strCommand, float* pValues, long lMaxLength, long* plActualLength, const CString& strListSeparator = _T(","), long lTimeout = CUR_TIMEOUT) abstract;

                virtual HRESULT QueryList(const CString& strCommand, long* pValues, long lMaxLength, long* plActualLength, const CString& strListSeparator = _T(","), long lTimeout = CUR_TIMEOUT) abstract;

                virtual HRESULT QueryList(const CString& strCommand, short* pValues, long lMaxLength, long* plActualLength, const CString& strListSeparator = _T(","), long lTimeout = CUR_TIMEOUT) abstract;

                virtual HRESULT QueryList(const CString& strCommand, BYTE* pValues, long lMaxLength, long* plActualLength, const CString& strListSeparator = _T(","), long lTimeout = CUR_TIMEOUT) abstract;

                virtual HRESULT QueryList(const CString& strCommand, CComBSTR* pValues, long lMaxLength, long* plActualLength, const CString& strListSeparator = _T(","), long lTimeout = CUR_TIMEOUT) abstract;

                virtual HRESULT QueryList(const CString& strCommand, SAFEARRAY** pValues, IoDataType  eType, const CString& strListSeparator = _T(","), long lTimeout = CUR_TIMEOUT) abstract;
Parameters
strCommand

[in] Command string to send to the device.

pValues

[out] Array of delimited values parsed from the device.

lMaxLength

[in] Maximum number or elements (not bytes) to read from the device.

plActualLength

[out] Actual number of elements (not bytes) read from the device.

strListSeparator

[in] Set of characters that act as delimiters between elements in the list.

[in] I/O timeout value in milliseconds.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

The QueryList function provides a mechanism of "send, then receive" typical to a device command sequences. In this manner, the response generated from the command can be read immediately. The device is not polled for errors after the write portion of the sequence.

The QueryList function performs a WriteStringNoPoll operation followed immediately by a ReadList operation.

List elements in the response can be separated by any of the characters in the strListSeparator parameter.

If the each element in device response could not be parsed into the type requested, this function returns an error.

Example

The following example demonstrates use of the QueryList function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_QueryData(SAFEARRAY** ppsa)
{
  HRESULT hr = S_OK;

  // Instrument response is:
  //    1.43,2E-6,5.66
  hr = io.QueryList(_T("DATA?"), ppsa, IoDataTypeReal64);

  return hr;
}
See Also

Other Resources

QueryListNoPoll
QueryString
QueryStringNoPoll
QueryNumber
QueryNumberNoPoll


QueryListNoPoll

Performs a write and read of a delimited list of results through as a single operation without polling for instrument errors after the read.

                virtual HRESULT QueryListNoPoll(const CString& strCommand, double* pValues, long lMaxLength, long* plActualLength, const CString& strListSeparator = _T(","), long lTimeout = CUR_TIMEOUT) abstract;

                virtual HRESULT QueryListNoPoll(const CString& strCommand, float* pValues, long lMaxLength, long* plActualLength, const CString& strListSeparator = _T(","), long lTimeout = CUR_TIMEOUT) abstract;

                virtual HRESULT QueryListNoPoll(const CString& strCommand, long* pValues, long lMaxLength, long* plActualLength, const CString& strListSeparator = _T(","), long lTimeout = CUR_TIMEOUT) abstract;

                virtual HRESULT QueryListNoPoll(const CString& strCommand, short* pValues, long lMaxLength, long* plActualLength, const CString& strListSeparator = _T(","), long lTimeout = CUR_TIMEOUT) abstract;

                virtual HRESULT QueryListNoPoll(const CString& strCommand, BYTE* pValues, long lMaxLength, long* plActualLength, const CString& strListSeparator = _T(","), long lTimeout = CUR_TIMEOUT) abstract;

                virtual HRESULT QueryListNoPoll(const CString& strCommand, CComBSTR* pValues, long lMaxLength, long* plActualLength, const CString& strListSeparator = _T(","), long lTimeout = CUR_TIMEOUT) abstract;

                virtual HRESULT QueryListNoPoll(const CString& strCommand, SAFEARRAY** pValues, IoDataType  eType, const CString& strListSeparator = _T(","), long lTimeout = CUR_TIMEOUT) abstract;
Parameters
strCommand

[in] Command string to send to the device.

pValues

[out] Array of delimited values parsed from the device.

lMaxLength

[in] Maximum number or elements (not bytes) to read from the device.

plActualLength

[out] Actual number of elements (not bytes) read from the device.

strListSeparator

[in] Set of characters that act as delimiters between elements in the list.

lTimeout

[in] I/O timeout value in milliseconds.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

This function behaves identically to QueryList except that the device is not polled for errors after the data is read.

Example

The following example demonstrates use of the QueryListNoPoll function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_QueryData(SAFEARRAY** ppsa)
{
  HRESULT hr = S_OK;

  // Instrument response is:
  //    1.43,2E-6,5.66
  hr = io.QueryListNoPoll(_T("DATA?"), ppsa, IoDataTypeReal64);

  return hr;
}
See Also

Other Resources

QueryList
QueryString
QueryStringNoPoll
QueryNumber
QueryNumberNoPoll


Write

Sends data to a device.

virtual HRESULT Write(char ch, bool bFlush = true, long lTimeout = CUR_TIMEOUT) abstract;

virtual HRESULT Write(BYTE* pBuf, long cbDesired, long* pcbActual = NULL, bool bFlush = true, long lTimeout = CUR_TIMEOUT) abstract;

virtual HRESULT Write(SAFEARRAY* psaBuf, long cbDesired = -1, long* pcbActual = NULL, bool bFlush = true, long lTimeout = CUR_TIMEOUT) abstract;
Parameters
ch

[in] Single character to send to the device.

pBuf

[in] Array of bytes to send to the device.

psaBuf

[in] SAFEARRAY of bytes to send to the device. if cbDesired is -1, all elements of the SAFEARRAY are sent.

cbDesired

[in] Number of elements (bytes) to send to the device. If set to -1 and the input is a SAFEARRAY, then all elements of the SAFEARRAY are sent.

pcbActual

[out] Actual number of elements (bytes) sent to the device.

bFlush

[in] If true, the formatted I/O write buffer is flushed to the device.

lTimeout

[in] I/O timeout value in milliseconds.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

The Write function sends raw bytes to the formatted I/O write buffer. If the bFlush parameter is true, then the contents of the I/O write buffer are flushed to the device. If bFlush is false, then the data is queued in the write buffer until the buffer is full or a subsequent operation forces a flush. Queueing data in this fashion can improve I/O performance by reducing the number of I/O roundtrips to the device.

Example

The following example demonstrates use of the Write function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_Configure(BYTE chData, SAFEARRAY* psaData)
{
  HRESULT hr = S_OK;

  // Queue up individual characters in the write buffer
  hr = io.Write('A', false);
  hr = io.Write('B', false);
  hr = io.Write(chData, false);

  // Send array of bytes and flush buffer to device
  hr = io.Write(psaData);

  return hr;
}
See Also

Other Resources

WriteNoPoll
WriteString
WriteNumber
WriteList
WriteBinaryBlock


WriteNoPoll

Sends data to a device without polling for instrument errors after the write.

virtual HRESULT WriteNoPoll(char ch, bool bFlush = true, long lTimeout = CUR_TIMEOUT) abstract;

virtual HRESULT WriteNoPoll(BYTE* pBuf, long cbDesired, long* pcbActual = NULL, bool bFlush = true, long lTimeout = CUR_TIMEOUT) abstract;

virtual HRESULT WriteNoPoll(SAFEARRAY* psaBuf, long cbDesired = -1, long* pcbActual = NULL, bool bFlush = true, long lTimeout = CUR_TIMEOUT) abstract;
Parameters
ch

[in] Single character to send to the device.

pBuf

[in] Array of bytes to send to the device.

psaBuf

[in] SAFEARRAY of bytes to send to the device. if cbDesired is -1, all elements of the SAFEARRAY are sent.

cbDesired

[in] Number of elements (bytes) to send to the device. If set to -1 and the input is a SAFEARRAY, then all elements of the SAFEARRAY are sent.

pcbActual

[out] Actual number of elements (bytes) sent to the device.

bFlush

[in] If true, the formatted I/O write buffer is flushed to the device.

lTimeout

[in] I/O timeout value in milliseconds.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

This function behaves identically to Write except that the device is not polled for errors after the data is sent.

Example

The following example demonstrates use of the WriteNoPoll function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_Configure(BYTE chData, SAFEARRAY* psaData)
{
  HRESULT hr = S_OK;

  // Queue up individual characters in the write buffer
  hr = io.WriteNoPoll('A', false);
  hr = io.WriteNoPoll('B', false);
  hr = io.WriteNoPoll(chData, false);

  // Send array of bytes and flush buffer to device
  hr = io.Write(psaData);

  return hr;
}
See Also

Other Resources

Write
WriteString
WriteNumber
WriteList
WriteBinaryBlock


WriteString

Sends data to a device.

virtual HRESULT WriteString(const CString& strData, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteString(BSTR strData, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteString(LPCTSTR strData, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;
Parameters
strData

[in] String data to send to the device.

bFlush

[in] If true, the formatted I/O write buffer is flushed to the device.

lTimeout

[in] I/O timeout value in milliseconds.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

The WriteString function sends string data to the formatted I/O write buffer. If the bFlush parameter is true, then the contents of the I/O write buffer are flushed to the device. If bFlush is false, then the data is queued in the write buffer until the buffer is full or a subsequent operation forces a flush. Queueing data in this fashion can improve I/O performance by reducing the number of I/O roundtrips to the device.

Example

The following example demonstrates use of the WriteString function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_Configure(BSTR bstrSource1, BSTR bstrSource2, BSTR bstrSource3)
{
  HRESULT hr = S_OK;

  // Queue up commands in the write buffer
  hr = io.WriteStringNoPoll(bstrSource1, false);
  hr = io.WriteStringNoPoll(bstrSource2, false);

  // Send string and flush buffer to device
  hr = io.WriteString(bstrSource3);

  return hr;
}
See Also

Other Resources

WriteStringNoPoll
Write
WriteNumber
WriteList
WriteBinaryBlock


WriteStringNoPoll

Sends data to a device without polling for instrument errors after the write.

virtual HRESULT WriteStringNoPoll(const CString& strData, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteStringNoPoll(BSTR strData, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteStringNoPoll(LPCTSTR strData, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;
Parameters
strData

[in] String data to send to the device.

bFlush

[in] If true, the formatted I/O write buffer is flushed to the device.

lTimeout

[in] I/O timeout value in milliseconds.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

This function behaves identically to WriteString except that the device is not polled for errors after the data is sent.

Example

The following example demonstrates use of the WriteStringNoPoll function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_Configure(BSTR bstrSource1, BSTR bstrSource2, BSTR bstrSource3)
{
  HRESULT hr = S_OK;

  // Queue up commands in the write buffer
  hr = io.WriteStringNoPoll(bstrSource1, false);
  hr = io.WriteStringNoPoll(bstrSource2, false);

  // Send string and flush buffer to device
  hr = io.WriteString(bstrSource3);

  return hr;
}
See Also

Other Resources

WriteString
Write
WriteNumber
WriteList
WriteBinaryBlock


WriteNumber

Formats a number as a string and sends it to a device.

virtual HRESULT WriteNumber(double value, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteNumber(float value, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteNumber(long value, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteNumber(short value, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteNumber(BYTE value, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteNumber(const CString& strCommand, double value, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteNumber(const CString& strCommand, float value, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteNumber(const CString& strCommand, long value, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteNumber(const CString& strCommand, short value, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteNumber(const CString& strCommand, BYTE value, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;
Parameters
strCommand

[in] Command to send to the device before sending the value.

value

[in] Number to format and send to the device.

bFlush

[in] If true, the formatted I/O write buffer is flushed to the device.

lTimeout

[in] I/O timeout value in milliseconds.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

The WriteNumber function formats a number as a string according to the default format settings specified in the I/O Page of the Driver Settings Editor. The resulting string is sent to the formatted I/O write buffer.

For more precise control of the numeric formatting (or to simply override the defaults), use the Printf function.

If the bFlush parameter is true, then the contents of the I/O write buffer are flushed to the device. If bFlush is false, then the data is queued in the write buffer until the buffer is full or a subsequent operation forces a flush. Queueing data in this fashion can improve I/O performance by reducing the number of I/O roundtrips to the device.

Example

The following example demonstrates use of the WriteNumber function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_Configure(long lCount, double dRange, double dResolution)
{
  HRESULT hr = S_OK;

  // Queue up commands in the write buffer
  hr = io.WriteNumberNoPoll(lCount, false);
  hr = io.WriteNumberNoPoll(dRange, false);

  // Send string and flush buffer to device
  hr = io.WriteNumber(dResolution);

  return hr;
}
See Also

Other Resources

WriteNumberNoPoll
Write
WriteString
WriteList
WriteBinaryBlock


WriteNumberNoPoll

Formats a number as a string and sends it to a device without polling for instrument errors after the write.

virtual HRESULT WriteNumberNoPoll(double value, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteNumberNoPoll(float value, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteNumberNoPoll(long value, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteNumberNoPoll(short value, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteNumberNoPoll(BYTE value, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteNumberNoPoll(const CString& strCommand, double value, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteNumberNoPoll(const CString& strCommand, float value, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteNumberNoPoll(const CString& strCommand, long value, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteNumberNoPoll(const CString& strCommand, short value, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteNumberNoPoll(const CString& strCommand, BYTE value, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;
Parameters
strCommand

[in] Command to send to the device before sending the value.

value

[in] Number to format and send to the device.

bFlush

[in] If true, the formatted I/O write buffer is flushed to the device.

lTimeout

[in] I/O timeout value in milliseconds.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

This function behaves identically to WriteNumber except that the device is not polled for errors after the data is sent.

Example

The following example demonstrates use of the WriteNumberNoPoll function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_Configure(long lCount, double dRange, double dResolution)
{
  HRESULT hr = S_OK;

  // Queue up commands in the write buffer
  hr = io.WriteNumberNoPoll(lCount, false);
  hr = io.WriteNumberNoPoll(dRange, false);

  // Send string and flush buffer to device
  hr = io.WriteNumber(dResolution);

  return hr;
}
See Also

Other Resources

WriteNumber
Write
WriteString
WriteList
WriteBinaryBlock


WriteList

Sends a delimited list of values to a device.

virtual HRESULT WriteList(double* pValues, long lLength, const CString& strListSeparator = _T(","), bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteList(float* pValues, long lLength, const CString& strListSeparator = _T(","), bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteList(long* pValues, long lLength, const CString& strListSeparator = _T(","), bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteList(short* pValues, long lLength, const CString& strListSeparator = _T(","), bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteList(BYTE* pValues, long lLength, const CString& strListSeparator = _T(","), bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteList(SAFEARRAY* pValues, const CString& strListSeparator = _T(","), bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteList(const CString& strCommand, double* pValues, long lLength, const CString& strListSeparator = _T(","), bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteList(const CString& strCommand, float* pValues, long lLength, const CString& strListSeparator = _T(","), bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteList(const CString& strCommand, long* pValues, long lLength, const CString& strListSeparator = _T(","), bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteList(const CString& strCommand, short* pValues, long lLength, const CString& strListSeparator = _T(","), bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteList(const CString& strCommand, BYTE* pValues, long lLength, const CString& strListSeparator = _T(","), bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteList(const CString& strCommand, SAFEARRAY* pValues, const CString& strListSeparator = _T(","), bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;
Parameters
strCommand

[in] Command to send to the device before sending the list.

pValues

[in] Array of numeric values to send to the device.

lLength

[in] Number of elements (not bytes) to send to the device. If the input is a SAFEARRAY, then all elements of the SAFEARRAY are sent.

bFlush

[in] If true, the formatted I/O write buffer is flushed to the device.

strListSeparator

[out] Characters to use as separators between elements in the list.

lTimeout

[in] I/O timeout value in milliseconds.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

The WriteList function formats each number in the pValues input array as a string according to the default format settings specified in the I/O Page of the Driver Settings Editor. Each element is separated by the strListSeparator. The resulting string is sent to the formatted I/O write buffer.

For more precise control of the numeric formatting (or to simply override the defaults), use the Printf function.

If the bFlush parameter is true, then the contents of the I/O write buffer are flushed to the device. If bFlush is false, then the data is queued in the write buffer until the buffer is full or a subsequent operation forces a flush. Queueing data in this fashion can improve I/O performance by reducing the number of I/O roundtrips to the device.

Example

The following example demonstrates use of the WriteList function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_Configure(SAFEARRAY* psaData)
{
  HRESULT hr = S_OK;

  // Sends comma-separated list of elements in psaData
  hr = io.WriteList(psaData);

  return hr;
}
See Also

Other Resources

WriteListNoPoll
Write
WriteString
WriteBinaryBlock
WriteNumber


WriteListNoPoll

Sends a delimited list of values to a device without polling for instrument errors after the write.

virtual HRESULT WriteListNoPoll(double* pValues, long lLength, const CString& strListSeparator = _T(","), bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteListNoPoll(float* pValues, long lLength, const CString& strListSeparator = _T(","), bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteListNoPoll(long* pValues, long lLength, const CString& strListSeparator = _T(","), bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteListNoPoll(short* pValues, long lLength, const CString& strListSeparator = _T(","), bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteListNoPoll(BYTE* pValues, long lLength, const CString& strListSeparator = _T(","), bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteListNoPoll(SAFEARRAY* pValues, const CString& strListSeparator = _T(","), bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteListNoPoll(const CString& strCommand, double* pValues, long lLength, const CString& strListSeparator = _T(","), bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteListNoPoll(const CString& strCommand, float* pValues, long lLength, const CString& strListSeparator = _T(","), bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteListNoPoll(const CString& strCommand, long* pValues, long lLength, const CString& strListSeparator = _T(","), bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteListNoPoll(const CString& strCommand, short* pValues, long lLength, const CString& strListSeparator = _T(","), bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteListNoPoll(const CString& strCommand, BYTE* pValues, long lLength, const CString& strListSeparator = _T(","), bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteListNoPoll(const CString& strCommand, SAFEARRAY* pValues, const CString& strListSeparator = _T(","), bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;
Parameters
strCommand

[in] Command to send to the device before sending the list.

pValues

[in] Array of numeric values to send to the device.

lLength

[in] Number of elements (not bytes) to send to the device. If the input is a SAFEARRAY, then all elements of the SAFEARRAY are sent.

bFlush

[in] If true, the formatted I/O write buffer is flushed to the device.

strListSeparator

[out] Characters to use as separators between elements in the list.

lTimeout

[in] I/O timeout value in milliseconds.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

This function behaves identically to WriteList except that the device is not polled for errors after the data is sent.

Example

The following example demonstrates use of the WriteListNoPoll function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_Configure(SAFEARRAY* psaData)
{
  HRESULT hr = S_OK;

  // Sends comma-separated list of elements in psaData
  hr = io.WriteListNoPoll(psaData);

  return hr;
}
See Also

Other Resources

WriteList
Write
WriteString
WriteBinaryBlock
WriteNumber


WriteBinaryBlock

Sends an IEEE 488.2 definite-length binary block to a device.

virtual HRESULT WriteBinaryBlock(double* pValues, long lLength, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteBinaryBlock(float* pValues, long lLength, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteBinaryBlock(long* pValues, long lLength, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteBinaryBlock(short* pValues, long lLength, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteBinaryBlock(BYTE* pValues, long lLength, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteBinaryBlock(SAFEARRAY* pValues, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteBinaryBlock(const CString& strCommand, double* pValues, long lLength, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteBinaryBlock(const CString& strCommand, float* pValues, long lLength, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteBinaryBlock(const CString& strCommand, long* pValues, long lLength, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteBinaryBlock(const CString& strCommand, short* pValues, long lLength, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteBinaryBlock(const CString& strCommand, BYTE* pValues, long lLength, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteBinaryBlock(const CString& strCommand, SAFEARRAY* pValues, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;
Parameters
strCommand

[in] Command to send to the device before sending the binary block.

pValues

[in] Array of numeric values to compose into a definite-length block and send to the device.

lLength

[in] Number of elements (not bytes) to send to the device. If the input is a SAFEARRAY, then all elements of the SAFEARRAY are sent.

bFlush

[in] If true, the formatted I/O write buffer is flushed to the device.

lTimeout

[in] I/O timeout value in milliseconds.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

The WriteBinaryBlock function formats the contents of the pValues input array as an IEEE 488.2 definite-length binary blockand sends it to the formatted I/O write buffer.

If the bFlush parameter is true, then the contents of the I/O write buffer are flushed to the device. If bFlush is false, then the data is queued in the write buffer until the buffer is full or a subsequent operation forces a flush. Queueing data in this fashion can improve I/O performance by reducing the number of I/O roundtrips to the device.

Example

The following example demonstrates use of the WriteBinaryBlock function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_Configure(SAFEARRAY* psaData)
{
  HRESULT hr = S_OK;

  // Sends contents of psaData as an IEEE 488.2 definite-length binary block
  hr = io.WriteBinaryBlock(psaData);

  return hr;
}
See Also

Other Resources

WriteBinaryBlockNoPoll
Write
WriteString
WriteNumber
WriteList


WriteBinaryBlockNoPoll

Sends an IEEE 488.2 definite-length binary block to a device without polling for instrument errors after the write.

virtual HRESULT WriteBinaryBlock(double* pValues, long lLength, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteBinaryBlock(float* pValues, long lLength, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteBinaryBlock(long* pValues, long lLength, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteBinaryBlock(short* pValues, long lLength, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteBinaryBlock(BYTE* pValues, long lLength, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteBinaryBlock(SAFEARRAY* pValues, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteBinaryBlock(const CString& strCommand, double* pValues, long lLength, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteBinaryBlock(const CString& strCommand, float* pValues, long lLength, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteBinaryBlock(const CString& strCommand, long* pValues, long lLength, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteBinaryBlock(const CString& strCommand, short* pValues, long lLength, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteBinaryBlock(const CString& strCommand, BYTE* pValues, long lLength, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT WriteBinaryBlock(const CString& strCommand, SAFEARRAY* pValues, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;
Parameters
strCommand

[in] Command to send to the device before sending the binary block.

pValues

[in] Array of numeric values to compose into a definite-length block and send to the device.

lLength

[in] Number of elements (not bytes) to send to the device. If the input is a SAFEARRAY, then all elements of the SAFEARRAY are sent.

bFlush

[in] If true, the formatted I/O write buffer is flushed to the device.

lTimeout

[in] I/O timeout value in milliseconds.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

This function behaves identically to WriteBinaryBlock except that the device is not polled for errors after the data is sent.

Example

The following example demonstrates use of the WriteBinaryBlockNoPoll function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_Configure(SAFEARRAY* psaData)
{
  HRESULT hr = S_OK;

  // Sends contents of psaData as an IEEE 488.2 definite-length binary block
  hr = io.WriteBinaryBlockNoPoll(psaData);

  return hr;
}
See Also

Other Resources

WriteBinaryBlock
Write
WriteString
WriteNumber
WriteList


Read

Reads data from a device.

virtual HRESULT Read(char& ch, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT Read(BYTE* pBuf, long cbDesired, long* pcbActual, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT Read(SAFEARRAY** pBuf, long cbDesired, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;
Parameters
ch

[out] Single character read from the device.

pBuf

[out] Array of bytes read from the device.

cbDesired

[in] Number of elements (bytes) to read from the device.

pcbActual

[out] Actual number of elements (bytes) read from the device.

bFlush

[in] If true, the formatted I/O read buffer is flushed.

lTimeout

[in] I/O timeout value in milliseconds.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

The Read function reads raw bytes from the formatted I/O read buffer. If the bFlush parameter is true, then the contents of the I/O read buffer are flushed. Flushing the read buffer ensures no unintentional data remains in the buffer for subsequent reads.

Example

The following example demonstrates use of the Read function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_QueryData(SAFEARRAY** ppsaData)
{
  HRESULT hr = S_OK;

  // Read 1000 bytes.  Type of elements is automatically determined from the type of the ppsaData SAFEARRAY parameter
  hr = io.Read(ppsaData, 1000);

  return hr;
}
See Also

Other Resources

ReadNoPoll
ReadString
ReadNumber
ReadList
ReadBinaryBlock


ReadNoPoll

Reads data from a device without polling for instrument errors after the read.

virtual HRESULT ReadNoPoll(char& ch, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT ReadNoPoll(BYTE* pBuf, long cbDesired, long* pcbActual, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT ReadNoPoll(SAFEARRAY** pBuf, long cbDesired, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;
Parameters
ch

[out] Single character read from the device.

pBuf

[out] Array of bytes read from the device.

cbDesired

[in] Number of elements (bytes) to read from the device.

pcbActual

[out] Actual number of elements (bytes) read from the device.

bFlush

[in] If true, the formatted I/O read buffer is flushed.

lTimeout

[in] I/O timeout value in milliseconds.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

This function behaves identically to Read except that the device is not polled for errors after the data is read.

Example

The following example demonstrates use of the ReadNoPoll function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_QueryData(SAFEARRAY** ppsaData)
{
  HRESULT hr = S_OK;

  // Read 1000 Bytes.  Type of elements is automatically determined from the type of the ppsaData SAFEARRAY parameter
  hr = io.ReadNoPoll(ppsaData, 1000);

  return hr;
}
See Also

Other Resources

Read
ReadString
ReadNumber
ReadList
ReadBinaryBlock


ReadString

Reads string data from a device.

virtual HRESULT ReadString(CString& pResult, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT ReadString(BSTR* pResult, long lTimeout = CUR_TIMEOUT) override;
Parameters
pResult

[out] String data read from the device.

lTimeout

[in] I/O timeout value in milliseconds.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

The ReadString function reads from the formatted I/O read buffer until an END condition or termination character is encountered.

Example

The following example demonstrates use of the ReadString function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_QueryData(BSTR* pbstrData)
{
  HRESULT hr = S_OK;

  // Read until END or termchar encountered
  hr = io.ReadString(pbstrData);

  return hr;
}
See Also

Other Resources

ReadNoPoll
ReadString
ReadNumber
ReadList
ReadBinaryBlock


ReadStringNoPoll

Reads string data from a device without polling for instrument errors after the read.

virtual HRESULT ReadString(CString& pResult, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT ReadString(BSTR* pResult, long lTimeout = CUR_TIMEOUT) override;
Parameters
pResult

[out] String data read from the device.

lTimeout

[in] I/O timeout value in milliseconds.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

This function behaves identically to ReadString except that the device is not polled for errors after the data is read.

Example

The following example demonstrates use of the ReadStringNoPoll function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_QueryData(BSTR* pbstrData)
{
  HRESULT hr = S_OK;

  // Read until END or termchar encountered
  hr = io.ReadStringNoPoll(pbstrData);

  return hr;
}
See Also

Other Resources

ReadString
ReadString
ReadNumber
ReadList
ReadBinaryBlock


ReadNumber

Reads numeric data from a device.

virtual HRESULT ReadNumber(double* pValue, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT ReadNumber(float* pValue, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT ReadNumber(long* pValue, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT ReadNumber(short* pValue, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT ReadNumber(BYTE* pValue, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;
Parameters
pValue

[out] Number read from the device.

bFlush

[in] If true, the formatted I/O read buffer is flushed.

lTimeout

[in] I/O timeout value in milliseconds.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

The ReadNumber function reads string data the formatted I/O read buffer and converts it to a number. Integers are converted in the base specified.

If the bFlush parameter is true, then the contents of the I/O read buffer are flushed. Flushing the read buffer ensures no unintentional data remains in the buffer for subsequent reads.

If the device response string cannot be converted into the numeric type requested, this function returns an error.

For more precise control of the response formatting and conversion, use the Scanf function.

Example

The following example demonstrates use of the ReadNumber function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_get_Count(long* plCount)
{
  HRESULT hr = S_OK;

  hr = io.ReadNumber(plCount);

  return hr;
}
See Also

Other Resources

ReadNumberNoPoll
Read
ReadString
ReadList
ReadBinaryBlock


ReadNumberNoPoll

Reads numeric data from a device without polling for instrument errors after the read.

virtual HRESULT ReadNumberNoPoll(double* pValue, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT ReadNumberNoPoll(float* pValue, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT ReadNumberNoPoll(long* pValue, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT ReadNumberNoPoll(short* pValue, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT ReadNumberNoPoll(BYTE* pValue, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;
Parameters
pValue

[out] Number read from the device.

bFlush

[in] If true, the formatted I/O read buffer is flushed.

lTimeout

[in] I/O timeout value in milliseconds.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

This function behaves identically to ReadNumber except that the device is not polled for errors after the data is read.

Example

The following example demonstrates use of the ReadNumberNoPoll function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_get_Count(long* plCount)
{
  HRESULT hr = S_OK;

  hr = io.ReadNumberNoPoll(plCount);

  return hr;
}
See Also

Other Resources

ReadNumber
Read
ReadString
ReadList
ReadBinaryBlock


ReadList

Reads a delimited list of values from a device.

                virtual HRESULT ReadList(double* pValues, long lMaxLength, long* plActualLength, const CString& strListSeparator = _T(","), long lTimeout = CUR_TIMEOUT) abstract;

                virtual HRESULT ReadList(float* pValues, long lMaxLength, long* plActualLength, const CString& strListSeparator = _T(","), long lTimeout = CUR_TIMEOUT) abstract;

                virtual HRESULT ReadList(long* pValues, long lMaxLength, long* plActualLength, const CString& strListSeparator = _T(","), long lTimeout = CUR_TIMEOUT) abstract;

                virtual HRESULT ReadList(short* pValues, long lMaxLength, long* plActualLength, const CString& strListSeparator = _T(","), long lTimeout = CUR_TIMEOUT) abstract;

                virtual HRESULT ReadList(BYTE* pValues, long lMaxLength, long* plActualLength, const CString& strListSeparator = _T(","), long lTimeout = CUR_TIMEOUT) abstract;

                virtual HRESULT ReadList(CComBSTR* pValues, long lMaxLength, long* plActualLength, const CString& strListSeparator = _T(","), long lTimeout = CUR_TIMEOUT) abstract;

                virtual HRESULT ReadList(SAFEARRAY** pValues, IoDataType eType, const CString& strListSeparator = _T(","), long lTimeout = CUR_TIMEOUT) abstract;
Parameters
pValues

[out] Array of delimited values parsed from the device.

IoDataType

[in] Type of element data for the SAFEARRAY.

lMaxLength

[in] Maximum number or elements (not bytes) to read from the device.

plActualLength

[out] Actual number of elements (not bytes) read from the device.

strListSeparator

[in] Set of characters that act as delimiters between elements in the list.

lTimeout

[in] I/O timeout value in milliseconds.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

The ReadList function reads delimited strings from a device and converts them into an array of numeric values. List elements in the response can be separated by any of the characters in the strListSeparator parameter. If the each element in device response could not be parsed into the type requested, this function returns an error.

Example

The following example demonstrates use of the ReadList function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_ReadData(SAFEARRAY** ppsa)
{
  HRESULT hr = S_OK;

  hr = io.WriteStringNoPoll(_T("DATA?"));

  // Instrument response is:
  //    1.43,2E-6,5.66
  hr = io.ReadList(ppsa, IoDataTypeReal64);

  return hr;
}
See Also

Other Resources

ReadNoPoll
ReadString
ReadNumber
ReadList
ReadBinaryBlock


ReadListNoPoll

Reads a delimited list of values from a device without polling for instrument errors after the read.

                virtual HRESULT ReadListNoPoll(double* pValues, long lMaxLength, long* plActualLength, const CString& strListSeparator = _T(","), long lTimeout = CUR_TIMEOUT) abstract;

                virtual HRESULT ReadListNoPoll(float* pValues, long lMaxLength, long* plActualLength, const CString& strListSeparator = _T(","), long lTimeout = CUR_TIMEOUT) abstract;

                virtual HRESULT ReadListNoPoll(long* pValues, long lMaxLength, long* plActualLength, const CString& strListSeparator = _T(","), long lTimeout = CUR_TIMEOUT) abstract;

                virtual HRESULT ReadListNoPoll(short* pValues, long lMaxLength, long* plActualLength, const CString& strListSeparator = _T(","), long lTimeout = CUR_TIMEOUT) abstract;

                virtual HRESULT ReadListNoPoll(BYTE* pValues, long lMaxLength, long* plActualLength, const CString& strListSeparator = _T(","), long lTimeout = CUR_TIMEOUT) abstract;

                virtual HRESULT ReadListNoPollReadListNoPoll(CComBSTR* pValues, long lMaxLength, long* plActualLength, const CString& strListSeparator = _T(","), long lTimeout = CUR_TIMEOUT) abstract;

                virtual HRESULT ReadListNoPoll(SAFEARRAY** pValues, IoDataType eType, const CString& strListSeparator = _T(","), long lTimeout = CUR_TIMEOUT) abstract;
Parameters
pValues

[out] Array of delimited values parsed from the device.

IoDataType

[in] Type of element data for the SAFEARRAY.

lMaxLength

[in] Maximum number or elements (not bytes) to read from the device.

plActualLength

[out] Actual number of elements (not bytes) read from the device.

strListSeparator

[in] Set of characters that act as delimiters between elements in the list.

lTimeout

[in] I/O timeout value in milliseconds.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

This function behaves identically to ReadList except that the device is not polled for errors after the data is read.

Example

The following example demonstrates use of the ReadListNoPoll function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_ReadData(SAFEARRAY** ppsa)
{
  HRESULT hr = S_OK;

  hr = io.WriteStringNoPoll(_T("DATA?"));

  // Instrument response is:
  //    1.43,2E-6,5.66
  hr = io.ReadList(ppsa, IoDataTypeReal64);

  return hr;
}
See Also

Other Resources

ReadList
ReadString
ReadNumber
ReadList
ReadBinaryBlock


ReadBinaryBlock

Reads an IEEE 488.2 definite-length binary block from a device.

                virtual HRESULT ReadBinaryBlock(double* pValues, long lMaxLength, long* plActualLength, bool bSeekToBlock = false, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

                virtual HRESULT ReadBinaryBlock(float* pValues, long lMaxLength, long* plActualLength, bool bSeekToBlock = false, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

                virtual HRESULT ReadBinaryBlock(long* pValues, long lMaxLength, long* plActualLength, bool bSeekToBlock = false, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

                virtual HRESULT ReadBinaryBlock(short* pValues, long lMaxLength, long* plActualLength, bool bSeekToBlock = false, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

                virtual HRESULT ReadBinaryBlock(BYTE* pValues, long lMaxLength, long* plActualLength, bool bSeekToBlock = false, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

                virtual HRESULT ReadBinaryBlock(SAFEARRAY** pValues, IoDataType eType, bool bSeekToBlock = false, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;
Parameters
strCommand

[in] Command to send to the device before sending the binary block.

pValues

[in] Array of numeric values parsed out of the binary block.

IoDataType

[in] Type of element data for the SAFEARRAY.

lMaxLength

[in] Maximum number or elements (not bytes) to read from the device.

bSeekToBlock

[in] If true, characters are read from the device until a valid IEEE 488.2 binary block header is found. If false, the first characters read must be a valid binary block header, else an error is returned.

bFlush

[in] If true, the formatted I/O read buffer is flushed.

lTimeout

[in] I/O timeout value in milliseconds.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

The ReadBinaryBlock function reads data from a device and parses it as an IEEE 488.2 definite-length binary block.

Example

The following example demonstrates use of the ReadBinaryBlock function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_QueryData(SAFEARRAY** ppsaData)
{
  HRESULT hr = S_OK;

  hr = io.WriteStringNoPoll(_T("FORM BIN; DATA?"));

  // Read IEEE 488.2 definite-length binary block
  hr = io.ReadBinaryBlock(ppsaData, IoDataTypeReal64);

  return hr;
}
See Also

Other Resources

ReadBinaryBlockNoPoll
Read
ReadString
ReadNumber
ReadList


ReadBinaryBlockNoPoll

Reads an IEEE 488.2 definite-length binary block from a device without polling for instrument errors after the read.

                virtual HRESULT ReadBinaryBlockNoPoll(double* pValues, long lMaxLength, long* plActualLength, bool bSeekToBlock = false, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

                virtual HRESULT ReadBinaryBlockNoPoll(float* pValues, long lMaxLength, long* plActualLength, bool bSeekToBlock = false, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

                virtual HRESULT ReadBinaryBlockNoPoll(long* pValues, long lMaxLength, long* plActualLength, bool bSeekToBlock = false, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

                virtual HRESULT ReadBinaryBlockNoPoll(short* pValues, long lMaxLength, long* plActualLength, bool bSeekToBlock = false, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

                virtual HRESULT ReadBinaryBlockNoPoll(BYTE* pValues, long lMaxLength, long* plActualLength, bool bSeekToBlock = false, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;

                virtual HRESULT ReadBinaryBlockNoPoll(SAFEARRAY** pValues, IoDataType eType, bool bSeekToBlock = false, bool bFlush = true, long lTimeout = CUR_TIMEOUT) override;
Parameters
strCommand

[in] Command to send to the device before sending the binary block.

pValues

[in] Array of numeric values parsed out of the binary block.

IoDataType

[in] Type of element data for the SAFEARRAY.

lMaxLength

[in] Maximum number or elements (not bytes) to read from the device.

bSeekToBlock

[in] If true, characters are read from the device until a valid IEEE 488.2 binary block header is found. If false, the first characters read must be a valid binary block header, else an error is returned.

bFlush

[in] If true, the formatted I/O read buffer is flushed.

lTimeout

[in] I/O timeout value in milliseconds.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

This function behaves identically to ReadBinaryBlock except that the device is not polled for errors after the data is read.

Example

The following example demonstrates use of the ReadBinaryBlockNoPoll function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_QueryData(SAFEARRAY** ppsaData)
{
  HRESULT hr = S_OK;

  hr = io.WriteStringNoPoll(_T("FORM BIN; DATA?"));

  // Read IEEE 488.2 definite-length binary block
  hr = io.ReadBinaryBlockNoPoll(ppsaData, IoDataTypeReal64);

  return hr;
}
See Also

Other Resources

ReadBinaryBlock
Read
ReadString
ReadNumber
ReadList


IoDataType Enumeration

Specifies the data type for an I/O operation.

enum IoDataType
Members
Member name | Description
IoDataTypeByte | Single byte data.
IoDataTypeInt16 | 16-bit integer.
IoDataTypeInt32 | 32-bit integer.
IoDataTypeInt64 | 64-bit integer.
IoDataTypeReal32 | 32-bit floating-point number.
IoDataTypeReal64 | 64-bit floating-point number.


Low-Level I/O Functions

Instrument communication in Nimbus IVI drivers is typically performed using buffered I/O. Buffering I/O data reduces the number of expensive I/O roundtrips to the instrument, and can improve overall application performance in many situations. Most Nimbus I/O functions send their data through the I/O buffer before passing it along to the instrument. By contrast, the functions described in this section do not perform buffered I/O. Instead, they send their data directly to the instrument without first passing it through the I/O buffer.

In This Section

SetSendEndEnabled

GetSendEndEnabled

LowLevelRead

LowLevelReadNoPoll

LowLevelReadString

LowLevelReadStringNoPoll

LowLevelWrite

LowLevelWriteNoPoll

LowLevelWriteString

LowLevelWriteStringNoPoll

See Also

Other Resources

Communicating With Instruments


SetSendEndEnabled

Specifies whether the IEEE 488.2 END signal should be asserted with the last byte of data transferred from the buffer to the device.

virtual HRESULT SetSendEndEnabled(bool bEnabled) abstract;
Parameters
bEnabled

[in] If true, the END signal is asserted with the last byte of the transfer. If false, no END signal is asserted.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Example

The following example demonstrates use of the SetSendEndEnabled function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::OnFinalInitialize()
{
  HRESULT hr = S_OK;

  hr = io.SetSendEndEnabled(true);

  return hr;
}
See Also

Other Resources

Communicating With Instruments
SetSendEndEnabled

Copyright 2001-2022 Pacific MindWorks. All rights reserved.

Send comments on this topic to support@pacificmindworks.com


GetSendEndEnabled

Indicates whether the IEEE 488.2 END signal will be asserted with the last byte of data transferred from the buffer to the device.

virtual HRESULT GetSendEndEnabled(bool* pbEnabled) abstract;
Parameters
pbEnabled

[out] If true, the END signal is asserted with the last byte of the transfer. If false, no END signal is asserted.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Example

The following example demonstrates use of the GetSendEndEnabled function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::OnFinalInitialize()
{
  HRESULT hr = S_OK;

  bool bSendEND;
  hr = io.GetSendEndEnabled(&bSendEND);

  return hr;
}
See Also

Other Resources

Communicating With Instruments
SetSendEndEnabled


LowLevelRead

Reads raw bytes directly from a device without going through the formatted I/O read buffer.

virtual HRESULT LowLevelRead(BYTE* pBuf, long cbDesired, long* pcbActual, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT LowLevelRead(SAFEARRAY** pBuf, long cbDesired, long lTimeout = CUR_TIMEOUT) override;
Parameters
pBuf

[out] Array of bytes read from the device.

cbDesired

[in] Number of bytes to read from the device.

pcbActual

[out] Actual number of bytes read from the device.

lTimeout

[in] I/O timeout value in milliseconds.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

Unlike the buffered I/O functions, such as Queryf, Read ReadNumber, etc., the LowLevelRead function reads raw bytes directly from the device, rather than going through formatted I/O read buffer.

Caution note Caution

It is critical that these low-level functions not be intermixed with buffered I/O functions in a sequence of operations, such as a set of calls implementing a single driver method. The buffered I/O functions assume that all data read from or sent to the device passes through the I/O buffer, and intermixing these calls with low-level functions that directly access the device can produce incorrect results and/or I/O errors.

Example

The following example demonstrates use of the LowLevelRead function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_QueryData(SAFEARRAY** ppsaData)
{
  HRESULT hr = S_OK;

  // Read 1000 bytes
  hr = io.LowLevel.LowLevelRead(ppsaData, 1000);

  return hr;
}
See Also

Other Resources

LowLevelReadNoPoll
LowLevelReadString
LowLevelReadStringNoPoll


LowLevelReadNoPoll

Reads raw bytes directly from a device without going through the formatted I/O read buffer.

virtual HRESULT LowLevelReadNoPoll(BYTE* pBuf, long cbDesired, long* pcbActual, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT LowLevelReadNoPoll(SAFEARRAY** pBuf, long cbDesired, long lTimeout = CUR_TIMEOUT) override;
Parameters
pBuf

[out] Array of bytes read from the device.

cbDesired

[in] Number of bytes to read from the device.

pcbActual

[out] Actual number of bytes read from the device.

lTimeout

[in] I/O timeout value in milliseconds.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

This function behaves identically to the LowLevelRead function except that the device is not polled for errors after the data is read.

Caution note Caution

It is critical that these low-level functions not be intermixed with buffered I/O functions in a sequence of operations, such as a set of calls implementing a single driver method. The buffered I/O functions assume that all data read from or sent to the device passes through the I/O buffer, and intermixing these calls with low-level functions that directly access the device can produce incorrect results and/or I/O errors.

Example

The following example demonstrates use of the LowLevelReadNoPoll function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_QueryData(SAFEARRAY** ppsaData)
{
  HRESULT hr = S_OK;

  // Read 1000 bytes
  hr = io.LowLevel.LowLevelReadNoPoll(ppsaData, 1000);

  return hr;
}
See Also

Other Resources

LowLevelRead
LowLevelReadString
LowLevelReadStringNoPoll


LowLevelReadString

Reads raw bytes directly from a device without going through the formatted I/O read buffer and returns the results as a string.

virtual HRESULT LowLevelReadString(CString& pBuf, long cchDesired, long lTimeout = CUR_TIMEOUT)  override;

virtual HRESULT LowLevelReadString(BSTR* pBuf, long cchDesired, long lTimeout = CUR_TIMEOUT) override;
Parameters
pBuf

[out] String read from the device.

cchDesired

[in] Number of bytes to read from the device.

lTimeout

[in] I/O timeout value in milliseconds.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

Unlike the buffered I/O functions, such as Queryf, Read ReadNumber, etc., the LowLevelReadString function reads raw bytes directly from the device, rather than going through formatted I/O read buffer.

Caution note Caution

It is critical that these low-level functions not be intermixed with buffered I/O functions in a sequence of operations, such as a set of calls implementing a single driver method. The buffered I/O functions assume that all data read from or sent to the device passes through the I/O buffer, and intermixing these calls with low-level functions that directly access the device can produce incorrect results and/or I/O errors.

Example

The following example demonstrates use of the LowLevelReadString function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_QueryName(BSTR* pbstrName)
{
  HRESULT hr = S_OK;

  // Read up to 50 bytes and return as a BSTR
  hr = io.LowLevel.LowLevelReadString(pbstrName, 50);

  return hr;
}
See Also

Other Resources

LowLevelRead
LowLevelReadNoPoll
LowLevelReadStringNoPoll


LowLevelReadStringNoPoll

Reads raw bytes directly from a device without going through the formatted I/O read buffer and returns the results as a string.

virtual HRESULT LowLevelReadString(CString& pBuf, long cchDesired, long lTimeout = CUR_TIMEOUT)  override;

virtual HRESULT LowLevelReadString(BSTR* pBuf, long cchDesired, long lTimeout = CUR_TIMEOUT) override;
Parameters
pBuf

[out] String read from the device.

cchDesired

[in] Number of bytes to read from the device.

lTimeout

[in] I/O timeout value in milliseconds.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

This function behaves identically to the LowLevelReadString function except that the device is not polled for errors after the data is read.

Caution note Caution

It is critical that these low-level functions not be intermixed with buffered I/O functions in a sequence of operations, such as a set of calls implementing a single driver method. The buffered I/O functions assume that all data read from or sent to the device passes through the I/O buffer, and intermixing these calls with low-level functions that directly access the device can produce incorrect results and/or I/O errors.

Example

The following example demonstrates use of the LowLevelReadStringNoPoll function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_QueryName(BSTR* pbstrName)
{
  HRESULT hr = S_OK;

  // Read up to 50 bytes and return as a BSTR
  hr = io.LowLevel.LowLevelReadStringNoPoll(pbstrName, 50);

  return hr;
}
See Also

Other Resources

LowLevelRead
LowLevelReadNoPoll
LowLevelReadString


LowLevelWrite

Writes raw bytes directly to a device without going through the formatted I/O write buffer.

virtual HRESULT LowLevelWrite(BYTE* pBuf, long cbDesired, long* pcbActual = NULL, bool bAddTrailing = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT LowLevelWrite(SAFEARRAY* pBuf, long cbDesired = -1, long* pcbActual = NULL, bool bAddTrailing = true, long lTimeout = CUR_TIMEOUT) override;
Parameters
pBuf

[int] Array of bytes to write to the device.

cbDesired

[in] Number of bytes to write to the device. If pBuf is a SAFEARRAY and cbDesired is -1, then the entire contents of the SAFEARRAY are sent to the device.

pcbActual

[out] Actual number of bytes written to the device. pcbActual may be set to NULL if the caller is not interested in knowing the actual number of bytes written.

bAddTrailing

[in] true to have the trailing characters specified by the SetTrailingForWrites function automatically added to pBuf before sending to the device.

lTimeout

[in] I/O timeout value in milliseconds.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

Unlike the buffered I/O functions, such as Printf, Write and WriteNumber, etc., the LowLevelWrite function sends raw bytes directly to the device, rather than going through formatted I/O write buffer.

Caution note Caution

It is critical that these low-level functions not be intermixed with buffered I/O functions in a sequence of operations, such as a set of calls implementing a single driver method. The buffered I/O functions assume that all data read from or sent to the device passes through the I/O buffer, and intermixing these calls with low-level functions that directly access the device can produce incorrect results and/or I/O errors.

Example

The following example demonstrates use of the LowLevelWrite function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_Configure(SAFEARRAY* psaData)
{
  HRESULT hr = S_OK;

  // Write 1000 bytes from psaData
  hr = io.LowLevel.LowLevelWrite(psaData, 1000);

  return hr;
}
See Also

Other Resources

LowLevelWriteNoPoll
LowLevelWriteString
LowLevelWriteStringNoPoll


LowLevelWriteNoPoll

Writes raw bytes directly to a device without going through the formatted I/O write buffer.

virtual HRESULT LowLevelWriteNoPoll(BYTE* pBuf, long cbDesired, long* pcbActual = NULL, bool bAddTrailing = true, long lTimeout = CUR_TIMEOUT) override;

virtual HRESULT LowLevelWriteNoPoll(SAFEARRAY* pBuf, long cbDesired = -1, long* pcbActual = NULL, bool bAddTrailing = true, long lTimeout = CUR_TIMEOUT) override;
Parameters
pBuf

[int] Array of bytes to write to the device.

cbDesired

[in] Number of bytes to write to the device. If pBuf is a SAFEARRAY and cbDesired is -1, then the entire contents of the SAFEARRAY are sent to the device.

pcbActual

[out] Actual number of bytes written to the device. pcbActual may be set to NULL if the caller is not interested in knowing the actual number of bytes written.

bAddTrailing

[in] true to have the trailing characters specified by the SetTrailingForWrites function automatically added to pBuf before sending to the device.

lTimeout

[in] I/O timeout value in milliseconds.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

This function behaves identically to the LowLevelWrite function except that the device is not polled for errors after the data is written.

Caution note Caution

It is critical that these low-level functions not be intermixed with buffered I/O functions in a sequence of operations, such as a set of calls implementing a single driver method. The buffered I/O functions assume that all data read from or sent to the device passes through the I/O buffer, and intermixing these calls with low-level functions that directly access the device can produce incorrect results and/or I/O errors.

Example

The following example demonstrates use of the LowLevelWriteNoPoll function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_Configure(SAFEARRAY* psaData)
{
  HRESULT hr = S_OK;

  // Write 1000 bytes from psaData
  hr = io.LowLevel.LowLevelWriteNoPoll(psaData, 1000);

  return hr;
}
See Also

Other Resources

LowLevelWrite
LowLevelWriteString
LowLevelWriteStringNoPoll


LowLevelWriteString

Writes raw bytes directly to a device without going through the formatted I/O write buffer.

virtual HRESULT LowLevelWriteString(const CString& strBuf, long* pcchActual = NULL, bool bAddTrailing = true, long lTimeout = CUR_TIMEOUT)  override;

virtual HRESULT LowLevelWriteString(BSTR strBuf, long* pcchActual = NULL, bool bAddTrailing = true, long lTimeout = CUR_TIMEOUT) override;
Parameters
strBuf

[int] Array of characters to be written to the device.

pcchActual

[out] Actual number of bytes written to the device. pcchActual may be set to NULL if the caller is not interested in knowing the actual number of bytes written.

bAddTrailing

[in] true to have the trailing characters specified by the SetTrailingForWrites function automatically added to strBuf before sending to the device.

lTimeout

[in] I/O timeout value in milliseconds.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

Unlike the buffered I/O functions, such as Printf, Write and WriteNumber, etc., the LowLevelWriteString function sends raw bytes directly to the device, rather than going through formatted I/O write buffer.

Each character in strBuf is converted to ASCII and sent to the device. An error is returned if one or more of the Unicode characters in strBuf cannot be converted to ASCII.

Caution note Caution

It is critical that these low-level functions not be intermixed with buffered I/O functions in a sequence of operations, such as a set of calls implementing a single driver method. The buffered I/O functions assume that all data read from or sent to the device passes through the I/O buffer, and intermixing these calls with low-level functions that directly access the device can produce incorrect results and/or I/O errors.

Example

The following example demonstrates use of the LowLevelWriteString function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_Configure(BSTR bstrData)
{
  HRESULT hr = S_OK;

  hr = io.LowLevel.LowLevelWriteString(bstrData);

  return hr;
}
See Also

Other Resources

LowLevelWrite
LowLevelWriteNoPoll
LowLevelWriteStringNoPoll


LowLevelWriteStringNoPoll

Writes raw bytes directly to a device without going through the formatted I/O write buffer.

virtual HRESULT LowLevelWriteStringNoPoll(const CString& strBuf, long* pcchActual = NULL, bool bAddTrailing = true, long lTimeout = CUR_TIMEOUT)  override;

virtual HRESULT LowLevelWriteStringNoPoll(BSTR strBuf, long* pcchActual = NULL, bool bAddTrailing = true, long lTimeout = CUR_TIMEOUT) override;
Parameters
strBuf

[int] Array of characters to be written to the device.

pcchActual

[out] Actual number of bytes written to the device. pcchActual may be set to NULL if the caller is not interested in knowing the actual number of bytes written.

bAddTrailing

[in] true to have the trailing characters specified by the SetTrailingForWrites function automatically added to strBuf before sending to the device.

lTimeout

[in] I/O timeout value in milliseconds.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

This function behaves identically to the LowLevelWriteString function except that the device is not polled for errors after the data is written.

Caution note Caution

It is critical that these low-level functions not be intermixed with buffered I/O functions in a sequence of operations, such as a set of calls implementing a single driver method. The buffered I/O functions assume that all data read from or sent to the device passes through the I/O buffer, and intermixing these calls with low-level functions that directly access the device can produce incorrect results and/or I/O errors.

Example

The following example demonstrates use of the LowLevelWriteStringNoPoll function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_Configure(BSTR bstrData)
{
  HRESULT hr = S_OK;

  hr = io.LowLevel.LowLevelWriteStringNoPoll(bstrData);

  return hr;
}
See Also

Other Resources

LowLevelWrite
LowLevelWriteNoPoll
LowLevelWriteString


Buffer Management Functions

Most instrument I/O functions in Nimbus rely upon buffered I/O. The functions in this section provide direct control over the I/O buffer itself.

In This Section

SetBufferSize

GetReadBufferSize

GetWriteBufferSize

FlushWrite

FlushRead

IoBufferMask Enumeration

See Also

Other Resources

Understanding Buffered I/O


SetBufferSize

Specifies the size of the I/O read and/or write buffers.

                virtual HRESULT SetBufferSize(IoBufferMask eMask, long cbSize) sealed override;
Parameters
eMask

[in] Specifies whether to set the size of the read buffer, the write buffer, or both buffers.

cbSize

[in] Desired size of the buffer(s) indicated by the eMask parameter.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

The default size of the read and write buffers is 4096 bytes.

Example

The following example demonstrates use of the SetBufferSize function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::OnFinalInitialize()
{
  HRESULT hr = S_OK;

  // Set both the read and write buffers to be 8K bytes
  hr = io.SetBufferSize(IoReadAndWriteBuffers, 8192);

  return hr;
}
See Also

Other Resources

GetReadBufferSize
GetWriteBufferSize
IoBufferMask Enumeration


GetReadBufferSize

Indicates the size of the I/O read buffer.

virtual HRESULT GetReadBufferSize(long* pcbSize) sealed override;
Parameters
pcbSize

[out] Current size of the I/O read buffer.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

The default size of the read buffer is 4096 bytes.

Example

The following example demonstrates use of the GetReadBufferSize function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::OnFinalInitialize()
{
  HRESULT hr = S_OK;

  long cbSize;
  hr = io.GetReadBufferSize(&cbSize);

  return hr;
}
See Also

Other Resources

Understanding Buffered I/O
SetBufferSize


GetWriteBufferSize

Indicates the size of the I/O write buffer.

virtual HRESULT GetWriteBufferSize(long* pcbSize) sealed override;
Parameters
pcbSize

[out] Current size of the I/O write buffer.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

The default size of the write buffer is 4096 bytes.

Example

The following example demonstrates use of the GetWriteBufferSize function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::OnFinalInitialize()
{
  HRESULT hr = S_OK;

  long cbSize;
  hr = io.GetWriteBufferSize(&cbSize);

  return hr;
}
See Also

Other Resources

Understanding Buffered I/O
SetBufferSize


FlushWrite

Flushes the contents of the I/O write buffer to the device.

virtual HRESULT FlushWrite(bool bSendEnd = true, long lTimeout = CUR_TIMEOUT) sealed override;
Parameters
bSendEnd

[in] If true, the END signal is asserted with the last byte of the transfer. If false, no END signal is asserted.

lTimeout

[in] I/O timeout value in milliseconds.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Example

The following example demonstrates use of the FlushWrite function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::Configure()
{
  HRESULT hr = S_OK;

  // Send an IEEE 488.2 END signal with the last byte in the buffer, use the existing timeout value
  hr = io.FlushWrite();

  return hr;
}
See Also

Other Resources

Understanding Buffered I/O
FlushRead


FlushRead

Flushes the contents of the I/O read buffer.

virtual HRESULT FlushRead(long lTimeout = CUR_TIMEOUT) sealed override;
Parameters
lTimeout

[in] I/O timeout value in milliseconds.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

Any existing data in the I/O read buffer is discarded. In addition, if the read buffer is non-empty and no EOI was read during the last read operation, then data is read from the device until an EOI is encountered.

Example

The following example demonstrates use of the FlushRead function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::Configure()
{
  HRESULT hr = S_OK;

  // Discard contents of the I/O read buffer and read from the device until EOI
  hr = io.FlushRead();

  return hr;
}
See Also

Other Resources

Understanding Buffered I/O
FlushWrite


IoBufferMask Enumeration

Specifies whether the operation should be performed on the I/O read buffer, the write buffer, or both buffers.

enum IoBufferMask
Members
Member name | Description
IoReadBuffer | I/O read buffer.
IoWriteBuffer | I/O write buffer.
IoReadAndWriteBuffers | Both the I/O read and write buffers.
See Also

Other Resources

Understanding Buffered I/O
Printf
Scanf


Instrument Error Functions

In This Section

PollInstrumentErrors


PollInstrumentErrors

Queries the instrument for device errors.

virtual HRESULT PollInstrumentErrors();
Return Value

Returns S_OK if the device indicated there were no errors, otherwise a failure HRESULT.

Remarks

By default, the PollInstrumentErrors function issues a "*ESR?" query to the device and parses the response to determine if an error occurred. If an error was reported by the device, an error HRESULT is returned. Driver implementers may override this function to provide specialized logic for interrogating their device for errors.

This function is typically not called directly by user code. Rather, it is used internally in the implementation of various Nimbus Template Library I/O functions, as demonstrated in the example below.

Example

The following example demonstrates use of the PollInstrumentErrors function.

C++
Copy
// NtlIo.inl
inline HRESULT CIoSession::WriteString(const CString& strData, bool bFlush, long lTimeout)
{
    HRESULT hr = S_OK;

    hr = WriteStringNoPoll(strData, bFlush, lTimeout);

    if (SUCCEEDED(hr))
    {
        hr = PollInstrumentErrors();
    }

    return hr;
}


VISA-Specific Functions

Most Nimbus I/O functions are independent of the underlying I/O provider. The functions in this section are only available when using either the VISA-C or VISA-COM I/O provider. None of these functions are available for custom I/O providers.

In This Section

Session Management Functions

Register-Based Functions

Low-Level I/O Functions

VISA-COM Specific Functions

VISA-C Specific Functions


Session Management Functions

The functions in this section control various settings global to a VISA instrument setting.

Note Note

The functions in this section are only available for the VISA-COM or VISA-C I/O providers. They are not available for custom I/O providers.

In This Section

SetProtocol

GetProtocol

VisaIoProtocol Enumeration

SetAttribute

GetAttribute

GetResourceName

GetInterfaceName

GetInterfaceType

VisaInterfaceType Enumeration

GetInterfaceNumber

GetSessionType

GetManufacturerName

GetManufacturerId

See Also

Other Resources

Communicating With Instruments


SetProtocol

Specifies which VISA I/O protocol to use.

                virtual HRESULT SetProtocol(VisaIoProtocol eProtocol) abstract;
Parameters
eProtocol

[in] I/O protocol to use.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

In VXI systems, for example, you can choose between normal word serial or fast data channel (FDC). In GPIB, you can choose between normal and high speed (HS488) data transfers. In ASRL and TCPIP systems, you can choose between normal and 488-style transfers.

Example

The following example demonstrates use of the SetProtocol function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_OnFinalInitialize()
{
  HRESULT hr = S_OK;

  hr = io.SetProtocol(VisaProtocolNormal);

  return hr;
}
See Also

Other Resources

GetProtocol
VisaIoProtocol Enumeration


GetProtocol

Gets the currently configured VISA I/O protocol.

                virtual HRESULT GetProtocol(VisaIoProtocol* peProtocol) abstract;
Parameters
peProtocol

[out] I/O protocol currently in use.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

In VXI systems, for example, you can choose between normal word serial or fast data channel (FDC). In GPIB, you can choose between normal and high speed (HS488) data transfers. In ASRL and TCPIP systems, you can choose between normal and 488-style transfers.

Example

The following example demonstrates use of the GetProtocol function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_OnFinalInitialize()
{
  HRESULT hr = S_OK;

  VisaIoProtocol eProtocol;
  hr = io.GetProtocol(&eProtocol);

  return hr;
}
See Also

Other Resources

SetProtocol


VisaIoProtocol Enumeration

Specifies the VISA I/O protocol.

enum VisaIoProtocol
Members
Member name | Description
VisaProtocolNormal | Normal.
VisaProtocolFdc | Fast data channel (FDC).
VisaProtocolHs488 | High-speed 488.
VisaProtocol4882Strs |
VisaProtocolUsbTmcVendor |
See Also

Other Resources

GetProtocol
SetProtocol


SetAttribute

Sets an attribute on the VISA I/O session.

virtual HRESULT SetAttribute(long lAttribute, UINT32 value) abstract;

virtual HRESULT SetAttribute(long lAttribute, UINT64 value) abstract;

virtual HRESULT SetAttribute(long lAttribute, bool value) abstract;

virtual HRESULT SetAttribute(long lAttribute, const CString& value) abstract;
Parameters
lAttribute

[in] Attribute ID of the session attribute to set.

value

[in] Value to which the attribute will be set.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

The SetAttribute function can be used to exercise very low-level control over the VISA I/O session. The allowed values for the lAttribute correspond to the VISA attribute ID values available in the VISA specification. These values may also be found in the visa.h header file. See the VISA specification for details.

Example

The following example demonstrates use of the SetAttribute function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_OnFinalInitialize()
{
  HRESULT hr = S_OK;

  hr = io.SetAttribute(VI_ATTR_SEND_END_EN, true);

  return hr;
}
See Also

Other Resources

GetAttribute


GetAttribute

Gets the value of an attribute on the VISA I/O session.

virtual HRESULT GetAttribute(long lAttribute, UINT32* pValue) abstract;

virtual HRESULT GetAttribute(long lAttribute, UINT64* pValue) abstract;

virtual HRESULT GetAttribute(long lAttribute, bool* pValue) abstract;

virtual HRESULT GetAttribute(long lAttribute, CString& pValue) abstract;
Parameters
lAttribute

[in] Attribute ID of the session attribute to set.

pValue

[out] Value of the specified attribute.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

The GetAttribute function can be used to retrieve very low-level information about the VISA I/O session. The allowed values for the lAttribute correspond to the VISA attribute ID values available in the VISA specification. These values may also be found in the visa.h header file. See the VISA specification for details.

Example

The following example demonstrates use of the GetAttribute function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_OnFinalInitialize()
{
  HRESULT hr = S_OK;

  CString strManufacturer;
  hr = io.GetAttribute(VI_ATTR_MANF_NAME, strManufacturer);

  return hr;
}
See Also

Other Resources

SetAttribute


GetResourceName

Gets the VISA resource name of the I/O session.

virtual HRESULT GetResourceName(CString& strName) abstract;
Parameters
strName

[out] VISA resource name of the I/O session.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Example

The following example demonstrates use of the GetResourceName function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_OnFinalInitialize()
{
  HRESULT hr = S_OK;

  CString strResourceName;
  hr = io.SessionInfo.GetResourceName(strResourceName);

  return hr;
}


GetInterfaceName

Gets the VISA interface name of the I/O session.

virtual HRESULT GetInterfaceName(CString& strName) abstract;
Parameters
strName

[out] VISA interface name of the I/O session.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Example

The following example demonstrates use of the GetResourceName function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_OnFinalInitialize()
{
  HRESULT hr = S_OK;

  CString strInterfaceName;
  hr = io.SessionInfo.GetInterfaceName(strInterfaceName);

  return hr;
}
See Also

Other Resources

GetInterfaceType
GetInterfaceNumber
GetSessionType


GetInterfaceType

Gets the VISA interface type of the I/O session.

                virtual HRESULT GetInterfaceType(VisaInterfaceType* peType) abstract;
Parameters
peType

[out] VISA interface type of the I/O session.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Example

The following example demonstrates use of the GetInterfaceType function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_OnFinalInitialize()
{
  HRESULT hr = S_OK;

  VisaInterfaceType eIntfType;
  hr = io.SessionInfo.GetInterfaceType(&eIntfType);

  return hr;
}
See Also

Other Resources

GetInterfaceName
GetInterfaceNumber
GetSessionType
VisaInterfaceType Enumeration


VisaInterfaceType Enumeration

Specifies the VISA interface type.

enum VisaInterfaceType
Members
Member name | Description
VisaInterfaceGpib | GPIB interface.
VisaInterfaceVxi | VXI interface.
VisaInterfaceGpibVxi | GPIB-VXI interface.
VisaInterfaceSerial | Serial interface.
VisaInterfacePxi | PXI interface.
VisaInterfaceTcpip | TCP/IP interface.
VisaInterfaceUsb | USB interface.
VisaInterfaceFirewire | Firewire interface.
VisaInterfaceOther | Unrecognized or non-standard interface.
See Also

Other Resources

GetInterfaceType


GetInterfaceNumber

Gets the VISA interface number of the I/O session.

virtual HRESULT GetInterfaceNumber(UINT16* pusNumber) abstract;
Parameters
pusNumber

[out] VISA interface number of the I/O session.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Example

The following example demonstrates use of the GetInterfaceNumber function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_OnFinalInitialize()
{
  HRESULT hr = S_OK;

  USHORT usIntfNum;
  hr = io.SessionInfo.GetInterfaceName(&usIntfNum);

  return hr;
}
See Also

Other Resources

GetInterfaceName
GetInterfaceType
GetSessionType


GetSessionType

Gets the VISA I/O session type.

virtual HRESULT GetSessionType(CString& strType) abstract;
Parameters
strType

[out] VISA I/O session type.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Example

The following example demonstrates use of the GetSessionType function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_OnFinalInitialize()
{
  HRESULT hr = S_OK;

  CString strType;
  hr = io.SessionInfo.GetSessionType(&strType);

  return hr;
}
See Also

Other Resources

GetInterfaceName
GetInterfaceType
GetInterfaceNumber


GetManufacturerName

Gets the VISA interface manufacturer name.

virtual HRESULT GetManufacturerName(CString& strName) abstract;
Parameters
strName

[out] VISA interface manufacturer name.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Example

The following example demonstrates use of the GetManufacturerName function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_OnFinalInitialize()
{
  HRESULT hr = S_OK;

  CString strManufacturerName;
  hr = io.SessionInfo.GetManufacturerName(strManufacturerName);

  return hr;
}
See Also

Other Resources

GetManufacturerId


GetManufacturerId

Gets the VISA interface manufacturer ID.

virtual HRESULT GetManufacturerId(UINT16* pusId) abstract;
Parameters
pusId

[out] VISA interface manufacturer ID.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Example

The following example demonstrates use of the GetManufacturerId function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_OnFinalInitialize()
{
  HRESULT hr = S_OK;

  USHORT usManufacturerId;
  hr = io.SessionInfo.GetManufacturerId(&usManufacturerId);

  return hr;
}
See Also

Other Resources

GetManufacturerName


Register-Based Functions

The functions in this section allow direct access to register-based devices.

Note Note

The functions in this section are only available for the VISA-COM or VISA-C I/O providers. They are not available for custom I/O providers.

In This Section

VisaAddressSpace Enumeration

In8

In16

In32

In64

Out8

Out16

Out32

Out64

MoveIn8

MoveIn16

MoveIn32

MoveIn64

MoveOut8

MoveOut16

MoveOut32

MoveOut64

Move

MoveAsync

VisaDataWidth Enumeration

SetSourceBigEndian

GetSourceBigEndian

SetDestinationBigEndian

GetDestinationBigEndian

SetSourceIncrement

GetSourceIncrement

SetDestinationIncrement

GetDestinationIncrement

AllocateMemory

FreeMemory


VisaAddressSpace Enumeration

Specifies the VISA address space for register-based operations.

enum VisaAddressSpace
Members
Member name | Description
VisaA16Space | Access the A16 address space of VXI/MXI bus.
VisaA24Space | Access the A24 address space of VXI/MXI bus.
VisaA32Space | Access the A32 address space of VXI/MXI bus.
VisaA64Space | Access the A64 address space of VXI/MXI bus.
VisaPxiCfgSpace | Access the PXI configuration space.
VisaPxiBar0Space | Access the PCI bar 0 space.
VisaPxiBar1Space | Access the PCI bar 1 space.
VisaPxiBar2Space | Access the PCI bar 2 space.
VisaPxiBar3Space | Access the PCI bar 3 space.
VisaPxiBar4Space | Access the PCI bar 4 space.
VisaPxiBar5Space | Access the PCI bar 5 space.
VisaPxiAllocSpace | Access physical locally allocated memory.


In8

Reads an 8-bit value from a register-based device.

                virtual HRESULT In8(VisaAddressSpace eSpace, UINT64 ullOffset, UINT8* puVal) abstract;
Parameters
eSpace

[in] Address space from which to read the value.

ullOffset

[in] Offset within eSpace to read the value.

puVal

Value read from the register-based device.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

Reads an 8-bit value from a register-based device at the specified memory space and offset.

Example

The following example demonstrates use of the In8 function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_ReadRegister()
{
  HRESULT hr = S_OK;

  UINT8 uVal;
  hr = io.Memory.In8(VisaA16Space, 0x10, &uVal);

  return hr;
}
See Also

Other Resources

In16
In32
In64
VisaAddressSpace Enumeration


In16

Reads an 16-bit value from a register-based device.

                virtual HRESULT In16(VisaAddressSpace eSpace, UINT64 ullOffset, UINT16* puVal) abstract;
Parameters
eSpace

[in] Address space from which to read the value.

ullOffset

[in] Offset within eSpace to read the value.

puVal

Value read from the register-based device.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

Reads a 16-bit value from a register-based device at the specified memory space and offset.

Example

The following example demonstrates use of the In16 function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_ReadRegister()
{
  HRESULT hr = S_OK;

  UINT16 uVal;
  hr = io.Memory.In16(VisaA16Space, 0x10, &uVal);

  return hr;
}
See Also

Other Resources

In8
In32
In64
VisaAddressSpace Enumeration


In32

Reads an 32-bit value from a register-based device.

                virtual HRESULT In32(VisaAddressSpace eSpace, UINT64 ullOffset, UINT32* puVal) abstract;
Parameters
eSpace

[in] Address space from which to read the value.

ullOffset

[in] Offset within eSpace to read the value.

puVal

Value read from the register-based device.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

Reads an 32-bit value from a register-based device at the specified memory space and offset.

Example

The following example demonstrates use of the In32 function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_ReadRegister()
{
  HRESULT hr = S_OK;

  UINT32 uVal;
  hr = io.Memory.In32(VisaA32Space, 0x10, &uVal);

  return hr;
}
See Also

Other Resources

In8
In16
In64
VisaAddressSpace Enumeration


In64

Reads an 64-bit value from a register-based device.

                virtual HRESULT In64(VisaAddressSpace eSpace, UINT64 ullOffset, UINT64* puVal) abstract;
Parameters
eSpace

[in] Address space from which to read the value.

ullOffset

[in] Offset within eSpace to read the value.

puVal

Value read from the register-based device.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

Reads an 64-bit value from a register-based device at the specified memory space and offset.

Example

The following example demonstrates use of the In64 function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_ReadRegister()
{
  HRESULT hr = S_OK;

  UINT64 uVal;
  hr = io.Memory.In64(VisaA64Space, 0x10, &uVal);

  return hr;
}
See Also

Other Resources

In8
In16
In32
VisaAddressSpace Enumeration


Out8

Writes an 8-bit value to a register-based device.

                virtual HRESULT Out8(VisaAddressSpace eSpace, UINT64 ullOffset, UINT8 uVal) abstract;
Parameters
eSpace

[in] Address space to which the value will be written.

ullOffset

[in] Offset within eSpace to write the value.

uVal

Value to write to the register-based device.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

Writes an 8-bit value to a register-based device at the specified memory space and offset.

Example

The following example demonstrates use of the Out8 function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_WriteRegister(BYTE val)
{
  HRESULT hr = S_OK;

  UINT8 uVal = val;
  hr = io.Memory.Out8(VisaA16Space, 0x10, uVal);

  return hr;
}
See Also

Other Resources

Out16
Out32
Out64
VisaAddressSpace Enumeration


Out16

Writes a 16-bit value to a register-based device.

                virtual HRESULT Out16(VisaAddressSpace eSpace, UINT64 ullOffset, UINT16 uVal) abstract;
Parameters
eSpace

[in] Address space to which the values will be written.

ullOffset

[in] Offset within eSpace to write the value.

uVal

Value to write to the register-based device.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

Writes an 16-bit value to a register-based device at the specified memory space and offset.

Example

The following example demonstrates use of the Out16 function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_WriteRegister(short sVal)
{
  HRESULT hr = S_OK;

  UINT16 uVal = sVal;
  hr = io.Memory.Out16(VisaA16Space, 0x10, sVal);

  return hr;
}
See Also

Other Resources

Out8
Out32
Out64
VisaAddressSpace Enumeration


Out32

Writes an 32-bit value to a register-based device.

                virtual HRESULT Out32(VisaAddressSpace eSpace, UINT64 ullOffset, UINT32 uVal) abstract;
Parameters
eSpace

[in] Address space to which the value will be written.

ullOffset

[in] Offset within eSpace to write the value.

uVal

Value to write to the register-based device.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

Writes an 32-bit value to a register-based device at the specified memory space and offset.

Example

The following example demonstrates use of the Out32 function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_WriteRegister(long lVal)
{
  HRESULT hr = S_OK;

  UINT32 uVal = lVal;
  hr = io.Memory.Out32(VisaA32Space, 0x10, uVal);

  return hr;
}
See Also

Other Resources

Out8
Out16
Out64
VisaAddressSpace Enumeration


Out64

Writes an 64-bit value to a register-based device.

                virtual HRESULT Out64(VisaAddressSpace eSpace, UINT64 ullOffset, UINT64 uVal) abstract;
Parameters
eSpace

[in] Address space to which the value will be written.

ullOffset

[in] Offset within eSpace to write the value.

uVal

Value to write to the register-based device.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

Writes an 64-bit value to a register-based device at the specified memory space and offset.

Example

The following example demonstrates use of the Out64 function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_WriteRegister(UINT64 uVal)
{
  HRESULT hr = S_OK;

  hr = io.Memory.Out64(VisaA64Space, 0x10, uVal);

  return hr;
}
See Also

Other Resources

Out8
Out16
Out32
VisaAddressSpace Enumeration


MoveIn8

Reads a block of 8-bit data values from the specified address space and offset to local memory.

                virtual HRESULT MoveIn8(VisaAddressSpace eSpace, UINT64 ullOffset, UINT32 ulLength, UINT8* pBuf) abstract;

                virtual HRESULT MoveIn8(VisaAddressSpaceeSpace, UINT64 ullOffset, UINT32 ulLength, SAFEARRAY** pBuf) abstract;

                virtual HRESULT MoveIn8(VisaAddressSpaceeSpace, UINT64 ullOffset, UINT32 ulLength, CComSafeArray<UINT8>& pBuf) abstract;
Parameters
eSpace

[in] Address space from which to read the data.

ullOffset

[in] Offset within eSpace to read the data.

pBuf

Data read from the register-based device.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

Reads a block of 8-bit values from a register-based device at the specified memory space and offset.

Example

The following example demonstrates use of the MoveIn8 function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_Read(SAFEARRAY** ppsaData)
{
  HRESULT hr = S_OK;

  hr = io.Memory.MoveIn8(VisaA16Space, 0x10, ppsaData);

  return hr;
}
See Also

Other Resources

MoveIn16
MoveIn32
MoveIn64
VisaAddressSpace Enumeration


MoveIn16

Reads a block of 16-bit data values from the specified address space and offset to local memory.

                virtual HRESULT MoveIn16(VisaAddressSpace eSpace, UINT64 ullOffset, UINT32 ulLength, UINT16* pBuf) abstract;

                virtual HRESULT MoveIn16(VisaAddressSpace eSpace, UINT64 ullOffset, UINT32 ulLength, SAFEARRAY** pBuf) abstract;

                virtual HRESULT MoveIn16(VisaAddressSpace eSpace, UINT64 ullOffset, UINT32 ulLength, CComSafeArray<UINT16>& pBuf) abstract;
Parameters
eSpace

[in] Address space from which to read the data.

ullOffset

[in] Offset within eSpace to read the data.

pBuf

Data read from the register-based device.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

Reads a block of 16-bit values from a register-based device at the specified memory space and offset.

Example

The following example demonstrates use of the MoveIn16 function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_Read(SAFEARRAY** ppsaData)
{
  HRESULT hr = S_OK;

  hr = io.Memory.MoveIn16(VisaA16Space, 0x10, ppsaData);

  return hr;
}
See Also

Other Resources

MoveIn8
MoveIn32
MoveIn64
VisaAddressSpace Enumeration


MoveIn32

Reads a block of 32-bit data values from the specified address space and offset to local memory.

                virtual HRESULT MoveIn32(VisaAddressSpace eSpace, UINT64 ullOffset, UINT32 ulLength, UINT32* pBuf) abstract;

                virtual HRESULT MoveIn32(VisaAddressSpaceeSpace, UINT64 ullOffset, UINT32 ulLength, SAFEARRAY** pBuf) abstract;

                virtual HRESULT MoveIn32(VisaAddressSpaceeSpace, UINT64 ullOffset, UINT32 ulLength, CComSafeArray<UINT32>& pBuf) abstract;
Parameters
eSpace

[in] Address space from which to read the data.

ullOffset

[in] Offset within eSpace to read the data.

pBuf

Data read from the register-based device.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

Reads a block of 32-bit values from a register-based device at the specified memory space and offset.

Example

The following example demonstrates use of the MoveIn32 function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_Read(SAFEARRAY** ppsaData)
{
  HRESULT hr = S_OK;

  hr = io.Memory.MoveIn32(VisaA32Space, 0x10, ppsaData);

  return hr;
}
See Also

Other Resources

MoveIn8
MoveIn16
MoveIn64
VisaAddressSpace Enumeration


MoveIn64

Reads a block of 64-bit data values from the specified address space and offset to local memory.

                virtual HRESULT MoveIn64(VisaAddressSpace eSpace, UINT64 ullOffset, UINT32 ulLength, UINT64* pBuf) abstract;

                virtual HRESULT MoveIn64(VisaAddressSpaceeSpace, UINT64 ullOffset, UINT32 ulLength, SAFEARRAY** pBuf) abstract;

                virtual HRESULT MoveIn64(VisaAddressSpaceeSpace, UINT64 ullOffset, UINT32 ulLength, CComSafeArray<UINT64>& pBuf) abstract;
Parameters
eSpace

[in] Address space from which to read the data.

ullOffset

[in] Offset within eSpace to read the data.

pBuf

Data read from the register-based device.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

Reads a block of 64-bit values from a register-based device at the specified memory space and offset.

Example

The following example demonstrates use of the MoveIn64 function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_Read(SAFEARRAY** ppsaData)
{
  HRESULT hr = S_OK;

  hr = io.Memory.MoveIn64(VisaA64Space, 0x10, ppsaData);

  return hr;
}
See Also

Other Resources

MoveIn8
MoveIn16
MoveIn32
VisaAddressSpace Enumeration


MoveOut8

Writes a block of 8-bit data values from local memory to the specified address space and offset.

                virtual HRESULT MoveOut8(VisaAddressSpace eSpace, UINT64 ullOffset, UINT32 ulLength, UINT8* pBuf) abstract;

                virtual HRESULT MoveOut8(VisaAddressSpaceeSpace, UINT64 ullOffset, UINT32 ulLength, SAFEARRAY* pBuf) abstract;

                virtual HRESULT MoveOut8(VisaAddressSpaceeSpace, UINT64 ullOffset, UINT32 ulLength, CComSafeArray<UINT8>& pBuf) abstract;
Parameters
eSpace

[in] Address space to which the data will be written.

ullOffset

[in] Offset within eSpace to write the data.

pBuf

Data to write to the register-based device.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

Writes a block of 8-bit data values from local memory to a register-based device at the specified address space and offset.

Example

The following example demonstrates use of the MoveOut8 function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_WriteBlock(SAFEARRAY* psaData)
{
  HRESULT hr = S_OK;

  hr = io.Memory.MoveOut8(VisaA16Space, 0x10, psaData);

  return hr;
}
See Also

Other Resources

MoveOut16
MoveOut32
MoveOut64
VisaAddressSpace Enumeration


MoveOut16

Writes a block of 16-bit data values from local memory to the specified address space and offset.

                virtual HRESULT MoveOut16(VisaAddressSpace eSpace, UINT64 ullOffset, UINT32 ulLength, UINT16* pBuf) abstract;

                virtual HRESULT MoveOut16(VisaAddressSpaceeSpace, UINT64 ullOffset, UINT32 ulLength, SAFEARRAY* pBuf) abstract;

                virtual HRESULT MoveOut16(VisaAddressSpaceeSpace, UINT64 ullOffset, UINT32 ulLength, CComSafeArray<UINT16>& pBuf) abstract;
Parameters
eSpace

[in] Address space to which the data will be written.

ullOffset

[in] Offset within eSpace to write the data.

pBuf

Data to write to the register-based device.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

Writes a block of 16-bit data values from local memory to a register-based device at the specified address space and offset.

Example

The following example demonstrates use of the MoveOut16 function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_WriteBlock(SAFEARRAY* psaData)
{
  HRESULT hr = S_OK;

  hr = io.Memory.MoveOut16(VisaA16Space, 0x10, psaData);

  return hr;
}
See Also

Other Resources

MoveOut8
MoveOut32
MoveOut64
VisaAddressSpace Enumeration


MoveOut32

Writes a block of 32-bit data values from local memory to the specified address space and offset.

                virtual HRESULT MoveOut32(VisaAddressSpace eSpace, UINT64 ullOffset, UINT32 ulLength, UINT8* pBuf) abstract;

                virtual HRESULT MoveOut32(VisaAddressSpaceeSpace, UINT64 ullOffset, UINT32 ulLength, SAFEARRAY* pBuf) abstract;

                virtual HRESULT MoveOut32(VisaAddressSpaceeSpace, UINT64 ullOffset, UINT32 ulLength, CComSafeArray<UINT32>& pBuf) abstract;
Parameters
eSpace

[in] Address space to which the data will be written.

ullOffset

[in] Offset within eSpace to write the data.

pBuf

Data to write to the register-based device.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

Writes a block of 32-bit data values from local memory to a register-based device at the specified address space and offset.

Example

The following example demonstrates use of the MoveOut32 function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_WriteBlock(SAFEARRAY* psaData)
{
  HRESULT hr = S_OK;

  hr = io.Memory.MoveOut32(VisaA32Space, 0x10, psaData);

  return hr;
}
See Also

Other Resources

MoveOut8
MoveOut16
MoveOut64
VisaAddressSpace Enumeration


MoveOut64

Writes a block of 64-bit data values from local memory to the specified address space and offset.

                virtual HRESULT MoveOut64(VisaAddressSpace eSpace, UINT64 ullOffset, UINT32 ulLength, UINT64* pBuf) abstract;

                virtual HRESULT MoveOut64(VisaAddressSpaceeSpace, UINT64 ullOffset, UINT32 ulLength, SAFEARRAY* pBuf) abstract;

                virtual HRESULT MoveOut64(VisaAddressSpaceeSpace, UINT64 ullOffset, UINT32 ulLength, CComSafeArray<UINT64>& pBuf) abstract;
Parameters
eSpace

[in] Address space to which the data will be written.

ullOffset

[in] Offset within eSpace to write the data.

pBuf

Data to write to the register-based device.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

Writes a block of 64-bit data values from local memory to a register-based device at the specified address space and offset.

Example

The following example demonstrates use of the MoveOut64 function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_WriteBlock(SAFEARRAY* psaData)
{
  HRESULT hr = S_OK;

  hr = io.Memory.MoveOut64(VisaA16Space, 0x10, psaData);

  return hr;
}
See Also

Other Resources

MoveOut8
MoveOut16
MoveOut32
VisaAddressSpace Enumeration


Move

Moves data from the specified source to the specified destination.

                virtual HRESULT Move(VisaAddressSpace eSrcSpace, UINT64 ullSrcOffset, VisaDataWidth eSrcWidth, VisaAddressSpace eDestSpace, UINT64 ullDestOffset, VisaDataWidth eDestWidth, UINT32 ulLength) abstract;
Parameters
eSrcSpace

[in] Address space from which the data will be moved.

ullSrcOffset

[in] Offset within eSrcSpace from which the data will be moved.

eSrcWidth

[in] Data width of the source data.

eDestSpace

[in] Address space to which the data will be moved.

ullDestOffset

[in] Offset within eDestSpace to which the data will be moved.

eDestWidth

[in] Data width of the destination data.

ulLength

[in] Number of elements (not byte) to transfer.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

The Move function moves data from the specified source to the specified destination. The source and the destination can either be local memory or the offset of an address space within a register-based device. This function uses the specified data width and address space.

Example

The following example demonstrates use of the Move function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_MoveBlock()
{
  HRESULT hr = S_OK;

  // Move 1000 bytes 16-bit words
  hr = io.Memory.Move(VisaA16Space, 0x10, VisaDataWidth16, VisaA16Space, 0x20, VisaDataWidth16, 1000);

  return hr;
}
See Also

Other Resources

MoveAsync
VisaAddressSpace Enumeration
VisaDataWidth Enumeration


MoveAsync

Moves data from the specified source to the specified destinationa asynchronously.

                virtual HRESULT MoveAsync(VisaAddressSpace eSrcSpace, UINT64 ullSrcOffset, VisaDataWidth eSrcWidth, VisaAddressSpace eDestSpace, UINT64 ullDestOffset, VisaDataWidth eDestWidth, UINT32 ulLength, UINT32* plJobId) abstract;
Parameters
eSrcSpace

[in] Address space from which the data will be moved.

ullSrcOffset

[in] Offset within eSrcSpace from which the data will be moved.

eSrcWidth

[in] Data width of the source data.

eDestSpace

[in] Address space to which the data will be moved.

ullDestOffset

[in] Offset within eDestSpace to which the data will be moved.

eDestWidth

[in] Data width of the destination data.

ulLength

[in] Number of elements (not byte) to transfer.

plJobId

[out] Identifier for the asychronous operation.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

The MoveAsync function moves data from the specified source to the specified destination asynchronously. The source and the destination can either be local memory or the offset of an address space within a register-based device. This function uses the specified data width and address space.

This function queues up the transfer in the system and then returns immediately without waiting for the transfer to carry out or complete. When the transfer terminates, an I/O completion event indicates the status of the transfer.

The plJobId is an integer job identifier for the MoveAsync operation. Each time an asynchronous move operation is called, it is assigned a unique job identifier.

Example

The following example demonstrates use of the Move function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_MoveBlock()
{
  HRESULT hr = S_OK;

  // Move 1000 bytes 16-bit words
  long lJobId;
  hr = io.Memory.MoveAsync(VisaA16Space, 0x10, VisaDataWidth16, VisaA16Space, 0x20, VisaDataWidth16, 1000, &lJobId);

  return hr;
}
See Also

Other Resources

Move
VisaAddressSpace Enumeration
VisaDataWidth Enumeration


VisaDataWidth Enumeration

Specifies the data width for VISA register-based operations.

enum VisaDataWidth
Members
Member name | Description
VisaDataWidth8 | Performs 8-bit (D08) transfers.
VisaDataWidth16 | Performs 16-bit (D16) transfers.
VisaDataWidth32 | Performs 32-bit (D32) transfers.
VisaDataWidth64 | Performs 64-bit (D64) transfers.


SetSourceBigEndian

Specifies the byte order to be used in high-level access operations, such as InXX and MoveInXX, when reading from the source.

virtual HRESULT SetSourceBigEndian(bool bBigEndian) abstract;
Parameters
bBigEndian

[in] true indicates big endian byte ordering. false indicates little endian byte ordering.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Example

The following example demonstrates use of the SetSourceBigEndian function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_Read(SAFEARRAY** ppsaData)
{
  // Source uses big endian byte ordering
  hr = io.SetSourceBigEndian(true);

  hr = io.Memory.MoveIn16(VisaA16Space, 0x10, ppsaData);

  return hr;
}
See Also

Other Resources

GetSourceBigEndian


GetSourceBigEndian

Gets the byte order currently in use in high-level access operations, such as InXX and MoveInXX, when reading from the source.

virtual HRESULT GetSourceBigEndian(bool* pbBigEndian) abstract;
Parameters
pbBigEndian

[out] true indicates big endian byte ordering. false indicates little endian byte ordering.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Example

The following example demonstrates use of the GetSourceBigEndian function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_Read()
{
  // Source uses big endian byte ordering
  bool bBigEndian.
  hr = io.Memory.GetSourceBigEndian(&bBigEndian);

  return hr;
}
See Also

Other Resources

SetSourceBigEndian


SetDestinationBigEndian

Specifies the byte order to be used in high-level access operations, such as InXX and MoveInXX, when writing to the destination.

virtual HRESULT SetDestinationBigEndian(bool bBigEndian) abstract;
Parameters
bBigEndian

[in] true indicates big endian byte ordering. false indicates little endian byte ordering.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Example

The following example demonstrates use of the SetDestinationBigEndian function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_Write(SAFEARRAY* psaData)
{
  // Destination uses big endian byte ordering
  hr = io.SetDestinationBigEndian(true);

  hr = io.Memory.MoveOut16(VisaA16Space, 0x10, psaData);

  return hr;
}
See Also

Other Resources

GetDestinationBigEndian


GetDestinationBigEndian

Gets the byte order currently in use for high-level access operations, such as InXX and MoveInXX, when writing to the destination.

virtual HRESULT GetDestinationBigEndian(bool* pbBigEndian) abstract;
Parameters
pbBigEndian

[in] true indicates big endian byte ordering. false indicates little endian byte ordering.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Example

The following example demonstrates use of the GetDestinationBigEndian function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_Read()
{
  bool bBigEndian;
  hr = io.Memory.GetDestinationBigEndian(&bBigEndian);

  return hr;
}
See Also

Other Resources

SetDestinationBigEndian


SetSourceIncrement

Specifies by how many elements the source offset is to be incremented after every InXX or MoveXX transfer.

virtual HRESULT SetSourceIncrement(long lIncrement) abstract;
Parameters
lIncrement

[in] Number of elements by which the source offset is incremented.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

The default value increment is 1 -- that is, the source address will be incremented by 1 after each transfer, and the MoveInXX operations move from consecutive elements. If this attribute is set to 0, the MoveInXX operations will always read from the same element, essentially treating the source as a FIFO register.

Example

The following example demonstrates use of the SetSourceIncrement function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_Read(SAFEARRAY** ppsaData)
{
  // Increment by two elements after MoveIn16
  hr = io.SetSourceIncrement(2);

  hr = io.Memory.MoveIn16(VisaA16Space, 0x10, ppsaData);

  return hr;
}
See Also

Other Resources

GetSourceIncrement


GetSourceIncrement

Gets the current setting for how many elements by which the source offset is incremented after every InXX or MoveXX transfer.

virtual HRESULT GetSourceIncrement(long* plIncrement) abstract;
Parameters
plIncrement

[in] Number of elements by which the source offset is incremented.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

The default value increment is 1 -- that is, the source address will be incremented by 1 after each transfer, and the MoveInXX operations move from consecutive elements. If this attribute is set to 0, the MoveInXX operations will always read from the same element, essentially treating the source as a FIFO register.

Example

The following example demonstrates use of the GetSourceIncrement function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_Read(SAFEARRAY** ppsaData)
{
  long lIncrement;
  hr = io.GetSourceIncrement(&lIncrement);

  hr = io.Memory.MoveIn16(VisaA16Space, 0x10, ppsaData);

  return hr;
}
See Also

Other Resources

SetSourceIncrement


SetDestinationIncrement

Specifies by how many elements the source offset is to be incremented after every OutXX or MoveOutXX transfer.

virtual HRESULT SetDestinationIncrement(long lIncrement) abstract;
Parameters
lIncrement

[in] Number of elements by which the destination offset is incremented.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

The default value increment is 1 -- that is, the destination address will be incremented by 1 after each transfer, and the MoveOutXX operations move into consecutive elements. If this attribute is set to 0, the MoveOutXX operations will always write to the same element, essentially treating the destination as a FIFO register.

Example

The following example demonstrates use of the SetDestinationIncrement function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_Write(SAFEARRAY* psaData)
{
  // Increment by two elements after MoveOut16
  hr = io.SetDestinationIncrement(2);

  hr = io.Memory.MoveOut16(VisaA16Space, 0x10, ppsaData);

  return hr;
}
See Also

Other Resources

GetDestinationIncrement


GetDestinationIncrement

Gets the current setting for how many elements by which the destination offset is incremented after every OutXX or MoveOutXX transfer.

virtual HRESULT GetDestinationIncrement(long* plIncrement) abstract;
Parameters
plIncrement

[in] Number of elements by which the destination offset is incremented.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

The default value increment is 1 -- that is, the destination address will be incremented by 1 after each transfer, and the MoveOutXX operations move into consecutive elements. If this attribute is set to 0, the MoveOutXX operations will always write to the same element, essentially treating the destination as a FIFO register.

Example

The following example demonstrates use of the GetSourceIncrement function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_Write(SAFEARRAY* psaData)
{
  long lIncrement;
  hr = io.GetDestinationIncrement(&lIncrement);

  hr = io.Memory.MoveOut16(VisaA16Space, 0x10, psaData);

  return hr;
}
See Also

Other Resources

SetDestinationIncrement


AllocateMemory

Allocate memory from a device’s memory region.

virtual HRESULT AllocateMemory(UINT64 ullSize, UINT64* pullOffset) abstract;
Parameters
ullSize

[in] Size of the allocation.

pullOffset

[out] Offset into device memory region where memory has been allocated.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

The AllocateMemory function returns an offset into a device’s memory region that has been allocated for use by this session. If the device is located on the local interface card, the memory can be allocated either on the device itself or on the computer’s system memory.

Example

The following example demonstrates use of the AllocateMemory function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_Configure()
{
  UINT64 ullOffset;
  hr = io.Memory.AllocateMemory(100, &ullOffset);

  // ...

  hr = io.Memory.FreeMemory(ulOffset);

  return hr;
}


FreeMemory

Free memory previously allocated using AllocateMemory.

virtual HRESULT FreeMemory(UINT64 ullOffset) abstract;
Parameters
ullOffset

[in] Offset into device memory region where memory was previouly allocated using AllocateMemory.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Example

The following example demonstrates use of the FreeMemory function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_Configure()
{
  UINT64 ullOffset;
  hr = io.Memory.AllocateMemory(100, &ullOffset);

  // ...

  hr = io.Memory.FreeMemory(ulOffset);

  return hr;
}


Low-Level I/O Functions

The functions in this section provide low-level access to the underlying VISA I/O session.

Note Note

The functions in this section are only available for the VISA-COM or VISA-C I/O providers. They are not available for custom I/O providers.

In This Section

ReadAsync

WriteAsync

AssertTrigger

VisaTriggerProtocol Enumeration

SendEndEnabled


ReadAsync

Reads data from a device asynchronously.

virtual HRESULT ReadAsync(BYTE* pBuf, long cbDesired, ULONG* plJobId) abstract;
Parameters
pBuf

[in] Data read from the device.

cbDesired

[in] Number of bytes to read from the device.

plJobId

[in] Asynchronous job identifier for the operation.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

The ReadAsync function asynchronously sends data to the device. Unlike the buffered I/O functions, such as Queryf, Read ReadNumber, etc., the ReadAsync function reads raw bytes directly from the device, rather than going through formatted I/O read buffer.

The ReadAsync function returns immediately. An I/O Completion event will be posted when the transfer is actually completed. The plJobId can be used with an I/O Completion event to identify which asynchronous write operation completed.

Example

The following example demonstrates use of the ReadAsync function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_Read(SAFEARRAY** ppsaData)
{
  HRESULT hr = S_OK;

  long lJobId;
  hr = io.LowLevel.ReadAsync(ppsaData, 1000, &lJobId);

  return hr;
}
See Also

Other Resources

WriteAsync


WriteAsync

Sends data to a device asynchronously.

virtual HRESULT WriteAsync(BYTE* pBuf, long cbDesired, ULONG* plJobId) abstract;

virtual HRESULT WriteAsync(SAFEARRAY** pBuf, long cbDesired, ULONG* plJobId) abstract;
Parameters
pBuf

[in] Data to send to the device.

cbDesired

[in] Number of bytes to send to the device.

plJobId

[in] Asynchronous job identifier for the operation.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

The WriteAsync function asynchronously writes data to the device. Unlike the buffered I/O functions, such as Printf, Write and WriteNumber, etc., the WriteAsync function sends raw bytes directly to the device, rather than going through formatted I/O write buffer.

The WriteAsync function returns immediately. An I/O Completion event will be posted when the transfer is actually completed. The plJobId can be used with an I/O Completion event to identify which asynchronous write operation completed.

Example

The following example demonstrates use of the WriteAsync function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_Write(SAFEARRAY** ppsaData)
{
  HRESULT hr = S_OK;

  // Start asynchronous write operation
  long lJobId;
  hr = io.LowLevel.WriteAsync(ppsaData, 1000, &lJobId);

  return hr;
}
See Also

Other Resources

ReadAsync


AssertTrigger

Asserts a software or hardware trigger.

                virtual HRESULT AssertTrigger(VisaTriggerProtocol eProtocol) abstract;
Parameters
eProtocol

[in] Trigger protocol to use during the assertion.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

The AssertTrigger function will source a software or hardware trigger dependent on the interface type.

  • For a GPIB device, the device is addressed to listen, and then the GPIB GET command is sent.

  • For a VXI device, if the attribute VI_ATTR_TRIG_ID is set to VI_TRIG_SW, then the device is sent the Word Serial Trigger command; for any other values of the attribute, a hardware trigger is sent on the line corresponding to the value of that attribute.

  • For a serial device or TCP/IP socket, if VI_ATTR_IO_PROT is VI_PROT_4882_STRS (see the SetProtocol function, the device is sent the string "*TRG\n"; otherwise, this operation is not valid.

  • For a USB device, this function sends the TRIGGER message ID on the Bulk-OUT pipe.

For GPIB, ASRL, USB, and VXI software triggers, VisaTriggerProtocolDefault is the only valid protocol. For VXI hardware triggers, VisaTriggerProtocolDefault is equivalent to VisaTriggerProtocolSync.

For a PXI resource, AssertTrigger will reserve a trigger line for assertion, or release such a reservation. Drivers should use AssertTrigger to ensure that they have ownership of a trigger line before performing any operation that could drive a signal onto that trigger line. The protocol parameter can be either VisaTriggerProtocolOn or VisaTriggerProtocolOff, which reserve a trigger line and release the reservation, respectively.

Example

The following example demonstrates use of the AssertTrigger function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_Configure()
{
  HRESULT hr = S_OK;

  hr = io.LowLevel.AssertTrigger(VisaTriggerProtocolSync);

  return hr;
}
See Also

Other Resources

VisaTriggerProtocol Enumeration


VisaTriggerProtocol Enumeration

Specifies the VISA trigger protocol.

enum VisaTriggerProtocol
Members
Member name | Description
VisaTriggerProtocolDefault | Default trigger protocol.
VisaTriggerProtocolOn | Reserve PXI trigger line.
VisaTriggerProtocolOff | Unreserve PXI trigger line.
VisaTriggerProtocolSync | Sync trigger protocol.
See Also

Other Resources

AssertTrigger


SendEndEnabled

Specifies whether to assert END during the transfer of the last byte of the buffer.

virtual HRESULT SendEndEnabled(bool bEnabled) abstract;
Parameters
bEnabled

[in] true enables sending END with the last byte; false disables it.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

On serial device sessions, if bEnabled is false, write operations will transmit the exact contents of the user buffer, without appending anything to the data being written. If bEnabled is true, VISA will perform the behavior described by the VISA attribute VI_ATTR_ASRL_END_OUT.

On GPIB, VXI, GPIB-VXI, TCP/IP INSTR, and USB device sessions, enabling the END indicator instructs VISA to include the 488.2 defined "end of message" terminator with the last byte of the write operation.

Example

The following example demonstrates use of the SendEndEnabled function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::IAcme4321_OnFinalInitialize()
{
  HRESULT hr = S_OK;

  hr = io.SendEndEnabled(true);

  return hr;
}


VISA-COM Specific Functions

Most Nimbus I/O functions are independent of the underlying I/O provider. The functions in this section are only available when using the VISA-COM I/O provider. None of these functions are available for the VISA-C provider or for custom I/O providers.

In This Section

GetIVisaSessionPointer

GetIFormattedIO488Pointer

GetIMessagePointer

GetIAsyncMessagePointer

GetIRegisterPointer

GetISharedRegisterPointer

GetIEventManagerPointer


GetIVisaSessionPointer

Retrieves an IVisaSession pointer from the VISA-COM I/O session.

virtual HRESULT GetIVisaSessionPointer(IVisaSession** ppVisaSession) override;
Parameters
ppVisaSession

[out] IVisaSession pointer.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

This function returns an IVisaSession pointer to the current VISA-COM I/O session. This can be useful for accessing VISA-COM functionality not directly exposed in the Nimbus Template Library. Also, the IVisaSession pointer can be passed out of the driver to the client application so that end users can directly manipulate aspects of the I/O session.

Caution note Caution

The pointer returned by this function is a referenced-counted COM interface pointer. Calling this function increments that reference count, so it is critical that the caller receiving the pointer properly call Release on the interface pointer. If the pointer is passed out of the driver to a client application, then it is the responsibility of the client application to properly release the pointer. Failure to properly manage this interface pointer will cause the entire VISA-COM I/O session to leak memory.

Example

The following example demonstrates use of the GetIVisaSessionPointer function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::OnFinalInitialize()
{
  HRESULT hr = S_OK;

  CComPtr<IVisaSession> spSession;
  hr = io.DirectIo.GetIVisaSessionPointer(&spSession);

  // Note that the CComPtr smart pointer class automatically calls release when the function exits

  return hr;
}


GetIFormattedIO488Pointer

Retrieves an IFormattedIO488 pointer from the VISA-COM I/O session.

virtual HRESULT GetIFormattedIO488Pointer(IFormattedIO488** ppFormatted) override;
Parameters
ppFormatted

[out] IFormattedIO488 pointer.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

This function returns an IFormattedIO488 pointer to the current VISA-COM I/O session. This can be useful for accessing VISA-COM functionality not directly exposed in the Nimbus Template Library. Also, the IFormattedIO488 pointer can be passed out of the driver to the client application so that end users can directly manipulate aspects of the I/O session.

Caution note Caution

The pointer returned by this function is a referenced-counted COM interface pointer. Calling this function increments that reference count, so it is critical that the caller receiving the pointer properly call Release on the interface pointer. If the pointer is passed out of the driver to a client application, then it is the responsibility of the client application to properly release the pointer. Failure to properly manage this interface pointer will cause the entire VISA-COM I/O session to leak memory.

Example

The following example demonstrates use of the GetIFormattedIO488Pointer function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::OnFinalInitialize()
{
  HRESULT hr = S_OK;

  CComPtr<IFormattedIO488> spFormatted;
  hr = io.DirectIo.GetIFormattedIO488Pointer(&spFormatted);

  // Note that the CComPtr smart pointer class automatically calls release when the function exits

  return hr;
}


GetIMessagePointer

Retrieves an IMessage pointer from the VISA-COM I/O session.

virtual HRESULT GetIMessagePointer(IMessage** ppMessage) override;
Parameters
ppMessage

[out] IMessage pointer.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

This function returns an IMessage pointer to the current VISA-COM I/O session. This can be useful for accessing VISA-COM functionality not directly exposed in the Nimbus Template Library. Also, the IMessage pointer can be passed out of the driver to the client application so that end users can directly manipulate aspects of the I/O session.

Caution note Caution

The pointer returned by this function is a referenced-counted COM interface pointer. Calling this function increments that reference count, so it is critical that the caller receiving the pointer properly call Release on the interface pointer. If the pointer is passed out of the driver to a client application, then it is the responsibility of the client application to properly release the pointer. Failure to properly manage this interface pointer will cause the entire VISA-COM I/O session to leak memory.

Example

The following example demonstrates use of the GetIMessagePointer function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::OnFinalInitialize()
{
  HRESULT hr = S_OK;

  CComPtr<IMessage> spMessage;
  hr = io.DirectIo.GetIMessagePointer(&spMessage);

  // Note that the CComPtr smart pointer class automatically calls release when the function exits

  return hr;
}


GetIAsyncMessagePointer

Retrieves an IAsyncMessage pointer from the VISA-COM I/O session.

virtual HRESULT GetIAsyncMessagePointer(IAsyncMessage** ppAsyncMessage) override;
Parameters
ppAsyncMessage

[out] IAsyncMessage pointer.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

This function returns an IAsyncMessage pointer to the current VISA-COM I/O session. This can be useful for accessing VISA-COM functionality not directly exposed in the Nimbus Template Library. Also, the IAsyncMessage pointer can be passed out of the driver to the client application so that end users can directly manipulate aspects of the I/O session.

Caution note Caution

The pointer returned by this function is a referenced-counted COM interface pointer. Calling this function increments that reference count, so it is critical that the caller receiving the pointer properly call Release on the interface pointer. If the pointer is passed out of the driver to a client application, then it is the responsibility of the client application to properly release the pointer. Failure to properly manage this interface pointer will cause the entire VISA-COM I/O session to leak memory.

Example

The following example demonstrates use of the GetIAsyncMessagePointer function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::OnFinalInitialize()
{
  HRESULT hr = S_OK;

  CComPtr<IAsyncMessage> spAsyncMessage;
  hr = io.DirectIo.GetIAsyncMessagePointer(&spAsyncMessage);

  // Note that the CComPtr smart pointer class automatically calls release when the function exits

  return hr;
}


GetIRegisterPointer

Retrieves an IRegister pointer from the VISA-COM I/O session.

virtual HRESULT GetIRegisterPointer(IRegister** ppRegister) override;
Parameters
ppRegister

[out] IRegister pointer.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

This function returns an IRegister pointer to the current VISA-COM I/O session. This can be useful for accessing VISA-COM functionality not directly exposed in the Nimbus Template Library. Also, the IRegister pointer can be passed out of the driver to the client application so that end users can directly manipulate aspects of the I/O session.

Caution note Caution

The pointer returned by this function is a referenced-counted COM interface pointer. Calling this function increments that reference count, so it is critical that the caller receiving the pointer properly call Release on the interface pointer. If the pointer is passed out of the driver to a client application, then it is the responsibility of the client application to properly release the pointer. Failure to properly manage this interface pointer will cause the entire VISA-COM I/O session to leak memory.

Example

The following example demonstrates use of the GetIRegisterPointer function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::OnFinalInitialize()
{
  HRESULT hr = S_OK;

  CComPtr<IRegister> spRegister;
  hr = io.DirectIo.GetIRegisterPointer(&spRegister);

  // Note that the CComPtr smart pointer class automatically calls release when the function exits

  return hr;
}


GetISharedRegisterPointer

Retrieves an ISharedRegister pointer from the VISA-COM I/O session.

virtual HRESULT GetISharedRegisterPointer(ISharedRegister** ppSharedRegister) override;
Parameters
ppSharedRegister

[out] ISharedRegister pointer.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

This function returns an ISharedRegister pointer to the current VISA-COM I/O session. This can be useful for accessing VISA-COM functionality not directly exposed in the Nimbus Template Library. Also, the ISharedRegister pointer can be passed out of the driver to the client application so that end users can directly manipulate aspects of the I/O session.

Caution note Caution

The pointer returned by this function is a referenced-counted COM interface pointer. Calling this function increments that reference count, so it is critical that the caller receiving the pointer properly call Release on the interface pointer. If the pointer is passed out of the driver to a client application, then it is the responsibility of the client application to properly release the pointer. Failure to properly manage this interface pointer will cause the entire VISA-COM I/O session to leak memory.

Example

The following example demonstrates use of the GetISharedRegisterPointer function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::OnFinalInitialize()
{
  HRESULT hr = S_OK;

  CComPtr<ISharedRegister> spSharedRegister;
  hr = io.DirectIo.GetISharedRegisterPointer(&spSharedRegister);

  // Note that the CComPtr smart pointer class automatically calls release when the function exits

  return hr;
}


GetIEventManagerPointer

Retrieves an IEventManager pointer from the VISA-COM I/O session.

virtual HRESULT GetIEventManagerPointer(IEventManager** ppEventManager) override;
Parameters
ppEventManager

[out] IEventManager pointer.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

This function returns an IEventManager pointer to the current VISA-COM I/O session. This can be useful for accessing VISA-COM functionality not directly exposed in the Nimbus Template Library. Also, the IEventManager pointer can be passed out of the driver to the client application so that end users can directly manipulate aspects of the I/O session.

Caution note Caution

The pointer returned by this function is a referenced-counted COM interface pointer. Calling this function increments that reference count, so it is critical that the caller receiving the pointer properly call Release on the interface pointer. If the pointer is passed out of the driver to a client application, then it is the responsibility of the client application to properly release the pointer. Failure to properly manage this interface pointer will cause the entire VISA-COM I/O session to leak memory.

Example

The following example demonstrates use of the GetIEventManagerPointer function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::OnFinalInitialize()
{
  HRESULT hr = S_OK;

  CComPtr<IEventManager> spEventManager;
  hr = io.DirectIo.GetIEventManagerPointer(&spEventManager);

  // Note that the CComPtr smart pointer class automatically calls release when the function exits

  return hr;
}


VISA-C Specific Functions

Most Nimbus I/O functions are independent of the underlying I/O provider. The functions in this section are only available when using the VISA-C I/O provider. None of these functions are available for the VISA-COM provider or for custom I/O providers.

In This Section

GetSession


GetSession

Retrieves a handle to the VISA-C I/O session.

virtual HRESULT GetSession(ViSession* pSession) abstract;
Parameters
pSession

[out] VISA-C I/O session handle.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

This function returns a session handle for the current VISA-C I/O session. This can be useful for accessing VISA-C functionality not directly exposed in the Nimbus Template Library. Also, the session can be passed out of the driver to the client application so that end users can directly manipulate aspects of the I/O session.

Example

The following example demonstrates use of the GetSession function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::OnFinalInitialize()
{
  HRESULT hr = S_OK;

  ViSession vi;
  hr = io.DirectIo.GetSession(&vi);

  return hr;
}


Instrument Command Functions

Nimbus provides a number of automatic command formatting features. For instance, the Instrument Command Editor is used to specify a command or response to associate with a method. The functions in this section are used to access the command or response that have been associated with a driver method, property, or enum.

In This Section

EnumFromResponse

EnumToCommand

GetInstrCommand

GetInstrResponse

InstrPrintCommand

InstrPrintCommandNoPoll

InstrQueryResponse


EnumFromResponse

Converts an instrument response string to its corresponding enum value.

template <typename T>
bool EnumFromResponse(const CString& strResponse, T& enumVal) const;
Parameters
strResponse

[in] Response string to convert to an enum value.

enumVal

[out] Enum value converted from the specified response string.

Return Value

Returns true if the conversion was successful, otherwise false.

Remarks

The Instrument Command Editor allows the developer to associate enum values with command strings that can be sent to an instruments. This function converts an instrument response string to its associated enum value.

For example, a developer may have associated the enum value Acme4321TriggerSourceExternal with the response string "EXT". The EnumFromResponse function can be used to convert a string response "EXT" into the enum value Acme4321TriggerSourceExternal.

It should be noted that directly calling EnumFromResponse within a method or property implementation is rarely necessary. This is because the Scanf function supports scanning strings as enums directly. (Indeed, the implementation of Scanf calls EnumFromResponse.)

Example

The following example demonstrates use of the EnumFromResponse function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::get_TriggerSource(Acme4321TriggerSourceEnum* peSource)
{
  HRESULT hr = S_OK;

  CString strResponse;
  hr = io.QueryString(_T("TRIG:SOUR?"), strResponse);

  Acme4321TriggerSourceEnum eSource;
  if (EnumFromResponse<Acme4321TriggerSourceEnum>(strResponse, eSource)
  {
    *peSource = eSource;
  }

  return hr;
}
See Also

Other Resources

Using the Instrument Command Editor


EnumToCommand

Converts an enum value into its corresponding instrument command.

template <typename T>
bool EnumToCommand(T enumVal, CString& strCommand) const;
Parameters
enumVal

[in] Enum value to be converted.

strCommand

[out] Command string associated with the specified enum value.

Return Value

Returns true if the conversion was successful, otherwise false.

Remarks

The Instrument Command Editor allows the developer to associate enum values with command strings that can be sent to an instruments. This function converts an enum value to its associated command string.

For example, a developer may have associated the enum value Acme4321TriggerSourceExternal with the command string "EXT". The EnumToCommand function can be used to help format a complete command string for setting, say, the trigger source.

It should be noted that directly calling EnumToCommand within a method or property implementation is rarely necessary. This is because the Printf function supports formatting enums as strings directly. (Indeed, the implementation of Printf calls EnumToCommand.)

Example

The following example demonstrates use of the EnumToCommand function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::ConfigureTriggerSource()
{
  HRESULT hr = S_OK;

  // Write, but don't flush since we need to add on the enum string
  hr = io.WriteString(_T("TRIG:SOUR "), false);

  Acme4321TriggerSourceEnum eSource = Acme4321TriggerSourceExternal;
  CString strSource;
  if (EnumToCommand<Acme4321TriggerSourceEnum>(eSource, strSource))
  {
    // Sends "EXT", assuming that we configured in the Enum Command Editor
    hr = io.WriteString(strSource);
  }

  return hr;
}
See Also

Other Resources

Using the Instrument Command Editor


GetInstrCommand

Retrieves the command for the current method from the command buffer.

const CString& GetInstrCommand() const;
Return Value

Returns the command for the current method with all parameter replacement tags replaced by the corresponding formatted parameter value.

Remarks

The GetInstrCommand function can be used to retrieve from the command buffer the processed command for the currently executing method. Developers may wish to use the GetInstrCommand function to perform custom processing of the command after Nimbus has performed all of the specified parameter replacement tag operations.

Multiple calls to GetInstrCommand from within a single method execution always return the same command string. That is to say, the command buffer remains unaffected by custom processing that is performed on the string returned from this function.

Example

The following example demonstrates use of the GetInstrCommand function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::Configure()
{
  HRESULT hr = S_OK;

  CString strCommand = GetInstrCommand();

  return hr;
}
See Also

Other Resources

GetInstrResponse
InstrPrintCommand


GetInstrResponse

Retrieves the response for the current method from the response buffer.

const CString& GetInstrResponse() const;
Return Value

Returns the response string for the current method with all parameter replacement tags replaced by the corresponding formatted parameter value.

Remarks

The GetInstrResponse function can be used to retrieve from the response buffer the processed response for the currently executing method. Developers may wish to use the GetInstrResponse function to perform custom processing of the response after Nimbus has performed all of the specified parameter replacement tag operations.

Multiple calls to GetInstrResponse from within a single method execution always return the same command string. That is to say, the response buffer remains unaffected by custom processing that is performed on the string returned from this function.

Example

The following example demonstrates use of the GetInstrResponse function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::Configure()
{
  HRESULT hr = S_OK;

  CString strResponse = GetInstrResponse();

  return hr;
}
See Also

Other Resources

GetInstrCommand
InstrQueryResponse


InstrPrintCommand

Sends the command for the current method to the device.

virtual HRESULT InstrPrintCommand();

virtual HRESULT InstrPrintCommand(SAFEARRAY* psaArg [, argument] ...);
Parameters
psaArg

[in] SAFEARRAY argument interpreted by the format string.

argument

[in] Optional arguments interpreted by the format string.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Example

The following example demonstrates use of the InstrPrintCommand function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::Configure(double Frequency, double Gain)
{
  HRESULT hr = S_OK;

  hr = InstrPrintCommand();

  return hr;
}
See Also

Other Resources

InstrPrintCommandNoPoll


InstrPrintCommandNoPoll

Sends the command for the current method to the device without polling for instrument errors after the write.

virtual HRESULT InstrPrintCommandNoPoll();

virtual HRESULT InstrPrintCommandNoPoll(SAFEARRAY* psaArg [, argument] ...);
Parameters
psaArg

[in] SAFEARRAY argument interpreted by the format string.

argument

[in] Optional arguments interpreted by the format string.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

This function behaves identically to the InstrPrintCommand function except that the device is not polled for errors after the command is written.

Example

The following example demonstrates use of the InstrPrintCommandNoPoll function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::Configure(double Frequency, double Gain)
{
  HRESULT hr = S_OK;

  hr = InstrPrintCommandNoPoll();

  return hr;
}
See Also

Other Resources

InstrPrintCommand


InstrQueryResponse

Sends the query command for the current method to the device and reads the response.

virtual HRESULT InstrQueryResponse(long lTimeout, [, argument] ...);
Parameters
lTimeout

[in] I/O timeout value in milliseconds.

argument

[in] Optional arguments interpreted by the write and read format strings.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Example

The following example demonstrates use of the InstrQueryResponse function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::Read(SAFEARRAY** ppsaData, double* pRange, double* pResolution)
{
  HRESULT hr = S_OK;

  hr = InstrQueryResponse(ppsaData, pRange, pResolution);

  return hr;
}
See Also

Other Resources

GetInstrResponse


The Error Reporter Object

The error reporter object exposes functions for returning errors from IVI drivers. A single class named C<ProjectName>ErrorReporter is automatically generated and maintained in the driver project file ErrorReporter.nimbus.h. A single instance of this class is instantiated and can be accessed within the driver via the err property.

Error Reporter Overview

The error reporter object contains one or more functions for each error that the driver may wish to return. The errors that can be returned include:

  • Standard IVI-defined errors that are part of every driver's inherent capabilities.

  • Instrument class-defined errors for each instrument class implemented by the driver.

  • Instrument-specific errors defined by the driver. See the topic Adding an Error.

When a function on the error reporter object is invoked, it does the following:

  • Sets the return value to the appropriate IVI-defined or instrument-defind HRESULT value.

  • Replaces any variable fields in the error message with the parameter values supplied to the error function.

  • Populates the COM error object with the appropriate information, such as the failure HRESULT, the error message, and the name of the driver.

Using the Error Reporter Object

One of the prime motivations for consolidating the error reporting functions into a single object was to better take advantage of IntelliSense when developers are writing error handling code. By simply typing "err.", the developer will immediately be presented with all errors available on the driver. As new errors are added to (or removed from) the project, Nimbus updates the error reporter class definition in ErrorReporter.nimbus.h, so that the developer is always working with only the set of errors relevant to their driver.

For example, consider the IVI-defined error "Invalid Value". The IVI-3.2: Inherent Capabilities Specification. defines this error as follows:

Name | HRESULT | Message String
Invalid Value | E_IVI_INVALID_VALUE (0x80047010) | "%s: Invalid value (%s1) for method %s2, parameter %s3." %s1 = out-of-range value %s2 = method name %s3 = parameter name

The message string defined above contains 4 replacement tags -- %s, %s1, %s2, and %s3. Each of these must be populated with the correct values for the specific error occurrence. The first tag (%s) is simply the driver name, so Nimbus fills this in automatically for all error functions. The remaining three tags must be supplied as parameters to the InvalidValue error function on the error reporter object. Correspondingly, the error reporter object contains an InvalidValue function that takes three parameters, as shown below:

C++
Copy
// "Invalid value (<strVal>) for method <pszMethod>, parameter <pszParam>."
virtual HRESULT InvalidValue(LPCTSTR pszMethod, LPCTSTR pszParam, BSTR bstrVal, const CString& strDetails = _T("")) const override

The InvalidValue function formats the error message by substituting the values passed for pszMethod, pszParam, and bstrVal for the replacement tags %s1, %s2, and %s3, respectively. The code below demonstrates how the InvalidValue function is used.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::Configure(BSTR Source)
{
  HRESULT hr = S_OK;

  CComBSTR bstrSource = Source;

  if (bstrSource == "Internal")
    return err.InvalidValue(_T("Configure"), _T("Source"), Source);

   // Resulting message sent to the client application is:
   //   "Acme4321: Invalid value (Internal), for method Configure, parameter Source"

  // ...

  return hr;
}

The InvalidValue function actually includes several overloads for various data types -- double, long, bool, and CString. In addition, InvalidValue includes overloads that do not require the pszMethod parameter. The method name can be determined automatically by the context of the call to InvalidValue. So, the example above could be slightly simplified, as in the example below.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::Configure(BSTR Source)
{
  HRESULT hr = S_OK;

  CComBSTR bstrSource = Source;

  if (bstrSource == "Internal")
    return err.InvalidValue(_T("Source"), Source);     // Method name automatically inferred from context

   // Resulting message sent to the client application is:
   //   "Acme4321: Invalid value (Internal), for method Configure, parameter Source"

  // ...

  return hr;
}
Error Reporter Functions for Inherent Capabilities

The error reporter object for every driver will include those errors defined in the IVI inherent capabilities specification. These error functions and their corresponding IVI error codes and messages are given in the table below.

Error Reporter Function | IVI HRESULT | Error Message
AlreadyInitialized | E_IVI_ALREADY_INITIALIZED | "The driver is already initialized."
BadOptionName | E_IVI_BAD_OPTION_NAME | "The %s name in the option string is unknown."
BadOptionValue | E_IVI_BAD_OPTION_VALUE | "The %s value in the option string is unknown."
BadlyFormedSelector | E_IVI_BADLY_FORMED_SELECTOR | "The repeated capability selector is badly-formed."
CannotChangeSimulateState | E_IVI_CANNOT_CHANGE_SIMULATION_STATE | "The simulation state cannot be changed."
CannotOpenFile | E_IVI_CANNOT_OPEN_FILE | "Cannot open file."
CannotRecover | E_IVI_CANNOT_RECOVER | "Failure cannot recover."
ChannelNameRequired | E_IVI_CHANNEL_NAME_REQUIRED | "A channel name is required."
FileNotFound | E_IVI_FILE_NOT_FOUND | "File not found."
InstrumentIdQueryFailed | E_IVI_ID_QUERY_FAILED | "Instrument ID query failed."
InstrumentStatus | E_IVI_INSTRUMENT_STATUS | "Instrument error detected. Use the ErrorQuery function to retrieve detailed error information."
InvalidFileFormat | E_IVI_INVALID_FILE_FORMAT | "Invalid file format."
InvalidNumberOfLevelsInSelector | E_IVI_INVALID_NUMBER_OF_LEVELS_IN_SELECTOR | "The number of levels in the selector is not valid for the %s repeated capability."
InvalidPathName | E_IVI_INVALID_PATHNAME | "The pathname is invalid."
InvalidRangeInSelector | E_IVI_INVALID_RANGE_IN_SELECTOR | "The range %s1 is not valid for the repeated capability %s2."
InvalidValue | E_IVI_INVALID_VALUE | "Invalid value (%s1) for method %s2, parameter %s3."
MethodNotSupported | E_IVI_METHOD_NOT_SUPPORTED | "Does not support this class-compliant feature: method %s."
MissingOptionName | E_IVI_MISSING_OPTION_NAME | "The option string is missing an option name."
MissingOptionValue | E_IVI_MISSING_OPTION_VALUE | "The option string is missing an option value."
PropertyNotSupported | E_IVI_PROPERTY_NOT_SUPPORTED | "Does not support this class-compliant feature: property %s."
NotInitialized | E_IVI_NOT_INITIALIZED | "A connection to the instrument has not been established."
NullPointer | E_IVI_NULL_POINTER | "Null pointer passed for method %s1, parameter %s2."
OperationPending | E_IVI_OPERATION_PENDING | "Operation in progress."
OutOfMemory | E_IVI_OUT_OF_MEMORY | "Could not allocate necessary memory."
ReadingFile | E_IVI_READING_FILE | "Error reading file."
InstrumentResetFailed | E_IVI_RESET_FAILED | "Instrument reset failed."
ResourceUnknown | E_IVI_RESOURCE_UNKNOWN | "Unknown resource."
StatusNotAvailable | E_IVI_STATUS_NOT_AVAILABLE | "The instrument status is not available."
TooManyOpenFiles | E_IVI_TOO_MANY_OPEN_FILES | "Too many files are open."
UnexpectedResponse | E_IVI_UNEXPECTED_RESPONSE | "Unexpected response from instrument."
UnknownChannelName | E_IVI_UNKNOWN_CHANNEL_NAME | "Unknown channel name."
UnknownNameInSelector | E_IVI_UNKNOWN_NAME_IN_SELECTOR | "Unknown name in selector."
UnknownPhysicalIdentifier | E_IVI_UNKNOWN_PHYSICAL_IDENTIFIER | "Unknown physical repeated capability selector."
ValueNotSupported | E_IVI_VALUE_NOT_SUPPORTED | "Does not support this class-compliant feature: (enumeration) value %s1 passed as the value for parameter %s2 in method %s3."
WritingFile | E_IVI_WRITING_FILE | "Error writing file."
ErrorQueryNotSupported | IDS_S_IVI_NSUP_ERROR_QUERY | "Error query is not supported by this instrument."
IdQueryNotSupported | IDS_S_IVI_NSUP_ID_QUERY | "ID Query is not supported by this instrument."
ResetNotSupported | IDS_S_IVI_NSUP_RESET | "Reset is not supported by this instrument."
RevisionQueryNotSupported | IDS_S_IVI_NSUP_REV_QUERY | "Firmware revision query is not supported by this instrument."
SelfTestNotSupported | IDS_S_IVI_NSUP_SELF_TEST | "Self test is not supported by this instrument."
See Also

Other Resources

Returning Errors from IVI-COM Drivers


Instrument Model Functions

During the initialization sequence of a Nimbus IVI driver, the connected instrument model is detected and stored within the driver itself. The functions described in this section provide access to basic information about the connected instrument model.

In This Section

GetModel

GetSerialNumber

InstrumentInFamily

InstrumentIsModel

InstrumentSupported

ModelInFamily

See Also

Other Resources

Adding Support for Multiple Instrument Models


GetModel

Get the model of the current instrument or the instrument that is simulated.

virtual CString GetModel() const abstract;
Return Value

Returns the current instrument model.

Remarks

The value returned by this function is established by implementation of the InitializeIdentification function. By default, that function parses the *IDN? result to retrieve detailed information about the connected instrument.

Example

The following example demonstrates use of the GetModel function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::Configure()
{
  HRESULT hr = S_OK;

  // This method is NOT supported by the models that end with "B"
  CString strModel = GetModel();
  if (strModel.Right(1) == _T("B"))
    return err.ModelNotSupported(strModel);

  hr = InstrPrintCommand();

  return hr;
}
See Also

Other Resources

Adding Support for Multiple Instrument Models
InstrumentInFamily
InstrumentIsModel


GetSerialNumber

Get the model of the current instrument or the instrument that is simulated.

virtual CString GetSerialNumber() const abstract;
Return Value

Returns the current instrument serial number.

Remarks

The value returned by this function is established by implementation of the InitializeIdentification function. By default, that function parses the *IDN? result to retrieve detailed information about the connected instrument.

Example

The following example demonstrates use of the GetModel function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::Configure()
{
  HRESULT hr = S_OK;

  // This method is NOT supported by instruments with serial numbers that end in "X"
  CString strSerial = GetSerialNumber();
  if (strSerial.Right(1) == _T("X"))
    return err.ModelNotSupported(GetModel());

  hr = InstrPrintCommand();

  return hr;
}


InstrumentInFamily

Indicates if the current instrument is a member of the specified family.

bool InstrumentInFamily(const CString& strFamily) const;
Parameters
strFamily

[in] Instrument family to test against.

Return Value

Returns true if the current model is in the specified family.

Example

The following example demonstrates use of the InstrumentInFamily function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::Configure()
{
  HRESULT hr = S_OK;

  // This method is NOT supported by any models that are part of the "Acme4200" family.
  if (InstrumentInFamily(_T("Acme4200")))
    return err.ModelNotSupported(GetModel());

  hr = InstrPrintCommand();

  return hr;
}
See Also

Other Resources

InstrumentIsModel
ModelInFamily


InstrumentIsModel

Indicates if the current instrument is the specified model.

bool InstrumentIsModel(const CString& strModel) const;
Parameters
strModel

[in] Instrument model to test against.

Return Value

Returns true if the current model is the specified model.

Example

The following example demonstrates use of the InstrumentIsModel function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::Configure()
{
  HRESULT hr = S_OK;

  // This method is NOT supported by model "Acme4322" family.
  if (InstrumentIsModel(_T("Acme4222")))
    return err.ModelNotSupported(GetModel());

  hr = InstrPrintCommand();

  return hr;
}
See Also

Other Resources

InstrumentInFamily
ModelInFamily


InstrumentSupported

Indicates if the current instrument is supported by the driver.

bool InstrumentSupported() const;
Return Value

Returns true if the current model is supported.

Remarks

In order for a model to be supported, it must be listed in the Models Page of the Driver Settings Editor.

Example

The following example demonstrates use of the InstrumentSupported function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::Configure()
{
  HRESULT hr = S_OK;

  if (!InstrumentSupported())
    return err.ModelNotSupported(GetModel());

  hr = InstrPrintCommand();

  return hr;
}
See Also

Other Resources

Adding Support for Multiple Instrument Models


ModelInFamily

Indicates if the specified model is a member of the specified family.

bool ModelInFamily(const CString& strModel, const CString& strFamily) const;
Parameters
strModel

[in] Instrument model.

strFamily

[in] Instrument family.

Return Value

Returns true if the specified model is in the specified family.

Example

The following example demonstrates use of the ModelInFamily function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::Configure(double Frequency, double Gain)
{
  HRESULT hr = S_OK;

  // There are three families of instruments: "Acme432X", "Acme433X", "Acme434X".

  // Get the current model
  CString strModel = GetModel();

  // The SCPI command is slightly different for the models in the "Acme433X" family
  CString strCmdFmt;
  if (ModelInFamily(strModel, _T("Acme433X")))
  {
    strCmdFmt = _T("FREQ %.15g;GAIN %.15g");
  }
  else
  {
    strCmdFmt = _T("FREQX %.15g;GAINX %.15g");
  }

  hr = io.Printf(strCmdFmt, Frequency, Gain);

  return hr;
}
See Also

Other Resources

InstrumentInFamily
InstrumentIsModel


Configuration Server Functions

The IVI Configuration Store is used as a repository for a wide variety of information about an installed IVI driver. Some of the most important information stored is the set of physical repeated capability names supported by the driver, as well as the set of virtual repeated capability names configured by the user. IVI drivers must accept virtual names or physical names when referring to repeated capabilities. The functions in this section provide a simple means to translate between repeated capability physical and virtual names.

In This Section

TranslatePhysicalName

TranslateVirtualName

See Also

Other Resources

IVI Shared Components


TranslatePhysicalName

Translates a physical repeated capability name to a virtual repeated capability name.

virtual CString TranslatePhysicalName(const CString& strPhysicalName) const abstract;
Parameters
strPhysicalName

[in] Physical name to be translated.

Return Value

Returns the virtual name if the translation was successful, otherwise strPhysicalName is returned.

Remarks

This function uses the physical-to-virtual name mappings created by the end user in the IVI Configuration Store. If strPhysical does not have a virtual name mapping, this function simply returns strPhysical.

Example

The following example demonstrates use of the TranslatePhysicalName function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::GetChannelName(BSTR* pbstrName)
{
  HRESULT hr = S_OK;

  CString strPhysicalName = "CH1";

  // Always hand out virtual names to the user
  CString strVirtualName = TranslatePhysicalName(strPhysicalName);

  *pbstrName = strVirtualName.AllocSysString();

  return hr;
}
See Also

Other Resources

TranslateVirtualName
Repeated Capabilities


TranslateVirtualName

Translates a virtual repeated capability name to a physical repeated capability name.

virtual CString TranslateVirtualName(const CString& strVirtualName) const abstract;
Parameters
strVirtualName

[in] Virtual name to be translated.

Return Value

Returns the physical name if the translation was successful, otherwise strVirtualName is returned.

Remarks

This function uses the physical-to-virtual name mappings created by the end user in the IVI Configuration Store. If the specified strVirtual does not have a physical name mapping, this function simply returns strVirtual.

Example

The following example demonstrates use of the TranslateVirtualName function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::ConfigureChannel(BSTR bstrName)
{
  HRESULT hr = S_OK;

  CString strVirtualName = COLE2T(bstrName);
  CString strPhysicalName = TranslateVirtualName(strVirtualName);

  return hr;
}
See Also

Other Resources

TranslatePhysicalName
Repeated Capabilities


Repeated Capability Functions

Nimbus implements collection-style repeated capabilities by using a separate class for each repeated capability. Each repeated capability instance, (e.g. Channel1, Channel2, etc.) is represented by a separate instance of the repeated capability class. Within a method implementation, it is often required to know on which repeated capability instance the method is executing. The functions in this section provide access to the current repeated capability instance. In the case of nested repeated capabilities, these functions also allow a driver developer to "navigate" to parent repeated capability instances.

In This Section

GetInstanceIndex

GetInstanceName

GetParent

GetRepCap

GetRepCapCount

GetRepCapItem

GetRepCapItemCount

GetRepCapItemName

GetRoot

See Also

Other Resources

Repeated Capabilities
Adding a Repeated Capability


GetInstanceIndex

Gets the zero-based index of the repeated capability instance.

int GetInstanceIndex() const;
Return Value

Returns the zero-based index of the repeated capability instance.

Example

The following example demonstrates use of the GetInstanceIndex function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::Configure(double dOffset)
{
  HRESULT hr = S_OK;

  // Format the command using the repeated capability index
  // GetInstanceIndex() is 0-based, the SCPI command is 1-based
  hr = io.Printf(_T("CH%d:OFFS %.15g"), GetInstanceIndex() + 1, dOffset);

  return hr;
}
See Also

Other Resources

GetInstanceIndex
Adding a Repeated Capability
Repeated Capabilities


GetInstanceName

Gets the physical name of the repeated capability instance.

const CString& GetInstanceName() const;
Return Value

Returns the physical name of the repeated capability instance.

Example

The following example demonstrates use of the GetInstanceName function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::Configure(double dOffset)
{
  HRESULT hr = S_OK;

 // Format the command using the repeated capability physical name
  // "CH1", "CH2", "CH3", ...
  hr = io.Printf(_T("%s:OFFS %.15g"), LPCTSTR(GetInstanceName()), dOffset);

  return hr;
}
See Also

Other Resources

GetInstanceIndex
Adding a Repeated Capability
Repeated Capabilities


GetParent

Gets the parent repeated capability instance.

template <typename T>
T* GetParent() const;
Return Value

Returns a pointer to the parent repeated capability instance.

Remarks

If the calling code is not on a repeated capability or the calling code is on the main driver class, this function returns a pointer to the main driver class. Thus, GetParent if safe to call from any driver function.

Example

The following example demonstrates use of the GetParent function.

C++
Copy
// CoAcme4321Channel.cpp
HRESULT Acme4321Channel::Configure(double dOffset)
{
  HRESULT hr = S_OK;

  CString strParentName = GetParent()->GetInstanceName();

  return hr;
}
See Also

Other Resources

GetRepCap
GetRoot


GetRepCap

Gets a pointer to a child repeated capability instance.

template <typename RepCapClass>
RepCapClass* GetRepCap(const CString& strInstanceName) const;

template <typename RepCapClass>
RepCapClass* GetRepCap(int nIndex) const;
Parameters
strInstanceName

[in] Physical name or virtual name of the desired repeated capability instance.

nIndex

[in] Zero-based index of the desired repeated capability instance.

Return Value

Returns a pointer to the repeated capability instance or NULL if the instance is not found.

Remarks

This function returns a pointer to a child repeated capability instance. The strInstanceName parameter may be either a physical name or a virtual name.

Since this function returns a direct pointer to the child repeated capability C++ class instance, not an interface pointer, you can call C++ functions defined on the class that are not in the public COM interface.

Example

The following example demonstrates use of the GetRepCap function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::PresetAll()
{
  HRESULT hr = S_OK;

  int nRepCapCount = GetRepCapCount<Acme4321Channel>();
  for (int i = 0; i < nRepCapCount; i++)
  {
    Acme4321Channel* pChannel = GetRepCap<Acme4321Channel>(i);

    // Call C++ functions on the Acme4321Channel class...
    pChannel->PresetHelper();    // Not a COM interface method
  }

  return hr;
}
See Also

Other Resources

GetParent
GetRoot


GetRepCapCount

Gets the total number of repeated capability instances of the specified class.

template <typename RepCapClass>
int GetRepCapCount() const;
Parameters
RepCapClass

Template parameter specifying the repeated capability class.

Return Value

Returns the total number of repeated capability instances of the class identified by the RepCapClass template parameter.

Remarks

The count returned by this function includes the sum of the static repeated capabilities and dynamic repeated capabilities.

Example

The following example demonstrates use of the GetRepCapCount function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::PresetAll()
{
  HRESULT hr = S_OK;

  int nRepCapCount = GetRepCapCount<Acme4321Channel>();
  for (int i = 0; i < nRepCapCount; i++)
  {
    Acme4321Channel* pChannel = GetRepCap<Acme4321Channel>(i);

    // Call C++ functions on the Acme4321Channel class...
    pChannel->PresetHelper();    // Not a COM interface method
  }

  return hr;
}
See Also

Other Resources

GetRepCapItem
GetRepCapItemCount
GetRepCapItemName


GetRepCapItem

Gets the root interface pointer of a child repeated capability instance.

template <typename RepCapClass, typename ItfType>
HRESULT GetRepCapItem(CComBSTR bstrInstanceName, ItfType** ppRepCap);
Parameters
RepCapClass

Template parameter identifying the repeated capability class.

bstrInstanceName

[in] Physical name or virtual name of the desired repeated capability instance.

ppRepCap

[out] Pointer to the root interface of the repeated capability instance identified by the RepCapClass and bstrInstanceName parameters.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

The signature of this function is specifically designed to match that of the standard Item method found on all collection-style repeated capabilities.

Example

The following example demonstrates use of the GetRepCapItem function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::IAcme4321Channels_get_Item(BSTR Name, IAcme4321Channel** val)
{
    HRESULT hr = S_OK;

    hr = GetRepCapItem<Acme4321Channel>(Name, val);

    return hr;
}
See Also

Other Resources

GetRepCapCount
GetRepCapItemCount
GetRepCapItemName


GetRepCapItemCount

Gets the total number of repeated capability instances of the specified class.

template <typename RepCapClass>
HRESULT GetRepCapItemCount(long* plCount);
Parameters
RepCapClass

Template parameter identifying the repeated capability class.

plCount

[out] Returns the total number of repeated capability instances of the class identified by the RepCapClass template parameter.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

The signature of this function is specifically designed to match that of the standard Count method found on all repeated capabilities.

Example

The following example demonstrates use of the GetRepCapItemCount function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::IAcme4321Channels_get_Count(long* val)
{
    HRESULT hr = S_OK;

    hr = GetRepCapItemCount<Acme4321Channel>(val);

    return hr;
}
See Also

Other Resources

GetRepCapCount
GetRepCapItem
GetRepCapItemName


GetRepCapItemName

Gets the physical name or virtual name of the repeated capability instance.

template <typename RepCapClass>
HRESULT GetRepCapItemName(long lIndex, BSTR* pbstrInstanceName);
Parameters
RepCapClass

Template parameter identifying the repeated capability class.

lIndex

[in] One-based index of the desired repeated capability instance.

pbstrInstanceName

[out] Virtual name of repeated capability instance. If no virtual name was mapped to the physical name, then the physical name is returned.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.

Remarks

The signature of this function is specifically designed to match that of the standard Name property found on all repeated capabilities.

Example

The following example demonstrates use of the GetRepCapItemName function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::IAcme4321Channels_get_Name(long Index, BSTR* val)
{
    HRESULT hr = S_OK;

    hr = GetRepCapItemName<Acme4321Channel>(Index, val);

    return hr;
}
See Also

Other Resources

GetRepCapCount
GetRepCapItemCount
GetRepCapItemName

Copyright 2001-2022 Pacific MindWorks. All rights reserved.

Send comments on this topic to support@pacificmindworks.com


GetRoot

Gets a pointer to the main driver class.

template <typename T>
T* GetRoot() const;
Return Value

Returns a pointer to the main driver class.

Remarks

This function always returns a pointer to the main driver class, even if it is called from the main driver. Thus, GetRoot if safe to call from any driver function.

Example

The following example demonstrates use of the GetRoot function.

C++
Copy
// CoAcme4321Channel.cpp
HRESULT Acme4321Channel::Configure(double dOffset)
{
  HRESULT hr = S_OK;

  Acme4321* pRoot = GetRoot();

  return hr;
}
See Also

Other Resources

GetParent
GetRepCap


State Caching Functions

Nimbus provides a state-caching editor that allows basic state caching settings to be configured without supplying any code. Simple couplings can be expressed to ensure good cache coherency. In more advanced state-caching scenarios where the couplings are more complex or the required logic is otherwise more involved, the driver developer may wish to manually implement state caching. The functions in this section allow direct control over the Nimbus state caching engine.

In This Section

CCacheEntry<T>::ContainsValue

CCacheEntry<T>::Invalidate

CCacheEntry<T>::IsValid

CCacheEntry<T>::GetValue

CCacheEntry<T>::SetValid

CCacheEntry<T>::UpdateValue

GetCacheEntryValue

GetOrCreateCacheEntry

InvalidateCache

InvalidateCacheAll

InvalidateCacheEntry

UpdateCacheEntry

See Also

Other Resources

State Caching Overview


CCacheEntry<T>::ContainsValue

Indicates if the specified entry is in the cache and is valid.

bool CCacheEntry<T>::ContainsValue(T value, const CString& strModel);
Parameters
value

[in] Value to check.

strModel

[in] The current instrument model.

Return Value

Returns true if the specified value is in the cache and is valid, otherwise false.

Example

The following example demonstrates use of the ContainsValue function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::put_Bandwidth(double Bandwidth)
{
  HRESULT hr = S_OK;

   // Retrieve the cache entry for the Bandwidth property
   CCacheEntry<double>* pEntry = GetOrCreateCacheEntry<double>(_T("IAcme4321.Bandwidth"));

   // If the value is in the cache AND is valid, simply return since we don't need to send the instrument command
   if (pEntry->ContainsValue(Bandwidth, GetModel()))
      return S_OK;

   // If we get this far, then the new value is not in the cache, so we
   // must communicate with the instrument to set the value
   HRESULT hr = io.Printf(_T("SENSE:BAND %.15g"), Bandwidth);

   if (SUCCEEDED(hr))
   {
      // The new value was successfully sent to the instrument, so update the cache
      pEntry->UpdateValue(Bandwidth);
   }

  return hr;
}
See Also

Other Resources

GetOrCreateCacheEntry
State Caching Overview


CCacheEntry<T>::Invalidate

Invalidates a cache entry so that the next set or get operation results in communication with the instrument.

virtual void CCacheEntry<T>::Invalidate();
Example

The following example demonstrates use of the Invalidate function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::put_Frequency(double Frequency)
{
  HRESULT hr = S_OK;

   // We want to couple the frequency to the bandwidth, so we must
   // invalidate the cached bandwidth whenever the frequency changes

   // Retrieve the cache entry for the Bandwidth property
   CCacheEntry<double>* pEntry = GetOrCreateCacheEntry<double>(_T("IAcme4321.Bandwidth"));

   // Invalidate the entry
   pEntry->Invalidate();

  return hr;
}
See Also

Other Resources

InvalidateCacheEntry
InvalidateCache
InvalidateCacheAll
GetOrCreateCacheEntry
State Caching Overview


CCacheEntry<T>::IsValid

Indicates whether or not a cache entry is valid.

virtual bool CCacheEntry<T>::IsValid() const;
Return Value

Returns true if the specified value is valid, otherwise false.

Example

The following example demonstrates use of the IsValid function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::Configure(double Frequency, double Gain)
{
  HRESULT hr = S_OK;

  // Retrieve the cache entry for the Frequency property
  CCacheEntry<double>* pEntry = GetOrCreateCacheEntry<double>(_T("IAcme4321.Frequency"));

  if (pEntry->IsValid())
  {
     // ...
  }

  return hr;
}
See Also

Other Resources

CCacheEntry<T>::SetValid
GetOrCreateCacheEntry
State Caching Overview


CCacheEntry<T>::GetValue

Retrieves the value of a cache entry.

bool CCacheEntry<T>::GetValue(T* pValue) const;
Parameters
pValue

[out] Cached value. If the value is not valid, then the value of this parameter is undefined.

Return Value

Returns true if the value is in the cache and is valid, otherwise false.

Example

The following example demonstrates use of the GetValue function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::get_Bandwidth(double* val)
{
  HRESULT hr = S_OK;

  // Retrieve the cache entry for the Bandwidth property
  CCacheEntry<double>* pEntry = GetOrCreateCacheEntry<double>(_T("IAcme4321.Bandwidth"));

  // If the value is in the cache AND is valid, retrieve the value and return
  if (pEntry->GetValue(val))
     return S_OK;

  // If we get this far, then the cached value is not valid, so we
  // must communicate with the instrument to retrieve the value
  hr = InstrQueryCommand(val);

  return hr;
}
See Also

Other Resources

UpdateCacheEntry
GetOrCreateCacheEntry
State Caching Overview


CCacheEntry<T>::SetValid

Sets the valid state of a cache entry to true.

virtual void CCacheEntry<T>::SetValid()
Example

The following example demonstrates use of the SetValid function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::put_Configure(double Frequency, double Gain)
{
  HRESULT hr = S_OK;

  hr = InstrPrintCommand(Frequency, Gain);

  if (SUCCEEDED(hr))
  {
     // ...

     // Retrieve the cache entry for the Frequency property
     CCacheEntry<double>* pEntry = GetOrCreateCacheEntry<double>(_T("IAcme4321.Frequency"));

     pEntry->SetValid();
  }

  return hr;
}
See Also

Other Resources

CCacheEntry<T>::IsValid
GetOrCreateCacheEntry
State Caching Overview


CCacheEntry<T>::UpdateValue

Retrieves the value of a cache entry if the entry is valid.

template <typename T>
void GetCacheEntryValue(const CString& strKey, T* value);
Parameters
strKey

[in] Name of the property for which we want to retrieve the cached value. For more information, see the topic Property Identifiers.

value

[out] Value of cache entry. If the entry is not valid, then this value is undefined.

Example

The following example demonstrates use of the UpdateValue function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::Configure(double Frequency, double Gain)
{
  HRESULT hr = S_OK;

  double dFreq = 0;
  GetCacheEntryValue(_T("IAcme4321.Frequency"), &dFreq);

  return hr;
}
See Also

Other Resources

UpdateCacheEntry
GetOrCreateCacheEntry
State Caching Overview


GetCacheEntryValue

Retrieves the value of a cache entry if the entry is valid.

template <typename T>
void GetCacheEntryValue(const CString& strKey, T* pValue);
Parameters
strKey

[in] Name of property from which to retreive the cached value. For more information, see property identifiers.

pValue

[out] Cached value. If the value is not valid, then the value of this parameter is undefined.

Return Value

Returns true if the specified value is in the cache and is valid, otherwise false.

Example

The following example demonstrates use of the GetCacheEntryValue function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::Configure(double Frequency, double Bandwidth)
{
  HRESULT hr = S_OK;

  double dFreq = 0;
  GetCacheEntryValue(_T("IAcme4321.Frequency"), &dFreq);

  return hr;
}
See Also

Other Resources

GetOrCreateCacheEntry
State Caching Overview


GetOrCreateCacheEntry

Creates or retrieves a cache entry for a specified property.

template <typename T>
CCacheEntry<T>* GetOrCreateCacheEntry(const CString& strKey);
Parameters
strKey

[in] Name of property to retrieve cache entry. For more information, see property identifiers.

Return Value

Returns a pointer to a CCacheEntry object, which represents the cache entry for the specified property.

Example

The following example demonstrates use of the GetOrCreateCacheEntry function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::put_Bandwidth(double val)
{
  HRESULT hr = S_OK;

  // Retrieve the cache entry for the Bandwidth property
  CCacheEntry<double>* pEntry = GetOrCreateCacheEntry<double>(_T("IAcme4321.Bandwidth"));

  // ...

  return hr;
}
See Also

Other Resources

State Caching Overview


InvalidateCache

Invalidates all cached properties on the class of the caller and all child repeated capabilities.

void InvalidateCache();
Example

The following example demonstrates use of the InvalidateCache function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::put_Bandwidth()
{
  HRESULT hr = S_OK;

  InvalidateCache();

  return hr;
}
See Also

Other Resources

CCacheEntry<T>::Invalidate
InvalidateCache
InvalidateCacheAll
InvalidateCacheEntry
GetOrCreateCacheEntry
State Caching Overview


InvalidateCacheAll

Invalidates all cached properties on all classes in the driver.

void InvalidateCacheAll();
Example

The following example demonstrates use of the InvalidateCacheAll function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::put_Bandwidth()
{
  HRESULT hr = S_OK;

  InvalidateCacheAll();

  return hr;
}
See Also

Other Resources

GetOrCreateCacheEntry
State Caching Overview


InvalidateCacheEntry

Retrieves the value of a cache entry if the entry is valid.

void InvalidateCacheEntry(const CString& strPath);
Parameters
strPath

[in] Name of property to invalidate. For more information, see property identifiers.

Example

The following example demonstrates use of the InvalidateCacheEntry function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::Configure(double Frequency, double Bandwidth)
{
  HRESULT hr = S_OK;

  InvalidateCacheEntry(_T("IAcme4321.Frequency"));

  return hr;
}
See Also

Other Resources

GetOrCreateCacheEntry
State Caching Overview


UpdateCacheEntry

Updates the cached value for the specified property.

template <typename T>
void UpdateCacheEntry(const CString& strKey, T value);
Parameters
strKey

[in] Name of property to invalidate. For more information, see property identifiers.

value

[in] New value to store in the cache for the specified property.

Example

The following example demonstrates use of the UpdateCacheEntry function.

C++
Copy
// CoAcme4321.cpp
STDMETHODIMP Acme4321::Configure(double Frequency, double Gain)
{
  HRESULT hr = S_OK;

  hr = io.Printf(_T("SENS:CONFIG %0.15g,%f"), Frequency, Gain);

  if (SUCCEEDED(hr))
  {
     UpdateCacheEntry(_T("IAcme4321.Frequency"), Frequency);

     UpdateCacheEntry(_T("IAcme4321.Gain"), Gain);
  }

  return hr;
}
See Also

Other Resources

GetOrCreateCacheEntry
State Caching Overview


Driver State Functions

A number of IVI driver settings that control the operation of the driver can be specified by the end user in a variety of ways. For instance, the end user can enable state caching by specifying it in the IVI Configuration Store. Alternatively, they can pass in Cache=True as part of the OptionString parameter passed to the Initialize function. Or, the user can set the Cache property on the driver itself at any time during the execution of the program.

Given the flexibility users have in specifying certain driver settings, it is difficult to manually track the current state of these settings. The functions described in this section are provided expressly for that purpose.

In This Section

GetCache

GetConfigSetting

GetDriverSetupOptionValue

GetInherentOptionValue

GetInitialized

GetInterchangeCheck

GetQueryInstrStatus

GetRangeCheck

GetRecordCoercions

GetResourceDescriptor

GetSimulate

GetTraceEnabled

SetTraceEnabled


GetCache

Indicates if state caching is enabled.

virtual bool GetCache() const abstract;
Return Value

Returns true if state caching is currently enabled, otherwise false.

See Also

Other Resources

State Caching Overview


GetConfigSetting

Get the value of an option in the IVI Configuration Store.

virtual bool GetConfigSetting(const CString& strName, CComVariant& value) const abstract;

virtual bool GetConfigSetting(const CString& strName, CString& value) const abstract;

virtual bool GetConfigSetting(const CString& strName, int& value) const abstract;

virtual bool GetConfigSetting(const CString& strName, double& value) const abstract;

virtual bool GetConfigSetting(const CString& strName, bool& value) const abstract;
Parameters
strName

[in] Name of the configurable setting.

value

[out] Value of the specified setting.

Return Value

Returns true if the specified config setting was found, otherwise false.

See Also

Other Resources

IVI Shared Components


GetDriverSetupOptionValue

Get the value of an option from the DriverSetup string.

virtual CString GetDriverSetupOptionValue(const CString& strName) const abstract;
Parameters
strName

[in] Name of the option to retrieve.

Return Value

Returns the value of the option by name. If not found an empty string is returned.

Remarks

The name/value pairs available are set by the DriverSetup string passed to the IIviDriver::Initialize function.


GetInherentOptionValue

Get the value of an option from the OptionString string.

virtual CString GetInherentOptionValue(const CString& strName) const abstract;
Parameters
strName

[in] Name of the option to retrieve.

Return Value

Returns the value of the option by name. If not found an empty string is returned.

Remarks

The name/value pairs available are set by the OptionString string passed to the IIviDriver::Initialize function.


GetInitialized

Indicates if the driver has been initialized.

virtual bool GetInitialized() const abstract;
Return Value

Returns true if the driver has been initialized, otherwise false.

Remarks

The driver is initialized between calls to IIviDriver::Initialize and IIviDriver::Close, assuming that IIviDriver::Initialize was successful.


GetInterchangeCheck

Indicates if interchangeability checking is enabled.

virtual bool GetInterchangeCheck() const abstract;
Return Value

Returns true if interchangeability checking is enabled, otherwise false.

See Also

Other Resources

What All IVI Drivers Do -- Inherent Capabilities


GetQueryInstrStatus

Indicates if instrument status query is enabled.

virtual bool GetQueryInstrumentStatus() const abstract;
Return Value

Returns true if instrument status query is enabled, otherwise false.


GetRangeCheck

Indicates if range checking is enabled.

virtual bool GetRangeCheck() const abstract;
Return Value

Returns true if range checking is enabled, otherwise false.

Example

The following example demonstrates use of the GetRangeCheck function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::Configure(double Frequency, double Gain)
{
  HRESULT hr = S_OK;

  // Perform range checking before communicating with instrument
  if (GetRangeCheck())
  {
    if (Frequency < 1.0E3 || Frequency > 1.0E12)
      return err.InvalidValue(_T("Frequency"), Frequency);

    if (Gain < 0)
      return err.InvalidValue(_T("Gain"), Gain);
  }

  hr = InstrPrintCommand();

  return hr;
}
See Also

Other Resources

What All IVI Drivers Do -- Inherent Capabilities


GetRecordCoercions

Indicates if coercion recording is enabled.

virtual bool GetRecordCoercions() const abstract;
Return Value

Returns true if coercion recording is enabled, otherwise false.


GetResourceDescriptor

Get the current resource descriptor used to initialize the instrument.

virtual CString GetResourceDescriptor() const abstract;
Return Value

Returns the resource descriptor used to initialize the instrument.


GetSimulate

Indicates if simulation is enabled.

virtual bool GetSimulate() const abstract;
Return Value

Returns true if simulation is enabled, otherwise false.

Example

The following example demonstrates use of the GetSimulate function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::Query(double* Frequency, double* Gain)
{
  HRESULT hr = S_OK;

  // Do not communicate with instrument if simulation is on
  if (GetSimulate())
  {
    // Return simulated values
    *Frequency = 1.2E9;
    *Gain = 0.5;
    return S_OK;
  }

  hr = io.QueryNumber(_T("FREQ?"), Frequency);
  if (SUCCEEDED(hr))
  {
    hr = io.QueryNumber(_T("GAIN?"), Gain);
  }

  return hr;
}
See Also

Other Resources

What All IVI Drivers Do -- Inherent Capabilities


GetTraceEnabled

Indicates if tracing is enabled.

HRESULT GetTraceEnabled(VARIANT_BOOL* val);
Parameters
val

[out] VARIANT_TRUE if tracing is enabled, otherwise VARIANT_FALSE.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.


SetTraceEnabled

Enables or disables tracing.

HRESULT SetTraceEnabled(VARIANT_BOOL val);
Parameters
val

[out] VARIANT_TRUE to enable tracing, VARIANT_FALSE to disable tracing.

Return Value

Returns S_OK if successful, otherwise a failure HRESULT.


Miscellaneous Functions

In This Section

EnumToName

EnumFromName

NTL_NO_VISA Macro

NTL_NO_VISACOM Macro


EnumToName

Converts an enum value into a string representation..

template <typename T>
bool EnumToName(T enumVal, CString& strName) const;
Parameters
enumVal

[in] Enum value to be converted to a string.

strName

[out] String version of the specified enum value.

Return Value

Returns true if the conversion was successful, otherwise false.

Remarks

This function is typically used to report errors when enum values are not supported. For instance, it is much more helpful to the user if an error is reported as "Trigger source cannot be set to Acme4321TriggerSourceExternal" as opposed to "Trigger source cannot be set to 3".

Note that this function is used for a completely different purpose than the EnumToCommand function, which is used to map between enum values and their associated instrument commands.

Example

The following example demonstrates use of the EnumToName function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::ConfigureTrigger(IviFgenTriggerSource eSource)
{
  HRESULT hr = S_OK;

  // Only internal and external triggering are supported
  switch (eSource)
  {
    case IviFgenTriggerSourceInternal:
      hr = io.WriteString(_T("TRIG:SOUR INT"));
      break;
    case IviFgenTriggerSourceExternal:
      hr = io.WriteString(_T("TRIG:SOUR EXT"));
      break;
    default:
      CString strEnum;
      EnumToName<IviFgenTriggerSource>(eSource, strEnum);

      hr = err.InvalidValue(_T("eSource"), strEnum);
      break;
  }

  return hr;
}
See Also

Other Resources

EnumFromName


EnumFromName

Converts the string name of an enum value to its numeric value.

template <typename T>
bool EnumFromName(const CString& strName, T& enumVal) const;
Parameters
strName

[in] String name of an enum value.

enumVal

[out] Enum value associated with the specified name.

Return Value

Returns true if the conversion was successful, otherwise false.

Example

The following example demonstrates use of the EnumFromName function.

C++
Copy
// CoAcme4321.cpp
HRESULT Acme4321::ConfigureTrigger()
{
  HRESULT hr = S_OK;

  IviFgenTriggerSource eSource;
  EnumFromString(_T("IviFgenTriggerSourceInternal"), eSource);

  ATLASSERT(eSource == IviFgenTriggerSourceInternal);

  return hr;
}
See Also

Other Resources

EnumToName


NTL_NO_VISA Macro

Preprocessor definition to prevent inclusion of the VISA header files.

#define NTL_NO_VISA
Remarks

Define NTL_NO_VISA before the include of "ntl.h" in order to prevent the VISA-C I/O provider from being compiled in your project. This is useful if you do not have VISA-C installed on your system.

Example

The following example demonstrates use of the NTL_NO_VISA macro.

C++
Copy
// stdafx.h

// Prevent inclusion of the VISA-C I/O provider header file
#define NTL_NO_VISA

#include "ntl.h"
See Also

Other Resources

NTL_NO_VISACOM Macro


NTL_NO_VISACOM Macro

Preprocessor definition to prevent inclusion of the VISA-COM header files.

#define NTL_NO_VISACOM
Remarks

Define NTL_NO_VISACOM before the include of "ntl.h" in order to prevent the VISA-COM I/O provider from being compiled in your project. This is useful if you do not have VISA-COM installed on your system.

Example

The following example demonstrates use of the NTL_NO_VISACOM macro.

C++
Copy
// stdafx.h

// Prevent inclusion of the VISA-COM I/O provider header file
#define NTL_NO_VISACOM

#include "ntl.h"
See Also

Other Resources

NTL_NO_VISA Macro


NTL_DISABLE_IVIC_ATTRIBUTE_C4244 Macro

Preprocessor definition to disable the C4244 compiler warning when performing certain parameter conversions in the IVI-C wrapper.

#define NTL_DISABLE_IVIC_ATTRIBUTE_C4244
Remarks

Define NTL_DISABLE_IVIC_ATTRIBUTE_C4244 before the include of "stdafx.nimbus.h" in order to prevent the C4244 compiler warning when converting between IVI-COM and IVI-C parameters within the IVI-C wrapper implementation. In some situations, the conversion might cast from a larger IVI-C parameter type to a smaller IVI-COM parameter type. This could result in a loss of data or precision.

For example, if an IVI-C attribute is of type ViInt32 and the corresponding IVI-COM attribute is of type Int16 (short), then the cast from ViInt32 to short will generate C4244 by default, warning that you are casting from a larger type (ViInt32) to a smaller type (short).

Important note Important

Only when you are certain that the required cast will not cause problems in the completed driver should you apply the NTL_DISABLE_IVIC_ATTRIBUTE_C4244 preprocessor definition to your "stdafx.h" file.

Example

The following example demonstrates use of the NTL_DISABLE_IVIC_ATTRIBUTE_C4244 macro.

C++
Copy
// stdafx.h

// Prevent C4244 within the IVI-C wrapper implementation
#define NTL_DISABLE_IVIC_ATTRIBUTE_C4244

#include "stdafx.nimbus.h"


Developing an IVI-C Driver

Developing an IVI-C driver involves a number of tasks. The New IVI-C Wizard is used to create the driver project. Various Nimbus features integrated into the Visual Studio IDE allow functionality to be added to the driver, while the Nimbus Runtime Library provides a rich set of support functions for implementing these features.

In This Section

Understanding IVI-C Driver Development Options

Creating an IVI-C Driver Project

Visual Studio Projects for an IVI-C Driver

Accessing Driver Settings

Adding Functionality to an IVI-C Driver

IVI-C Item Editors

Implementing Driver Functions and Attributes

Customizing the Driver Header File

Understanding State Caching

Implementing Dynamic Repeated Capabilities

Customizing Driver Initialization and Shutdown

Testing an IVI-C Driver

The Nimbus Runtime Library (NRT)


Creating an IVI-C Driver Project

The first step in developing an IVI-C driver is to create the IVI driver project. Nimbus supplies a custom project type to the Visual Studio project system just for this purpose. The topics in this section explain how to run the New IVI-C Driver Wizard as well as the Visual Studio projects that are created in the process. Also, certain the topics in this section explain the Visual Studio settings that must be properly configured to build the IVI-C driver project.

In This Section

Using The IVI-C Driver Wizard

Required Visual Studio Configuration Changes

Building the IVI-C Driver


Using The IVI-C Driver Wizard

The first step in creating an IVI-C driver is running the IVI-C Driver Wizard. The wizard is launched from within the Visual Studio IDE, just as native Visual Studio project types.

To launch the New IVI-C Driver Wizard

  1. From within Visual Studio, click on the File menu, select New and then choose Project.

  2. The standard Visual Studio New Project Dialog appears.

  3. Under Installed Templates on the left, choose Nimbus Driver Studio and then select IVI-C Driver from the list of templates displayed.

  4. Review the Name suggested for the new IVI-C driver project at the bottom of the dialog, changing it if desired.

  5. Review the directory Location suggested for the new IVI-C driver project, changing it if desired.

  6. Review the Solution name and other settings suggested for the new IVI-C driver project, changing them if desired.

  7. Press the OK button.

  8. The IVI-C Driver Project Wizard appears.

Tip Tip

When filling out the wizard pages, keep in mind that any of the options selected can be changed later using the Driver Settings Editor.

The remaining topics in this section discuss each wizard page separately.

In This Section

General Page, New IVI-C Driver Wizard

Features Page, New IVI-C Driver Wizard

I/O Page, New IVI-C Driver Wizard

LXI Compliance, New IVI-C Driver Wizard

Projects Page, New IVI-C Driver Wizard

See Also

Other Resources

Visual Studio Projects for an IVI-C Driver


General Page, New IVI-C Driver Wizard

The General Page of the New IVI-C Driver Wizard presents basic information about the IVI-C driver project.

Driver name

The driver name is the primary identifier for the IVI-C driver project. Many names associated with the driver will be based on the driver name. The driver project name, the IVI Configuration Store entries, and other items are based on this entry. Importantly, the driver DLL itself is not based on this name; rather, the driver DLL is named according to the driver Prefix setting.

Instrument manufacturer

The instrument manufacturer is used to identify the manufacturer of the instrument for which the driver is being written. This entry is used in the IVI Configuration Store registration as well as in the implementation of the INSTRUMENT_MANUFACTURER attribute.

Driver vendor

The driver vendor identifies the company responsible for development and support of the driver. This entry is used in the IVI Configuration Store registration as well as in the implementation of the SPECIFIC_DRIVER_VENDOR attribute.

Instrument model

The name of the instrument model for which the driver is being written. The driver must be able to use this string to identify the actual connected instrument during driver initialization, such as through the use of a "*IDN?" query. See the topic Customizing the Initialization and Shutdown Sequence for information on identifying the connected model.

If the driver is to support multiple instrument models, enter one of the most common models here. The Models Page of the Driver Settings Editor can be used to add models to the driver. See the topic Adding Support for Multiple Instrument Models for more information on multi-model drivers.


Features Page, New IVI-C Driver Wizard

Code generation
Automatically generate getter functions for IVI-C attributes

This setting controls whether getter functions are automatically generated when an IVI-C attribute is added to the driver.

Getter function prefix

This setting controls the name of automatically generated IVI-C attribute getter functions. For example, if an attribute named OUTPUT_VOLTAGE is created, and this setting is chosen to be Get, Nimbus will automatically generate an IVI-C getter function named GetOutputVoltage.

The name resulting from selections made here represent the initial name given to the getter function. Individual getter functions can be renamed as desired.

Automatically generate setter functions for IVI-C attributes

This setting controls whether setter functions are automatically generated when an IVI-C attribute is added to the driver.

Setter function prefix

This setting controls the name of automatically generated IVI-C attribute setter functions. For example, if an attribute named OUTPUT_VOLTAGE is created, and this setting is chosen to be Set, Nimbus will automatically generate an IVI-C setter function named SetOutputVoltage.

The name resulting from selections made here represent the initial name given to the setter function. Individual setter functions can be renamed as desired.

See Also

Other Resources

Adding Attribute Getter and Setter Functions


I/O Page, New IVI-C Driver Wizard

Instrument I/O
Enable VISA-based I/O

This setting controls whether the driver uses the VISA library for instrument communication. When true, Nimbus will link against VISA so that the driver implementation can use any of the standard VISA functions. In addition, Nimbus will automatically open a VISA session upon driver initialization (and close it when the driver's close function is executed. Nimbus will also implement the following functions automatically using standard instrument commands when this setting is true:

  • Disable

  • error_query

  • reset

  • self_test

Integer format

Specifies the default format code to use for integer values in instrument command strings. Explicit format codes used in the instrument command override this setting.

See the topics under Working With Instrument Commands for more information.

Floating-point format

Specifies the default format code to use for floating-point values in instrument command strings. Explicit format codes used in the instrument command override this setting.

See the topics under Working With Instrument Commands for more information.

String format

Specifies the default format code to use for string values in instrument response strings. Explicit format codes used in the instrument command override this setting. This setting is only used for reading values from the instrument -- not for formatting values sent to the instrument.

See the topics under Working With Instrument Commands for more information.

Boolean True

Specifies a comma-separated list of instrument responses that should be interpreted as a boolean true. For instrument commands, the first string in the list will be used to send a boolean true to the device.

Boolean False

Specifies a comma-separated list of instrument responses that should be interpreted as a boolean false. For instrument commands, the first string in the list will be used to send a boolean false to the device.

SCPI compliant

Indicates whether the instrument uses SCPI-compliant instrument commands. Nimbus provides specialized support for SCPI-compliant instruments. See the topic Special Features For SCPI Commands for detailed information.

Generate direct I/O functions and attributes

This setting controls whether the wizard will generate the IVI-defined functions and attributes for directly communicating with the instrument using the underlying I/O mechanism. For a driver using VISA as its underlying I/O library, Nimbus will generate a working implementation of these functions and attributes. For a non-VISA-based driver, Nimbus will generate stub implementations that the driver developer must then fill in with an implementation appropriate for their specific I/O library.

The exact syntax and behavior of these functions is prescribed in IVI-3.4: API Sytle Guide.

Important note Important

In order to comply with the IVI Generation IVI-2014, drivers must implement these direct I/O functions and attributes. These functions and attributes can be created after the wizard runs, but it is typically easier to let the wizard create them upfront.

Enable simulation code generation

Determines whether or not Nimbus ever generates automatic simulation handling code. When true, Nimbus enables the Simulation Editor for attributes so that the developer can choose on an attribute-by-attribute basis whether or not to instruct Nimbus to generate simulation handling code. Nimbus also generates "stub" simulation code blocks for functions so that the developer has a convenient place to insert their manual function simulation code.

When this setting is false, all attributes are set to Manual simulation mode, and the Simulation Editor is disabled. Nimbus also does not generate "stub" simulation code blocks for functions in this case.

This setting is useful in situations where a lower-level software component is handling all of the simulation logic, and the Nimbus driver is simply delegating to that lower-level component. In such cases, it's inconveninet for the developer to explicitly set all attributes to Manual simulation mode and to delete all residual and unneeded simulation code generated for functions and attributes. With this setting, the developer can simply disable simulation code generation "globally".

See Also

Other Resources

Communicating With Instruments
Working With Instrument Commands
Special Features for SCPI Commands


LXI Compliance, New IVI-C Driver Wizard

The LXI Compliance Page of the New IVI-C Driver Wizard allows you to select whether the instruments support LXI and which LXI extension groups are supported. Based upon the selections made here, Nimbus automatically creates a project with the appropriate LXI repeated capabilities and repeated capability names and the required IviLxiSync functions and attributes.

Note Note

It is not necessary to decide upon the degress of LXI compliance when running the wizard. Support for LXI can be added and removed at any stage of development using commands available within the IDE. See the topic Adding Support for LXI for more information.

Conformance

Indicates whether the driver supports any level of LXI conformance. No modifications are performed based on this selection alone, but by selecting LXI Core 2016, the checkboxes for the various LXI-defined extension groups become enabled and selecting those extension groups does cause Nimbus to modify the driver code.

LXI Extension Groups

Selecting any of the LXI-defined extension groups adds the IviLxiSync functions, attributes, and repeated capabilities to the driver.

For the added repeated capabilities, Nimbus adds the LXI-defined repeated capability names for LAN triggers (LAN0...7).

If LXI Wired Trigger Bus is selected, Nimbus adds LXI-defined repeated capability names for the LXI hardware trigger lines (LXI0...7).

See Also

Other Resources

Adding Support for LXI


Projects Page, New IVI-C Driver Wizard

The Projects Page of the New IVI-C Driver Wizard allows you to select which additional Nimbus-generated Visual Studio projects should be created and added to the driver solution.

Note Note

Any of the projects available via the wizard can be added later by right-clicking on the Solution node in Solution Explorer and choosing Add and then selecting New Project.

Create unit test project

Specifies whether a unit test project for the IVI-C driver should be created and added to the driver solution.

Nimbus provides advanced IVI-C driver unit testing features that integrate directly with the Visual Studio IDE. For more information, see the topic Testing an IVI-C Driver.

Create help project

Specifies whether a help project for the IVI-C driver should be created and added to the driver solution. The project is generated based on your per-user preferences for help projects.

Create setup project

Specifies whether a setup project for the IVI-C driver should be created and added to the driver solution.

Create C++ console application

This option creates a starter Visual C++ project for exercising the IVI-C driver. The project is generated with the appropriate initialization and shutdown calls as well as basic error checking code. This project is a good starting point for building more involved C++ client applications or for simply testing driver operation in C++.

See Also

Other Resources

Visual Studio Projects for an IVI-C Driver
Testing an IVI-C Driver
Using Per-User Preferences


Required Visual Studio Configuration Changes

Before building an IVI-C driver project, several configuration settings must be manually changed. The Visual Studio project system does not expose this functionality in a way that allows Nimbus to automatically perform these configuration changes, so this topic explains each step the driver developer must perform.

To configure the appropriate solution platforms

  1. From Solution Explorer, right click on the solution and choose Configuration Manager. The Configuration Manager Dialog Box appears.

  2. From the Active solution platform combo box, choose <Edit...>. The Edit Solution Platforms dialog box appears.

  3. The following platforms should be present:

    • Any CPU

    • Mixed Platforms

    • Win32

    • x64

    • x86

  4. For most developers, only one or two solution platforms are needed. The recommended solution platforms to keep depend upon whether you are creating a linked IVI-C driver as part of the solution or simply creating an IVI-C driver without a linked IVI.NET driver.

    For solutions that have only an IVI-C driver, typically x86 and x64 will be needed. Other solution platforms can be safely deleted.

    For solutions that have an IVI.NET driver and a linked IVI-C driver, both Mixed Platforms and x64 will typically be needed. Other solution platforms can be safely deleted.

  5. Close the Edit Solution Platforms dialog.

  6. From the Configuration Manager dialog, choose the x86 (or the Mixed Platforms) platform from the Action solution platform combo box.

  7. Make sure that the Platform column setting and Build column setting for each project is set according to the table below. (Note the list of projects that appears depends upon the driver options chosen.)

    Project

    Platform

    Build

    <driverName>CDriverConsoleApplication

    Win32

    Checked

    <driverName>CDriver

    Win32

    Checked

    <driverName>CDriverHelp

    Any CPU

    Unchecked

    <driverName>CDriverSetup

    x86

    Unchecked

    <driverName>CDriverUnitTest

    Win32

    Checked

  8. Use the Active solution configuration combo box to repeat the above settings for both Debug and Release configurations.

  9. From the Configuration Manager dialog, choose the x64 platform from the Action solution platform combo box.

  10. Make sure that the Platform column setting and Build column setting for each project is set according to the table below. (Note the list of projects that appears depends upon the driver options chosen.)

    Project

    Platform

    Build

    <driverName>CDriverConsoleApplication

    x64

    Checked

    <driverName>CDriver

    x64

    Checked

    <driverName>CDriverHelp

    Any CPU

    Unchecked

    <driverName>CDriverSetup

    x64

    Unchecked

    <driverName>CDriverUnitTest

    x64

    Checked

  11. Use the Active solution configuration combo box to repeat the above settings for both Debug and Release configurations.

See Also

Other Resources

Building the IVI-C Driver


Building the IVI-C Driver

Project Dependencies

A Nimbus driver solution consists of several Visual Studio projects. The topic Visual Studio Projects for an IVI-C Driver discusses each of these projects. When these projects are created and added to the driver solution, Nimbus adds the appropriate build dependencies so that the projects are built in the proper order when the entire driver solution is built.

For example, the unit test project obviously relies upon the driver project, so Nimbus adds to the unit test project a dependency on the driver project. This ensures the driver project is built before the unit test project is built. Similarly, the driver setup project requires the driver and the help project to be built before it can be built, so it has dependencies on both of those projects.

To view the project dependencies

  1. From Solution Explorer, right click on the solution node (not the Nimbus node), and choose Properties.

  2. The Solution Property Pages Dialog appears.

  3. Choose Project Dependencies from the tree view on the left.

  4. Use the Project combo box on the right to view the project dependencies for the various Visual Studio projects in the driver solution.

Building the Driver

Building a complete Nimbus IVI driver requires up to three separate compilation steps. First, the build steps for 32-bit and 64-bit driver builds are separate because Visual Studio can only compile against one platform at a time. Also, the build step for compiling the help file and the driver installer is intentionally separate from the build step for compiling other projects in the driver solution because the help and installer projects are typically built less often than the driver project and the unit test projects. This is why the help and installer projects are unchecked in the x86 and x64 solution configurations.

Important note Important

Before building the driver, it is important to properly setup the Visual Studio solution build configurations. Visual Studio does not provide programmatic access to these settings, so Nimbus is unable to automatically configure them. The topic Required Visual Studio Configuration Changes provides details on what exactly must be done before building.

To perform a complete build of the IVI-C driver:

  1. From the Solution Platforms combo box (typically near the top of the IDE), choose x86.

  2. From the Build menu, select Build Solution.

    This will perform a 32-bit compilation of the driver project, the unit test projects, and any client application projects in the solution.

    For a Debug build, the output files will be placed in the following folder:

    • <solutionFolder>\build\Debug\x86

    For a Release build, the output files will be placed in the following folder:

    • <solutionFolder>\build\Release\x86

  3. From the Solution Platforms combo box, choose x64.

  4. From the Build menu, select Build Solution.

    This will perform a 64-bit compilation of the driver project, the unit test projects, and any client application projects in the solution.

    For a Debug build, the output files will be placed in the following folder:

    • <solutionFolder>\build\Debug\x64

    For a Release build, the output files will be placed in the following folder:

    • <solutionFolder>\build\Release\x64

See Also

Other Resources

Required Visual Studio Configuration Changes


Visual Studio Projects for an IVI-C Driver

Nimbus supplies two custom project types to the Visual Studio project system that enable IVI-C driver development, documentation, and installation.

  • IVI-C Driver Help Project

    This project type is used to build the driver help file(s) for an associated IVI-C driver. Each help project is associated with a single IVI-C driver project, and includes the help template files used to control the look and feel of the driver documentation being produced. A driver help project may be created by the IVI-C Driver Wizard based on your selections, or added to the driver solution later.

  • IVI-C Driver Setup Project

    This project type is used to build the driver installer for an associated IVI-C driver. Each setup project is associated with a single IVI-C driver project, and includes the WiX source files used to produce the driver installer (MSI). A driver setup project may be created by the IVI-C Driver Wizard based on your selections, or added to the driver solution later.

In addition to the above custom project types, Nimbus also supports adding two standard Visual Studio project types to a driver solution.

  • Unit Test Project

    This is a standard Visual Studio project type that enables unit testing of IVI-C drivers. Although Nimbus leverages the standard Visual Studio unit testing framework, the Nimbus driver automatically adds and removes unit test methods from this project as you interact with the Nimbus driver designer.

  • C++ Console Application

    This is a standard Visual Studio project type for building a C++ console application that exercises the IVI-C driver. After adding this type of project to a driver solution, Nimbus performs no further modifications. This provides a convenient way to create a starter application associated with your driver that can be used for additional testing or as sample code.

Nimbus-Managed Files

There are a number of files in a Nimbus driver project that are automatically updated as part of the Nimbus roundtripping logic. For instance, when new functions or attributes are added to a driver, the <prefix>.h file must be updated with the appropriate function definition or macro definition. Nimbus automatically updates this file, so it is important that users never manually make changes to such files. These are referred to as Nimbus-managed files. Most files in an IVI-C driver project are Nimbus-managed files.

Important note Important

Any manual changes made to any Nimbus-managed file will be automatically overwritten by Nimbus whenever the driver project is edited. It is important to never directly edit a Nimbus-managed file.

The following files in an IVI-C driver project are Nimbus-managed files:

  • Attributes.cpp

  • Attributes.h

  • DriverInfo.cpp

  • Enums.h

  • Enums.cpp

  • Errors.cpp

  • Models.cpp

  • RepCaps.h

  • <prefix>.h

  • <prefix>.fp

  • <prefix>.sub

  • <projectName>.def

There are only a two driver files that a driver developer generally needs to edit -- <prefix>.cpp file and the DriverSession.h file. The former contains nearly all of the implementation code for the IVI-C driver's functions and attributes, while the latter is sometimes needed to customize the default implementation Nimbus supplied for certain driver features.

Managing Multiple Drivers in a Solution

In some situations, it may be desirable to manage multiple IVI drivers in a single solution. Since a Nimbus IVI driver project is simply another type of Visual Studio project, this can be supported using standard Visual Studio techniques.

To add a Nimbus driver project to an existing solution

  1. From Solution Explorer, right-click on the Solution node.

  2. Choose Add and then either New Project... or Existing Project....

  3. For a new Nimbus IVI driver project, choose Nimbus Projects from the New Project Wizard and proceed as usual with the New IVI-C Driver Wizard. For an existing Nimbus IVI driver project, browse to the .vcproj file for the desired driver.

  4. The added Nimbus IVI driver project will be loaded into Visual Studio with all of its associated projects -- setup, installer, unit test, etc. A separate Nimbus node with its subnodes will appear in Solution Explorer.


Accessing Driver Settings

Nimbus supplies a number of project-wide settings that are used to control important driver features. These are collectively referred to as the Driver Settings Editor. Note that unlike the per-user options which are applied across driver projects, the Driver Settings Editor pertain only to a specific driver project.

To access the IVI-C driver settings

  1. From Solution Explorer, double-click the Driver Settings Editor node.

  2. A tabbed document window appears with various settings on each tab.

    The remaining topics in this section provide a detailed explanation of the properties available on each tab.

In This Section

General Page, IVI-C Driver Settings

I/O Page, IVI-C Driver Settings

Features Page, IVI-C Driver Settings

Capability Groups Page, IVI-C Driver Settings

Models Page, IVI-C Driver Settings

LXI Page, IVI-C Driver Settings


General Page, IVI-C Driver Settings

Prefix

This setting controls the IVI-C prefix for the driver. This prefix is very important as it controls the name of many items associated with the driver. The driver DLL itself will be named using this prefix. The names of all functions and attributes begin with this prefix. Additionally, the driver install location is governed by the prefix chosen here.

Important note Important

The IVI specifications require that the first two letters of this prefix match the official two-letter abbreviation assigned to the driver vendor by the IVI Foundation in the specification "VPP-9: Instrument Vendor Abbreviations" . If the driver vendor does not have an assigned two-letter prefix, one can be obtained from the IVI Foundation. Visit the IVI Foundation website for details.

Instrument manufacturer

The instrument manufacturer is used to identify the manufacturer of the instrument for which the driver is being written. This entry is used in the IVI Configuration Store registration as well as in the implementation of the INSTRUMENT_MANUFACTURER attribute.

Driver vendor

The driver vendor identifies the company responsible for development and support of the driver. This entry is used in the IVI Configuration Store registration as well as in the implementation of the SPECIFIC_DRIVER_VENDOR attribute.

Description

A description of your driver. This value is used in the implementation of the SPECIFIC_DRIVER_DESCRIPTION attribute.

Copyright

The copyright statement to use for your driver. This value is used in the comments of some source files and in the driver help file.

Version

The 3-digit version number to use for this driver. The value expressed here controls a variety of things, such as the driver DLL version info resource and the driver installer generation. Nimbus will always use a value of 0 for the 4th digit making up the assembly version number.

See Also

Other Resources

General Page, Driver Installer Project Properties


I/O Page, IVI-C Driver Settings

Instrument I/O
Enable VISA-based I/O

This setting controls whether the driver uses the VISA library for instrument communication. When true, Nimbus will link against VISA so that the driver implementation can use any of the standard VISA functions. In addition, Nimbus will automatically open a VISA session upon driver initialization (and close it when the driver's close function is executed. Nimbus will also implement the following functions automatically using standard instrument commands when this setting is true:

  • Disable

  • error_query

  • reset

  • self_test

Integer format

Specifies the default format code to use for integer values in instrument command strings. Explicit format codes used in the instrument command override this setting.

See the topics under Working With Instrument Commands for more information.

Floating-point format

Specifies the default format code to use for floating-point values in instrument command strings. Explicit format codes used in the instrument command override this setting.

See the topics under Working With Instrument Commands for more information.

String format

Specifies the default format code to use for string values in instrument response strings. Explicit format codes used in the instrument command override this setting. This setting is only used for reading values from the instrument -- not for formatting values sent to the instrument.

See the topics under Working With Instrument Commands for more information.

Boolean True

Specifies a comma-separated list of instrument responses that should be interpreted as a boolean true. For instrument commands, the first string in the list will be used to send a boolean true to the device.

Boolean False

Specifies a comma-separated list of instrument responses that should be interpreted as a boolean false. For instrument commands, the first string in the list will be used to send a boolean false to the device.

SCPI compliant

Indicates whether the instrument uses SCPI-compliant instrument commands. Nimbus provides specialized support for SCPI-compliant instruments. See the topic Special Features For SCPI Commands for detailed information.

Enable simulation code generation

Determines whether or not Nimbus ever generates automatic simulation handling code. When true, Nimbus enables the Simulation Editor for attributes so that the developer can choose on an attribute-by-attribute basis whether or not to instruct Nimbus to generate simulation handling code. Nimbus also generates "stub" simulation code blocks for functions so that the developer has a convenient place to insert their manual function simulation code.

When this setting is false, all attributes are set to Manual simulation mode, and the Simulation Editor is disabled. Nimbus also does not generate "stub" simulation code blocks for functions in this case.

This setting is useful in situations where a lower-level software component is handling all of the simulation logic, and the Nimbus driver is simply delegating to that lower-level component. In such cases, it's inconveninet for the developer to explicitly set all attributes to Manual simulation mode and to delete all residual and unneeded simulation code generated for functions and attributes. With this setting, the developer can simply disable simulation code generation "globally".

See Also

Other Resources

Communicating With Instruments
Working With Instrument Commands
Special Features for SCPI Commands


Features Page, IVI-C Driver Settings

Code generation
Automatically generate getter functions for IVI-C attributes

This setting controls whether getter functions are automatically generated when an IVI-C attribute is added to the driver.

Getter function prefix

This setting controls the name of automatically generated IVI-C attribute getter functions. For example, if an attribute named OUTPUT_VOLTAGE is created, and this setting is chosen to be Get, Nimbus will automatically generate an IVI-C getter function named GetOutputVoltage.

The name resulting from selections made here represent the initial name given to the getter function. Individual getter functions can be renamed as desired.

Automatically generate setter functions for IVI-C attributes

This setting controls whether setter functions are automatically generated when an IVI-C attribute is added to the driver.

Setter function prefix

This setting controls the name of automatically generated IVI-C attribute setter functions. For example, if an attribute named OUTPUT_VOLTAGE is created, and this setting is chosen to be Set, Nimbus will automatically generate an IVI-C setter function named SetOutputVoltage.

The name resulting from selections made here represent the initial name given to the setter function. Individual setter functions can be renamed as desired.

Synchronize Code

Use this button to bring up a dialog that allows you to update all getter and setter functions with the current selections made on this page.

See Also

Other Resources

Adding Attribute Getter and Setter Functions


Capability Groups Page, IVI-C Driver Settings

The Group Capabilities page is used to specify which instrument class capability groups a driver supports. All extension groups for an instrument class supported by the driver are listed in the Capability Groups listbox. If the driver does not support an IVI instrument class, the listbox will be empty.

To specify that the driver supports a particular extension group, check the box next to the supported capability group. Nimbus uses the information specified here for the following purposes:

  • The list of supported groups is registered in the IVI Configuration Store.

  • The list of supported groups is used to implement the GROUP_CAPABILITIES attribute.

  • The list of supported groups is used in the generation of the IVI compliance information in the driver help file.

See Also

Other Resources

How IVI Drivers Provide Interchangeability


Models Page, IVI-C Driver Settings

The Models Page is used to define the list of instrument models supported by the driver. Nimbus allows the driver's method and property behavior to vary based on model or family. The topic Adding Support for Multiple Instrument Models explains many of the multi-model Nimbus concepts.

To add a supported instrument model

  1. Right-click a model or family node.

  2. Choose Add Model.

  3. Enter the desired model name.

    Important note Important

    The name chosen here is NOT an arbitrary identifier. This name must exactly match the model string read from the device during initialization, such as the response to the "*IDN?" string. See the topic Adding Support for Multiple Instrument Models for an explanation of how Nimbus determines the connected instrument model.

Nimbus allows a driver to organize its supported list of models into related groups called families. Only a single level of hierarchy is supported -- in other words, you cannot have families of families. Unlike the instrument model names, the instrument family names are not used directly in any externally visible way. They are only used within Nimbus to group and organize models.

To add an instrument family

  1. Right-click an existing family.

  2. Choose Add Family.

  3. Enter the desired family name.

    Note Note

    The name chosen here is treated as an arbitrary identifier as does not need to match any actual identifier read from the instrument.

Nimbus supports the notion of a default model to handle the situation where the driver is operating in simulation mode and thus cannot determine what instrument model to use when executing driver-specific implementation code. The default model is used only for simulated driver sessions and only if no Model parameter is passed to Initialize.

See the topic Adding Support for Multiple Instrument Models for a discussion of the default instrument model.

To specify the default model for simulation

  1. Right-click an existing model.

  2. Choose Make default model.

  3. The selected model is shown in bold font.

See Also

Other Resources

Adding Support for Multiple Instrument Models
Retrieving the Instrument Model


LXI Page, IVI-C Driver Settings

This page allows you to change the level of LXI support offered by your driver. Refer to this page for a complete description of these options.

Note Note

Changing the level of LXI support is a fairly major operation. As a result, you may be prompted to confirm that you wish to proceed before the requested changes are applied to your driver project.

See Also

Other Resources

LXI Compliance, New IVI-C Driver Wizard


Adding Functionality to an IVI-C Driver

One of the principal tasks in creating an IVI-C driver is using the Driver Designer to add functionality, such as functions, attributes and enumerations. IVI-C drivers also often support an instrument class and may include repeated capabilities.

The topics in this section explain how Nimbus is used to added various pieces of driver functionality.

In This Section

Defining New Data Types Inline

Adding a Function

Adding a Parameter

Adding an Attribute

Adding Attribute Getter and Setter Functions

Adding an Enumeration

Adding an Error

Adding a Warning

Adding a Child Branch

Adding a Repeated Capability

Adding Help Information

Adding State Caching to an Attribute

Adding Range Checking and Coercion to an Attribute

Adding Simulation to an Attribute

Adding Support for an Instrument Class

Adding Support for LXI


Defining New Data Types Inline

When adding functions and attributes to a driver, it can be convenient to create the data types needed at the same time the method or property itself is being defined. Nimbus allows enums to be created and defined when entering new parameters, attribute types, or callback function return types. This is simpler than defining an enum ahead of time in one portion of the Driver Designer and then returning to where the desired function or attribute is to be created and using that newly defined enum.

Creating an enum when defining a function or attribute

As an example of creating a new enum when defining an attribute, after executing the Add Attribute command, and while still in edit mode, the following text can be used to create a StartTrigger attribute using a newly created TriggerSource enum. enum.

StartTrigger : new enum TriggerSource

In addition to creating the enum, the enum members can be defined at the same time as the enum, as in the following:

StartTrigger : new enum TriggerSource; Internal = 2, External = 0x15, Software = 47

The above example creates a new TriggerSource enum with three member, each with member numeric values specified.

See the Shorthand section of the Adding an Enumeration topic for details on enum creation shorthand.

Tip Tip

The syntax for creating new enums inline can be used in the driver designer tree view for method return types, parameter types, and property types. It can also be used in the Type text boxes in the item editors for those items.

See Also

Other Resources

Adding an Enumeration


Adding a Function

To add a function to a driver

  1. From Solution Explorer, double-click the Driver Designer node under the Nimbus node.

  2. The IVI-C Driver Designer tree view opens.

  3. Expand the root node and locate and then select the desired branch in the hierarchy where the new function is desired.

  4. Right-click on the selected node and choose Add Function.

  5. A new function is added with a default name and the tree node enters edit mode.

  6. With the function node still in edit mode, type the desired name of the function and hit the Enter key.

    Note Note

    When adding functions to the driver hierarchy, the name chosen is actually the display name of the function. This display name is used in the function panel (.fp) file and in displaying the hierarchy of functions and attributes in the Driver Designer. The actual function name used in the generated driver header file will be created from this display name by removing whitespace and other non-alphanumeric characters.

  7. After the function is added, the IVI-C Function General Editor appears in the right portion of the IVI-C Driver Designer. See the help topic for that Item Editor for details on defining the function further.

  8. Once a function has been added, parameters can be added to the function . See the topic Adding a Parameter for details on adding parameters.

See Also

Other Resources

Adding an Attribute
Adding a Parameter
Adding a Child Branch


Adding a Parameter

To add a parameter to a function

  1. Right-click on the function in the IVI-C Driver Designer tree view and choose Add Parameter.

  2. A new parameter is added with a default name and the tree node enters edit mode. By default the parameter type is ViReal64.

  3. With the parameter node still in edit mode, type the desired name of the parameter followed by a colon (:) followed by the name of the desired type, and hit the Enter key. The colon and type can be excluded if the desired type is ViReal64.

    Any of the following data types may be entered as a parameter type:

    • Boolean

    • String

    • Byte

    • Int16

    • Int32

    • Int64

    • Single

    • Double

    • Any enum defined in the driver.

    • An array of any of the above -- designated by appending opening and closing square brackets ([]) to the type name.

      Example: Enter double[] for an array of double-precision floating-pointer numbers.

    When choosing a parameter name, the following naming rules apply:

    • The name must be unique within its parent function.

    • The name must contain only alphanumeric characters.

    • Spaces are not allowed.

    • The name must begin with a capital letter.

  4. After the parameter is added, the IVI-C Parameter General Editor appears in the right portion of the IVI-C Designer. See the help topic for that Item Editor for details on defining the parameter further.

See Also

Other Resources

Adding a Method
Adding a Property
Understanding Parameter Direction


Adding an Attribute

To add an attribute to a driver

  1. From Solution Explorer, double-click the Driver Designer node under the Nimbus node.

  2. The IVI-C Driver Designer tree view opens.

  3. Expand the root node and locate and then select the desired branch where the new attribute is desired.

  4. Right-click on the selected node and choose Add Attribute.

  5. A new attribute is added with a default name and the tree node enters edit mode. By default the attribute type is Double.

  6. With the attribute node still in edit mode, type the desired name of the property followed by a colon (:) followed by the name of the return type, and hit the Enter key. The colon and type can be excluded if the desired property type is Double.

    Note Note

    When adding attributes to the driver hierarchy, the name chosen is actually the display name of the attribute. This display name is used in the attribute information (.sub) file and in displaying the hierarchy of functions and attributes in the Driver Designer. The actual attribute macro name used in the generated driver header file will be created from this display name by converting whitespace to underscores. All attribute macro names are prefixed by PREFIX_ATTR_, but this portion of the macro name is never displayed in the designer for clarity.

  7. After the attribute is added, the IVI-C Attribute General Editor appears in the right portion of the IVI-C Driver Designer. See the help topic for that Item Editor for details on defining the attribute further.

See Also

Other Resources

Adding a Function
Adding a Child Branch


Adding Attribute Getter and Setter Functions

Using the IVI standard attribute accessor functions to manipulate driver attributes can be cumbersome for users. For example, consider the following code required to get the value of a RESOLUTION_BANDWIDTH attribute:

C++
Copy
auto status = acme4301_SetAttributeViReal64(session, VI_NULL, ACME4301_ATTR_RESOLUTION_BANDWIDTH, 1.5E6);

Not only is the above code tedious, it is error prone. For instance, there is no compile-time verification of the parameters supplied to any of the accessor functions. The user must know from the driver documentation that the RESOLUTION_BANDWIDTH attribute is of type ViReal and that the SetAttributeViReal64 must then be used. Additionally, the user must know that the RESOLUTION_BANDWITH attribute is not associated with any particular repeated capability, and, as such, the value VI_NULL must be supplied for the second parameter to the SetAttributeViReal64 call. If the user makes a mistake, there is no indication at compile time. Only at runtime will the error be revealed.

To provide a much more convenient and less error-prone mechanism for manipulating IVI-C attributes, Nimbus can automatically generate and implement type-safe attribute getter and setter functions that wrap the calls to the attribute accessors, such as the SetAttributeViReal64 call above.

For example, the setter function for the RESOLUTION_BANDWIDTH attribute above would look like the following:

C++
Copy
auto status = acme4301_SetResolutionBandwidth(session, 1.5E6);

The above function is simpler, type safe, clearer to read, and much easier for the user to type. In editors such as the Visual Studio code editor, which offers IntelliSense support when typing, the attribute setter above is far easier to type, as the user can simply begin typing resolu and the SetResolutionBandwith function (as well as the corresponding GetResolutionBandwith function) will appear in the completion list. In contrast, the attribute accessors, such as SetAttributeViReal64 require the user to type enough text to bring up the SetAttributeViReal64 suggestion, and then they must continue typing until the third parameter and attempt to get IntelliSense to suggestion a value for the attribute ID (ACME4301_ATTR_RESOLUTION_BANDWIDTH).

How to Add Attribute Getter and Setter Functions

Attribute getter and setter functions are automatically generated when the applicable options are enabled on the Features Page of the Driver Settings Editor. There, getter function generation and setter function generation can be enabled and configured separately. Function generation can be enabled or disabled at any point in driver development, and the desired prefix for the getter and setter functions can also be changed at any time.

Nimbus automatically implements the attribute getter and setter functions by delegating to the appropriate attribute accessor (e.g. SetAttributeViReal64. The getter and setter function signatures are also completely managed by Nimbus. For instance, when a parameter is added or removed or a parameter data type or direction is changed, the associated IVI-C getter and setter functions are updated appropriately. The same holds true for attributes that are associated with a repeated capability -- Nimbus will add or remove a repeated capability selector parameter to the attribute getter and setter functions as appropriate for the attribute in question.

In addition to controlling getter and setter function generation at the project level, Nimbus allows control on a per-attribute basis. Individual getter and setter functions can simply be deleted in the normal fashion. To restore a deleted getter or setter function, simply right-click on the attribute in question, and execute the Create Getter Funtion command or the Create Setter Function command, as appropriate.

Individual getter and setter functions can also be renamed if it is desirable in certain cases to deviate from the name created automatically based on the project-level selections on the Features Page of the Driver Settings Editor.

To make bulk changes to the getter and setter functions across the driver, use the Synchronize Code button on the Features Page of the Driver Settings Editor. Based on the selections made in the resulting dialog, getter and setter functions will be added, removed, and renamed as desired.

See Also

Other Resources

Features Page, IVI-C Driver Settings


Adding an Enumeration

IVI-C drivers do not explicitly support the enum data type, as do IVI-COM and IVI.NET drivers. Enumerated types are not allowed in IVI-C driver APIs. However, IVI-C drivers support sets of defined values which can very accurately be though of as enums. These defined numeric values are simply #define macros exported in the IVI-C driver's header file. They share the characteristics of enums in that they represent a set of related values, any one of which is a valid attribute or parameter value. This means that each defined value must be unique within its related set of defined values. Additionally, enumerated values can be very conveniently mapped to instrument command strings when working with message-based devices. For these reasons, Nimbus models these sets of related defined values as enums when working within the Nimbus user interface.

To add an enum to a driver

  1. From Solution Explorer, double-click the Driver Designer node under the Nimbus node.

  2. The IVI-C Driver Designer tree view opens.

  3. Right-click on the Enums node and select Add Enum.

  4. A new enum is added with a default name and the tree node enters edit mode.

  5. With the enum node still in edit mode, type the desired name of the enum and hit the Enter key.

    Note Note

    Since there are no enum data types in IVI-C drivers, no code is actually added to the driver as a result of adding an enum. Only when enum members are added will Nimbus generate #define macros for the enum member values.

  6. After the enum is added, the Enum General Editor appears in the right portion of the IVI-C Driver Designer.

Tip Tip

Use the Info Panel in the lower portion of the IVI-C Driver Designer to view and navigate to functions and attribute that use the enum.

To add an enum member to an enum

  1. Locate the enum to be modified under the Enums node in the IVI-C Driver Designer

  2. Right click on the enum name and select Add Enum Member.

  3. A new enum member is added with a default name and the tree node enters edit mode.

  4. With the enum member node still in edit mode, type the desired name of the enum member and hit the Enter key.

    When choosing an enum member name, the following naming rules apply:

    • The member name must be unique within the enum being modified.

    • The name must contain only alphanumeric characters, and must start with an alphabetic character.

    • Spaces are not allowed.

    Tip Tip

    The enum member value can be entered in either hexadecimal or decimal format. It will be converted to the format configured for that enum. Right-click on the parent enum to see a context menu which enables or disables hexadecimal display mode.

  5. After the enum member is added, the Enum Member Editor appears in the right portion of the IVI-C Driver Designer.

Shorthand notation for defining enums

Nimbus supports a convenient shorthand notation for defining enums. The enum and its members can be defined all at once when the enum is initially added.

After executing the Add Enum command, and while still in edit mode, the following text can be used to define a TriggerSource enum with members Internal, External, and Software.

TriggerSource; Internal, External, Software

In the above, the enum name TriggerSource is specified first, followed by a semicolon to delineate it from the enum member specifications. Enum members follow and are separated by commas.

This shorthand notation can also be used to define the enum member values, as in the following:

TriggerSource; Internal = 2, External = 0x15, Software = 47

Note that when assigning enum member values, either hex format or decimal format may be used.

Once an enum is defined, additional enum members can be added using this same shorthand notation, except that the enum name is excluded. After executing the Add Enum Member command, and while still in edit mode, the following text can be used to add a series of TTL trigger source lines to the existing TriggerSource enum from the above example:

TTL0, TTL1 = 5, TTL2 = 6, TTL3, TTL4, TTL5 = 0x14, TTL6, TTL7


Adding an Error

Defining custom errors in an IVI-C driver allows you to return a proper ViStatus return code and a properly formatted error message that can be displayed retrieved by the user via the GetError function. Internally, the errors and warnings defined for a particular IVI-C driver are managed #define macros that begin with PREFIX_ERROR_ or PREFIX_WARN_. Nimbus manages a mapping of error codes to error messages in the Errors.cpp file in the driver project. This map is used to retrieve the error message string and associate it with the driver session when the ReportError or ReportErrorEx utility functions are used in the driver implementation.

To add an error to an IVI-C driver

  1. From Solution Explorer, double-click the Driver Designer node under the Nimbus node.

  2. The Driver Designer opens as a tabbed document window. Select the IVI-C tab.

  3. Right-click on the Errors node and choose Add Error.

  4. A new error is added with a default name and the tree node enters edit mode.

  5. With the error node still in edit mode, type the desired name of the error and hit the Enter key.

    Note Note

    By convention, error names start with PREFIX_ERROR_. However, when typing an error name in the tree view a shortened form of the name can be used. The PREFIX_ERROR_ prefix prefix can be excluded. For example, if the desired error is PREFIX_ERROR_BAD_SWEEP, then type only BAD_SWEEP and the full error name will be expanded when the Enter key is pressed.

    When choosing an error name, the following naming rules apply:

    • The name must be unique within the driver.

    • The name must contain only alphanumeric characters and the underscore (_) character.

    • Spaces are not allowed.

    • The name must be uppercase.

  6. After the error is added, the IVI-C Error General Editor appears in the right portion of the IVI-C Designer. See the help topic for that Item Editor for details on defining the error further.

See Also

Other Resources

Adding a Warning
Returning Errors from IVI-COM Drivers


Adding a Warning

Defining custom warnings in an IVI-C driver allows you to return a proper ViStatus return code and a properly formatted error message that can be displayed retrieved by the user via the GetError function. Internally, the errors and warnings defined for a particular IVI-C driver are managed #define macros that begin with PREFIX_ERROR_ or PREFIX_WARN_. Nimbus manages a mapping of error codes to error messages in the Errors.cpp file in the driver project. This map is used to retrieve the error message string and associate it with the driver session when the ReportError or ReportErrorEx utility functions are used in the driver implementation.

To add a warning to an IVI-C driver

  1. From Solution Explorer, double-click the Driver Designer node under the Nimbus node.

  2. The Driver Designer opens as a tabbed document window. Select the IVI-C tab.

  3. Right-click on the Warnings node and choose Add Warning.

  4. A new warning is added with a default name and the tree node enters edit mode.

  5. With the warning node still in edit mode, type the desired name of the warning and hit the Enter key.

    Note Note

    By convention, warning names start with PREFIX_WARN_. However, when typing a warning name in the tree view a shortened form of the name can be used. The PREFIX_WARN_ prefix prefix can be excluded. For example, if the desired warning is PREFIX_WARN_SWEEP_BUSY, then type only SWEEP_BUSY and the full warning name will be expanded when the Enter key is pressed.

    When choosing a warning name, the following naming rules apply:

    • The name must be unique within the driver.

    • The name must contain only alphanumeric characters and the underscore (_) character.

    • Spaces are not allowed.

    • The name must be uppercase.

  6. After the warning is added, the IVI-C Warning General Editor appears in the right portion of the IVI-C Designer. See the help topic for that Item Editor for details on defining the warning further.

See Also

Other Resources

Adding an Error
Returning Errors from IVI-COM Drivers


Adding a Child Branch

IVI-C drivers are arranged in a hierarchy of functions and attributes by managing two special files defined by the IVI specifications -- the function panel file (<prefix>.fp) and the attribute information file (<prefix>.sub). The exported functions and #define macros (for attributes) in the <prefix>.h file are simply a flat list from the client programmer's perspective. But, these .fp and .sub files are understood by various ADEs and can greatly simplify working with IVI-C driver APIs.

Nimbus uses the term branch to refer to a level of hierarchy an IVI-C driver.

To add a child branch to a driver

  1. From Solution Explorer, double-click the Driver Designer node under the Nimbus node.

  2. The IVI-C Driver Designer tree view opens.

  3. Expand the root node.

  4. Right-click on the desired location within the hierarchy and choose Add Child Branch. You can add a new child branch directly below the root node or at any level in the hierarchy.

  5. A new branch node is added with a default name and the tree node enters edit mode. Type the desired name for the branch and hit the Enter key.

See Also

Other Resources

Adding a Function
Adding an Attribute


Adding a Repeated Capability

Repeated capabilities allow the driver to expose duplicate functionality in an instrument using IVI-defined functions and conventions. For instance, a single set of methods and properties can be defined for operating on a series of channels in an oscillscope. IVI terms this duplicate functionality a repeated capability.

For a complete discussion of repeated capabilities, see the IVI Backgrounder topic entitled Repeated Capabilities.

Nimbus provides two ways to initiate the process of adding a new repeated capability to a driver, each of which is described in detail below.

To add a repeated capability to the main driver interface

  1. From Solution Explorer, expand the Nimbus node.

  2. Right-click on the Repeated Capabilities node.

  3. Choose Add Repeated Capability...

  4. The Add Repeated Capability Wizard appears.

  5. Follow the steps outlined below for using the Add Repeated Capability Wizard.

The remaining topics in this section discuss each wizard page separately.

Tip Tip

After adding a repeated capability using the Wizard, you can bring up the Repeated Capabilities Editor by double-clicking the Driver Settings Editor in Solution Explorer and choosing the Repeated Capabilities tab. The Repeated Capabilities Editor allows you to view and edit characteristics of all driver repeated capabilities, such as the physical names defined for each repeated capability.

In This Section

Add Repeated Capability Dialog

See Also

Other Resources

Repeated Capabilities


Add Repeated Capability Dialog

For a complete discussion of repeated capabilities, see the IVI Backgrounder topic entitled Repeated Capabilities.

Name

Specifies the repeated capability name. This name serves as a unique identifier for the repeated capability. The name chosen here is registered by the driver installer in the IVI Configuration Store.

Parent

Repeated capabilities can be nested. For instance, an instrument may have multiple channels where each channel has multiple traces. This would be modeled in an IVI driver by creating a Channel repeated capability and then creating a Trace repeated capability with its parent set to be the Channel repeated capability.

For IVI-C drivers, only parameter-style repeated capabilities can be nested -- selector-style repeated capabilities cannot be nested, as per the IVI specifications. Thus, the Parent repeated capability combo box is disabled when the Style is set to Selector.

Style

The type of repeated capability to be added to the driver.

Parameter-style should almost always be the style chosen for IVI-C drivers. Selector-style is for special circumstances that typically do not occur in instrument-specific driver APIs.

A discussion of the three types of IVI repeated capabilities can be found in the topic Repeated Capabilities.

Dynamic

Indicates if the driver supports dynamic repeated capability names. Dynamic repeated capabilities allow the driver to decide at runtime what repeated capability names the driver supports, often based on information it reads from the instrument during the driver's initialization sequence.

If checked, an override of the function GetDynamicRepCapNames(String, IListString) must be manually added to the appropriate class in the driver project. See the topic Implementing Dynamic Repeated Capabilities for detailed information on using this function.

Physical names list

Use the Add, Remove, and Edit buttons to manage the list of physical names to associate with the repeated capability. The names entered here represent the static repeated capability instances -- that is, they will be available irrespective of what is discovered about the connected instrument at runtime. The names added here will be registered with the IVI Configuration Store by the driver installer.

Tip Tip

Use '-' to specify a range of physical names. For example, entering Channel(1-3) is equivalent to creating three separate entries: Channel1, Channel2, and Channel3. The range must follow the base name and be enclosed in parentheses. The beginning value in the range must be smaller than the end value.

Tip Tip

To modify the list of physical names after running the wizard, double-click the Driver Settings Editor node in Solution Explorer and choose the Repeated Capabilities tab from Driver Settings Editor, editor that appears.

See Also

Other Resources

Repeated Capabilities


Adding Help Information

Most of the items in an IVI-C driver (functions, attributes, parameters, etc.) have help information associated with them. The help content is used to generate HTML help files as well as other help-based artifacts, such as the function panel file (.fp) and attribute information file (.sub). The topics under Creating a Driver Help File provide detailed information on how driver help content is used.

Irrespective of where Nimbus uses the help information for an item, the content for each item is managed from a single location -- the Help Editor.

To add help information to an item

  1. From Solution Explorer, double-click the Driver Designer node under the Nimbus node.

  2. The IVI-C Driver Designer tree view opens.

  3. Expand the root node, which will be named after the driver assembly (e.g.: Acme.Acme4321).

  4. Expand the root node and locate the desired item beneath the main Hierarchy node, the Enums node, or any of the other nodes corresponding to entities defined within the driver.

  5. Select the desired item in the tree view.

  6. On the right-side of the IVI-C Driver Designer, click the Help tab along the lower section of the designer.

    Note Note

    The Help tab will only be enabled if there is a help project in the active solution that is associated with the driver being modified. If the Help tab is disabled, simply add a new help project to the solution and then return to the IVI.NET Driver Designer in order to enter the desired help information.

  7. The Help Editor appears. Select the desired tab (Summary, Remarks, etc.) and enter the desired help information. See the Help Editor topic for details.

See Also

Other Resources

Using the Nimbus Driver Designer
Creating a Driver Help File


Adding State Caching to an Attribute

To add state caching to an attribute

  1. From Solution Explorer, double-click the Driver Designer node under the Nimbus node.

  2. The IVI-C Driver Designer tree view opens.

  3. Select the attribute of interest.

  4. On the right-side of the IVI-C Driver Designer, click the State Caching button along the lower section of the designer.

  5. The State Caching Editor appears. See the State Caching Editor topic for details.

    Important note Important

    Refer to the Understanding State Caching help topic for important details on state caching in Nimbus.

See Also

Other Resources

What All IVI Drivers Do -- Inherent Capabilities
Understanding State Caching


Adding Range Checking and Coercion to an Attribute

To add range checking to an attribute

  1. From Solution Explorer, double-click the Driver Designer node under the Nimbus node.

  2. The IVI-C Driver Designer tree view opens.

  3. Locate and then select the desired property from the tree view.

  4. On the right-side of the IVI-C Driver Designer, click the Range Checking tab along the lower section of the designer.

  5. The Range Checking Editor appears. See the Range Checking Editor topic for details.

See Also

Other Resources

What All IVI Drivers Do -- Inherent Capabilities


Adding Simulation to an Attribute

To add simulation to an attribute

  1. From Solution Explorer, double-click the Driver Designer node under the Nimbus node.

  2. The IVI-C Driver Designer tree view opens.

  3. Locate and then select the desired attribute from the tree view.

  4. On the right-side of the IVI-C Driver Designer, click the Simulation button along the lower section of the designer.

  5. The Simulation Editor appears. See the Simulation Editor topic for details.

See Also

Other Resources

What All IVI Drivers Do -- Inherent Capabilities


Adding Support for an Instrument Class

To add support for an instrument class

  1. From Solution Explorer, right-click the Instrument Classes node under the Nimbus node and choose Add Instrument Class...

  2. The Add Instrument Class Wizard appears.

  3. When the wizard is completed, the functions and attributes defined in the instrument class will appear in the IVI-C Driver Designer tree view. In addition, Nimbus performs a variety of tasks to add support for the selected instrument classes:

    • Any repeated capabilities defined by the instrument class are added to the driver and any supporting functions, attributes, enums, errors and warnings are added to the driver hierarchy.

    • Implementation code for the functions and attributes defined on the instrument class are added to the driver project.

    • Unit test code for exercising the instrument class functions and attributes is added to the unit test project.

    • The driver installer is updated to register the driver with the IVI Configuration Store as supporting the selected instrument class.

Important note Important

By default, all of the class capability groups defined by a selected instrument class are marked as being supported by the driver. After adding an instrument class to the driver, it is important to visit the Capability Groups Page of the Driver Settings Editor to select the appropriate capability groups.

The remaining topics in this section discuss each wizard page separately.

In This Section

General Page, Add Instrument Class Wizard

Excluding Functions and Attributes from an Instrument Class

See Also

Other Resources

How IVI Drivers Provide Interchangeability
Repeated Capabilities


General Page, Add Instrument Class Wizard

The General Page of the Add Instrument Class Wizard allows you to select which instrument class will be supported by the driver. Nimbus performs a number of roundtripping operations based upon the selected instrument class.

Important note Important

By default, all of the class capability groups defined by a selected instrument class are marked as being supported by the driver. After adding an instrument class to the driver, it is important to visit the Capability Groups Page of the Driver Settings Editor to select the appropriate capability groups.

Select an instrument class

List of installed instrument classes that are available to be implemented by the driver. This list appearing here corresponds to the set of instrument class project files (.iviproj) installed in the NimbusInstallDir\IviInstrumentClasses folder.

See Also

Other Resources

How IVI Drivers Provide Interchangeability


Excluding Functions and Attributes from an Instrument Class

With IVI-C drivers, functions and attributes defined in the instrument class but not supported by the instrument should not be exposed from the driver at all. Nimbus supplies a special command to exclude specific IVI-defined functions and attributes from an IVI-C driver. This prevents the function or attribute definition from appearing in the header file or from being exported from the driver DLL.

To exclude a class-compliant function or attribute from the IVI-C driver

  1. From Solution Explorer, double-click the Driver Designer node.

  2. The IVI-C Designer opens as a tabbed document window.

  3. Locate the IVI-defined function or attribute that you with to exclude. Note that IVI-defined items appear with greyed text in the tree views, indicating that their definition cannot be modified.

  4. Right-click on the function or attribute and choose Exclude from IVI-C Driver. The node now appears with a strikethrough.

    Nimbus will remove the implementation code for the function or attribute. It will also remove the function or attribute from the IVI-C driver header file (.h), import library (.lib), main DLL (.dll), function panel (.fp), and attribute information file (.sub).

    Caution note Caution

    When you exclude an IVI-C function or attribute, Nimbus will automatically delete the implementation code. Be sure no code of interest remains before executing this command.

  5. To restore an IVI-C function or attribute that has been excluded, right-click the item and choose Include in IVI-C Driver.


Adding Support for LXI

The level of LXI compliance supported by the driver can be changed at any stage of development. Nimbus performs a number of roundtripping operations based upon the specific level of LXI compliance chosen. For example, changing the conformance from None to LXI Core 2016 and adding support for LXI Event Messaging adds several repeated capabilities to the driver as well as a host of functions and attributes. Correspondingly, decreasing the level of compliance will cause Nimbus to remove code from the project.

Caution note Caution

When decreasing the level of LXI compliance, Nimbus removes implementation and test code from the project. It is important to ensure that no code of interest exists in the LXI-related implementation and test files before changing the driver to support a lower level of LXI compliance.

To adjust the LXI support level

  1. From Solution Explorer, double-click the Driver Settings Editor node to bring up the Driver Settings Editor.

  2. Click on the LXI tab of the Driver Settings Editor that is displayed.

    This page allows you to change the level of LXI support offered by your driver. Refer to this page for a complete description of these options.

    Note Note

    Changing the level of LXI support is a fairly major operation. As a result, you may be prompted to confirm that you wish to proceed before the requested changes are applied to your driver project.

See Also

Other Resources

LXI Page, IVI-C Driver Settings


Adding Callback Functions

The IVI specifications define a mechanism for a driver to invoke a function on client code in response to some event within the driver. Such a function is referred to as a callback function. Unlike other functions created with the Nimbus Driver Designer, callback functions are implemented by the client. The driver only provides the function signature in the driver header file and the client must take care to implement the callback function using that exact signature.

Adding a callback function to a driver results in code such as the following being added to the driver's header file:

C++
Copy
/*- Callback Functions */

#ifdef IVI_INSTR_CALLBACKS

typedef ViBoolean (_VI_FUNCH * acme_ReadHandler) (ViReal64 Data[]);

ViStatus _VI_FUNC acme_ReadWaveformData(ViSession Vi, acme_ReadHandler Handler);

#endif

In the above code, the typedef specifies a callback function that accepts an array of ViReal64 as an input parameter and returns a ViBoolean.

The ReadWaveformData function above accepts a ReadHandler callback as an input parameter. The semantics of how and when the driver invokes the client's callback function is completely driver defined, as is the thread on which the client may receive the callback.

To add a callback function

  1. From Solution Explorer, double-click the Driver Designer node under the Nimbus node.

  2. The IVI-C Driver Designer tree view opens.

  3. Right-click on the Callbacks node and select Add Callback Function.

  4. A new callback function is added with a default name and a void return type, and the tree node enters edit mode.

  5. With the callback function node still in edit mode, type the desired name and return type of the callback function and hit the Enter key.

    Note Note

    Unlike normal IVI-C driver functions which must always return ViStatus, callback functions can be defined to return any IVI-C data type (other than another callback function).

  6. After the callback function is added, the IVI-C Callback Function General Editor appears in the right portion of the IVI-C Driver Designer. See the help topic for that Item Editor for details on defining the function further.

  7. Once a function has been added, parameters can be added to the callback function in the same fashion as normal IVI-C driver functions. Notably, callback functions cannot have parameters that are themselves callback functions.


IVI-C Item Editors

When the IVI-C Designer is open, a tree view of the driver methods, properties, and enums appears on the left, while a set of tabbed controls for the selected tree view item appears on the right. As the tree view selection changes, these controls are updated with the details of the selected item. Developers manipulate the selected item by working with these controls. Such an arrangement is often referred to in user interface design as a master-details view. Nimbus uses the term Item Editor to refer to the various tabbed controls available when workign with the IVI-C Designer tree view.

The topics in this section explain each of the IVI-C Item Editors in detail.

In This Section

Function General Editor

Function Parameter General Editor

Callback Function General Editor

Attribute General Editor

Enum Editor

Enum Member Editor

Error Editor

Warning Editor

See Also

Other Resources

Managing IVI-C Driver Functionality
Linking IVI-COM and IVI-C Methods and Properties


Function General Editor

Name

Name of the function. Function names must start with a capital letter and can contain only alphanumeric characters.

Return type

Return type of the function.

If an array is desired, append opening and closing square brakets ([]) to the type name. For example, to have the method return an array of double, enter Double[].

Tip Tip

The following syntax can be used in the Return type text box to create a new enum type and use that enum as the return type all in one operation:

new enum TriggerSource; Internal = 2, External = 0x15, Software = 47

See the topic Defining New Data Types Inline for more information on this feature.

Display

Display name that will be used to identify the function in the function tree.

Repeated capability

The repeated capability with which the function is associated.

Implementation

Choosing the Instrument command option instructs Nimbus to automatically generate all of the implementation code needed to send the specified command and to read a response if the Response text box is non-empty. Nimbus generates calls to standard VISA functions, such as viPrintf, viScanf, and viQueryf to send instrument commands and to receive instrument responses.

Choosing the Manual option requires the driver developer to provide the method implementation. This choice is often used for functions that rely upon non-message-based device communications, such as register-based devices or drivers that rely upon a support DLL.

Choosing the Manual with instrument command option is the same as Manual except that the Command and Response textboxes are enabled and used to populate the Instrument Command section of the driver help page for the function. This is useful for functions that require manual implementation but that ultimately rely upon an instrument command in their manually added code.

Important note Important

See the topic Fundamentals of Function and Attribute Implementation to understand how these options affect code generation and roundtripping.

Command

Specifies the command to send to the device. Nimbus supports a rich command and response formatting syntax, which can include the parameters, repeated capabilities, and more. Please see the topic Working With Instrument Commands for a detailed discussion of automatic command formatting.

Response

Specifies the format of the response to read back from the device. Nimbus supports a rich command formatting syntax, which can include the parameters, repeated capabilities, and more. Please see the topic Working With Instrument Commands for a detailed discussion of automatic command formatting.

If no response is specified, Nimbus will only send the command specified in the Command text box -- no response will be read from the device.

Use auto-generated preamble

For manual method implementations, Nimbus can be instructed to still generate pre-processing code for features such as parameter validation, state-caching, and range-checking. If unchecked, Nimbus will not generate any pre-processing code and the driver developer must supply all function logic.

Caution note Caution

It is recommended that this option remain checked. Many Nimbus features can be "short-circuited" if the standard Nimbus preamble code is not generated. This option is intended for advanced scenarios.

See Also

Other Resources

Defining New Data Types Inline


Function State Caching Editor

Nimbus allows state caching to be enabled on a attribute-by-attribute basis. The Function State Caching Editor allows the driver developer to specify cache couplings. See the topic Understanding State Caching for more information.

Attributes invalidated when this function executes

This list contains the names of any cached attributes that will be invalidated whenever this function is invoked. Invoking this function will cause any previously cached values corresponding to the specified attributes to be discarded.

To add an attribute to the invalidation list

  1. Click in the first available entry of the list.

  2. Enter an attribute name, without the driver PREFIX_ATTR_ portion. For example, for an attribute with a full attribute ID of ACME4321_ATTR_TRIGGER_SOURCE, only the string TRIGGER_SOURCE would be entered here.

  3. Press the enter key.

To remove an attribute from the invalidation list

  1. Click on the row selector to the left of a attribute name.

  2. Press the delete key.

See Also

Other Resources

Adding Functionality to an IVI-C Driver
Understanding State Caching


Function Parameter General Editor

Name

Name of the parameter. Parameter names must start with a capital letter and can contain only alphanumeric characters.

Type

Data type of the parameter.

If an array is desired, append opening and closing square brakets ([]) to the type name. For example, to specify an array of ViReal64, enter ViReal64[].

Tip Tip

The following syntax can be used in the Type text box to create a new enum type and use that enum as the type all in one operation:

new enum TriggerSource; Internal = 2, External = 0x15, Software = 47

See the topic Defining New Data Types Inline for more information on this feature.

Direction

Choose the Input to specify an input parameter.

Choose the Output to specify an output parameter.

Choose the Input/Output to specify an output parameter.

Buffer size

The buffer size combo box will only appear for array parameters and for string output parameters. Use this control to select which parameter indicates the number of array elements (or string characters) allocated by the caller. Only Int32 and Int64 parameters may be used as the buffer size parameter.

Actual size

The actual size combo box will only appear for array output parameters. Use this control to select which parameter indicates the number of array elements returned by the driver to the caller. Only Int32 and Int64 parameters may be used as the actual size parameter.

Tip Tip

For functions with more than one array parameter, each with the same number of elements, it is convenient to have all of the array parameters share a single buffer size parameter and a single actual size parameter. Nimbus initially creates separate buffer size and actual size parameters for each array parameter. Consolidate these by first visiting each array parameter and changing the Buffer size and Actual size combo boxes and then deleting the extra buffer size and actual size parameters. Note that you will not be able to delete a parameter if it is used by an array or string as a buffer size or actual size. Finally, order the parameters such that the shared buffer size parameter appears immediately before the first array parameter, then the array parameters, then the shared actual size parameter.

See Also

Other Resources

Defining New Data Types Inline


Callback Function General Editor

Name

Name of the function. Callback function names must start with a capital letter and can contain only alphanumeric characters.

Return type

Return type of the function. Unlike normal IVI-C functions, callback functions can have return types other than ViStatus.

If an array is desired, append opening and closing square brakets ([]) to the type name. For example, to have the method return an array of double, enter Double[].

Tip Tip

The following syntax can be used in the Return type text box to create a new enum type and use that enum as the return type all in one operation:

new enum TriggerSource; Internal = 2, External = 0x15, Software = 47

See the topic Defining New Data Types Inline for more information on this feature.

See Also

Other Resources

Defining New Data Types Inline


Attribute General Editor

Name

Name of the attribute. This name corresponds to the IVI-C macro name used in the <prefix>.h #define statement, except that the driver prefix and ATTR are excluded. Attribute names consist only of capital letters, numbers, and the underscore character and must start with a capital letter.

Type

Data type of the attribute.

Note Note

As per the IVI specifications, array-type properties are not permitted. If you need to read or write an array, then use explicit "Get" and "Set" methods.

Tip Tip

The following syntax can be used in the Type text box to create a new enum type and use that enum as the type all in one operation:

new enum TriggerSource; Internal = 2, External = 0x15, Software = 47

See the topic Defining New Data Types Inline for more information on this feature.

Display

Display name that will be used to identify the attribute in the function tree.

Access

Indicates if the attribute is read-write, read-only, or write-only

ID

The numeric value of the attribute macro used in the <prefix>.h #define statement. Note that IVI prescribes the base attribute value, so only the offset is editable.

Repeated capability

The repeated capability with which the function is associated.

Implementation

Choosing the Instrument command option instructs Nimbus to automatically generate all of the implementation code needed to send the specified command and to read a response if the Response text box is non-empty. Nimbus generates calls to standard VISA functions, such as viPrintf, viScanf, and viQueryf to send instrument commands and to receive instrument responses.

Choosing the Manual option requires the driver developer to provide the method implementation. This choice is often used for attributes that rely upon non-message-based device communications, such as register-based devices or drivers that rely upon a support DLL.

Choosing the Manual with instrument command option is the same as Manual except that the command and response textboxes are enabled and used to populate the Instrument Command section of the driver help page for the attribute. This is useful for attributes that require manual implementation but that ultimately rely upon an instrument command in their manually added code.

Important note Important

See the topic Fundamentals of Function and Attribute Implementation to understand how these options affect code generation and roundtripping.

Setter command

Specifies the command to send to the device when the value of the attribute is set (i.e. the attribute setter executes). This control is not enabled for read-only attributes. Nimbus supports a rich command and response formatting syntax. Please see the topic Working With Instrument Commands for a detailed discussion of automatic command formatting.

Getter command

Specifies the query to send to the device when the value of the attribute value is read (i.e. the attribute getter executes). This control is not enabled for write-only attributes. Nimbus supports a rich command and response formatting syntax. Please see the topic Working With Instrument Commands for a detailed discussion of automatic command formatting.

Getter response

Specifies the format of the response to read back from the device when the property value is read. This control is not enabled for write-only attributes.

Use auto-generated preamble

For manual attribute implementations, Nimbus can be instructed to still generate pre-processing code for features such as parameter validation, state-caching, and range-checking. If unchecked, Nimbus will not generate any pre-processing code and the driver developer must supply all function logic.

Caution note Caution

It is recommended that this option remain checked. Many Nimbus features can be "short-circuited" if the standard Nimbus preamble code is not generated. This option is intended for advanced scenarios.

See Also

Other Resources

Defining New Data Types Inline


Attribute Simulation Editor

Nimbus offers two different styles of automatic simulation support -- returning a fixed value for the attribute and returning the last value to which the attribute was set.

Important note Important

The simulation logic for either option is only executed when simulation is enabled by the end user. This can be done by passing Simulate=VI_TRUE as part of the OptionString parameter to the driver's InitWithOptions function, or it can be done after driver initialization via the SIMULATE attribute.

Manual

Specifies that no automatic simulated value should be returned for the attribute. Selecting this option indicates that the driver developer will manually implement simulation logic in the attribute implementation.

Fixed value

Instructs Nimbus to simply return the value specified in the Value text box when the attribute is read in simulation mode. Setting the attribute to a different value has no effect on the driver behavior.

Last Value Set

Specifies that the driver should cache the value of the attribute when it is set and return the most recent value set when the attribute is read. If the attribute is read without having been set, then the value specified in the Default text box is returned.

Model-Specific Programming with the Models Window

The Attribute Simulation Editor contains a collapsible Models Window in the right portion of the editor. This window is used to customize simulation settings on a per-model or per-family basis.

Note Note

The Models Window cannot be used to define new models for the driver. The list of models supported by the driver is specified on the Models Page of the Driver Settings Editor.

The root node of the Models Window is labeled "All Models". This node can be thought of as the "default behavior" for the property. By default, all instrument models share the same simulation settings. Thus, the editor controls are initially only enabled when "All Models" is selected in the Models Window. This changes when model-specific behavior is specified, as explained below.

When simulation behavior on a per-model or per-family basis, Nimbus generates code that will use different simulated values based upon the actual model detected at runtime. See the discussion of the GetIdentificationInfo function to understand how Nimbus determines the connected model at runtime.

The only simulation settings that can be customized on a per-model basis are the constant returned when the Fixed Value option is chosen and the default value used when the Last Value Set option is chosen. The simulation style (manual, last value set, fixed) must be the same for all models.

To customize the simulation settings for a model

  1. From the Models Window, right-click on the desired model or family.

  2. Choose Customize settings

  3. The Value text boxes or the Default text box is enabled for the selected model, allowing a model-specific value to be set. The model appears in bold font for the customized model.

    Note that if a family was selected, all models in the family appear in bold font, indicating that they will all the same simulation values.

  4. To have an attribute return to using the simulation settings, right-click the model and choose Remove custom settings. The model appears in normal font and the editor controls are once again disabled when the model is selected, indicating that the model is controlled via the default settings specified when the "All Models" node is selected.

See Also

Other Resources

Adding Functionality to an IVI-C Driver


Attribute Range Checking Editor

Nimbus offers two different styles of automatic range checking -- validation against a continous range of values, or checking against a list of discrete values. In both cases, Nimbus generates code that raises the proper IVI-defined error code and error message if the range check condition fails.

Important note Important

The range-checking logic for any option is only executed when range-checking is enabled by the end user. This can be done by passing RangeCheck=VI_TRUE as part of the OptionString parameter to the driver's InitWithOptions function, or it can be done after driver initialization via the RANGE_CHECK property.

None

Specifies that no automatic range checking should be performed on the attribute.

Continuous range

Enables range checking for the selected attribute against a continuous range of values between the specified Minimum and Maximum. The two Inclusive check boxes are used to specify if the Minimum and Maximum values are included in the list of valid values for the attribute.

Discrete values

Enables range checking for the selected attribute against a discrete set of values specifed as a comma-separated list.

Using this option also enables coercion of the attribute value. If the attribute value falls between two values in the list of Allowed values, then the Coercion combo box indicates whether the attribute value should rounded to the next higher value in the list (coerce Up), to the next lower value in the list (coerce Down), or should generate an error (coercion set to None).

Model-Specific Programming with the Models Window

The Attribute Range Checking Editor contains a collapsible Models Window in the right portion of the editor. This window is used to customize range-checking settings on a per-model or per-family basis.

Note Note

The Models Window cannot be used to define new models for the driver. The list of models supported by the driver is specified on the Models Page of the Driver Settings Editor.

The root node of the Models Window is labeled "All Models". This node can be thought of as the "default behavior" for the attribute. By default, all instrument models share the same range-checking settings. Thus, the editor controls are initially only enabled when "All Models" is selected in the Models Window. This changes when model-specific behavior is specified, as explained below.

When customizing range-checking behavior on a per-model or per-family basis, Nimbus generates code that will use different allowed values based upon the actual model detected at runtime. See the discussion of the GetIdentificationInfo function to understand how Nimbus determines the connected model at runtime.

The only range checking settings that can be customized on a per-model basis are the Minimum and Maximum values for continuous range checking and the Allowed values list for discrete range checking. The range checking style (none, continuous, discrete) must be the same for all models.

To customize the range checking settings for a model

  1. From the Models Window, right-click on the desired model or family.

  2. Choose Customize settings

  3. The Minimum and Maximum text boxes or the Allowed values text box are enabled for the selected model, allowing model-specific values to be set. The model appears in bold font for the customized model.

    Note that if a family was selected, all models in the family appear in bold font, indicating that they will all the same custom range checking values.

  4. To have an attribute return to using the default range checking settings, right-click the model and choose Remove custom settings. The model appears in normal font and the editor controls are once again disabled when the model is selected, indicating that the model is controlled via the default settings specified when the "All Models" node is selected.

See Also

Other Resources

Adding Functionality to an IVI-C Driver
Adding Range Checking and Coercion to an Attribute


Attribute State Caching Editor

Nimbus allows state caching to be enabled on an attribute-by-attribute basis. The Attribute State Caching Editor allows the driver developer to enable or disable state caching for the selected attribute and to specify cache couplings. See the topic Understanding State Caching for more information.

Important note Important

The state caching logic specified here is only executed when state caching is enabled by the end user. This can be done by passing Cache=VI_TRUE as part of the OptionString parameter to the driver's InitWithOptions function, or it can be done after driver initialization via the CACHE attribute.

Enable caching of this attribute

When checked, Nimbus will generate code in the attribute getter and setter preamble sections that caches the attribute value between calls. This can reduce I/O traffic if redundant calls to the attribute occur, but it can also lead to cache coherency issues (data in memory out-of-sync with the actual instrument settings) if the property couplings are not thorougly understood and properly specified.

Attributes invalidated when this attribute is set

This list contains the names of any cached attributes that will be invalidated whenever this attribute is set. Invoking the attribute setter will cause any previously cached values corresponding to the specified attributes to be discarded.

To add an attribute to the invalidation list

  1. Click in the first available entry of the list.

  2. Enter an attribute name, without the driver PREFIX_ATTR_ portion. For example, for an attribute with a full attribute ID of ACME4321_ATTR_TRIGGER_SOURCE, only the string TRIGGER_SOURCE would be entered here.

  3. Press the enter key.

To remove an attribute from the invalidation list

  1. Click on the row selector to the left of a attribute name.

  2. Press the delete key.

See Also

Other Resources

Adding Functionality to an IVI-C Driver
Understanding State Caching


Enum Editor

Name

Name of the enum. Enum names must start with a capital letter and can contain only alphanumeric characters.

It is important to note that enumerated types are not supported in IVI-C drivers, so defining an IVI-C enum in Nimbus does not actually produce a enum definition anywhere in the driver API. This name serves to associated a set of related defined values (the enum members). For message-based drivers that use automatic command formatting, this name is also used to create special command converter classes that translate instrument commands and responses to and from their corresponding enum member values, as assigned in the Enum Member Editor.

These enum converter classes are defined in the enum macro map maintained in the driver project's Enums.h file. All of the converter classes derive from the EnumConverter base class and expose functions for converting instrument commands and responses to and from enum member values. See the discussion of the EnumConverter in the Nimbus Runtime Library for details.

See Also

Other Resources

Working With Instrument Commands
Enum Member Editor
EnumConverter Class


Enum Member Editor

Name

Name of the enum member. This name corresponds to the IVI-C macro name used in the <prefix>.h #define statement, except that the driver prefix and VAL are excluded. Attribute names consist only of capital letters, numbers, and the underscore character and must start with a capital letter.

Value

The numeric value of the enum member value macro used in the <prefix>.h #define statement.

Display

Display name that will be used to identify the enum member in function panel controls.

Command

Specifies the string that should be sent to the instrument when this value is used in a function or attribute as part of an automatically formatted instrument command. The string specified here is also used to translate instrument responses received from the instrument back to this numeric value.

The value configured here is used in building the enum macro map maintained in the driver project's Enums.h file. The enum macro map generates translation code that Nimbus uses in providing command formatting services within automatically implemented functions and attributes.

Additional Responses

In some cases, an instrument may define more than one string that corresponds to the same logical response. In these cases, the Additional Responses textbox can be used to specify a comma-separated list of strings that should also be mapped to this numeric value.

See Also

Other Resources

Working With Instrument Commands
EnumConverter Class


Error Editor

The values entered in this editor are used to expose error codes via the driver's main header file (<prefix>.h) and to define the error message macro map maintained in the driver project's Errors.cpp file. That map is used to implement the ReportError and ReportErrorEx functions. See the topic Returning Errors from IVI-C Drivers for additional information.

Name

Name of the error. This name corresponds to the IVI-C macro name used in the <prefix>.h #define statement, except that the driver prefix is excluded. Error names consist only of capital letters, numbers, and the underscore character and must start with a capital letter.

Value

The numeric value of the error code macro used in the <prefix>.h #define statement. Note that IVI prescribes the base error code value, so only the offset is editable.

Message

Error message that will be set on the driver session when the error is reported. Client applications use the GetError function to retrieve the error message.

See Also

Other Resources

DriverSession::ReportError
DriverSession::ReportErrorEx


Warning Editor

The values entered in this editor are used to expose error codes via the driver's main header file (<prefix>.h) and to define the error message macro map maintained in the driver project's Errors.cpp file. That map is used to implement the ReportError and ReportErrorEx functions. See the topic Returning Errors from IVI-C Drivers for additional information.

Name

Name of the warning. This name corresponds to the IVI-C macro name used in the <prefix>.h #define statement, except that the driver prefix is excluded. Warning names consist only of capital letters, numbers, and the underscore character and must start with a capital letter.

Value

The numeric value of the warning code macro used in the <prefix>.h #define statement. Note that IVI prescribes the base warning code value, so only the offset is editable.

Message

Warning message that will be set on the driver session when the warning is reported. Client applications use the GetError function to retrieve the warning message;

See Also

Other Resources

DriverSession::ReportError
DriverSession::ReportErrorEx


Implementing Driver Functions and Attributes

The topics in this section explain the basics of IVI-C driver function and attribute implementation.

In This Section

Fundamentals of Function And Attribute Implementation

Communicating With Instruments

Working With Instrument Commands

Returning Errors from IVI-C Drivers

Retrieving the Instrument Model

Retrieving Initialization Options


Fundamentals of Function And Attribute Implementation

IVI-C driver functions and attributes are implemented in a single file named <prefix>.cpp. For message-based devices that use the VISA library for instrument communication, Nimbus can generate all of the necessary implementation code by associating instrument commands with a function or attribute.

Because many IVI-C drivers are not message-based or do not use the VISA library at all, Nimbus also allows the developer to manually implement each function and attribute. Even with manually implemented functions and attributes, Nimbus provides support for automatically generating required code for performing important (and, indeed, IVI-required) operations, such as thread safe locking, parameter validation, repeated capability name management and more. Having a solid understanding of the basic anotomy of IVI-C function and attribute implementation code and how the Nimbus editors interact with this code is vital to any kind of IVI-C driver development with Nimbus.

Anatomy of an IVI-C Function

An IVI-C function implementation in Nimbus is divided into two main sections -- the preamble and the main body. The preamble code performs a variety of important tasks such as parameter validation, thread safety checks, state cache management, range checking, and simulation. The main body appears after the preamble and performs the core logic of the function, which is typically sending an instrument command or calling into a helper DLL. The preamble is separated from the main body via a standard line of code that Nimbus always inserts in a function or attribute implementation and that Nimbus relies upon for all of its roundtripping support. The separator line of code is the following:

C++
Copy
auto status = VI_SUCCESS;
Caution note Caution

The above line of code must appear as-is in each IVI-C function or attribute implementation if the function or attribute is being implemented automatically or if it is being implemented manually but has opted to use the standard preamble by selecting the Use auto-generated preamble option in the Function General Editor or the Attribute General Editor. If the above line of code is modified, then Nimbus will not be able to roundtrip the function and the driver developer will need to manually implement all of the code in the function.

The code below illustrates how an IVI-C function implementation is divided into preamble and main body sections:

C++
Copy
ViStatus _VI_FUNC acme4321_Configure(ViSession Vi, ViReal64 Frequency, ViReal64 Bandwidth)
{
    //
    // Everything here is part of the preamble
    //

    auto status = VI_SUCCESS;

    //
    // Everything here is part of the main body
    //
}

As an example, consider a complete function implementation, such as the following:

C++
Copy
ViStatus _VI_FUNC acme4321_Configure(ViSession Vi, ViReal64 Frequency, ViReal64 Bandwidth)
{
    ValidateSession(Vi);
    ObtainLock(Vi);

    if (SimulationEnabled(Vi))
    {
        return VI_SUCCESS;
    }

    auto status = VI_SUCCESS;

    status = viPrintf(GetVisaSession(Vi), "SENS:FREQ %0.15lg; SENS:BAND %0.15lg\n", Frequency, Bandwidth);
    ReturnOnError(status);

    status = PollInstrumentErrors(Vi);

    return status;
}

In the above example, the ValidateSession macro call, the ObtainLock macro call, and the if-statement for simulation are all part of the function preamble. The main body consists of the viPrintf call and the call to the PollInstrumentErrors function.

The contents of the preamble will vary depending upon the number and type of parameters, whether the function is associated with a repeated capability, and whether the implementation is a function, an attribute getter, or an attribute setter.

Tip Tip

For details on functions and macros appearing in the preamble code, see the topics in the Nimbus Runtime Library.

For further information on the VISA library functions that Nimbus generates for auto-implemented functions and attributes, see your VISA vendor's documentation.

Roundtripping IVI-C Functions and Attributes

The reason that Nimbus divides an IVI-C function or attribute implementation into preamble and main body sections is so that it can roundtrip those sections independently. For message-based devices that use the VISA library, Nimbus can implement the preamble code and the main body, so it roundtrips the entire contents of the implementation. For manually implemented functions and attributes (such as those that are either not message-based or that do not use VISA at all), Nimbus allows the driver developer to manually implement the main body but still have Nimbus generate and roundtrip the contents of the preamble. This is very useful because the preamble code is almost always appropriate -- even for manually implemented functions. If, however, the driver developer wishes to have full control over the entire function or attribute implementation, then Nimbus supports this as well.

Important note Important

Nimbus always roundtrips the function signature (the line of code containing the function name and parameters) as you add, remove, rename and otherwise modify the function definition. Never manually modify the function declaration line, even when manually implementing a function or attribute.

The roundtripping that Nimbus performs in IVI-C function and attribute implementation code is governed by two simple settings that appear on the Function General Editor and the Attribute General Editor. The table below explains what Nimbus roundtrips based on these settings.

Caution note Caution

It is crucial to understand what Nimbus roundtrips when using the IVI-C items editors. When Nimbus is roundtripping the preamble (as is typically the case), then any custom code placed in the preamble section will be overwritten by Nimbus. Similarly, if a function is being fully automatically implemented (as with message-based drivers using VISA), then any custom code placed (nearly) anywhere in the function implementation will be overwritten by Nimbus. Note that there is an exception to this policy related to simulation, which is dicussed later in this topic.

Implementation combo box | Use auto-generated preamble | Roundtripping policy
Instrument command | (always checked) | Entire function is roundtripped. Any code anywhere in the implementation (outside of the simulation block) is overwritten.
Manual Manual with instrument command | checked | Only the preamble code is roundtripped. Any code in the preamble section (outside of the simulation block) is overwritten.
Manual Manual with instrument command | unchecked | No roundtripping is performed on the function implementation. All code appearing in the implementation is fully preserved. Driver developer is fully responsible for performing the IVI-required preamble tasks, such as thread locking and parameter validation.
Note Note

Note that the roundtripping behavior for Manual and Manual with instrument command is identical. These two options differ only in how Nimbus generates help for the function or attribute. When Manual is selected, Nimbus generates no Instrument Command section in the help page for the function or attribute, which is appropriate when the function or attribute is not message-based. However, for functions and attributes that are manually implemented but ultimately still use an instrument command in the manually supplied code, Nimbus allows the driver developer to still specify the instrument command they are using so that it appears in the driver help pages.

Supporting Simulation

Simulation is often automatically implemented for IVI-C attributes. However, IVI-C functions must always supply manual code for simulation. Nimbus does not support automatically generating and roundtripping functions as it does for attributes. Nimbus inserts a stub implementation into a method with a TODO comment inserted and an error code being returned by default. This portion of the implementation appears in the preamble and is referred to as the simulation block and typically looks like the following:

C++
Copy
if (SimulationEnabled(Vi))
{
   return IVIC_ERROR_FUNCTION_NOT_SUPPORTED;    // TODO;
}

Since the preamble code is almost always roundtripped for manually implemented and automatically implemented functions and attributes as explained above, one might reasonably expect the simulation block to be automatically roundtripped as well. However, since the contents of the simulation block in IVI-C functions always need to be supplied by the driver developer, Nimbus does not roundtrip the contents of this simulation block. Driver developers can safely place their simulation logic within this if-statement and Nimbus will not overwrite any of the custom code.

Important note Important

It is crucial that the simulation block be structured exactly as above -- specifically, with a single if-statement (including the curly braces) that calls the SimulationEnabled function. Any arbitrary logic may be placed within the simulation block, but the outermost structure must be exactly as generated by Nimbus.

Anatomy of Attribute Implementation Code

Client applications manipulate IVI-C driver attribute values using the standard IVI-defined attribute accessor functions, such as GetAttributeViInt32 and SetAttributeViReal64. IVI-C attributes themselves are simply #define'd macro values in the driver's <prefix>.h file. The client application simply passes the macro value (referred to as the attribute ID) to the appropriate attribute accessor based on the attribute's data type (e.g. ViBoolean, ViInt32, ViReal64, etc).

With such an architecture, one might expect that a Nimbus IVI-C driver would implement the logic for all ViInt32 attributes, for example, within the body of the GetAttributeViInt32 function and/or the SetAttributeViInt32 function. Any such implementation of these attribute accessors would be unduly complex because it would essentially require use of a very large switch statement where each case statement contained all of the logic for an entire attribute (preamble, custom code, simulation and anything else required).

Rather than implementing attribute getter and setter logic within each attribute accessor, Nimbus generates separate getter and setter functions for each attribute. This allows the logic for the reading the attribute to be placed in one function, while the logic for writing the attribute is isolated in a separate function. Both the getter and setter functions are maintained in the driver project's <prefix>.cpp file alongside the IVI-C functions. Nimbus uses a specific naming convention for these getter and setter functions, as follows:

<prefix>_get_<attribute ID>

<prefix>_set_<attribute ID>

For example, for a TRIGGER_SOURCE attribute, the function definitions for the getter and setter would be as follows:

C++
Copy
ViStatus _VI_FUNC acme4321_get_TRIGGER_SOURCE(ViSession Vi, ViConstString RepCapIdentifier, ViInt32* AttributeValue)

ViStatus _VI_FUNC acme4321_set_TRIGGER_SOURCE(ViSession Vi, ViConstString RepCapIdentifier, ViInt32 AttributeValue)

These getter and setter functions are invoked by the Nimbus-supplied implementation of the various attribute accessors. Those default implementations rely upon entries in the maintained in the driver's Attributes.cpp file.

Supporting Repeated Capabilities

IVI-C drivers support parameter-style and selector-style repeated capabilities. When a function or attribute is associated with a repeated capability, the client application supplies a repeated capability selector to the function or attribute to indicate which physical names should be operated upon. These repeated capability selectors can contain virtual names, comma-separated lists of names, and ranges of names. This complicates the implementation of repeated capability-based functions and attributes because a single invocation might need to trigger multiple operations, such as multiple instrument commands being sent to the device. Because of the inherent complications in processing these repeated capability selectors, Nimbus provides special classes to process these selectors and generates the code necessary to perform repeated capability-based operations.

Consider the following ConfigureGlitchArmSource function which is associated with the ArmSource repeated capability:

C++
Copy
ViStatus _VI_FUNC acme4321_ConfigureGlitchArmSource(ViSession Vi, ViConstString Source, ViReal64 Level, ViReal64 Width, ViInt32 Polarity, ViInt32 Condition)
{
   ValidateSession(Vi);
   ObtainLock(Vi);

   PhysicalNameList<::ArmSource> physicalNames;
   ReturnOnError(ArmSource::ExpandSelector(Vi, Source, physicalNames));

   // ...
}

The first thing the function implementation must do, after validating the parameters and obtaining the thread lock, is to apply the IVI-defined rules for expanding a user-supplied repeated capability selector. As mentioned previously, the Source parameter in the function above might contain virtual names that need to be translated to physical names via the IVI Configuration Store. It may also contain lists and ranges of names. This Source parameter must be expanded according to the rules laid out in IVI 3.1, Section 4.4.7. The ExpandSelector function above does exactly that and it stores the resulting PhysicalName objects in a PhysicalNameList so that the main body can perform the necessary operations on each repeated capability name specified.

Functions that are automatically implemented using the VISA library would take the resulting PhysicalNameList and iterate through each contained PhysicalName to compose a unique instrument command upon each iteration. The code below demonstrates how such a function would be implemented by Nimbus:

C++
Copy
ViStatus _VI_FUNC acme4321_ConfigureGlitchArmSource(ViSession Vi, ViConstString Source, ViReal64 Level, ViReal64 Width, ViInt32 Polarity, ViInt32 Condition)
{
    ValidateSession(Vi);
    ObtainLock(Vi);

    PhysicalNameList<::ArmSource> physicalNames;
    ReturnOnError(ArmSource::ExpandSelector(Vi, Source, physicalNames));

    if (SimulationEnabled(Vi))
    {
        return VI_SUCCESS;
    }

    auto status = VI_SUCCESS;

    for (const auto& physicalName : physicalNames)
    {
        status = viPrintf(GetVisaSession(Vi), "CONFIG:GLITCH:SOUR:%s\n", physicalName.Name());
        ReturnOnError(status);
    }

    status = PollInstrumentErrors(Vi);

    return status;
}

The processing for attribute setters is identical to the above. However, for attribute getters and for functions that have an output parameter, it is not valid to specify a repeated capability selector with more than one physical name. Read operations can only return a single result, so the Nimbus-generated preamble code uses the ExpandSingleSelector function to perform the virtual-to-physical name translation and to enforce the use of only a single physical name.

The code below shows how the getter for an ARM_COUPLING attribute would be implemented to ensure only single physical names were used. The code for a function with an output parameter would be structured similarly in its use of the ExpandSingleSelector function.

C++
Copy
ViStatus _VI_FUNC acme4321_get_ARM_COUPLING(ViSession Vi, ViConstString RepCapIdentifier, ViInt32* AttributeValue)
{
    ValidateSession(Vi);
    ObtainLock(Vi);
    CheckForNull(Vi, AttributeValue);

    PhysicalName<ArmSource> physicalName;
    ReturnOnError(ArmSource::ExpandSingleSelector(Vi, RepCapIdentifier, physicalName));

    // ... same code as non-repeated-capabilty-based attribute
}

In the code above, the ExpandSingleSelector function will return an error if the RepCapIdentifier parameter represents more than one physical name. If it succeeds, then the result is stored in a single PhysicalName object (as opposed to a list of PhysicalName objects, as was the case for attribute setters and functions with no output parameters). Since only a single physical name can be specified, the remainder of the implementation code is very much the same as in the non-repeated-capability case.


Communicating With Instruments

Nimbus can be used to build IVI-C drivers for instruments that use virtually any I/O protocol. Many instruments are accessed via standard protocols, such as TCP/IP, USB, GPIB, or serial. For these kinds of instruments, Nimbus leverages the VISA library to perform I/O operations. VISA implementations available from any VISA vendor, such as National Instruments or Keysight Technologies, will work equally well with Nimbus and the resulting IVI-C drivers are not tied to any particular VISA vendor.

Important note Important

Even though Nimbus provides built-in, easy-to-access support for instruments that communicate using VISA-supported protocols, there is no intrinsic dependence that Nimbus has on VISA. Fully compliant IVI-C drivers can be built with Nimbus using a custom DLL that implements any private I/O protocol required.

Using Automatic Command Formatting

To use automatic command formatting, you must first associate an instrument command with the function or attribute by choosing the Instrument Command implementation type in the Function General Editor or the Attribute General Editor . Within the function implementation, Nimbus will generate a call to a standard VISA method -- typically viPrintf and/or viScanf. The code below is an example of the complete implementation of a function that uses the automatic command formatting features of the Function General Editor and the Attribute General Editor.

C++
Copy
ViStatus _VI_FUNC acme4321_Configure(ViSession Vi, ViReal64 Frequency, ViReal64 Bandwidth)
{
    ValidateSession(Vi);
    ObtainLock(Vi);

    if (SimulationEnabled(Vi))
    {
        return VI_SUCCESS;
    }

    auto status = VI_SUCCESS;

    status = viPrintf(GetVisaSession(Vi), "SENS:FREQ %0.15lg; SENS:BAND %0.15lg\n", Frequency, Bandwidth);
    ReturnOnError(status);

    status = PollInstrumentErrors(Vi);

    return status;
}


Working With Instrument Commands

The most common way to implement Nimbus IVI-C driver functions and attributes is by specifying an instrument command and relying upon Nimbus to generate all of the necessary code to send the command and, optionally, to read back a response. Nimbus provides a powerful instrument command syntax that allows method parameters and other information to be automatically formatted into the command.

In This Section

Instrument Command Syntax

Special Features for SCPI Commands


Instrument Command Syntax

Nimbus provides a very flexible syntax for specifying instrument commands and responses that are associated with functions and attributes. The command syntax described here applies to commands and responses entered in the Function General Editor or the Attribute General Editor.

When the user associates an instrument command or response with a function or attribute, Nimbus generates code to automatically format the command using the values of parameters passed to the function. Correspondingly, when responses are read back from an instrument, the results are parsed and assigned to out-parameters according to the response string specified by the user. Commands and responses can contain parameter replacement tags to control how each parameter is associated with the command or response. Additionally, commands (not responses) may include repeated capability replacement tags for inserting the repeated capability instance name or index into the command string.

Parameter Replacement Tags

Parameter replacement tags are enclosed in curly braces { } and can appear anywhere within an instrument command. They have the following general form:

{<paramName> | value[:<formatSpec>]}

The paramName is the name of the parameter in the function signature.

The value keyword is used to refer to the attribute value itself when defining attribute setter commands and attribute getter responses. The value keyword is also used to refer to a function return value. Use of the {value} keyword is discussed further in the sections below.

The formatSpec is an optional format specification for the parameter. This format specification is similar to that supported by the C Run-Time Library's familiar sprintf function. More precisely, this format specification can be any of those supported by the standard VISA library's viPrintf or viScanf functions. For a complete list of format specifications, see the documentation for your VISA supplier.

If no formatSpec is provided, then the default format specification is used. The default format specification only applies to integers, floating-point, and boolean parameters. These defaults are configured on the I/O Page of the Driver Settings Editor.

Special support is provided for formatting boolean and enum parameters.

Example: Basic Parameter Replacement

This example shows a Configure function that takes three parameters -- resolution bandwidth (ResBW), video bandwidth (VideoBW), and sweep time (SweepTime). Assume a function defined as follows

C++
Copy
ViStatus _VI_FUNC acme4321_Configure(ViSession Vi, ViReal64 ResBW, ViReal64 VideoBW, ViInt32 SweepTime)

The following instrument command is associated with the Configure function:

SENS:BAND{ResBW}; SWE:TIME{SweepTime:%d}; BAND:VID{VideoBW:%3.2f};

Given this function definition and the replacement tags shown, the instrument command would be formatted as follows:

  • The replacement tag {ResBW} would be replaced with the run-time value of the ResBW parameter. Since no format specification is provided, the default format for floating-point values would be applied.

  • The replacement tag {SweepTime:%d} would be replaced with the run-time value of the SweepTime parameter and formatted as a decimal as dictated by the %d format specification.

  • The replacement tag {VideoBW} would be replaced with the run-time value of the VideoBW parameter and formatted as a floating point number as dictated by the %3.2f format specification.

Formatting Attribute Setters

Attribute setters support a special {value} replacement tag to represent the value of the attribute itself. This special tag allows you to insert the runtime value of the attribute into the command string.

The following instrument command applied to a attribute setter would append the value of the attribute to the SENS:BAND string:

SENS:BAND {value}

Since most functionality in IVI-C drivers is provided by attributes, Nimbus simplifies the instrument command syntax by not requiring a replacement tag to be provided explicitly for attribute setters. Rather, the formatted attribute value will simply be appended to the command string. If the formatted parameter should appear elsewhere in the command string, then an explicit parameter replacement tag must be specified.

Given this shorthand notation, the following two instrument commands applied to a attribute setter produce identical results:

  • SENS:BAND

  • SENS:BAND {value}

Both command strings will append the formatted value of the attribute to the SENSE:BAND string. Note that in both cases the default parameter formatting for the attribute type will be applied, since no format specification is provided. If an alternate format specification is desired, then the {value} replacement tag must be specified.

The following example shows an instrument command using the {value} tag with a format specification:

SENS:BAND {value:%3.2e}

The above example will append the value of the attribute in exponentional form with a minimum length of 3 characters and 2 digits following the decimal point.

Formatting Attribute Getters

Attribute getters utilize the {value} tag in precisely the same way as functions use the tag for responses. Only the getter response string may use the {value} tag -- the getter command may only use input and input/output parameter tags and repeated capability tags, not the {value}. See the discussion in the following section on how to use the {value} tag in function responses.

Formatting Boolean And Enum Parameters

When an instrument command parameter tag refers to a boolean or enum parameter, Nimbus must generate code that converts the boolean or enum value to a string. Correspondingly, when an instrument response uses a parameter tag that references a boolean or enum, the instrument response string must be parsed and converted to the appropriate boolean or enum value.

The string-to-enum mappings are created using the Enum Member Editor. These mappings will apply to every attribute and function in which that enum is used as a parameter or attribute value. If a particular function or attribute using that enum needs unique string-to-enum mappings, then that function or attribute must be manually implemented.

The string-to-boolean mappings are managed differently -- by simply changing the settings in the I/O Page of the Driver Settings Editor.

As an example, consider an attribute named TRIGGER_SOURCE (the PREFIX_ATTR portion is excluded for brevity). Nimbus generates a #define macro for that attribute in the <prefix>.h file that looks like the following:

C++
Copy
// acme4321.h
#define ACME4321_ATTR_TRIGGER_SOURCE    (IVI_SPECIFIC_ATTR_BASE + 3L)  /* ViInt32, read-write */

The command for the setter is defined as:

TRIG:SOUR {value}

The command for the getter is defined as:

TRIG:SOUR?

Finally, the response for the getter is defined simply as:

{value}

When the setter is executed, the specified value for the TRIGGER_SOURCE attribute needs to be converted to a string and inserted into the setter command where the {value} tag appears. For instance, if the attribute were set to the value ACME4321_VAL_TRIGGER_SOURCE_EXTERNAL, the enum value might need to be converted to EXT to produce the following command:

TRIG:SOUR EXT

Similarly, when the TRIG:SOUR? query is issued upon executing the attribute getter, the instrument might respond with a string such as INT (to represent an internal trigger source). This string needs to be converted to a valid enum value, such as ACME4321_VAL_TRIGGER_SOURCE_INTERNAL.

Repeated Capability Replacement Tags

Instrument commands sent from functions implemented on repeated capability classes often need to incorporate runtime information about the specific repeated capability instance issuing the command. For example, a spectrum analyzer driver might define a repeated capability class to represent multiple traces stored in the instrument. A command that would read data from a specific trace might look something like the following:

DATA:TRACE4:READ?

Note that the 4 included in the command refers to a specific trace within the instrument.

Note Note

Repeated capability tags cannot appear in instrument response strings.

Repeated capability replacement tags are used to insert into command strings runtime information about the repeated capability instance sending the command. These special tags can be replaced by either the name or the index of the repeated capability.

For more information on repeated capabilities, see Repeated Capabilities.

Repeated capability replacement tags are enclosed in curly braces { } and can appear anywhere within an instrument command. They have the following general form:

{ [<parentRepCap>.]rcindex[+|-<offset>] | rcname }

The rcindex keyword is used to insert into the command string the runtime value of the index of the repeated capability instance issuing the command. The rcindex keyword can optionally be followed by an offset, such as +1 or -3, to account for differences between how repeated capabilities are indexed by the driver and how the instrument expects them to appear in the command string.

The rcname keyword is used to insert into the command string the runtime value of the name of the repeated capability instance issuing the command.

The parentRepCap is an optional parameter used to designate a parent (or any ancestor) repeated capability.

Example: Using the repeated capability index in instrument commands

This example shows a RESOLUTION attribute that is defined on a repeated capability that represents multiple markers. In order to set the resolution for the correct marker, the index of the current repeated capability instance must be included in the command string.

The following instrument command is assigned to the RESOLUTION attribute:

CALC:MARK{rcindex}:RES

When the attribute setter for the RESOLUTION attribute is supplied a value of for the RepCapIdentifier parameter, Nimbus will translate that physical or virtual name into an index based upon the ordering of physical names the driver developer assigned. The formatted string sent to the instrument would be something such as the following:

CALC:MARK3:RES

Example: Using the repeated capability index with an offset

In this example, the RESOLUTION attribute of a marker repeated capability uses an instrument command with a positive offset of 1 for the repeated capability index. Assume a attribute definition as follows:

The following instrument command is assigned to the RESOLUTION attribute:

CALC:MARK{rcindex+1}:RES

When the attribute setter for the RESOLUTION attribute is supplied a value of for the RepCapIdentifier parameter, Nimbus will translate that physical or virtual name into an index based upon the ordering of physical names the driver developer assigned. The formatted string sent to the instrument would be something such as the following:

CALC:MARK4:RES

Example: Using the repeated capability name in an instrument command

This example demonstrates the use of the rcname keyword to insert the name of the a repeated capability instance into the instrument command. Assume an AMPLITUDE attribute has been defined.

The following instrument command is assigned to the AMPLITUDE attribute:

TRAC:DAT? {rcname}

If the attribute setter for the AMPLITUDE attribute was passed a value of TR1 for the RepCapIdentifier parameter, then the formatted string sent to the instrument would be as follows:

TRACE:DAT? TR1

Example: Building instrument commands with nested repeated capabilities

This example demonstrates the use of repeated capability replacement tags when nested repeated capabilities are involved.

Here, the command string includes two repeated capability replacement tags. One tag does not specify a parent repeated capability and, hence, implicitly refers to the repeated capability on which the function is defined (as in the previous examples). The other replacement tag refers to the Display repeated capability, which is a parent repeated capability of the one on which the function is defined. Assume the following function definition:

C++
Copy
ViStatus _VI_FUNC acme4321_StoreReferenceTrace(ViSession Vi, ViConstString RepCapIdentifier)

The following instrument command is assigned to the StoreReferenceTrace function:

CALC:DISP{Display.rcindex}:SRTR{rcindex}:REF

When nested repeated capabilities are used, the RepCapIdentifier parameter must be supplied with a nested physical name, where the desired physical name for each repeated capability in the hierarchy is separated by colons. For instance, if the user wanted to execute the StoreReferenceTrace function on a trace named TR1 within a display named DISP2, then the user would pass the value DISP2:TR1 for the RepCapIdentifier parameter. The function implementation would translate these names into the appropriate repeated capability indexes and compose a formatted command similar to the following:

CALC:DISP2:SRTR1:REF


Special Features for SCPI Commands

Many instruments today follow the SCPI (Standard Commands for Programmable Instruments) standard supported command set. Nimbus offers special convenience features for SCPI-based instruments. By checking the SCPI compliant check box on the I/O Page of the Driver Settings Editor, you are telling Nimbus that the instrument commands associated with functions and attributes are SCPI compliant.

When a driver project is SCPI-compliant, Nimbus automatically strips the optional characters from the SCPI command string. This allows the developer to enter the full verbose form of the SCPI command in the Function General Editor (as well as the Attribute General Editor and the Enum Member Editor) and have the full text appear in the help page for the function. However, the Nimbus-generated code that sends the command to the instrument will use the minimal form of the command.

Consider the SCPI command below:

[SENSe:]FREQuency[:VOLTage]:RANGe[:UPPer]

If this command is associated with a function or attribute via the item editor, the command that will ultimately be sent to the instrument as follows:

FREQ:RANG

Note that all of the optional characters enclosed in square brackets have been removed, as have all of the lowercase characters.

Tip Tip

It is best to always enter the full SCPI command when associating instrument commands with functions and attributes so that the full text shows up in the driver help file. Nimbus automatically adds the instrument commands to the driver help file index and builds a special page that maps instrument commands to driver functions and attributes. Most users will expect to see the full form of the SCPI command in such contexts.

See Also

Other Resources

I/O Page, IVI.NET Driver Settings


Returning Errors from IVI-C Drivers

IVI-C drivers report errors by returning a failure ViStatus result. The IVI specifications then require that the user be able to call the IVI-defined GetError function to retrieve both the current error code and error message associated with the driver session. Nimbus supplies functions that make it simple for driver developers to define and compose helpful error messages and report them to users from within the driver implementation code.

Error Reporting Basics

Consider a situation where a method in an IVI-C driver receives a bad input parameter value. The IVI specifications say that the driver is supposed to return the IVI-defined error PREFIX_ERROR_INVALID_VALUE. In addition, the driver function is supposed to compose an error message of the following form:

Invalid value '%s' for method '%s', parameter '%s'.

The %s replacement tags are supposed to be filled in with the invalid value itself, the name of the function that generated the error and the name of the parameter. A properly formatted error message might look something like the following:

Invalid value '-2' for method 'ConfigureRamp', parameter 'Time'.

In addition to returning a valid ViStatus value and a properly formatted error message, IVI-C drivers are required to associated the error with the IVI session so that the client application can call the driver's GetError function to retrieve the full error details.

All of the tedious operations related to message formatting and session error management are handled by the ReportError and ReportErrorEx functions. These functions can be used to compose an error message for any error that as been added to the driver or is already available as one of the standard IVI-defined errors.

The code below demonstrates how an error would be properly composed and returned from an IVI-C driver.

C++
Copy
ViStatus _VI_FUNC acme4321_ConfigureArmCount(ViSession Vi, ViConstString RepCapIdentifier, ViInt32 ArmCount)
{
    // ...

    if (AttributeValue < 0)
    {
        return ReportError(Vi, ACME4321_ERROR_INVALID_VALUE, std::to_string(AttributeValue).c_str(), "ConfigureArmCount", "ArmCount");
    }
}
Reporting Errors for Invalid Enum Values

Nimbus provides the MemberName function as part of the EnumConverter class for the specific purpose of converting user-supplied enum numeric values to their macro name. This makes it much more convenient to return helpful error messages to users when improper enum values are passed to an IVI-C driver function.

The code below demonstrates the typical usage of the MemberName function.

C++
Copy
ViStatus _VI_FUNC acme4321_ConfigureDmmFunction(ViSession Vi, ViInt32 Function)
{
    // ...

    // We only support AC, DC, and Frequency measurements
    //
    switch (Function)
    {
      case ACME4321_VAL_AC_VOLTS:
        // ...
        break;

      case ACME4321_VAL_DC_VOLTS:
        // ...
        break;

      case ACME4321_VAL_FREQ:
        // ...
        break;

      default:
        // The strMemberName variable will be set to the member name that corresponds to the unsupported value, for
        // instance, "ACME4321_VAL_AC_CURRENT" or "ACME4321_VAL_TEMPERATURE".  If the value supplied by the user
        // does not correspond to any of the defined values for the enum, then the MemberName function will simply
        // return the numeric value itself converted to a string.
        //
        auto strMemberName = FunctionEnum::MemberName(Function);
        return ReportError(Vi, ACME4321_ERROR_INVALID_VALUE, strMemberName.c_str(), "ConfigureDmmFunction", "Function");
    }
}
See Also

Other Resources

Adding an Error
Adding a Warning


Retrieving the Instrument Model

When a client application initializes a driver via the init or InitWithOptions function, the standard Nimbus implementation of those functions execute the GetIdentificationInfo function to query the instrument for identification information, such as the manufacturer, the firmware revision, and the specific instrument model. Nimbus caches the results of this process so that the driver developer (and the Nimbus-generated code) can use functions within the Nimbus Runtime Library to retrieve the identification information at any time during the driver session.

The InstrumentModel function is provided to allow driver code to retrieve the specific instrument model with which the driver is currently communicating. The driver developer can use the InstrumentModel function in a multi-model driver project to implement conditional logic. For instance, in the code example below, the InstrumentModel function is used to determine the exact SCPI command that should be sent to the instrument to program the voltage range.

C++
Copy
ViStatus _VI_FUNC acme4321_ConfigureRange(ViSession Vi, ViReal64 Range)
{
   // ...

   auto strModel = InstrumentModel(Vi);

   if (strModel == "4301")
   {
      status = viPrintf(GetVisaSession(Vi), "SENS:FREQ:VOLT:RANGE %.15g", Range);
   }
   else if (strModel == "4302")
   {
      status = viPrintf(GetVisaSession(Vi), "FREQ:RANGE %.15g", Range);
   }
   else
   {
      status = viPrintf(GetVisaSession(Vi), "FREQ:VOLT:RANGE %.15g", Range);
   }

   // ...
}
Retrieving the Instrument Model in Simulation Mode

When a driver is initialized in simulation mode, the InitWithOptions function obviously cannot use the GetIdentificationInfo function to query the instrument for its identification information, such as the instrument model. Rather, the instrument model must be provided to the driver so that all of the model-based logic (both developer-written and Nimbus-generated) will operate properly. The model that is provided during simulation is referred to as the simulated model. When the driver is running in simulation mode, the InstrumentModel function can be used in exactly the same fashion as with a live session.

The simulated model can be specified in one of two ways:

  • By using the Models Page of the Driver Settings Editor to specify a default model. The default model is stored by the driver installer in the IVI Configuration Store and is automatically retrieved by the Nimbus implementation InitWithOptions.

  • By passing in a DriverSetup string to the InitWithOptions function. The client application includes in the DriverSetup string a name-value pair of the form "Model=<model>". A simulated model provided in this way overrides the default model specified by the driver developer in the Driver Settings Editor.

The code below demonsrates how a client application can specify a simulated model when calling the driver's InitWithOptions method.

C++
Copy
// Client.cpp
ViSession session;
ViStatus status = acme4321_InitWithOptions("GPIB::14", VI_FALSE, VI_FALSE, "Simulate=true, DriverSetup= Model=4302", &session);
See Also

Other Resources

Adding Support for Multiple Instrument Models
DriverSession::InstrumentModel
DriverSession::InstrumentInFamily
DriverSession::InstrumentIsModel
DriverSession::ModelInFamily


Retrieving Initialization Options

When client applications initialize an IVI driver via the InitWithOptions function, they may provide a series of initialization options in the form of name-value pairs. Two types of initialization options may be passed to a driver's InitWithOptions method - inherent options and driver setup options.

The inherent options are specific name-value pairs defined by the IVI Foundation. These include options such as Cache to turn on/off state caching and Simulation to indicate whether simulation should be enabled or not. The driver setup options are custom name-value pairs defined by the driver developer. Driver setup options may be used to control driver-specific features or to perform any custom setup. They are delineated from the inherent options by the IVI-defined DriverSetup keyword.

The example below shows a typical client application instantiating and then initializing a driver.

C++
Copy
// Client.cpp
ViSession session;
ViStatus status = acme4321_InitWithOptions("GPIB::10", VI_TRUE, VI_TRUE, "InterchangeCheck=VI_FALSE, Simulate=VI_TRUE, DriverSetup=OptionA=Foo,OptionB=VI_TRUE", &session);

InterchangeCheck option is an inherent option being passed in with a value of VI_FALSE. Simulate is also an inherent option specified with a value of VI_TRUE in the code above. Two driver setup options, OptionA and OptionB are being passed in with values of Foo and VI_TRUE, respectively.

The Nimbus implementation of the InitWithOptions function automatically saves the values of all inherent and driver setup options. If some of the IVI-defined inherent options are not specified, Nimbus caches IVI-defined default values for those options.

Nimbus provides several functions for retrieving the values of the IVI-defined inherent options. These functions are fully documented in the Nimbus Runtime Library documentation. The table below shows each inherent option and the Nimbus function available to retrieve its value. The IVI-defined default value of each option is also shown.

Inherent Options | Accessor Function | Default Value
Cache | CacheEnabled | True
InterchangeCheck | InterchangeCheckEnabled | False
QueryInstrStatus | QueryInstrStatusEnabled | False
RangeCheck | RangeCheckEnabled | True
RecordCoercions | RecordCoercionsEnabled | False
Simulate | SimulationEnabled | False

The Nimbus Runtime Library also provides the GetDriverSetupOption function for retrieving the value of driver setup options passed to the InitWithOptions function. A simple example of using the GetDriverSetupOption function is shown below.

C++
Copy
ViStatus _VI_FUNC acme4321_Configure(ViSession Vi, ViReal64 Frequency, ViReal64 Bandwidth)
{
    std::string strOption;

    if (GetDriverSetupOption(Vi, "OptionA", strOption))
    {
        // ...
    }
}


Customizing the Driver Header File

The header file for an IVI-C driver (<prefix>.h) is automatically generated by Nimbus. The code generation for this file is governed by the contents of a Nimbus text template (.ntt) file included in the IVI-C driver project. Driver developers can add content to the text template file to control certain aspects of how the header is generated. For instance, #include statements can be added to the text template file and they will be retained in the generated header file.

Basics of the header file template

The text template (<prefix>.ntt) file appears in the driver project with the generated header file (<prefix>.h) appearing as a dependency.

Header File Template
Caution note Caution

Do not modify the contents of the header file (.h), as those changes will be overwritten by Nimbus.

The template file (.ntt) presents the layout of the header file that will be generated. The auto-generated portions are represented by replacement tags that are delineated by percent signs (%). For instance, the following excerpt from a template file shows two replacement tags -- %Copyright% and %PrefixUpper%.

C++
Copy
/******************************************************************************
 *
 * %Copyright%
 *
 *****************************************************************************/

#ifndef __%PrefixUpper%_HEADER
#define __%PrefixUpper%_HEADER

#include <ivivisatype.h>

The following excerpt shows the replacement tags where Nimbus injects attribute definitions and function declarations.

C++
Copy
/*===== IVI Inherent Instrument Attributes ==============================*/
%InherentAttributeDeclarations%

/*===== Instrument-Specific Attributes =====================================*/
%SpecificAttributeDeclarations%

/****************************************************************************
*------------------------ Attribute Value Defines -------------------------*
****************************************************************************/
%AttributeValueDeclarations%

/****************************************************************************
*---------------- Instrument Driver Function Declarations -----------------*
****************************************************************************/
%FunctionDeclarations%

At build time, these tags are replaced by Nimbus code generation with the appropriate values. It is important that these values not be removed or modified. Any customizations to the help template should be done "around" these replacement tags.

Example Customization: Adding an include file

A simple and common usage for IVI-C header template files is inclusion of additional header files specific to the driver under development. In the code excerpt below, two additional include files foo.h and bar.h. are added to the text template.

C++
Copy
/******************************************************************************
 *
 * %Copyright%
 *
 *****************************************************************************/

#ifndef __%PrefixUpper%_HEADER
#define __%PrefixUpper%_HEADER

#include <ivivisatype.h>
#include <foo.h>
#include <bar.h>

When the build runs, the resulting header file would be generated with the following content in place of the above.

C++
Copy
/******************************************************************************
 *
 * Copyright 2020 Pacific MindWorks. All rights reserved.
 *
 *****************************************************************************/

#ifndef __ACME_HEADER
#define __ACME_HEADER

#include <ivivisatype.h>
#include <foo.h>
#include <bar.h>


Understanding State Caching

State caching is a feature of IVI drivers that can improve performance by minimizing the number of I/O calls to an instrument. For instance, if a driver attribute value is set and the driver sends the programmed value to the instrument, subsequent calls to the same attribute need not communicate with the instrument if the value being set is the same as the previous value. Correspondingly, reading a driver attribute need not result in instrument communication if the driver can somehow "remember" the last value that was sent to the instrument. When a client application invokes a driver attribute, the driver caches the value specified in memory so that subsequently the driver can simply retrieve the value from the driver's cache when the attribute is read or avoid making a redundant call to the instrument when the attribute is written. In this way, the instrument I/O traffic is minimized and the overall client application performance can be improved.

Understanding Cache Couplings

When a driver caches the value of a attribute, it should ideally return the cached value when the attribute is later read, rather than incurring the performance hit of querying the instrument for the attribute value. This will work so long as nothing takes place within the instrument that would invalidate the value cached in the driver. If, after caching the value of a attribute, the driver performs a different instrument operation that directly or indirectly changes the value of the attribute within the instrument, then the driver's cache and the "real" setting in the instrument are inconsistent. This is one form of what is termed a cache coherency problem.

If setting some driver attribute produces a change in an instrument setting represented by another attribute, the two attributes are said to be coupled. For state caching to work properly, these cache couplings must be programmed into the driver, so that the driver knows when to invalidate specific cached values. For instance, if the driver is caching a Frequency attribute, then setting the Bandwidth attribute may also change the frequency setting within the instrument. This means that the driver must know to invalidate the cached value for the Frequency attribute whenever the Bandwidth is set.

State Caching Features in Nimbus

Nimbus provides two mechanisms for controlling state caching -- automatic state caching and manual state caching. The automatic state caching feature of Nimbus is the simplest to use and will suffice in mostcircumstances. With this technique, Nimbus automatically creates and manages a cache entry for every driver attribute for which state caching has been enabled. The State Caching Editor is used to turn state caching on and off on a attribute-by-attribute basis. The other bit of information that the driver developer must provide via the State Caching Editor is the list of attributes to which the cached attribute is coupled. In other words, the driver developer must specify which driver attributes, when changed, will cause the value of the cached attribute to become invalid. This allows Nimbus to keep its in-memory cache consistent with the settings in the instrument.

In addition to the automatic state caching features of Nimbus exposed by the State Caching Editor, Nimbus also supplies support in the Nimbus Runtime Library for directly manipulating the attribute cache maintained on the driver session. The GetCacheEntry function is used to retrieve a an instance of a CacheEntry class for a particular attribute. Then, functions on the CacheEntry class allow the cached value to be retrieved, updated, invalidated, etc.

When To Enable State Caching

State caching is a feature that certainly must be used with care. Cache coherency problems can easily arise if the driver developer is not keenly aware of the details of the instrument behavior and/or does not accurately and thorougly represent instrument couplings in the driver. Thus, in general, it is advisable to consider enabling state caching for those attributes that have the following characteristics:

  1. They require considerable time to execute (and, hence, stand to improve performance the most when cached).

  2. They have a modest and easily expressed set of couplings to other attributes.

Enabling state caching broadly across all attributes in a driver is almost never feasible, as correctly implementing the driver code would involve effectively replicating much of the instrument firmware logic itself. Consequently, Nimbus disables state caching by default for all attributes.

See Also

Other Resources

GetCacheEntry Function
CacheEntry Struct


Implementing Dynamic Repeated Capabilities

Nimbus supports two types of repeated capabilities -- static repeated capabilities and dynamic repeated capabilities. Static repeated capabilities represent the fixed functionality of the instrument -- such as physical channels on an oscilloscope. These repeated capabilities must be configured at driver development time using the Driver Settings Editor for the repeated capability in question.

Dynamic repeated capabilities are those that cannot be determined at driver development time. Rather, the driver must "discover" by communicating with the instrument what repeated capabilities are present. For example, a driver for a multi-slot digital I/O mainframe has no way to know at driver development time what type and number of digital I/O cards will be plugged into the available mainframe slots.

In order to support dynamic repeated capabilities, Nimbus provides the Add Physical Names and RemovePhysicalNames functions on each repeated-capability derived class. For each repeated capability supported by the driver, Nimbus generates an entry in the repeated capability macro map maintained in the driver project's RepCaps.h file. Each entry in that macro map produces a class definition that matches the name of the repeated capability, and the static Add Physical Names and RemovePhysicalNames funtions can be invoked directly on these generated repeated capability classes.

Physical names can be added or removed from a repeated capability at any point after driver initialization. Often, physical names are added after during the initialization sequence. The code below demonstrates how to add physical names to a repeated capability called Channel.

C++
Copy
ViStatus _VI_FUNC acme4321_InitWithOptions(ViRsrc ResourceName, ViBoolean IdQuery, ViBoolean Reset, ViConstString OptionsString, ViSession* Vi)
{
   auto status = VI_SUCCESS;

   status = nrt::InitWithOptions<Acme4321DriverSession>(ResourceName, IdQuery, Reset, OptionsString, Vi);
    ReturnOnError(status);

   if (Reset)
   {
       status = acme_reset(*Vi);
       ReturnOnError(status);
   }

   ReturnOnError(status);

   // Query the instrument for the number of channels
   //
   long cChannels;
   status = viQueryf(GetVisaSession(Vi), "SYST:CTYP:COUN?\n", "%lg%*t", &cChannels);
   ReturnOnError(status);

   // Note that the AddPhysicalNames function accepts selectors, so it can include ranges and comma-separated lists of
   // physical names.  Each channel name is of the form "CH[channel]".  We'll add all of the channels in one go by building
   // a selector that includes a range from 1 to the cChannels we queried from the device.
   //
   auto strSelector = "CH1-CH" + std::to_string(cChannels);
   status = Channel::AddPhysicalNames(Vi, strSelector);

   return status;
}
See Also

Other Resources

Repeated Capabilities
Adding a Repeated Capability


Customizing Driver Initialization and Shutdown

The initialization of an IVI-C driver session begins with a client application invoking the init or InitWithOptions function and ends with a call to the driver's close function. Nimbus provides a default implementation of all three of these functions that handles a great deal of processing in an IVI-compliant way, such as loading information from the IVI Configuration Store, parsing initialization options, instantiating an IVI session object, and more.

Much of the standard processing in the default implementation of the driver initialization and shutdown functions is suitable for all drivers and need not (and, indeed, should not) be customized for specific drivers. However, some of that implementation logic necessarily makes assumptions about how the driver supports certain operations, such as how it opens an I/O session, how it identifies the instrument and how it clears the I/O session. Since IVI drivers can vary wildly in how these operations should be performed, Nimbus provides a simple means to override only those specific aspects of initialization while still leveraging those portions that work for all drivers.

When the driver's init or InitWithOptions function is called, Nimbus creates an instance of a driver session object. The definition of the driver session class is maintained in the driver project's DriverSession.h file and is named <prefix>DriverSession. This class derives from the standard Nimbus Runtime Library's DriverSession class, and Nimbus relies heavily upon virtual functions on this DriverSession class. Driver developers override these virtual DriverSession class functions to customize the behavior of the driver.

The table below presents the sequence of operations that take place over the lifetime of a typical IVI-C driver session and which functions are available to customize this sequence to meet specific driver requirements.

Step | Function Called | Description
1 | Client application calls the driver's InitWithOptions function. | The client application may also call init, but the sequence of operations presented here is identical.
2 | InitializeIO | This function is used to establish an I/O connection with the device. By default, this function will use the VISA library to open an instrument session using the viOpen function. In simulation mode, this function should do nothing. This function must be overridden for non-VISA-based drivers.
3 | ClearIOStatus | This function is used to clear out any I/O errors that may be in the device at initialization. This allows the user to initialize the driver, even if the device is in an error state. By default, this function will use the VISA library to send a *CLS command to the instrument. In simulation mode, this function should do nothing. Drivers that need to use an alternate mechanism for clearing the instrument I/O status must override this function.
4 | GetIdentificationInfo | This function is used to set the instrument model, manufacturer, serial number, and firmware revision. By default, this function will use the VISA library to send a *IDN? query and it will expect a standard IEEE 488.2 response. Drivers that need to use an alternate mechanism for identifying the connected instrument must override this function.
5 | InstrumentSupported | This function checks if the connected instrument is supported by the driver. By default, this function checks that the model detected by the GetIdentificationInfo function in an earlier step is in the list of supported models. This function can be overridden to implement more advanced logic, such as cases where the number of instrument models supported is prohibitively large and/or not precisely enumerable by the driver.
6 | The InitWithOptions function completes (if all previous steps succeeded). |
7 | Client application calls the driver's close function. |
8 | CloseIO | This function closes the connection with the instrument. By default, Nimbus uses the VISA library viClose function to sever the connection with the instrument. Non-VISA-based drivers must override this function to perform custom I/O shutdown and to release any custom I/O resources.
9 | The close function completes. |


Testing an IVI-C Driver

One of the most important aspects of IVI driver development is authoring and maintaining a suite of driver tests. Nimbus provides integrated unit testing support for IVI-C drivers using standard Visual Studio unit test projects. This topic discusses these IVI-C driver unit testing features.

Important note Important

When testing an IVI-C driver using the Visual Studio debugger, whether it be inside a unit test or in a standalone application, there is a debugger setting that should be changed from its default value. From the Tools menu, choose Options to bring up the Options Dialog.

From the tree view on the left, choose Debugging. Uncheck the box labeled Enable property evaluation and other implicit function calls.

If this option is left at its default enabled setting, then the Visual Studio debugger will sporadically execute properties on the driver and other classes as you are debugging. This can trigger unexpected and undesired instrument communication and produce confusing results.

Creating an IVI-C Driver Unit Test

All of the unit test code for an IVI-C driver is housed in a single Visual C++ project created by Nimbus. Typically, this project is created upfront with the other driver projects after the New IVI-C Driver Wizard runs. This is controlled by the Create unit test check box on the Projects page of the New IVI-C Driver Wizard.

If the IVI-C unit test project is not created by the wizard, then it can always be generated at any stage of driver development by right-clicking on the solution node in Solution Explorer and choosing Add New Project....

Structure of an IVI-C Unit Test

The IVI-C unit tests are contained within the IVI-C unit test project, named as follows:

<driverName>CDriverUnitTest

This Visual C++ project contains a single source file -- UnitTest.cpp. This source file contains one test function for each IVI-C function and attribute.

C++
Copy
// UnitTest.cpp
TEST_METHOD(ConfigureEdgeTriggerSource)
{
    ViStatus status = VI_SUCCESS;
    ViConstString Source = "External";
    ViReal64 Level = 0.1;
    ViInt32 Slope = ACME4321_VAL_NEGATIVE;
    status = acme4321_ConfigureEdgeTriggerSource(g_session, Source, Level, Slope);
    Assert::AreEqual(VI_SUCCESS, status);
}

The above code shows a test function for the ConfigureEdgeTriggerSource IVI-C function. The TEST_METHOD macro marks the function as being a unit test for the Visual Studio unit test execution engine.

The Assert::AreEqual method is used to check that the status returned from the ConfigureEdgeTriggerSource driver function is equal to VI_SUCCESS. If the comparison fails, then a test failure is reported.

Test Initialization and Shutdown

The IVI-C unit test code includes two special functions known as the initialize and cleanup functions. These two functions appear at the top of the UnitTest.cpp file and are declared with two special macros -- the TEST_METHOD_INITIALIZE macro and the TEST_METHOD_CLEANUP attribute. The code below shows two typical initialize and cleanup functions.

C++
Copy
// UnitTest.cpp
TEST_METHOD_INITIALIZE(Initialize)
{
    auto status = acme4321_InitWithOptions(g_resourceDesc, VI_TRUE, VI_TRUE, "QueryInstrStatus=True, Simulate=False, DriverSetup= ", &g_session);
    Assert::AreEqual(VI_SUCCESS, status);
}

TEST_METHOD_CLEANUP(Cleanup)
{
    if (g_session != VI_NULL)
    {
        auto status = acme4321_close(g_session);
        Assert::AreEqual(VI_SUCCESS, status);
        g_session = VI_NULL;
    }
}

The initialize function executes before each test method in the project, while the cleanup function executes after each test method. The primary role of the initialize function is to initialze the driver by calling the InitWithOptions function. If the init call is successful, then the driver session is stored in the g_session global variable. All of the test functions use the g_session to execute driver functions. Correspondingly, the role of the cleanup function is to close the driver session by executing the driver's close function on the global g_session.

Drivers that require special configuration or setup prior to testing methods can add custom code to the setup function. Though less common, custom code can also be added to the teardown function.

Running Unit Tests

The unit tests generated by Nimbus integrate directly with Visual Studio's native unit testing features. All unit test interaction is performed via the Test Explorer tool window.

Once the Test Explorerwindow is shown, executing tests proceeds in the exact same fashion as any other Visual Studio unit test. For details on working with the Visual Studio unit testing features, see the MSDN topic Verifying Code by Using Unit Tests.

See Also

Other Resources

Verifying Code by Using Unit Tests


The Nimbus Runtime Library (NRT)

The Nimbus Runtime Library (NRT) provides functions and classes used in implementing IVI-C drivers in Nimbus. The functionality in the NRT provides the base implementation of many of the IVI inherent capabilities as well as functions for managing repeated capabilities in IVI drivers and for formatting instrument commands for message-based devices. All of the NRT exists within a single file installed with Nimbus -- Nrt.h.

Understanding the NRT requires familiarity with C++ templates, the C++ Standard Library, and the features added to the C++ language with C++ 11. There are a wide variety of online resources for learning more about the C++ techniques used in the NRT.

The topics in this section provide a reference for classes and functions in the NRT that most commonly appear in IVI-C driver implementation code.

In This Section

DriverInfo Struct

DriverSession Class

EnumConverter Class

Miscellaneous Functions

Repeated Capability Functions

Simulation and State Caching Functions

Validation Functions


DriverInfo Struct

The Nimbus Runtime Library supplies the DriverInfo structure for controlling the standard Nimbus implementation of various IVI-defined functions. A single instance of this structure is maintained in the driver project's DriverInfo.cpp file.

A single, global instance of the DriverInfo structure is maintained in the DriverInfo.cpp file and managed by Nimbus. The table below explains each of the members and the role they play in controlling the Nimbus implementation of various functions. It is important that all of these members are controlled via various settings in the Driver Settings Editor. Changes made by directly editing the values in the DriverInfo.cpp will be overwritten by Nimbus.

Important note Important

All of the members below in the DriverInfo.cpp are routinely overwritten by Nimbus when the Driver Settings are modified. To change one of these values based on your driver, you must not edit the DriverInfo.cpp file.

DriverInfo Members
Member | Data Type | How to Set | Default | Description
DriverVendor | std::string | Driver Settings | Specified in wizard | Used to implement the SPECIFIC_DRIVER_VENDOR attribute.
DriverDescription | std::string | Driver Settings | Specified in wizard | Used to implement the SPECIFIC_DRIVER_DESCRIPTION attribute.
DriverRevision | std::string | Driver Settings | 0.1.0.0 | Used to implement the SPECIFIC_DRIVER_REVISION attribute.
GroupCapabilities | std::string | Driver Settings | All groups in selected classes | Used to implement the GROUP_CAPABILITIES attribute.
DefaultSimulatedModel | std::string | Driver Settings | First supported model | Used to determine which model is assumed when simulating and no Model option is passed to the InitWithOptions function.
SpecificationMajorVersion | int | Driver Settings | Major version of class spec | Used to implement the SPECIFIC_DRIVER_CLASS_SPEC_MAJOR_VERSION attribute.
SpecificationMinorVersion | int | Driver Settings | Minor version of class spec | Used to implement the SPECIFIC_DRIVER_CLASS_SPEC_MINOR_VERSION attribute.


DriverSession Class

The DriverSession class houses a great deal of the functionality in the Nimbus Runtime Library. Each IVI-C driver project contains a definition for a single DriverSession-derived class maintained in the driver project's DriverSession.h file. This class is named <driverProject>DriverSession, and a single instance of this class is created when a client application calls the driver's init or InitWithOptions function.

The driver session class serves a couple of very important roles in implementing an IVI-C driver. First, it serves as a repository for session-specific state. Each driver session must track the value of driver operational attriutes, such as the simulation state, the state of range checking, etc. Each driver session also holds the cached value of any attributes for which state caching has been enabled. It also holds special maps for supporting repeated capabilities.

The driver session class also provides a means to override the default behavior of certain driver operations provided by the Nimbus Runtime Library. For instance, drivers that do not use the VISA library for their I/O communications must override functions such as InitializeIO and CloseIO. These overrides are placed within the definition of the driver session class in the driver project's DriverSession.h file.

Because the driver session class plays such a central role in IVI-C driver operation, its functions can be accessed in two ways -- from within the DriverSession-derived class in the DriverSession.h file, and by using global functions from within a function or attribute implementation in the driver project's <prefix>.cpp file. Both forms are functionally equivalent and differ only the first parameter -- the ViSession parameter which must be supplied when accessing the driver session class from outside the class definition. For this reason, both forms of each function are presented together in this section.

In This Section

Configuration Store Functions

Driver State Functions

Error Reporting Functions

Instrument Model Functions

I/O Functions

Miscellaneous Functions

State Caching Functions


Configuration Store Functions

The IVI Configuration Store is used as a repository for a wide variety of information about an installed IVI driver. Some of the most important information stored is the set of physical repeated capability names supported by the driver, as well as the set of virtual repeated capability names configured by the user. IVI drivers must accept virtual names or physical names when referring to repeated capabilities. The functions in this section provide a simple means to translate between repeated capability physical and virtual names.

In This Section

DriverSession::ConfigSettings

DriverSession::GetConfigSetting

DriverSession::TranslatePhysicalName

DriverSession::TranslateVirtualName

DriverSession::VirtualNameMappings


DriverSession::ConfigSettings

Retrieves all of the configurable initial settings (of a particular type) associated with either the driver session or the software module in the IVI Configuration Store.

virtual const DriverSettingsMap<bool>& ConfigSettingsBoolean() const;
virtual const DriverSettingsMap<int>& ConfigSettingsInt32() const;
virtual const DriverSettingsMap<double>& ConfigSettingsReal64() const;
virtual const DriverSettingsMap<std::string>& ConfigSettingsString() const;

const DriverSettingsMap<bool>& ConfigSettingsBoolean(ViSession Vi);
const DriverSettingsMap<int>& ConfigSettingsInt32(ViSession Vi);
const DriverSettingsMap<double>& ConfigSettingsReal64(ViSession Vi);
const DriverSettingsMap<std::string>& ConfigSettingsString(ViSession Vi);
Parameters
Vi

[in] ViSession handle for the driver session.

Return Value

Returns a map of name-value pairs for all of the configurable initial settings loaded from the IVI Configuration Store. The map uses case-insensitive lookups for the setting name.

Remarks

The IVI Configuration Store supports arbitrary name-value pairs that can be associated with either a driver session or a software module. These name-value pairs are called configurable initial settings and can be set by the driver installer or they may be added or modified by an end user. The IVI specifications do not prescribe any particular use for configurable initial settings. They are intended as a means to store driver-defined data in a standard location that other drivers, tools, and application can readily access.

Nimbus automatically loads any configurable initial settings associated with the driver's IVI Configuration Store session or software module. Four different functions are provided to access the settings loaded during driver initialization -- one function for each of the four data types supported by the IVI Configuration Store.

This function is used to retrieve all of the configurable initial settings of a particular type. The DriverSettingsMap is simply an alias for a standard std::map with case-insensitive name lookup. To retrieve individual settings, see the GetConfigSetting Functions.

Example

The following code demonstrates use of the GetConfigSettingInt32 function:

C++
Copy
ViStatus _VI_FUNC acme4321_ConfigureSweep(ViSession Vi, ViReal64 StartFrequency, ViReal64 StopFrequency)
{
    auto settings = ConfigSettingsInt32(Vi);
    auto it = settings.find("MySetting");

    if (it != std::end(settings))
    {
        auto myValue = it->second;
    }

    // ...
}


DriverSession::GetConfigSetting

Retrieves the value of a configurable initial setting associated with either the driver session or the software module in the IVI Configuration Store.

virtual bool GetConfigSettingBoolean(const std::string& strName, bool& bValue) const;
virtual bool GetConfigSettingInt32(const std::string& strName, int& nValue) const;
virtual bool GetConfigSettingReal64(const std::string& strName, double& dValue) const;
virtual bool GetConfigSettingString(const std::string& strName, std::string& strValue) const;

bool GetConfigSettingBoolean(ViSession Vi, const std::string& strName, bool& bValue);
bool GetConfigSettingInt32(ViSession Vi, const std::string& strName, int& nValue);
bool GetConfigSettingReal64(ViSession Vi, const std::string& strName, double& dValue);
bool GetConfigSettingString(ViSession Vi, const std::string& strName, std::string& strValue);
Parameters
Vi

[in] ViSession handle for the driver session.

strName

[in] Name of the configurable initial setting to return. This name is case insensitive.

bValue, nValue, dValue, strValue

[out] Strongly typed value of the setting corresponding to the strName parameter. If the named value is not found, this parameter value is undefined.

Return Value

Returns true if the named value was loaded from the IVI Configuration Store and false otherwise.

Remarks

The IVI Configuration Store supports arbitrary name-value pairs that can be associated with either a driver session or a software module. These name-value pairs are called configurable initial settings and can be set by the driver installer or they may be added or modified by an end user. The IVI specifications do not prescribe any particular use for configurable initial settings. They are intended as a means to store driver-defined data in a standard location that other drivers, tools, and application can readily access.

Nimbus automatically loads any configurable initial settings associated with the driver's IVI Configuration Store session or software module. Four different functions are provided to access the settings loaded during driver initialization -- one function for each of the four data types supported by the IVI Configuration Store.

These functions are used to retrieve the settings individually. See the ConfigSettings functions to retrieve all loading settings at once.

Example

The following code demonstrates use of the GetConfigSettingInt32 function:

C++
Copy
ViStatus _VI_FUNC acme4321_ConfigureSweep(ViSession Vi, ViReal64 StartFrequency, ViReal64 StopFrequency)
{
    std::string strMySetting;
    auto bFound = GetConfigSettingInt32(Vi, "MySetting", strMySetting);
    assert(bFound);

    printf(strMySetting.c_str());

    // ...
}


DriverSession::TranslatePhysicalName

Returns the repeated capability virtual name associated with the specified physical name.

virtual const std::string TranslatePhysicalName(const std::string& strPhysicalName) const;

const std::string TranslatePhysicalName(ViSession Vi, const std::string& strPhysicalName);
Parameters
Vi

[in] ViSession handle for the driver session.

strPhysicalName

[in] Repeated capability physical name for which the corresponding virtual name should be returned.

Return Value

The repeated capability virtual name associated with the specified physical name. If the strPhysicalName supplied is not in the map then that same strPhysicalName value is returned.

Remarks

When a client application initializes an IVI driver using a logical name or a driver session name for the ResourceName parameter in the init or InitWithOptions function, the driver is required to load all of the repeated capability virtual names that the end user may have created in the IVI Configuration Store. The driver is then required to accept any of these virtual names as valid identifiers for repeated capabilities when the client application performs operations on repeated capability-based functions or attributes. The driver supports this functionality by translating virtual names, which are user-specified, to physical names, which are driver specified and which must ultimately be used in the driver implementation. The TranslatePhysicalName function exposes the capability to perform physical-name based lookups of virtual name mappsings.

The reverse operation of translating from physical names to virtual names is provided by the TranslateVirtualName function. In addition, the entire set of virtual-to-physical name mappings can be retrieved at once via the VirtualNameMappings Function.

For additional information on repeated capability virtual names and physical names, see the topic on Repeated Capabilities in the IVI Backgrounder section.


DriverSession::TranslateVirtualName

Returns the repeated capability physical name associated with the specified virtual name.

virtual const std::string TranslateVirtualName(const std::string& strVirtualName) const;

const std::string TranslateVirtualName(ViSession Vi, const std::string& strVirtualName);
Parameters
Vi

[in] ViSession handle for the driver session.

strVirtualName

[in] Repeated capability virtual name for which the corresponding physical name should be returned.

Return Value

The repeated capability physical name associated with the specified virtual name. If the strVirtualName supplied is not in the map then that same strVirtualName value is returned.

Remarks

When a client application initializes an IVI driver using a logical name or a driver session name for the ResourceName parameter in the init or InitWithOptions function, the driver is required to load all of the repeated capability virtual names that the end user may have created in the IVI Configuration Store. The driver is then required to accept any of these virtual names as valid identifiers for repeated capabilities when the client application performs operations on repeated capability-based functions or attributes. The driver supports this functionality by translating virtual names, which are user-specified, to physical names, which are driver specified and which must ultimately be used in the driver implementation. The TranslateVirtualName function exposes this translation capability.

The reverse operation of translating from physical names to virtual names is provided by the TranslatePhysicalName function. In addition, the entire set of virtual-to-physical name mappings can be retrieved at once via the VirtualNameMappings Function.

For additional information on repeated capability virtual names and physical names, see the topic on Repeated Capabilities in the IVI Backgrounder section.


DriverSession::VirtualNameMappings

Returns a map of virtual names to physical names for all virtual names loaded from the IVI Configuration Store when the driver was initialized.

virtual const VirtualNameMap& VirtualNameMappings() const;

const VirtualNameMap& VirtualNameMappings(ViSession Vi);
Parameters
Vi

[in] ViSession handle for the driver session.

Return Value

Returns a map of virtual names to physical names for all virtual names loaded from the IVI Configuration Store when the driver was initialized.

Remarks

If the ResourceName parameter passed to the init or InitWithOptions function does not map to a logcal name or driver session in the IVI Configuration Store, then this map will be empty.

The VirtualNameMap class returned here is simply an alias for a standard std::map with case-insensitive name lookup.

This function allows access to all of the virtual-to-physical name mappings at once. It is more common to need to translate individual virtual names to physical names and to translate individual physical names to virtual names. This functionality is provided by the TranslateVirtualName and TranslatePhysicalName functions. See the documentation for those functions for further information.

Example

The following code demonstrates how to use the GetDriverSetupOption function:

C++
Copy
ViStatus _VI_FUNC acme4321_ConfigureSweep(ViSession Vi, ViReal64 StartFrequency, ViReal64 StopFrequency)
{
    auto mappings = VirtualNameMappings(Vi);
    auto it = mappings.find("MyVirtualName");

    if (it != std::end(mappings))
    {
        printf(it->second.c_str());    // prints the physical name mapped to "MyVirtualName" in the config store
    }

    // ...
}


Driver State Functions

A number of IVI driver settings that control the operation of the driver can be specified by the end user in a variety of ways. For instance, the end user can enable state caching by specifying it in the IVI Configuration Store. Alternatively, they can pass in Cache=VI_TRUE as part of the OptionsString parameter passed to the InitWithOptions function. Or, the user can set the CACHE attribute on the driver itself at any time during the execution of the program.

Given the flexibility users have in specifying certain driver settings, it is difficult to manually track the current state of these settings. The functions described in this section are provided expressly for that purpose.

In This Section

DriverSession::CacheEnabled

DriverSession::CacheEnabledOriginal

DriverSession::InterchangeCheckEnabled

DriverSession::InterchangeCheckEnabledOriginal

DriverSession::QueryInstrStatusEnabled

DriverSession::QueryInstrStatusEnabledOriginal

DriverSession::RangeCheckEnabled

DriverSession::RangeCheckEnabledOriginal

DriverSession::RecordCoercionsEnabled

DriverSession::RecordCoercionsEnabledOriginal

DriverSession::SimulationEnabled

DriverSession::SimulationEnabledOriginal

DriverSession::SetCacheEnabled

DriverSession::SetInterchangeCheckEnabled

DriverSession::SetQueryInstrStatusEnabled

DriverSession::SetRangeCheckEnabled

DriverSession::SetRecordCoercionsEnabled

DriverSession::SetSimulationEnabled

DriverSession::ResetDefaults

DriverSession::InitOptions

DriverSession::InherentOptions

DriverSession::DriverSetup

DriverSession::GetDriverSetupOption

DriverSession::DriverSetupOptions


DriverSession::CacheEnabled

Indicates if state caching is currently enabled for the driver session.

virtual bool CacheEnabled() const;

bool CacheEnabled(ViSession Vi);
Parameters
Vi

[in] ViSession handle for the driver session.

Return Value

Returns true if state caching is currently enabled and false otherwise.

Remarks

This value is initially set at driver initialization time by interrogating both the OptionsString parameter to the InitWithOptions function and any session information the user may have configured in the IVI Configuration Store. After session initialization, the client application may change this value via the CACHE attribute.


DriverSession::CacheEnabledOriginal

Indicates if state caching was enabled for the driver session when the session was originally initialized.

virtual bool CacheEnabledOriginal() const;

bool CacheEnabledOriginal(ViSession Vi);
Parameters
Vi

[in] ViSession handle for the driver session.

Return Value

Returns true if state caching was enabled for the driver session when the session was orginally initialized and false otherwise.

Remarks

This value is initially set at driver initialization time by interrogating both the OptionsString parameter to the InitWithOptions function and any session information the user may have configured in the IVI Configuration Store. Unlike the CacheEnabled function, which returns a value that can change over the lifetime of a driver session, this function always returns the initial value at session initialization time.


DriverSession::InterchangeCheckEnabled

Indicates if interchangeability checking is currently enabled for the driver session.

virtual bool InterchangeCheckEnabled() const;

bool InterchangeCheckEnabled(ViSession Vi);
Parameters
Vi

[in] ViSession handle for the driver session.

Return Value

Returns true if interchangeability checking is currently enabled and false otherwise.

Remarks

This value is initially set at driver initialization time by interrogating both the OptionsString parameter to the InitWithOptions function and any session information the user may have configured in the IVI Configuration Store. After session initialization, the client application may change this value via the INTERCHANGE_CHECK attribute.


DriverSession::InterchangeCheckEnabledOriginal

Indicates if interchangeability checking was enabled for the driver session when the session was originally initialized.

virtual bool InterchangeCheckEnabledOriginal() const;

bool InterchangeCheckEnabledOriginal(ViSession Vi);
Parameters
Vi

[in] ViSession handle for the driver session.

Return Value

Returns true if interchangeability checking was enabled for the driver session when the session was orginally initialized and false otherwise.

Remarks

This value is initially set at driver initialization time by interrogating both the OptionsString parameter to the InitWithOptions function and any session information the user may have configured in the IVI Configuration Store. Unlike the InterchangeCheckEnabled function, which returns a value that can change over the lifetime of a driver session, this function always returns the initial value at session initialization time.


DriverSession::QueryInstrStatusEnabled

Indicates if instrument error polling is currently enabled for the driver session.

virtual bool QueryInstrStatusEnabled() const;

bool QueryInstrStatusEnabled(ViSession Vi);
Parameters
Vi

[in] ViSession handle for the driver session.

Return Value

Returns true if range checking is currently enabled and false otherwise.

Remarks

This value is initially set at driver initialization time by interrogating both the OptionsString parameter to the InitWithOptions function and any session information the user may have configured in the IVI Configuration Store. After session initialization, the client application may change this value via the QUERY_INSTR_STATUS attribute.


DriverSession::QueryInstrStatusEnabledOriginal

Indicates if instrument error polling was enabled for the driver session when the session was originally initialized.

virtual bool QueryInstrStatusEnabledOriginal() const;

bool QueryInstrStatusEnabledOriginal(ViSession Vi);
Parameters
Vi

[in] ViSession handle for the driver session.

Return Value

Returns true if instrument error polling was enabled for the driver session when the session was orginally initialized and false otherwise.

Remarks

This value is initially set at driver initialization time by interrogating both the OptionsString parameter to the InitWithOptions function and any session information the user may have configured in the IVI Configuration Store. Unlike the QueryInstrStatusEnabled function, which returns a value that can change over the lifetime of a driver session, this function always returns the initial value at session initialization time.


DriverSession::RangeCheckEnabled

Indicates if range checking is currently enabled for the driver session.

virtual bool RangeCheckEnabled() const;

bool RangeCheckEnabled(ViSession Vi);
Parameters
Vi

[in] ViSession handle for the driver session.

Return Value

Returns true if state caching is currently enabled and false otherwise.

Remarks

This value is initially set at driver initialization time by interrogating both the OptionsString parameter to the InitWithOptions function and any session information the user may have configured in the IVI Configuration Store. After session initialization, the client application may change this value via the RANGE_CHECK attribute.


DriverSession::RangeCheckEnabledOriginal

Indicates if range checking was enabled for the driver session when the session was originally initialized.

virtual bool RangeCheckEnabledOriginal() const;

bool RangeCheckEnabledOriginal(ViSession Vi);
Parameters
Vi

[in] ViSession handle for the driver session.

Return Value

Returns true if range checking was enabled for the driver session when the session was orginally initialized and false otherwise.

Remarks

This value is initially set at driver initialization time by interrogating both the OptionsString parameter to the InitWithOptions function and any session information the user may have configured in the IVI Configuration Store. Unlike the RangeCheckEnabled function, which returns a value that can change over the lifetime of a driver session, this function always returns the initial value at session initialization time.


DriverSession::RecordCoercionsEnabled

Indicates if coercion recording is currently enabled for the driver session.

virtual bool RecordCoercionsEnabled() const;

bool RecordCoercionsEnabled(ViSession Vi);
Parameters
Vi

[in] ViSession handle for the driver session.

Return Value

Returns true if coercion recording is currently enabled and false otherwise.

Remarks

This value is initially set at driver initialization time by interrogating both the OptionsString parameter to the InitWithOptions function and any session information the user may have configured in the IVI Configuration Store. After session initialization, the client application may change this value via the RECORD_COERCIONS attribute.


DriverSession::RecordCoercionsEnabledOriginal

Indicates if coercion recording was enabled for the driver session when the session was originally initialized.

virtual bool RecordCoercionsEnabledOriginal() const;

bool RecordCoercionsEnabledOriginal(ViSession Vi);
Parameters
Vi

[in] ViSession handle for the driver session.

Return Value

Returns true if coercion recording was enabled for the driver session when the session was orginally initialized and false otherwise.

Remarks

This value is initially set at driver initialization time by interrogating both the OptionsString parameter to the InitWithOptions function and any session information the user may have configured in the IVI Configuration Store. Unlike the RecordCoercions function, which returns a value that can change over the lifetime of a driver session, this function always returns the initial value at session initialization time.


DriverSession::SimulationEnabled

Indicates if simulation is currently enabled for the driver session.

virtual bool SimulationEnabled() const;

bool SimulationEnabled(ViSession Vi);
Parameters
Vi

[in] ViSession handle for the driver session.

Return Value

Returns true if simulation is currently enabled and false otherwise.

Remarks

This value is initially set at driver initialization time by interrogating both the OptionsString parameter to the InitWithOptions function and any session information the user may have configured in the IVI Configuration Store. After session initialization, the client application may change this value via the SIMULATE attribute.


DriverSession::SimulationEnabledOriginal

Indicates if simulation was enabled for the driver session when the session was originally initialized.

virtual bool SimulationEnabledOriginal() const;

bool SimulationEnabledOriginal(ViSession Vi);
Parameters
Vi

[in] ViSession handle for the driver session.

Return Value

Returns true if simulation was enabled for the driver session when the session was orginally initialized and false otherwise.

Remarks

This value is initially set at driver initialization time by interrogating both the OptionsString parameter to the InitWithOptions function and any session information the user may have configured in the IVI Configuration Store. Unlike the SimulationEnabled function, which returns a value that can change over the lifetime of a driver session, this function always returns the initial value at session initialization time.


DriverSession::SetCacheEnabled

Enables or disables state caching for the driver session.

virtual void SetCacheEnabled(bool bValue);

void SetCacheEnabled(ViSession Vi, bool bValue);
Parameters
Vi

[in] ViSession handle for the driver session.

bValue

[in] Set to True to enable state caching or False to disable it.


DriverSession::SetInterchangeCheckEnabled

Enables or disables interchangeability checking for the driver session.

virtual void SetInterchangeCheckEnabled(bool bValue);

void SetInterchangeCheckEnabled(ViSession Vi, bool bValue);
Parameters
Vi

[in] ViSession handle for the driver session.

bValue

[in] Set to True to enable interchangeability checking or False to disable it.


DriverSession::SetQueryInstrStatusEnabled

Enables or disables intrument error polling for the driver session.

virtual void SetQueryInstrStatusEnabled(bool bValue);

void SetQueryInstrStatusEnabled(ViSession Vi, bool bValue);
Parameters
Vi

[in] ViSession handle for the driver session.

bValue

[in] Set to True to enable instrument error polling or False to disable it.


DriverSession::SetRangeCheckEnabled

Enables or disables range checking for the driver session.

virtual void SetRangeCheckEnabled(bool bValue);

void SetRangeCheckEnabled(ViSession Vi, bool bValue);
Parameters
Vi

[in] ViSession handle for the driver session.

bValue

[in] Set to True to enable range checking or False to disable it.


DriverSession::SetRecordCoercionsEnabled

Enables or disables coercion recording for the driver session.

virtual void SetRecordCoercionsEnabled(bool bValue);

void SetRecordCoercionsEnabled(ViSession Vi, bool bValue);
Parameters
Vi

[in] ViSession handle for the driver session.

bValue

[in] Set to True to enable coercion recording or False to disable it.


DriverSession::SetSimulationEnabled

Enables or disables simulation for the driver session.

virtual void SetSimulationEnabled(bool bValue);

void SetSimulationEnabled(ViSession Vi, bool bValue);
Parameters
Vi

[in] ViSession handle for the driver session.

bValue

[in] Set to True to enable simulation or False to disable it.


DriverSession::ResetDefaults

Configures the initial settings for the driver and instrument based on the settings loaded from the IVI Configuration Store the driver session was initialized.

virtual ViStatus ResetDefaults();
Remarks

This function is used in the implementation of the IVI-defined ResetWithDefaults function. The ResetWithDefaults function performs the same operations as the reset function and then applies the settings to the driver that were initially in effect when the driver session was initialized.

The default implementation of ResetDefaults restores the six IVI-defined inherent initialization options to the original values they had when the driver session was initialized. These six IVI-defined inherent options are Cache, InterchangeCheck, QueryInstrStatus, RangeCheck, RecordCoercions, and Simulate.

Rather than customize the implementation of the ResetWithDefaults function directly, driver developers can override the ResetDefaults function in their DriverSession-derived class in the DriverSession.h file in order to apply additional initial settings. The example below demonstrates this.

Example

The following code demonstrates how to override the InstrumentSupported function to implement custom model validation logic:

C++
Copy
// DriverSession.h
class Acme4321DriverSession : public DriverSession
{
public:
    Acme4321DriverSession(ViSession handle)
        : DriverSession(handle, 2000, 2000, 2000, false, 1000)
    {
    }

    virtual ViStatus ResetDefaults()
    {
        // It's important to always call the base implementation, because the standard IVI inherent options, such as
        // state caching, range checking, simulation, etc, all need to be set to their original values.
        //
        auto status = __super::ResetDefaults();
        ReturnOnError(status);

        // Read a driver-defined configurable initial setting and use it to perform some driver-specific re-initialization
        //
        std::string strMySetting;
        auto bFound = GetConfigSettingInt32(Vi, "MySetting", strMySetting);
        assert(bFound);

        // ... Use the strMySetting to reset some piece of driver state

        return status;
    }
};


DriverSession::InitOptions

Returns the contents of the OptionsString parameter that was passed to the InitWithOptions function when the session was created.

virtual const std::string& InitOptions() const;

const std::string& InitOptions(ViSession Vi);
Parameters
Vi

[in] ViSession handle for the driver session.

Return Value

Returns the string containing the entire contents of the OptionsString parameter passed to the InitWithOptions function.


DriverSession::InherentOptions

Returns a map of the inherent options passed to the InitWithOptions function when the driver session was created.

virtual const DriverSettingsMap<std::string>& InherentOptions() const;

const DriverSettingsMap<std::string>& InherentOptions(ViSession Vi);
Parameters
Vi

[in] ViSession handle for the driver session.

Return Value

A map of name-value pairs representing the values of all inherent options passed to the InitWithOptions function when the driver session was created. The map returned uses case-insensitive lookups for the option name.

Remarks

The IVI specifications define six inherent options (in addition to the DriverSetup) option that maybe be passed in the OptionsString parameter to the InitWithOptions function. These six inherent options are:

  • Cache

  • InterchangeCheck

  • QueryInstrStatus

  • RangeCheck

  • RecordCoercions

  • Simulate

The DriverSettingsMap is simply an alias for a standard std::map with case-insensitive name lookup.

Important note Important

The values stored in this map do not represent values that may have been loaded from the IVI Configuration Store during initialization nor do they necessarily represent the current values of the corresponding IVI driver attributes. To retrieve the current values of the corresponding attributes use functions such as CacheEnabled and SimulationEnabled or CacheEnabledOriginal and SimulationEnabledOriginal. Those functions take into account values that may have been loaded from the IVI Configuration Store as well as changes to the values that the user may have performed after the driver was initialized.

Example

The following code demonstrates use of the InherentOptions function:

C++
Copy
ViStatus _VI_FUNC acme4321_ConfigureSweep(ViSession Vi, ViReal64 StartFrequency, ViReal64 StopFrequency)
{
    auto options = InherentOptions(Vi);
    auto it = options.find("simulate");

    if (it != std::end(options))
    {
        auto strSimulate = it->second;
    }

    // ...
}


DriverSession::DriverSetup

Returns the DriverSetup option that was passed as part of the OptionsString parameter to the InitWithOptions function when the driver session was created or that was read from the IVI Configuration Store.

virtual const std::string& DriverSetup() const;

const std::string& DriverSetup(ViSession Vi);
Parameters
Vi

[in] ViSession handle for the driver session.

Return Value

Returns the DriverSetup string associated with the driver session.

Remarks

This function returns the DriverSetup string that was either passed to the driver upon initialization or that was read from the IVI Configuration Store. The DriverSetup string is typically parsed by Nimbus into a set of name-value pairs. This function returns the entire string with no processing.


DriverSession::GetDriverSetupOption

Retrieves the value of an option passed as part of the DriverSetup string during driver initialization.

virtual bool GetDriverSetupOption(const std::string& strName, std::string& strValue) const;

bool GetDriverSetupOption(ViSession Vi, const std::string& strName, std::string& strValue);
Parameters
Vi

[in] ViSession handle for the driver session.

strName

[in] Name of the DriverSetup option to return. This name is case insensitive.

strValue

[out] Value of the DriverSetup option corresponding to the strName parameter. If the named value is not found, this parameter value is undefined.

Return Value

Returns true if the named value was passed as part of the DriverSetup string and false otherwise.

Remarks

When the driver is initialized, Nimbus parses the DriverSetup string into name-value pairs and stores them with the session. Note that the DriverSetup string may be passed directly to the driver's InitWithOptions function or it may be read from the IVI Configuration Store. This function is used to retrieve the results of that DriverSetup string parsing. This provides a simple mechanism to define and process driver-specific initialization options.

Example

The following code demonstrates how to use the GetDriverSetupOption function:

C++
Copy
/////////////////////////
// Client.cpp
//
// Client code initializes the driver.
//
ViSession session;
ViStatus status = acme4321_InitWithOptions("GPIB0::13", VI_FALSE, VI_FALSE, "Cache=VI_TRUE, DriverSetup= Model=ModelA, MyOption=Foo, YourOption=Bar", &session);

/////////////////////////
// acme4321.cpp
//
// Driver implementation access the parsed DriverSetup name-value pairs.
//
ViStatus _VI_FUNC acme4321_ConfigureSweep(ViSession Vi, ViReal64 StartFrequency, ViReal64 StopFrequency)
{
    std::string strMyOption;
    auto bFound = GetDriverSetupOption(Vi, "MyOption", strMyOption);
    assert(bFound);

    printf(strMyOption.c_str());    // prints "Foo"

    std::string strYourOption;
    bFound = GetDriverSetupOption(Vi, "YourOption", strYourOption);
    assert(bFound);

    printf(strYourOption.c_str());  // prints "Bar"

    // ...
}


DriverSession::DriverSetupOptions

Retrieves a map of all name-value pairs parsed from the DriverSetup string during initialization.

virtual const DriverSettingsMap<std::string>& DriverSetupOptions() const;

const DriverSettingsMap<std::string>& DriverSetupOptions(ViSession Vi);
Parameters
Vi

[in] ViSession handle for the driver session.

Return Value

Returns a map of all name-value pairs parsed from the DriverSetup string during initialization.

Remarks

This function allows all name-value pairs from the DriverSetup string to be retrieved at once. To retrieve individual values, use the GetDriverSetupOption function.

The DriverSettingsMap is simply an alias for a standard std::map with case-insensitive name lookup.

Example

The following code demonstrates how to use the GetDriverSetupOption function:

C++
Copy
/////////////////////////
// Client.cpp
//
// Client code initializes the driver.
//
ViSession session;
ViStatus status = acme4321_InitWithOptions("GPIB0::13", VI_FALSE, VI_FALSE, "Cache=VI_TRUE, DriverSetup= Model=ModelA, MyOption=Foo, YourOption=Bar", &session);

/////////////////////////
// acme4321.cpp
//
// Driver implementation access the parsed DriverSetup name-value pairs.
//
ViStatus _VI_FUNC acme4321_ConfigureSweep(ViSession Vi, ViReal64 StartFrequency, ViReal64 StopFrequency)
{
    auto options = DriverSetupOptions(Vi);
    auto it = options.find("MyOption");

    if (it != std::end(options))
    {
        printf(it->second.c_str());    // prints "Foo"
    }

    it = options.find("YourOption");

    if (it != std::end(options))
    {
        printf(it->second.c_str());    // prints "Bar"
    }

    // ...
}


Error Reporting Functions

IVI-C drivers are required to report ViStatus error codes and to compose a useful error message. Both the error message and error code must be associated with the driver session so that a client application can retrieve the error message and error code via the standard IVI-defined GetError function. The functions in this section provide a convenient mechanism for reporting errors from IVI-C driver implementation code.

In This Section

DriverSession::ReportError

DriverSession::ReportErrorEx


DriverSession::ReportError

Constructs a formatted error message based on the message associated with the specified error code and then associates the error code and the error message with the driver session.

virtual ViStatus ReportError(ViStatus errorCode, ...) const;

ViStatus ReportError(ViSession Vi, ViStatus errorCode, ...);
Parameters
Vi

[in] ViSession handle for the driver session.

errorCode

[in] The errorCode to report to the calling program.

... (variable argument list)

[in] Comma-separated list of string arguments to use in formatting the error message.

Return Value

The same ViStatus error code supplied as the errorCode parameter.

Remarks

This function is used to report errors from IVI-C driver implementation code. It performs two important tasks. First, it formats the error message associated with the specified error code. Nimbus maintains a an error message macro map in the driver project's Errors.cpp file. Each entry in that map associates an error code with an error message and this association drives the implementation of the ReportError function's message formatting.

The second task performed by this function is to associate the error code and formatted error message with the driver session so that the client application can use the standard IVI-defined GetError function to retrieve both the error code and the formatted error message.

Important note Important

Because this function necessarily uses variable argument lists, there are two common mistakes that can be made with the ReportError function. The first error is to supply a different number of string arguments than are defined in the error message. Such a mismatch between the number of replacement tags in the error message and the number of string arguments supplied can produce unpredictable results, including program crashes. You can view the definition of an error message and the number of replacement tags ('%s' characters) via the Error Editor or by directly looking at the error message macro map in the driver project's Errors.cpp file.

The second common mistake that can be made with the ReportError function is to supply a std::string argument instead of a plain ANSI-C string (i.e. a char*). If you wish to use a std::string argument, then simply access the c_str() member or the data() member by supplying an expression such as strMyArg.c_str().

Example

The following example demonstrates use of the ReportError function.

C++
Copy
ViStatus _VI_FUNC acme4321_ConfigureArmCount(ViSession Vi, ViConstString RepCapIdentifier, ViInt32 ArmCount)
{
    // ...

    // The INVALID_VALUE error message is defined to have 3 string parameters, as follows:
    //
    //  "Invalid value '%1' for method '%2', parameter '%3'.
    //

    if (AttributeValue < 0)
    {
        // WRONG!! WRONG!! -- Don't do this. The std::to_string function returns a std::string, not a char*
        //
        return ReportError(Vi, ACME4321_ERROR_INVALID_VALUE, std::to_string(AttributeValue), "ConfigureArmCount", "ArmCount");

        // WRONG!! WRONG!! -- Don't do this. The INVALID_VALUE message needs 3 arguments, not just two
        //
        return ReportError(Vi, ACME4321_ERROR_INVALID_VALUE, std::to_string(AttributeValue).c_str(), "ConfigureArmCount");

        // Correct use.
        //
        return ReportError(Vi, ACME4321_ERROR_INVALID_VALUE, std::to_string(AttributeValue).c_str(), "ConfigureArmCount", "ArmCount");
    }
}


DriverSession::ReportErrorEx

Constructs a formatted error message based on the message associated with the specified error code and then associates the error code and the error message with the driver session.

virtual ViStatus ReportErrorEx(ViStatus errorCode, const std::string strElaboration, ...) const;

ViStatus ReportErrorEx(ViSession Vi, ViStatus errorCode, const std::string strElaboration, ...);
Parameters
Vi

[in] ViSession handle for the driver session.

errorCode

[in] The errorCode to report to the calling program.

strElaboration

[in] Additional information to append to the formatted error message associated with the specified errorCode.

... (variable argument list)

[in] Comma-separated list of string arguments to use in formatting the error message.

Return Value

The same ViStatus error code supplied as the errorCode parameter.

Remarks

This function is functionally equivalent to the ReportError function except that an additional strElaboration parameter is available for appending custom information about the particular error occurrence. See the documentation of the ReportError function for additional information.

The string arguments supplied to the ReportErrorEx function are used to format the error message associated with the specified errorCode and to format the strElaboration. The arguments are first used to replace an '%s' tags in the error message associated with the error code and then the remaining arguments are used to replace any '%s' tags in the strElaboration string. Getting the order of string arguments correct is crucial in composing a properly formatted error message.

Important note Important

Because this function necessarily uses variable argument lists, there are three common mistakes that can be made with the ReportError function. The first error is to supply a different number of string arguments than are defined in the error message. Such a mismatch between the number of replacement tags in the error message and the number of string arguments supplied can produce unpredictable results, including program crashes. You can view the definition of an error message and the number of replacement tags ('%s' characters) via the Error Editor or by directly looking at the error message macro map in the driver project's Errors.cpp file.

The second common mistake that can be made with the ReportErrorEx function is to supply a std::string argument instead of a plain ANSI-C string (i.e. a char*). If you wish to use a std::string argument, then simply access the c_str() member or the data() member by supplying an expression such as strMyArg.c_str().

The third common mistake that can be made with the ReportErrorEx function is to specify the string arguments for the strElaboration parameter before those for the error message associated with the error code. The arguments supplied are first used to format the error message associated with the error code and then any remaining arguments are used to format the strElaboration parameter.

Example

The following example demonstrates use of the ReportError function.

C++
Copy
ViStatus _VI_FUNC acme4321_ConfigureArmCount(ViSession Vi, ViConstString RepCapIdentifier, ViInt32 ArmCount)
{
    // ...

    // The FUNCTION_NOT_SUPPORTED error message is defined to have 1 string parameter, as follows:
    //
    // Does not support this class-compliant feature: method '%1'
    //

    if (AttributeValue < 0)
    {
        // WRONG!! WRONG!! -- Don't do this. The InstrumentModel function returns a std::string, not a char*
        //
        return ReportErrorEx(Vi, ACME4321_ERROR_FUNCTION_NOT_SUPPORTED, "Function is not supported for instrument model '%s'", "ConfigureArmCount", InstrumentModel());

        // WRONG!! WRONG!! -- Don't do this. We need a total of two arguments, not just one
        //
        return ReportErrorEx(Vi, ACME4321_ERROR_FUNCTION_NOT_SUPPORTED, "Function is not supported for instrument model '%s'", "ConfigureArmCount");

        // WRONG!! WRONG!! -- Don't do this. The instrument model will be used to format the FUNCTION_NOT_SUPPORTED message instead of the elaboration message
        //
        return ReportErrorEx(Vi, ACME4321_ERROR_FUNCTION_NOT_SUPPORTED, "Function is not supported for instrument model '%s'", InstrumentModel().c_str(), "ConfigureArmCount");

        // Correct use.
        //
        return ReportErrorEx(Vi, ACME4321_ERROR_FUNCTION_NOT_SUPPORTED, "Function is not supported for instrument model '%s'", "ConfigureArmCount", InstrumentModel().c_str());
    }
}


Instrument Model Functions

During the initialization sequence of a Nimbus IVI driver, the connected instrument model is detected and stored within the driver itself. The functions described in this section provide access to basic information about the connected instrument model.

In This Section

DriverSession::InstrumentInFamily

DriverSession::InstrumentIsModel

DriverSession::InstrumentModel

DriverSession::InstrumentSupported

DriverSession::ModelInFamily


DriverSession::InstrumentInFamily

Indicates if the connected instrument (or model being simulated) is a member of the specified instrument family.

virtual bool InstrumentInFamily(const std::string& strFamily) const;

bool InstrumentInFamily(ViSession Vi, const std::string& strFamily);
Parameters
Vi

[in] ViSession handle for the driver session.

strFamily

[in] The instrument family to test the connected instrument model against for membership.

Return Value

Returns true if the connected instrument (or the model being simulated) is a member of the specified instrument family and false otherwise.

Remarks

The list of instrument models and their instrument family association is configured using the Models Property Page.


DriverSession::InstrumentIsModel

Indicates if the connected instrument (or model being simulated) is the same as the specified model.

virtual bool InstrumentIsModel(const std::string& strModel) const;

bool InstrumentIsModel(ViSession Vi, const std::string& strModel);
Parameters
Vi

[in] ViSession handle for the driver session.

strModel

[in] The instrument model to test against the current instrument model.

Return Value

Returns true if the connected instrument (or the model being simulated) is the same as the specified model and false otherwise.

Remarks

The list of instrument models and their instrument family association is configured using the Models Property Page.


DriverSession::InstrumentModel

Returns the instrument model of the device with which the driver is communicating.

virtual const std::string& InstrumentModel() const;

const std::string& InstrumentModel(ViSession Vi);
Parameters
Vi

[in] ViSession handle for the driver session.

Return Value

Returns the instrument model of the device with which the driver is communicating.

Remarks

The value returned here is set by the implementation of the GetIdentificationInfo function. By default, Nimbus implements the GetIdentificationInfo by sending a *IDN? query to the instrument and parsing an IEEE 488.2 response.

When simulating, this function returns the Model value passed as part of the DriverSetup string. If no Model value was passed to the driver initialization function, then the default instrument model is returned when simulating.


DriverSession::InstrumentSupported

Indicates if the connected instrument (or model being simulated) is supported by the driver.

virtual bool InstrumentSupported() const;

bool InstrumentSupported(ViSession Vi);
Parameters
Vi

[in] ViSession handle for the driver session.

Return Value

Returns true if the connected instrument (or the model being simulated) is supported by the driver and false otherwise.

Remarks

The value for the instrument model tested here is set by the implementation of the GetIdentificationInfo function. By default, Nimbus implements the GetIdentificationInfo by sending a *IDN? query to the instrument and parsing an IEEE 488.2 response. The model parsed from this response is then compared to the list of models configured on the Models Property Page.

Driver developers can override this function in their DriverSession-derived class in the DriverSession.h file in order to provide different comparison logic for validating the connected instrument model. The example below demonstrates this.

When simulating, the model used is set by the Model value passed as part of the DriverSetup string. If no Model value was passed to the driver initialization function, then the default instrument model is returned when simulating.

Example

The following code demonstrates how to override the InstrumentSupported function to implement custom model validation logic:

C++
Copy
// DriverSession.h
class Acme4321DriverSession : public DriverSession
{
public:
    Acme4321DriverSession(ViSession handle)
        : DriverSession(handle, 2000, 2000, 2000, false, 1000)
    {
    }

    virtual bool InstrumentSupported() const
    {
        // Check the static list of models first
        //
        auto bSupported = __super::InstrumentSupported();

        if (!bSupported)
        {
            // Doesn't match a pre-configured model, so try a regular expression
            //
            static const std::regex rx("MODEL[a-eA-E]", std::regex_constants::icase);

            bSupported = std::regex_match(InstrumentModel(), rx);
        }

        return bSupported;
    }
};


DriverSession::ModelInFamily

Indicates if the specified instrument model is a member of the specified instrument family.

virtual bool ModelInFamily(const std::string& strModel, const std::string& strFamily) const;

bool ModelInFamily(ViSession Vi, const std::string& strModel, const std::string& strFamily);
Parameters
Vi

[in] ViSession handle for the driver session.

strModel

[in] The instrument model to test against membership in the specified strFamily.

strFamily

[in] The instrument family to test the specified strModel against for membership.

Return Value

Returns true if the specified instrument model is a member of the specified instrument family and false otherwise.

Remarks

The list of instrument models and their instrument family association is configured using the Models Property Page.


I/O Functions

The functions in this section provide control over creating, clearing and managing the I/O connection between the IVI-C driver and the instrument. When creating an IVI driver that is not using the standard VISA library for instrument communication, several of these functions will have to be overridden in the driver's DriverSession-derived class maintained in the DriverSesion.h file.

In This Section

DriverSession::ClearIOStatus

DriverSession::CloseIO

DriverSession::GetIdentificationInfo

DriverSession::GetVisaResourceManager

DriverSession::GetVisaSession

DriverSession::InitializeIO

DriverSession::PollInstrumentErrors


DriverSession::ClearIOStatus

Clears out any I/O errors that may be in the device at initialization.

virtual ViStatus ClearIOStatus();

ViStatus ClearIOStatus(ViSession Vi);
Parameters
Vi

[in] ViSession handle for the driver session.

Return Value

Returns a VI_SUCCESS if the operation was successful or a failure ViStatus otherwise.

Remarks

This function is automatically called as part of driver initialization and is used to clear out any I/O errors that may be in the device at initialization. This allows the user to initialize the driver, even if the device is in an error state. By default, this function will use the VISA library to send a *CLS command to the instrument. In simulation mode, this function should do nothing.

Important note Important

This function must be overridden for drivers that need to use something other than a VISA-based *CLS command for clearing the instrument I/O status.

Example

The following code demonstrates how to override the ClearIOStatus function:

C++
Copy
// DriverSession.h
class Acme4321DriverSession : public DriverSession
{
public:
    Acme4321DriverSession(ViSession handle)
        : DriverSession(handle, 2000, 2000, 2000, false, 1000)
    {
    }

    virtual ViStatus ClearIOStatus() override
    {
        ViStatus status = VI_SUCCESS;

        status = viPrintf(GetVisaSession(), "STAT:CLEAR\n");

        return status;
    }
};


DriverSession::CloseIO

Closes the I/O connection with the instrument.

virtual ViStatus CloseIO();

ViStatus CloseIO(ViSession Vi);
Parameters
Vi

[in] ViSession handle for the driver session.

Return Value

Returns a VI_SUCCESS if the operation was successful or a failure ViStatus otherwise.

Remarks

This function is automatically called as part of driver shutdown and is used to sever the I/O connection with the instrument. By default, Nimbus uses the VISA library viClose function to sever the connection with the instrument.

Important note Important

This function must be overridden for non-VISA-based drivers to perform custom I/O shutdown and to release any custom I/O resources.

Example

The following code demonstrates how to override the CloseIO function:

C++
Copy
// DriverSession.h
class Acme4321DriverSession : public DriverSession
{
public:
    Acme4321DriverSession(ViSession handle)
        : DriverSession(handle, 2000, 2000, 2000, false, 1000)
    {
    }

    virtual ViStatus CloseIO() override
    {
        // We're still using VISA, so we delegate to the base class, but then we perform custom post-processing.
        // Non-VISA-based drivers would override in a similar fashion but *not* delegate to the base.  Rather,
        // they would perform a custom operation such as invoking functions on a helper DLL specific to the
        // I/O protocol in use.
        //
        auto status = __super::CloseIO();
        ReturnOnError(status);

        // ... free up additional driver specific resources.

        return status;
    }
};


DriverSession::GetIdentificationInfo

Sets the instrument model, manufacturer, serial number, and firmware revision used in implementing various driver functions.

virtual ViStatus GetIdentificationInfo(std::string& strManufacturer, std::string& strModel, std::string& strSerialNumber, std::string& strFirmwareRevision);
Parameters
strManufacturer

[out] The instrument manufacturer for the connected device.

strModel

[out] The model of the connected device.

strSerialNumber

[out] The serial number of the connected device.

strFirmwareRevision

[out] The firmware revision of the connected device.

Return Value

Returns a VI_SUCCESS if the operation was successful or a failure ViStatus otherwise.

Remarks

This function is automatically called as part of driver initialization and is used to set important instrument identification data stored in the driver session. By default, this function will use the VISA library to send a *IDN? query and it will expect a standard IEEE 488.2 response.

Important note Important

This function must be overridden for drivers that need to something other than a VISA-based *IDN? query for identifying the connected instrument.

Example

The following code demonstrates how to override the GetIdentificationInfo function:

C++
Copy
// DriverSession.h
class Acme4321DriverSession : public DriverSession
{
public:
    Acme4321DriverSession(ViSession handle)
        : DriverSession(handle, 2000, 2000, 2000, false, 1000)
    {
    }

    virtual ViStatus GetIdentificationInfo(std::string& strManufacturer, std::string& strModel, std::string& strSerialNumber, std::string& strFirmwareRevision) override
    {
        ViStatus status = VI_SUCCESS;

        // Query the instrument for its ID string using the command "SYST:ID?"
        //
        // The instrument returns an ID string in the following form:
        //
        //   <manufacturer>;<serialNumber>;<firmwareRevision>;<model>
        //
        char szManufacturer[256], szSerial[256], szFirmware[256], szModel[256];
        status = viQueryf(GetVisaSession(), "SYST:ID?\n", "%256[^,],%256[^,],%256[^,],%256[^,]", szManufacturer, szSerial, szFirmware, szModel);
        ReturnOnError(status);

        strManufacturer = szManufacturer;
        strSerial = szSerial;
        strFirmware = szFirmware;
        strModel = szModel;

        return status;
    }
};


DriverSession::GetVisaResourceManager

Returns the VISA resource manager that was used to create the VISA I/O session associated with the driver session.

ViSession GetVisaResourceManager() const;

ViSession GetVisaResourceManager(ViSession Vi);
Parameters
Vi

[in] ViSession handle for the driver session.

Return Value

Returns the ViSession handle to the VISA resource manager that was used to create the VISA I/O session.

Remarks

This function is only defined when the driver is configured to use VISA as its underlying I/O mechanism on the I/O Property Page.

Example

The following example demonstrates use of the GetVisaResourceManager function.

C++
Copy
ViStatus _VI_FUNC acme4321_ConfigureSweep(ViSession Vi, ViReal64 StartFrequency, ViReal64 StopFrequency)
{
    auto resourceManager = GetVisaResourceManager(Vi);

    // ...
}


DriverSession::GetVisaSession

Returns the VISA I/O session associated with the driver session.

ViSession GetVisaSession() const;

ViSession GetVisaSession(ViSession Vi);
Parameters
Vi

[in] ViSession handle for the driver session.

Return Value

Returns the ViSession handle associated with the underlying VISA I/O session.

Remarks

This function is only defined when the driver is configured to use VISA as its underlying I/O mechanism on the I/O Property Page.

Example

The following example demonstrates use of the GetVisaSession function.

C++
Copy
ViStatus _VI_FUNC acme4321_ConfigureSweep(ViSession Vi, ViReal64 StartFrequency, ViReal64 StopFrequency)
{
    auto ioSession = GetVisaSession(Vi);

    // ...
}


DriverSession::InitializeIO

Establishes the I/O connection with the instrument.

virtual ViStatus InitializeIO();
Return Value

Returns a VI_SUCCESS if the operation was successful or a failure ViStatus otherwise.

Remarks

This function is automatically called as part of driver initialization and is used to establish the I/O connection with the instrument. By default, this function will use the VISA library to open an instrument session using the viOpen function. In simulation mode, this function should do nothing.

Important note Important

This function must be overridden for non-VISA-based drivers.

Example

The following code demonstrates how to override the InitializeIO function:

C++
Copy
// DriverSession.h
class Acme4321DriverSession : public DriverSession
{
public:
    Acme4321DriverSession(ViSession handle)
        : DriverSession(handle, 2000, 2000, 2000, false, 1000)
    {
    }

    virtual ViStatus InitializeIO() override
    {
        ViStatus status = VI_SUCCESS;

        // Don't try to establish an I/O connection if we're simulating, because, well, that's what "simulating" means
        //
        if (!SimulationEnabled())
        {
            // ... establish the I/O connection using a custom DLL or other appropriate mechanism
        }

        return status;
    }
};


DriverSession::PollInstrumentErrors

If instrument error polling is enabled, (i.e. the QUERY_INSTR_STATUS attribute is VI_TRUE) this function polls the instrument to determine if an error condition exists.

virtual ViStatus PollInstrumentErrors();

ViStatus PollInstrumentErrors(ViSession Vi);
Parameters
Vi

[in] ViSession handle for the driver session.

Return Value

Returns a VI_SUCCESS if no instrument error was detected. If an instrument error was detected, this function returns the standard IVI error code IVIC_ERROR_INSTRUMENT_STATUS.

Remarks

This function is automatically called whenever commands are sent to the instrument. The function should only query the instrument for errors when the QUERY_INSTR_STATUS attribute is VI_TRUE.

The default implementation of PollInstrumentErrors uses the VISA library to send a *ESR? query to the instrument and expects an IEEE 488.2 response.

Important note Important

This function must be overridden for non-VISA-based drivers or drivers that use something other than the *ESR? query to poll the instrument for errors.

Example

The following code demonstrates how to override the PollInstrumentErrors function:

C++
Copy
// DriverSession.h
class Acme4321DriverSession : public DriverSession
{
public:
    Acme4321DriverSession(ViSession handle)
        : DriverSession(handle, 2000, 2000, 2000, false, 1000)
    {
    }

    virtual ViStatus PollInstrumentErrors() override
    {
        auto status = VI_SUCCESS;

        // Don't poll unless error polling has been enabled by the client program
        //
        if (QueryInstrStatusEnabled())
        {
            // Perform a driver-specific query to determine if there is an error eithin the instrument
            //
        }

        return status;
    }
};


Miscellaneous Functions

The topics in this section present functions that provide a variety of services for driver implementations to use.

In This Section

DriverSession::FirmwareRevision

DriverSession::Handle

DriverSession::IoDescriptor

DriverSession::LogicalName

DriverSession::Manufacturer

DriverSession::ResourceName

DriverSession::SerialNumber


DriverSession::FirmwareRevision

Returns the firmware revision of the device with which the driver is communicating.

virtual const std::string& FirmwareRevision() const;

const std::string& FirmwareRevision(ViSession Vi);
Parameters
Vi

[in] ViSession handle for the driver session.

Return Value

Returns the firmware revision of the device with which the driver is communicating.

Remarks

The value returned here is set by the implementation of the GetIdentificationInfo function. By default, Nimbus implements the GetIdentificationInfo by sending a *IDN? query to the instrument and parsing an IEEE 488.2 response. This function returns an empty string when simulating.


DriverSession::Handle

Returns the ViSession handle that was used to create DriverSession-derived object.

virtual ViSession Handle() const;
Return Value

Returns the IVI session handle associated with the DriverSession-derived object.

Remarks

When a client program invokes the driver's init or InitWithOptions function, an instance of the driver's DriverSession-derived class is created. This class is maintained in the driver project's DriverSession.h file. This instance is associated with an IVI session handle via the standard IVI function IviSession_New. The IviSession_New function is part of the IVI Shared Component and is used to store and retrieve IVI driver session state information in a standard and thread-safe fashion.

Nimbus IVI-C drivers use the standard IviSession_New function to create an IVI session and associate the driver's DriverSession object with that IVI session. When the IVI session is created, the IviSession_New function returns a ViSession handle that must be used in all subsequent function calls on that IVI session. Every IVI-C driver function (other than init and InitWithOptions) accepts of ViSession parameter that is used to retrieve the DriverSession object via the GetDriverSession function.

While global functions, such as typical IVI-C driver functions and attributes, accept a ViSession parameter from which the DriverSession object can be retrieved, functions defined on the DriverSession class itself do not accept a ViSession parameter. These functions are already defined on the DriverSession instance, so they need only access the IVI session handle member variable that was stored on the DriverSession instance when it was created. The Handle function provides access to that member variable.

Example

The following code demonstrates how to override the Handle function:

C++
Copy
// DriverSession.h
class Acme4321DriverSession : public DriverSession
{
public:
    Acme4321DriverSession(ViSession handle)
        : DriverSession(handle, 2000, 2000, 2000, false, 1000)
    {
    }

    void MyHelper()
    {
        auto iviSession = Handle();

        // ...
    }
};


DriverSession::IoDescriptor

Returns the I/O resource descriptor associated with the driver session.

virtual const std::string& IoDescriptor() const;

const std::string& IoDescriptor(ViSession Vi);
Parameters
Vi

[in] ViSession handle for the driver session.

Return Value

Returns the I/O resource descriptor associated with the driver session.

Remarks

If the ResourceName parameter is mapped to a logical name or a driver session in the IVI Configuration Store, then this function returns the resource descriptor that is associated with the hardware asset in the IVI Configuration Store. If the ResourceName parameter does not map to a logical name or a driver session, then this function assumes that the ResourceName represents an I/O descriptor and returns the ResourceName.


DriverSession::LogicalName

Returns the logical name associated with the driver session.

virtual const std::string& LogicalName() const;

const std::string& LogicalName(ViSession Vi);
Parameters
Vi

[in] ViSession handle for the driver session.

Return Value

Returns the logical name associated with the driver session.

Remarks

If the ResourceName parameter is mapped to a logical name or a driver session in the IVI Configuration Store, then this function returns that logical name or driver session. If the ResourceName parameter does not map to a logical name or a driver session, then this function returns an empty string.


DriverSession::Manufacturer

Returns the instrument manufacturer associated with the device with which the driver is communicating.

virtual const std::string& Manufacturer() const;

const std::string& Manufacturer(ViSession Vi);
Parameters
Vi

[in] ViSession handle for the driver session.

Return Value

Returns the instrument manufacturer associated with the device with which the driver is communicating.

Remarks

The value returned here is set by the implementation of the GetIdentificationInfo function. By default, Nimbus implements the GetIdentificationInfo by sending a *IDN? query to the instrument and parsing an IEEE 488.2 response. This function returns an empty string when simulating.


DriverSession::ResourceName

Returns the ResourceName parameter that was passed to the init or InitWithOptions function when the session was created.

virtual const std::string& ResourceName() const;

const std::string& ResourceName(ViSession Vi);
Parameters
Vi

[in] ViSession handle for the driver session.

Return Value

Returns the ResourceName parameter that was passed to the init or InitWithOptions function when the session was created.


DriverSession::SerialNumber

Returns the serial number of the device with which the driver is communicating.

virtual const std::string& SerialNumber() const;

const std::string& SerialNumber(ViSession Vi);
Parameters
Vi

[in] ViSession handle for the driver session.

Return Value

Returns the serial number of the device with which the driver is communicating.

Remarks

The value returned here is set by the implementation of the GetIdentificationInfo function. By default, Nimbus implements the GetIdentificationInfo by sending a *IDN? query to the instrument and parsing an IEEE 488.2 response. This function returns an empty string when simulating.


State Caching Functions

Nimbus provides a state-caching editor that allows basic state caching settings to be configured without supplying any code. Simple couplings can be expressed to ensure good cache coherency. In more advanced state-caching scenarios where the couplings are more complex or the required logic is otherwise more involved, the driver developer may wish to manually implement state caching. The functions in this section allow direct control over the Nimbus state caching engine.

In addition to the DriverSession-based functions presented here, the CacheEntry class and GetCacheEntry function provide direct control over state caching behavior.

In This Section

DriverSession::InvalidateAttributes

DriverSession::InvalidateAllAttributes


DriverSession::InvalidateAttributes

Invalidates the cached value of one or more attributes.

template <typename... Args>
void InvalidateAttributes(ViAttr attributeId, Args... args);

template <typename TRepCap, typename... Args>
void InvalidateAttributes(const PhysicalNameList<TRepCap>& physicalNames, ViAttr attributeId, Args... args);

template <typename TRepCap>
void InvalidateAttributes(const PhysicalNameList<TRepCap>& physicalNames, ViAttr attributeId);

template <typename... Args>
void InvalidateAttributes(ViSession Vi, ViAttr attributeId, Args... args);

template <typename TRepCap, typename... Args>
void InvalidateAttributes(ViSession Vi, const PhysicalNameList<TRepCap>& physicalNames, ViAttr attributeId, Args... args);
Parameters
Vi

[in] ViSession handle for the driver session.

physicalNames

[in] List of physical names for the repeated capabilities on which all of the supplied attribute cache values should be invalidated.

The PhysicalNamesList class used here is simply an alias for a std::vector of PhysicalName objects.

attributeId

[in] Attribute ID whose cache value should be invalidated (e.g. ACME4321_ATTR_TRIGGER_SOURCE).

args (variable argument list)

[in] Variable argument list of attribute IDs whose cache values should be invalidated.

Remarks

This function is used to invalidate the cached value of one or more attributes. Invalidating a cached attribute forces the driver to communicate with the instrument the next time the attribute is read or written.

For attributes associated with a repeated capability, the cached attribute values can be invalidated for specific repeated capabilities as indicated by the physicalNames parameter. If no physicalNames parameter is supplied, then the cached attribute values for all repeated capabilities are invalidated.

Example

The following example demonstrates use of the ReportError function.

C++
Copy
ViStatus _VI_FUNC acme4321_ConfigureArmCount(ViSession Vi, ViConstString RepCapIdentifier, ViInt32 ArmCount)
{
    // Invalidate the CLOCK_RATE attribute.  If CLOCK_RATE is associated with a repeated capability such
    // as a channel, then the cached CLOCK_RATE values for all channels will be invalidated.  If the CLOCK_RATE
    // is not associated with a repeated capability, then the one and only cached value will be invalidated.
    //
    InvalidateAttributes(Vi, ACME4321_ATTR_CLOCK_RATE);

    // Invalidate the BANDWITH attribute on channels C1 and C2.
    //
    PhysicalNameList<Channel> physicalNames{ "C1", "C2" };
    InvalidateAttributes(Vi, physicalNames, ACME4321_ATTR_BANDWIDTH);

    // ...
}


DriverSession::InvalidateAllAttributes

Invalidates the cached value of all attributes on all repeated capabilities.

virtual void InvalidateAllAttributes();

ViStatus InvalidateAllAttributes(ViSession Vi);
Parameters
Vi

[in] ViSession handle for the driver session.

Remarks

This function is used to invalidate the cached value of all attributes. Invalidating a cached attribute forces the driver to communicate with the instrument the next time the attribute is read or written.

Example

The following example demonstrates use of the InvalidateAllAttributes function.

C++
Copy
ViStatus _VI_FUNC acme4321_ConfigureArmCount(ViSession Vi, ViConstString RepCapIdentifier, ViInt32 ArmCount)
{
    InvalidateAllAttributes(Vi);

    // ...
}


EnumConverter Class

Nimbus provides special features for message-based devices that greatly simplify sending commands to and from instruments. The topic on Working With Instrument Commands discusses many of these features. One of the key components of the automatic command formatting features offerred by Nimbus is the ability to convert enum parameters to and from instrument command strings.

The Nimbus Runtime Library provides the EnumConverter class for converting between driver-defined enums and instrument command strings. The driver developer uses the Enum Member Editor to associate instrument command strings with specific enum members. For each enum with command mappings configured via this editor, Nimbus creates an entry in the enum macro map maintained in the driver project's Enums.h file. Each entry in that map produces a class definition that derives from EnumConverter and that exposes a ToCommand function for converting enum member values to instrument command strings and a FromResponse function for converting instrument command strings to enum member values.

Using an EnumConverter

In the following example, the TRIGGER_SOURCE attribute is defined to have enum members mapped as follows:

  • TRIGGER_SOURCE_VAL_INTERNAL -> INT

  • TRIGGER_SOURCE_VAL_EXTERNAL -> EXT

  • TRIGGER_SOURCE_VAL_SOFTWARE -> SW

Note that the name of the EnumConverter-derived class is always the name of the enum chosen by the driver developer followed by the string Enum. In the below, the enum converter class is TriggerSourceEnum.

C++
Copy
ViStatus _VI_FUNC acme4321_set_TRIGGER_SOURCE(ViSession Vi, ViConstString RepCapIdentifier, ViInt32 AttributeValue)
{
    // ...

    // The ToCommand function will convert the AttributeValue to one of the defned strings -- "INT", "EXT" or "SW".
    // If the AttributeValue is not one of the defined enum member values, then an the IVI-defined error code
    // IVIC_ERROR_CANNOT_RECOVER will be returned, along with a descriptive error message.
    //
    std::string strAttributeValue;
    status = TriggerSourceEnum::ToCommand(Vi, AttributeValue, strAttributeValue);
    ReturnOnError(status);

    // At this point, the strAttributeValue variable has the value "INT", "EXT", or "SW", so we use it
    // directly in formatting the overall instrument command for the operation.
    //
    status = viPrintf(GetVisaSession(Vi), "CONFIG:SOUR %s\n", strAttributeValue.c_str());
    ReturnOnError(status);

    // ...
}

The EnumConverter classes are also used when reading instrument responses and returning them as attribute values. The getter implementation of the same TRIGGER_SOURCE enum might look something like the code below.

C++
Copy
ViStatus _VI_FUNC acme4321_set_TRIGGER_SOURCE(ViSession Vi, ViConstString RepCapIdentifier, ViInt32 AttributeValue)
{
    // ...

    // The viQueryf function will read the instrument response into the szAttributeValue variable.
    //
    char szAttributeValue[MAX_ENUM_RESPONSE];
    int cbAttributeValue = _countof(szAttributeValue);
    status = viQueryf(GetVisaSession(Vi), "CONFIG:SOUR?\n", "%#s%*t", &cbAttributeValue, szAttributeValue);
    ReturnOnError(status);

    // At this point, the szAttributeValue variable should have the value "INT", "EXT", or "SW".
    // The FromResponse function will map that string back to one of the three attribute values:
    // TRIGGER_SOURCE_VAL_INTERNAL, TRIGGER_SOURCE_VAL_EXTERNAL, or TRIGGER_SOURCE_VAL_SOFTWARE.
    // If the szAttributeValue does not have one of the expected string values, then the FromResponse
    // function will return the error code IVIC_ERROR_UNEXPECTED_RESPONSE along with a descriptive message.
    //
    status = TriggerSourceEnum::FromResponse(Vi, szAttributeValue, AttributeValue);
    ReturnOnError(status);

    // ...
}


Miscellaneous Functions

Required introduction


GetDriverSession

Retrieves a pointer to the DriverSession-derived class maintained in the driver project's DriverSession.h file.

template <typename TSession = DriverSession>
TSession* GetDriverSession(ViSession Vi);
Parameters
Vi

[in] ViSession handle for the driver session. This handle is initially created using the IVI Shared Components IviSession_New function. See the discussion of the Handle function for more information on the association of this ViSession handle with the DriverSession object.

Return Value

Returns a pointer to the DriverSession-derived class associated with the IVI session specified in the Vi parameter.

Remarks

Much of the functionality in the Nimbus Runtime Library is implemented on the DriverSession class, which serves as a base class for the driver-specific session class maintained in the driver project's DriverSession.h file. For convenience, the DriverSession functions most commonly used are exposed as global functions that internally access the DriverSession instance created at initialization.

In some cases it may be necessary to directly access the DriverSession class from within a function or attribute implementation. This would occur if the desired functionality was not exposed via a global function. This would also typically occur if the driver developed defined custom helper functions or driver-specific member variables on the specific DriverSession class defined in the DriverSession.h file. The GetDriverSession function provides access to the DriverSession class for directly accessing such member functions and member variables.

Example

The following example demonstrates use of the GetDriverSession function.

C++
Copy
ViStatus _VI_FUNC acme4321_Configure(ViSession Vi, ViReal64 Frequency, ViReal64 Bandwidth)
{
    // ...

    // Not specifying a template parameter yields a pointer of type DriverSesion, so only public functions
    // defined in the Nimbus Runtime Library can be accessed.
    //
    auto pBase = GetDriverSession(Vi);
    pBase->SomeNimbusHelper();       // OK -- can access any public function on DriverSession
    pBase->MyHelper();               // ERROR -- MyHelper function is defined on Acme4321DriverSession, not DriverSession

    // Specifying a template parameter yields a pointer of type Acme4321DriverSession
    //
    auto pDerived = GetDriverSession<Acme4321DriverSession>(Vi);
    pDerived->SomeNimbusHelper();    // Still OK -- can access any public function on DriverSession
    pDerived->MyHelper();            // OK -- can access any public function defined on Acme4321DriverSession

    // ...
}


NRT_NO_VISA Symbol

The NRT_NO_VISA preprocessor symbol is used to control whether or not the Nimbus Runtime Library is compiled with support for the VISA library.

#define NRT_NO_VISA
Remarks

When NRT_NO_VISA is defined, then VISA is not required to be installed on the driver developer computer nor on the end user computer using the compiled driver, as no VISA dependencies will be included when building the driver. Such drivers must implement specific I/O functions that would otherwise be implemented using VISA library calls. These functions are discussed in the section on I/O Functions. In addition to these functions, the driver developer must use an alternate mechanism, such as a custom DLL or support library, for all driver and attribute implementations.

When NRT_NO_VISA is not defined, then the Nimbus Runtime Library compiles in calls into the VISA library. Thus, VISA must be installed on the driver developer and on the end user computer using the driver, as VISA dependencies will be included in the driver. When VISA support is compiled into the driver, the Nimbus Runtime Library implements several important I/O Functions automatically. Also, Nimbus can be instructed to implement driver functions and attributes using standard VISA function calls such as viPrintf and viScanf.

Important note Important

This NRT_NO_VISA symbol should not be explicitly defined in driver developer code. This symbol is controlled by an MSBuild property in the IVI-C driver project file.


VisaTimeoutManager Class

This class is used to change the timeout of the underlying VISA library for a specific sequence of operations. This class is only defined when the driver is using VISA for its underlying I/O, as specified in the I/O Property Page.

To use this class to increase or decrease the VISA timeout for a sequence of operations, simply declare a local variable of type VisaTimeoutManager within the function or code block of interest. The constructor of the VisaTimeoutManager class will store the current value of the VISA timeout attribute before changing its value to the desired value specified in the class constructor. When the function or code block exists, the VisaTimeoutManager destructor runs, which restores the timeout to its previous value.

The VisaTimeoutManager can be used in nested code blocks, as demonstrated below, to achieve specific timeout requirements.

The following example demonstrates use of the VisaTimeoutManager class.

C++
Copy
ViStatus _VI_FUNC acme4321_ConfigureSweep(ViSession Vi, ViReal64 StartFrequency, ViReal64 StopFrequency)
{
    VisaTimeoutManager timeout1(Vi, 3000);

    // All code here executes with a VISA timeout of 3 seconds
    //

    {
        VisaTimeoutManager timeout2(Vi, 4000);

        // All code here executes with a VISA timeout of 4 seconds
        //
        // ...

    }   // When this point is reached, the previous timeout of 3 seconds is restored

    // All code here executes with a VISA timeout of 3 seconds
    //
    // ...

}   // When this point is reached, the previous timeout (before invoking this function) is restored


Repeated Capability Functions

In This Section

ParameterStyleRepCap Class

PhysicalName Class

PhysicalNameList Class

SelectorStyleRepCap Class


ParameterStyleRepCap Class

For each parameter-style repeated capability defined in an IVI-C driver, Nimbus defines a repeated capability class of the same name and that class derives from the ParameterStyleRepCap class presented in this section.

The repeated capability class is defined by use of the repeated capability macro map maintained in the driver project's RepCaps.h. The ParameterStyleRepCap class exposes several methods required to properly manage repeated capability-based functions and attributes in an IVI-C driver. The topics in this section present the functions available for managing repeated capabilities in IVI-C drivers.

In This Section

ParameterStyleRepCap::AddPhysicalNames

ParameterStyleRepCap::ClearPhysicalNames

ParameterStyleRepCap::ExpandSelector

ParameterStyleRepCap::ExpandSingleSelector

ParameterStyleRepCap::GetPhysicalNameAtIndex

ParameterStyleRepCap::GetPhysicalNames

ParameterStyleRepCap::PhysicalNameCount

ParameterStyleRepCap::RemovePhysicalNames


ParameterStyleRepCap::AddPhysicalNames

Adds one or more physical names to a repeated capability.

static ViStatus AddPhysicalNames(ViSession Vi, const std::string& strSelector);
Parameters
Vi

[in] ViSession handle for the driver session.

strSelector

[in] A repeated capability selector which can include virtual names, physical names, comma-separated lists of names and physical name ranges.

Return Value

Returns a VI_SUCCESS if the operation was successful or a failure ViStatus otherwise.

Remarks

The AddPhysicalNames function is used to add physical names to a repeated capability. This can be useful for drivers that support dynamic repeated capabilities -- that is, repeated capabilities where the exact number of repeated capabilities is not know upfront. The driver can query the instrument to determine which physical names are present in the device and the driver can use the AddPhysicalNames function to add those names.

The strSelector parameter can include lists and ranges of physical names and is parsed and expanded according the the IVI-defined rules for repeated capability selectors, as presented in "IVI 3.1 Section 4.4.7 Formal Syntax for Repeated Capability Selectors".

Selectors have a general form such as the following:

a1,a3,a5-a7:b2:[c5,c7]

Example

The following example demonstrates how a developer might query the instrument for physical names during the initialization sequence and use the results to populate a repeated capability using the AddPhysicalNames function.

C++
Copy
ViStatus _VI_FUNC acme4321_InitWithOptions(ViRsrc ResourceName, ViBoolean IdQuery, ViBoolean Reset, ViConstString OptionsString, ViSession* Vi)
{
   auto status = VI_SUCCESS;

   status = nrt::InitWithOptions<Acme4321DriverSession>(ResourceName, IdQuery, Reset, OptionsString, Vi);
    ReturnOnError(status);

   if (Reset)
   {
       status = acme_reset(*Vi);
       ReturnOnError(status);
   }

   ReturnOnError(status);

   // Query the instrument for the number of channels
   //
   long cChannels;
   status = viQueryf(GetVisaSession(Vi), "SYST:CTYP:COUN?\n", "%lg%*t", &cChannels);
   ReturnOnError(status);

   // Note that the AddPhysicalNames function accepts selectors, so it can include ranges and comma-separated lists of
   // physical names.  Each channel name is of the form "CH[channel]".  We'll add all of the channels in one go by building
   // a selector that includes a range from 1 to the cChannels we queried from the device.
   //
   auto strSelector = "CH1-CH" + std::to_string(cChannels);
   status = Channel::AddPhysicalNames(Vi, strSelector);

   return status;
}


ParameterStyleRepCap::ClearPhysicalNames

Removes all physical names from a repeated capability.

static void ClearPhysicalNames(ViSession Vi);
Parameters
Vi

[in] ViSession handle for the driver session.

Remarks

The ClearPhysicalNames function is used to remove physical names from a repeated capability. This can be useful for drivers that support dynamic repeated capabilities -- that is, repeated capabilities where the exact number of repeated capabilities is not know upfront or where the driver exposes functions that allow the end user to control the physical names present

Example

The following example demonstrates how a developer might use the ClearPhysicalNames function.

C++
Copy
ViStatus _VI_FUNC acme_RemoveAllTriggerSources(ViSession Vi)
{
   auto status = VI_SUCCESS;

   status = TriggerSource::ClearPhysicalNames(Vi);

   return status;
}


ParameterStyleRepCap::ExpandSelector

Generates the complete list of repeated capability physical Names represented by the specified repeated capability selector.

static ViStatus ExpandSelector(ViSession Vi, ViConstString szSelector, PhysicalNameList<T>& physicalNames, bool bVerifyPhysicalNamesExist = true);
Parameters
Vi

[in] ViSession handle for the driver session.

szSelector

[in] A repeated capability selector which can include virtual names, physical names, comma-separated lists of names and physical name ranges.

physicalNames

[out] A PhysicalNameList object containing the results of the expansion of the szSelector parameter.

bVerifyPhysicalNamesExist

[in] Indicates if the implementation should return an error if the expanded PhysicalNameList contains physical names that have not been defined for the repeated capability. This parameter defaults to true and should always be left at the default of true by driver developer code. Use of a false value here is reserved for internal Nimbus implementation purposes.

Return Value

Returns a VI_SUCCESS if the operation was successful or a failure ViStatus otherwise. Some of the error codes that can be reported by this function based on various error conditions in the szSelector are as follows:

  • IVIC_ERROR_CHANNEL_NAME_REQUIRED

  • IVIC_ERROR_BADLY_FORMED_SELECTOR

  • IVIC_ERROR_INVALID_RANGE_IN_SELECTOR

  • IVIC_ERROR_INVALID_NUMBER_OF_LEVELS_IN_SELECTOR

  • IVIC_ERROR_UNKNOWN_PHYSICAL_IDENTIFIER

Remarks

This function first replaces virtual names with their corresponding physical names (and ranges) and then expands the resulting expression. The procedure followed for the expansion and virtual name substituion are described in "IVI 3.1 Section 4.4.7 Formal Syntax for Repeated Capability Selectors". The relevant details of that formal syntax is reproduced below for convenience.

Repeated capability selectors are widely used in IVI-C drivers, and this function performs critical validation and error checking required by the IVI specifications. Thus, this function should be used whenever a repeated capability selector is passed by the user as a driver function parameter.

If the szSelector parameter is VI_NULL or whitespace, then this function validates that the repeated capability has only a single physical name defined. If more than one physical name is defined when szSelector is VI_NULL or whitespace, then this function returns a ViStatus value of IVIC_ERROR_CHANNEL_NAME_REQUIRED, as required by the IVI specifications.

The following describes the formal syntax for repeated capability selectors:

  • A syntactically valid repeated capability selector consists of zero or more repeated capability path segments separated by colons (:). White space around colons is ignored.

  • A repeated capability path segment consists of one or more repeated capability list elements, separated by commas (,). White space after commas is ignored. A repeated capability path segment may be enclosed in square brackets ([]).

  • A repeated capability list element consists of a repeated capability token or a repeated capability range.

  • A repeated capability range consists of two repeated capability tokens separated by a hyphen (-).

  • The order of precedence of operators is square brackets ([]), hyphen (-), colon (:), and comma (,). Each operator is evaluated from left to right.

  • A repeated capability token is a physical repeated capability identifer or a virtual repeated capability identifier.

  • A syntactically valid physical or virtual repeated capability identifier consists of one or more of the following characters: a z, A Z, 0 9, !, and _.

Example

The following example demonstrates use of the ExpandSelector function.

C++
Copy
ViStatus _VI_FUNC acme4321_ConfigureGlitchArmSource(ViSession Vi, ViConstString Source, ViReal64 Level, ViReal64 Width, ViInt32 Polarity, ViInt32 Condition)
{
    // Assume the Source parameter value supplied is "C1,C3,C5-C8"
    //
    PhysicalNameList<::ArmSource> physicalNames;
    ReturnOnError(ArmSource::ExpandSelector(Vi, Source, physicalNames));

    for (const auto& physicalName : physicalNames)
    {
        cout << physicalName.Name();
    }

    // Prints the following:
    //
    //    C1
    //    C3
    //    C5
    //    C6
    //    C7
    //    C8
    //
}


ParameterStyleRepCap::ExpandSingleSelector

Translates a repeated capability selector into a single physical name.

static ViStatus ExpandSingleSelector(ViSession Vi, ViConstString szSelector, PhysicalName<T>& physicalName);
Parameters
Vi

[in] ViSession handle for the driver session.

szSelector

[in] A repeated capability selector, which can be a virtual name. An error results if more than one physical name is represented by this parameter.

physicalName

[out] A PhysicalName object containing the physical name corresponding to the supplied szSelector.

Return Value

Returns a VI_SUCCESS if the operation was successful or a failure ViStatus otherwise. If the szSelector parameter represents more than one physical name, the the error code IVIC_ERROR_BADLY_FORMED_SELECTOR is returned. That same error code is also returned if the szSelector parameter contains invalid physical name characters.

Remarks

If the szSelector parameter represents a virtual name, this function translates that virtual name to the corresponding physical name.

Repeated capability selectors are widely used in IVI-C drivers, and this function performs critical validation and error checking required by the IVI specifications. Thus, this function should be used whenever a repeated capability selector is passed by the user as a driver function parameter AND only a single selector is expected. For instance, whenever a user calls the getter for an attribute (e.g. GetAttributeViInt32), the implementation can only supply a single value, so the function must validate that the RepCapIdentifier parameter represents only a single physical name. Such cases can be handled using the ExpandSingleSelector function.

If the szSelector parameter is VI_NULL or whitespace, then this function validates that the repeated capability has only a single physical name defined. If more than one physical name is defined when szSelector is VI_NULL or whitespace, then this function returns a ViStatus value of IVIC_ERROR_CHANNEL_NAME_REQUIRED, as required by the IVI specifications.

Example

The following example demonstrates use of the ExpandSingleSelector function.

C++
Copy
ViStatus _VI_FUNC acme4321_get_BANDWIDTH(ViSession Vi, ViConstString RepCapIdentifier, ViReal64* AttributeValue)
{
    PhysicalName<Channel> physicalName;
    ReturnOnError(Channel::ExpandSingleSelector(Vi, RepCapIdentifier, physicalName));

    // ...
}


ParameterStyleRepCap::GetPhysicalNameAtIndex

Returns full physical name at the specified 1-based index.

static ViStatus GetPhysicalNameAtIndex(ViSession Vi, ViInt32 nIndex, ViInt32 nNameBufferSize, ViChar szName[]);

static ViStatus GetPhysicalNameAtIndex(ViSession Vi, ViConstString parentPhysicalName, ViInt32 nIndex, ViInt32 nNameBufferSize, ViChar szName[]);
Parameters
Vi

[in] ViSession handle for the driver session.

parentPhysicalName

[in] The full physical name of the parent repeated capability. This parameter is only available in the overload for nested repeated capabilities.

nIndex

[in] The 0-based index of the physical name to return. For nested repeated capabilities, this represents the index within the specific parent repeated capability instance's collection of child physical names.

nNameBufferSize

[in] The number of characters allocated in the szName parameter.

szName

[out] The full physical name located at the specified index within the driver's internal list of physical names for this repeated capability.

Return Value

Returns a VI_SUCCESS if the operation was successful or a failure ViStatus otherwise.

Remarks

Only one of the above overloads will be available for a particular repeated capability. The first overload (without the parentPhysicalName parameter) will be available for non-nested repeated capabilities, while the second overload must be used for nested repeated capabilities.

Example

The following example demonstrates use of the GetPhysicalNameAtIndex function.

C++
Copy
ViStatus _VI_FUNC acme4321_ConfigureArmCount(ViSession Vi, ViConstString RepCapIdentifier, ViInt32 ArmCount)
{
    // The Trace repeated capability is a child repeated capability of some other repeated capability
    // that defines a "C1" physical name.  The "trace" variable below represents the "T1" Trace instance
    // within the C1 instance of the parent repeated capability.
    //
    // Assume the following repeated capability physical names are defined in the following order for the Trace repeated capability:
    //
    //     "C1:T1"
    //     "C1:T2"
    //     "C1:T3"
    //     "C2:T1"
    //     "C2:T2"
    //     "C2:T3"  <-- this is the one we're after
    //     "C3:T1"
    //     "C3:T2"
    //     "C3:T3"
    //

    // Note that we ask for the physical name at index 2 and not 5
    //
    char szName[256];
    auto status = Trace::GetPhysicalNameAtIndex(Vi, "C2", 2, _countof(szName), sz);
    ReturnOnError(status);

    cout << szName;   // prints "C2:T3"
}


ParameterStyleRepCap::GetPhysicalNames

Returns the PhysicalNameList containing all of the PhysicalName objects currently defined for the repeated capability.

static const PhysicalNameList<T>& GetPhysicalNames(ViSession Vi);

static const PhysicalNameList<T>& GetPhysicalNames(ViSession Vi, const PhysicalName<TParent>& parentPhysicalName);
Parameters
Vi

[in] ViSession handle for the driver session.

parentPhysicalName

[in] The physical name of the parent repeated capability. This parameter is only available in the overload for nested repeated capabilities.

Return Value

The PhysicalNameList containing all of the PhysicalName objects currently defined for the repeated capability.

Remarks

Only one of the above overloads will be available for a particular repeated capability. The first overload (without the parentPhysicalName parameter) will be available for non-nested repeated capabilities, while the second overload must be used for nested repeated capabilities.

Example

The following example demonstrates use of the GetPhysicalNames function.

C++
Copy
ViStatus _VI_FUNC acme4321_ConfigureArmCount(ViSession Vi, ViConstString RepCapIdentifier, ViInt32 ArmCount)
{
    // Assume a Trace repeated capability is defined as a child of a Channel repeated capability and has the
    // following physical names defined in the following order.
    //
    //     "C1:T1"
    //     "C1:T2"
    //     "C1:T3"
    //     "C2:T1"
    //     "C2:T2"
    //     "C2:T3"
    //     "C3:T1"
    //     "C3:T2"
    //     "C3:T3"
    //

    auto channels = Channel::GetPhysicalNames(Vi);

    for (const auto& channel : channels)
    {
        cout << channel.FullName();
    }

    // The above loop prints the following:
    //
    //    C1
    //    C2
    //    C3
    //

    auto traces = Trace::GetPhysicalNames(Vi, "C2");

    for (const auto& trace : traces)
    {
        cout << trace.FullName();
    }

    // The above loop prints the following:
    //
    //    C2:T1
    //    C2:T2
    //    C2:T3
    //
}


ParameterStyleRepCap::PhysicalNameCount

Returns the number of physical names currently defined for the repeated capability.

static int PhysicalNameCount(ViSession Vi);
Parameters
Vi

[in] ViSession handle for the driver session.

Return Value

Returns the number of physical names currently defined for the repeated capability.


ParameterStyleRepCap::RemovePhysicalNames

Removes one or more physical names from a repeated capability.

static ViStatus RemovePhysicalNames(ViSession Vi, const std::string& strSelector);
Parameters
Vi

[in] ViSession handle for the driver session.

strSelector

[in] A repeated capability selector which can include virtual names, physical names, comma-separated lists of names and physical name ranges.

Return Value

Returns a VI_SUCCESS if the operation was successful or a failure ViStatus otherwise.

Remarks

The RemovePhysicalNames function is used to remove physical names from a repeated capability. This can be useful for drivers that support dynamic repeated capabilities -- that is, repeated capabilities where the exact number of repeated capabilities is not know upfront or where the driver exposes functions that allow the end user to control the physical names present, as in the standard IVI-defined IviLxiSync API.

The strSelector parameter can include lists and ranges of physical names and is parsed and expanded according the the IVI-defined rules for repeated capability selectors, as presented in "IVI 3.1 Section 4.4.7 Formal Syntax for Repeated Capability Selectors".

Selectors have a general form such as the following:

a1,a3,a5-a7:b2:[c5,c7]

Example

The following example demonstrates how a developer might use the RemovePhysicalNames function to implement the RemoveArmSource function defined in the IviLxiSync API.

C++
Copy
ViStatus _VI_FUNC acme_IviLxiSync_RemoveArmSource(ViSession Vi, ViConstString SourceName)
{
   auto status = VI_SUCCESS;

   status = ArmSource::RemovePhysicalNames(Vi, SourceName);

   return status;
}


PhysicalName Class

The PhysicalName class is used to help manage repeated capability physical names. Repeated capability physical names can be nested or non-nested and can be qualified or non-qualified. The PhysicalName class exposes functions for accessing these features of repeated capability physical names.

The PhysicalName class is a template class which is bound to the type of a specific repeated capability class declared within the driver. Instances of the PhysicalName class can also be associated with a parent repeated capability in order to manage nested repeated capability physical names. These associations provides for compile-time type safety when using the PhysicalName class.

For example, the AncestorName, AncestorFullName, and AncestorIndex functions do not exist when creating a PhysicalName instance for a non-nested repeated capability, because non-nested repeated capabilities obviously have no ancestors. Attempting to invoke any of those functions on a non-nested PhysicalName instance will yield a compile-time error, which is far preferrable to a runtime error that may reach the end user and which they would have no understanding of how to address.

The topics in this section present each of the member functions PhysicalName class along with examples of their usage.

In This Section

PhysicalName Constructor

PhysicalName Comparison Operators

PhysicalName::AncestorFullName

PhysicalName::AncestorIndex

PhysicalName::AncestorName

PhysicalName::ExportedName

PhysicalName::ExportedFullName

PhysicalName::FullName

PhysicalName::Index

PhysicalName::Name

PhysicalName::ParentList

PhysicalName::ParentName

PhysicalName::ParentFullName

PhysicalName::QualifiedName

PhysicalName::QualifiedFullName


PhysicalName Constructor

Constructs a new instance of a PhysicalName object from a full name specification.

PhysicalName(const char* szFullName);
PhysicalName(std::string strFullName = std::string());
Parameters
szFullName, strFullName

[in] The full physical name of the desired repeated capability instance.

Remarks

For a nested repeated capability, the name used to create the PhysicalName instance must include the full name of the parent instance. The name must not include any qualified repeated capability names (i.e. Channel!!C1).

If the name supplied does not have the same number of levels of hierarchy as the repeated capability with which the PhysicalName is associated, then this constructor will assert at runtime in debug builds and yield unpredictable results in release builds.

For example, for a repeated capability with no parents, the name supplied here would simply be something such as the following:

C1

By constrast, for a repeated capability that is nested two levels deep (it has a parent and a "grandparent" repeated capability), the name supplied must be of the following form:

C1:T1:M1

It would be an error to construct an instance of such a repeated capability using only M1 or T1:M1.

Example

The following example demonstrates how to properly construct a PhysicalName object.

C++
Copy
ViStatus _VI_FUNC acme4321_ConfigureArmCount(ViSession Vi, ViConstString RepCapIdentifier, ViInt32 ArmCount)
{
    // For the following to work, the Channel repeated capability must be non-nested
    //
    PhysicalName<Channel> channel("C1");

    // Assume the Trace repeated capabilty is defined as a child of the Channel repeated capability
    //
    PhysicalName<Trace> trace1("T1");     // WRONG!! WRONG!! -- runtime assert because "T1" can exist within multiple parent
                                          // Channel instances, so the desired parent channel must be specified.

    PhysicalName<Trace> trace2("C1:T1");  // Correctly constructs a "T1" instance of the Trace repeated capability
}


PhysicalName Comparison Operators

Allows PhysicalName objects to be compared with one another.

bool operator==(const PhysicalName<TRepCap>& other) const;
bool operator!=(const PhysicalName<TRepCap>& other) const;
bool operator<(const PhysicalName<TRepCap>& other) const;
bool operator>(const PhysicalName<TRepCap>& other) const;
bool operator<=(const PhysicalName<TRepCap>& other) const;
bool operator>=(const PhysicalName<TRepCap>& other) const;
Parameters
other

[in] The PhysicalName instance to which the current instance should be compared.

Return Value

Returns true if the comparison operation is true and false otherwise.

Remarks

The comparison of PhysicalName objects is performed using the QualifiedFullName, which contains all components of the physical name. See the help topic on the QualifiedFullName function for more information.


PhysicalName::AncestorFullName

Returns the full repeated capability physical name of an ancestor repeated capability. The full name includes the identifiers for all parent repeated capability instances.

template <typename TAncestor>
const char* AncestorFullName() const;
Return Value

Returns the full repeated capability physical name of an ancestor repeated capability.

Remarks
Important note Important

This function is only available for PhysicalName instances that are associated with a nested repeated capability. Attempting to access this function from a non-nested PhysicalName instance will produce a compile error.

Physical names for nested repeated capabilities have the following form:

a1:b2:c3

This function can be used to access the a1:b2 component of the full physical name.

The parent repeated capability (immediate ancestor) can be accessed more succinctly using the ParentFullName function.

Example

The following example demonstrates use of the AncestorFullName function.

C++
Copy
ViStatus _VI_FUNC acme4321_ConfigureArmCount(ViSession Vi, ViConstString RepCapIdentifier, ViInt32 ArmCount)
{
    // Assume the following nested repeated capability definition exists:
    //
    //     Channel -> Trace -> Marker
    //
    //     where the Channel repeated capability is the highest-level parent repeated capability
    //
    PhysicalName<Marker> marker("C1:T3:M2");

    cout << marker.AncestorName<Channel>();   // prints "C1"
    cout << marker.AncestorName<Trace>();     // prints "C1:T3"
}


PhysicalName::AncestorIndex

Returns the 0-based index of any parent or ancestor component of a physical name.

template <typename TAncestor>
int AncestorIndex(ViSession Vi) const;
Parameters
Vi

[in] ViSession handle for the driver session.

Return Value

The 0-based index of an ancestor repeated capability instance. If the physical name is not defined for the repeated capability associated with the PhysicalName object, then this function returns -1.

Remarks
Important note Important

This function is only available for PhysicalName instances that are associated with a nested repeated capability. Attempting to access this function from a non-nested PhysicalName instance will produce a compile error.

Example

The following example demonstrates use of the AncestorIndex function.

C++
Copy
ViStatus _VI_FUNC acme4321_ConfigureArmCount(ViSession Vi, ViConstString RepCapIdentifier, ViInt32 ArmCount)
{
    // The Trace repeated capability is a child repeated capability of a Channel repeated capability
    // that defines a "C1" physical name.  The "trace" variable below represents the "T1" Trace instance
    // within the C1 instance of the parent repeated capability.
    //
    // Assume the following repeated capability physical names are defined in the following order for the Trace repeated capability:
    //
    //     "C1:T1"
    //     "C1:T2"
    //     "C1:T3"
    //     "C2:T1"
    //     "C2:T2"
    //     "C2:T3"
    //     "C3:T1"
    //     "C3:T2"
    //     "C3:T3"
    //
    PhysicalName<Trace> trace1("C2:T3");

    cout << trace1.AncestorIndex<Channel>(Vi);  // prints "1" (not "5")

    PhysicalName<Trace> trace2("C2:T1");

    cout << trace2.AncestorIndex<Channel>(Vi);  // still prints "1" (not "3")

    PhysicalName<Trace> trace3("C1:T3");

    cout << trace3.AncestorIndex<Channel>(Vi);  // prints "0" (not "2")
}


PhysicalName::AncestorName

Returns the physical name of an ancestor repeated capability.

template <typename TAncestor>
const char* AncestorName() const;
Return Value

Returns the physical name of an ancestor repeated capability.

Remarks
Important note Important

This function is only available for PhysicalName instances that are associated with a nested repeated capability. Attempting to access this function from a non-nested PhysicalName instance will produce a compile error.

Physical names for nested repeated capabilities have the following form:

a1:b2:c3

This function can be used to access the a1 and b2 components of the full physical name.

The parent repeated capability (immediate ancestor) can be accessed more succinctly using the ParentName function.

Example

The following example demonstrates use of the AncestorName function.

C++
Copy
ViStatus _VI_FUNC acme4321_ConfigureArmCount(ViSession Vi, ViConstString RepCapIdentifier, ViInt32 ArmCount)
{
    // Assume the following nested repeated capability definition exists:
    //
    //     Channel -> Trace -> Marker
    //
    //     where the Channel repeated capability is the highest-level parent repeated capability
    //
    PhysicalName<Marker> marker("C1:T3:M2");

    cout << marker.AncestorName<Channel>();   // prints "C1"
    cout << marker.AncestorName<Trace>();     // prints "T3"
}


PhysicalName::ExportedName

Returns either the qualified or unqualified repeated capability physical name based upon whether the repeated capability has been configured to use qualified physical names.

const char* ExportedName() const;
Return Value

Returns either the qualified or unqualified repeated capability physical name.

Remarks

Repeated capabilities can be configured to use either qualified or unqualified physical names when registering names in the IVI Configuration Store and when returning physical name strings from the driver functions such as GetChannelName. This selection is made in the Driver Settings Editor.

This function will behave exactly as either the Name function or the QualifiedName function depending upon how the repeated capability has been configured. See the help topics on those functions for more information.


PhysicalName::ExportedFullName

Returns either the qualified or unqualified repeated capability full physical name based upon whether the repeated capability has been configured to use qualified physical names.

const char* ExportedFullName() const;
Return Value

Returns either the qualified or unqualified repeated capability physical full name.

Remarks

Repeated capabilities can be configured to use either qualified or unqualified physical names when registering names in the IVI Configuration Store and when return physical name strings from the driver functions such as GetChannelName. This selection is made in the Driver Settings Editor.

This function will behave exactly as either the FullName function or the QualifiedFullName function depending upon how the repeated capability has been configured. See the help topics on those functions for more information.


PhysicalName::FullName

Returns the full repeated capability physical name which includes the identifiers for all parent repeated capability instances.

const char* FullName() const;
Return Value

The full repeated capability physical name.

Remarks

For a nested repeated capability, this represents the entire string of identifiers in the hierarchy of physical names.

For example, the full name of a nested repeated capability would be of the form:

a1:b2:c3

This FullName function would have the value a1:b2:c3.

Example

The following example demonstrates use of the FullName function.

C++
Copy
ViStatus _VI_FUNC acme4321_ConfigureArmCount(ViSession Vi, ViConstString RepCapIdentifier, ViInt32 ArmCount)
{
    // The Trace repeated capability is a child repeated capability of some other repeated capability
    // that defines a "C1" physical name.  The "trace" variable below represents the "T1" Trace instance
    // within the C1 instance of the parent repeated capability.
    //
    PhysicalName<Trace> trace("C1:T1");

    cout << trace.FullName();  // prints "C1:T1"
}


PhysicalName::Index

Returns the 0-based index of the physical name.

int Index(ViSession Vi) const;
Parameters
Vi

[in] ViSession handle for the driver session.

Return Value

The 0-based index of the physical name. If the physical name is not defined for the repeated capability associated with the PhysicalName object, then this function returns -1.

Remarks

For nested repeated capabilities, this represents the index within the specific parent repeated capability instance's collection of child physical names.

Example

The following example demonstrates use of the Index function.

C++
Copy
ViStatus _VI_FUNC acme4321_ConfigureArmCount(ViSession Vi, ViConstString RepCapIdentifier, ViInt32 ArmCount)
{
    // The Trace repeated capability is a child repeated capability of some other repeated capability
    // that defines a "C1" physical name.  The "trace" variable below represents the "T1" Trace instance
    // within the C1 instance of the parent repeated capability.
    //
    // Assume the following repeated capability physical names are defined in the following order for the Trace repeated capability:
    //
    //     "C1:T1"
    //     "C1:T2"
    //     "C1:T3"
    //     "C2:T1"
    //     "C2:T2"
    //     "C2:T3"  <-- this is the one we're after
    //     "C3:T1"
    //     "C3:T2"
    //     "C3:T3"
    //
    PhysicalName<Trace> trace("C2:T3");

    cout << trace.Index(Vi);  // prints "2" (not "5")
}


PhysicalName::Name

Returns the repeated capability physical name.

const char* Name() const;
Return Value

The repeated capability physical name.

Remarks

For a nested repeated capability, this represents the identifier for this particular repeated capability instance within the parent repeated capability instance.

For example, the full name of a nested repeated capability would be of the form:

a1:b2:c3

This Name function would have the value c3 if this physical name were associated with the most nested repeated capability of the three repeated capabilities in the hierarhcy implied above.

Example

The following example demonstrates use of the Name function.

C++
Copy
ViStatus _VI_FUNC acme4321_ConfigureArmCount(ViSession Vi, ViConstString RepCapIdentifier, ViInt32 ArmCount)
{
    // The Trace repeated capability is a child repeated capability of some other repeated capability
    // that defines a "C1" physical name.  The "trace" variable below represents the "T1" Trace instance
    // within the C1 instance of the parent repeated capability.
    //
    PhysicalName<Trace> trace("C1:T1");

    cout << trace.Name();  // prints "T1"
}


PhysicalName::ParentList

Returns a PhysicalNameList containing the PhysicalName objects for all repeated capabilities defined on the parent instance.

const PhysicalNameList<TRepCap>& ParentList(ViSession Vi) const;
Parameters
Vi

[in] ViSession handle for the driver session.

Return Value

Returns a PhysicalNameList containing the PhysicalName objects for all repeated capabilities defined on the parent instance.

Remarks

For nested repeated capabilities, each child instance exists in a list maintained on the parent instance. The ParentList function returns that list, which contains the current physical name and all of its "sibling" physical names.

Example

The following example demonstrates use of the ParentList function.

C++
Copy
ViStatus _VI_FUNC acme4321_ConfigureArmCount(ViSession Vi, ViConstString RepCapIdentifier, ViInt32 ArmCount)
{
    // The Trace repeated capability is a child repeated capability of a Channel repeated capability.
    //
    // Assume the following repeated capability physical names are defined in the following order for the Trace repeated capability:
    //
    //     "C1:T1"
    //     "C1:T2"
    //     "C1:T3"
    //     "C2:T1"
    //     "C2:T2"
    //     "C2:T3"
    //
    PhysicalName<Trace> trace("C2:T3");

    for (auto& it : trace.ParentList(Vi)
    {
        cout << it.FullName();
    }

    // Prints the following:
    //
    //    C2:T1
    //    C2:T2
    //    C2:T3
    //
}


PhysicalName::ParentName

Returns the repeated capability physical name of the parent repeated capability.

const char* ParentName() const;
Return Value

Returns the repeated capability physical name of the parent repeated capability.

Remarks
Important note Important

This function is only available for PhysicalName instances that are associated with a nested repeated capability. Attempting to access this function from a non-nested PhysicalName instance will produce a compile error.

Physical names for nested repeated capabilities have the following form:

a1:b2:c3

This function can be used to access the b2 component of the full physical name.

Other ancestor components of the full physical name (grandparent repeated capabilities, etc) can be accessed using the more general AncestorName function.

Example

The following example demonstrates use of the ParentName function.

C++
Copy
ViStatus _VI_FUNC acme4321_ConfigureArmCount(ViSession Vi, ViConstString RepCapIdentifier, ViInt32 ArmCount)
{
    // Assume the following nested repeated capability definition exists:
    //
    //     Channel -> Trace -> Marker
    //
    //     where the Channel repeated capability is the highest-level parent repeated capability
    //
    PhysicalName<Marker> marker("C1:T3:M2");

    cout << marker.ParentName();   // prints "T3"
}


PhysicalName::ParentFullName

Returns the full repeated capability physical name of the parent repeated capability. The full name includes the identifiers for all parent repeated capability instances.

std::string ParentFullName() const;
Return Value

Returns the full repeated capability physical name of the parent repeated capability.

Remarks
Important note Important

This function is only available for PhysicalName instances that are associated with a nested repeated capability. Attempting to access this function from a non-nested PhysicalName instance will produce a compile error.

Physical names for nested repeated capabilities have the following form:

a1:b2:c3

This function can be used to access the a1:b2 component of the full physical name.

Other ancestor components of the full physical name (grandparent repeated capabilities, etc) can be accessed using the more general AncestorFullName function.

Example

The following example demonstrates use of the ParentFullName function.

C++
Copy
ViStatus _VI_FUNC acme4321_ConfigureArmCount(ViSession Vi, ViConstString RepCapIdentifier, ViInt32 ArmCount)
{
    // Assume the following nested repeated capability definition exists:
    //
    //     Channel -> Trace -> Marker
    //
    //     where the Channel repeated capability is the highest-level parent repeated capability
    //
    PhysicalName<Marker> marker("C1:T3:M2");

    cout << marker.ParentFullName();   // prints "C1:T3"
}


PhysicalName::QualifiedName

Returns the qualified physical name (e.g. Channel!!C1).

const char* QualifiedName() const;
Remarks

Repeated capability physical names can be either qualified or unqualified. Qualified physical names include the prefix of the repeated capability itself followed by a !!. These qualifiers are used to uniquely identify repeated capability instances in cases where the unqualified physical name alone would not be unique. For instance, a driver may define both a "Measurement" and a "Channel" repeated capability with a physical name of C1. The physical name recorded in the IVI Configuration Store must be unique across the driver, so the qualified name would be used for each, yielding Measurement!!C1 and Channel!!C1.

Example

The following example demonstrates use of the QualifiedName function.

C++
Copy
ViStatus _VI_FUNC acme4321_ConfigureArmCount(ViSession Vi, ViConstString RepCapIdentifier, ViInt32 ArmCount)
{
    PhysicalName<Channel> channel("C1");

    cout << channel.QualifiedName();   // prints "Channel!!C1"
}


PhysicalName::QualifiedFullName

Returns the qualified full physical name (e.g. Channel!!c1::Trace!!t2).

const char* QualifiedName() const;
Remarks

Repeated capability physical names can be either qualified or unqualified. Qualified physical names include the prefix of the repeated capability itself followed by a !!. These qualifiers are used to uniquely identify repeated capability instances in cases where the unqualified physical name alone would not be unique. For instance, a driver may define both a "Measurement" and a "Channel" repeated capability with a physical name of C1. The physical name recorded in the IVI Configuration Store must be unique across the driver, so the qualified name would be used for each, yielding Measurement!!C1 and Channel!!C1.

Example

The following example demonstrates use of the QualifiedFullName function.

C++
Copy
ViStatus _VI_FUNC acme4321_ConfigureArmCount(ViSession Vi, ViConstString RepCapIdentifier, ViInt32 ArmCount)
{
    // Assume the Trace repeated capability is defined as a child of the Channel repeated capability
    //
    PhysicalName<Trace> trace("C1:T2");

    cout << trace.QualifiedFullName();   // prints "Channel!!C1::Trace!!T2"
}


PhysicalNameList Class

The PhysicalNameList class is simply an alias for a std::vector of PhysicalName objects and is declared as follows:

C++
Copy
template <typename TRepCap>
using PhysicalNameList = std::vector < PhysicalName<TRepCap> > ;
Remarks

For nested repeated capabilities, each child instance exists in a list maintained on the parent instance. The ParentList function returns that list, which contains the current physical name and all of its "sibling" physical names.

Example

The PhysicalNameList class is typically received as an output parameter from the ExpandSelector function on a repeated capability class as demonstrated in the example below.

C++
Copy
ViStatus _VI_FUNC acme4321_ConfigureArmCount(ViSession Vi, ViConstString RepCapIdentifier, ViInt32 ArmCount)
{
    // ...

    PhysicalNameList<Channel> physicalNames;
    ReturnOnError(Channel::ExpandSelector(Vi, ChannelName, physicalNames));

    for (const auto& physicalName : physicalNames)
    {
        cout << physicalName.Name();
    }

    // If the supplied RepCapIdentifier parameter represented a range of physical names,
    // such as CH1-CH4, then the above would print the following:
    //
    //    C1
    //    C2
    //    C3
    //    C4
    //
}


SelectorStyleRepCap Class

For each selector-style repeated capability defined in an IVI-C driver, Nimbus defines a repeated capability class of the same name and that class derives from the SelectorStyleRepCap class presented in this section.

The repeated capability class is defined by use of the repeated capability macro map maintained in the driver project's RepCaps.h. The SelectorStyleRepCap class exposes several methods required to properly manage repeated capability-based functions and attributes in an IVI-C driver. The topics in this section present the functions available for managing repeated capabilities in IVI-C drivers.

Important note Important

The SelectorStyleRepCap class includes all of the functions defined on the ParameterStyleRepCap class in addition to those presented in this section. This section presents only those functions unique to the SelectorStyleRepCap class. For details on the full set of functions available, see the functions listed under the topic discussing the ParameterStyleRepCap class.

In This Section

SelectorStyleRepCap::ExpandActiveSelector

SelectorStyleRepCap::ExpandSingleActiveSelector

SelectorStyleRepCap::GetActivePhysicalName

SelectorStyleRepCap::GetActivePhysicalNames

SelectorStyleRepCap::GetActiveSelector

SelectorStyleRepCap::SetActiveSelector


SelectorStyleRepCap::ExpandActiveSelector

Expands the currently active selector into a list of PhysicalName objects.

static ViStatus ExpandActiveSelector(ViSession Vi, PhysicalNameList<T>& physicalNames);
Parameters
Vi

[in] ViSession handle for the driver session.

physicalNames

[out] The PhysicalNameList containing the physical names resulting from the expansion of the active selector set by the most recent call to the SetActiveSelector function.

Return Value

Returns a VI_SUCCESS if the operation was successful or a failure ViStatus otherwise.

Remarks

This function is equivalent to calling GetActiveSelector and passing that result to ExpandSelector. Further information on those operations can be found in their respective help topics.

Important note Important

Unlike the SetActiveSelector function, this function does not store the physical names resulting from the expansion in the driver's internally maintained list of active physical names. The active physical name list is unaffected by calling this function. Thus, the ExpandActiveSelector function can safely be used to interrogate the currently active list of physical names without affecting the state of the driver.

Example

The following example demonstrates use of the ExpandActiveSelector function.

C++
Copy
ViStatus _VI_FUNC acme4321_ConfigureMeasurement(ViSession Vi, ViReal64 Frequency, ViReal64 Bandwidth)
{
    // ...

    // Assume a Channel repeated capability is defined and the active selector is "CH1-CH4"
    //
    PhysicalNameList<Channel> channels;
    auto status = Channel::ExpandActiveSelector(Vi, channels);
    ReturnOnError(status);

    for (const auto& channel : channels)
    {
        cout << channel.FullName();
    }

    // The above loop prints the following:
    //
    //    CH1
    //    CH2
    //    CH3
    //    CH4

    // ...
}


SelectorStyleRepCap::ExpandSingleActiveSelector

Translates the active repeated capability selector into a single physical name.

static ViStatus ExpandSingleActiveSelector(ViSession Vi, PhysicalName<T>& physicalName);
Parameters
Vi

[in] ViSession handle for the driver session.

physicalName

[out] A PhysicalName object containing the physical name corresponding to the currently active selector for the repeated capability.

Return Value

Returns a VI_SUCCESS if the operation was successful or a failure ViStatus otherwise. If the currently active selector represents more than one physical name, the the error code IVIC_ERROR_BADLY_FORMED_SELECTOR is returned.

Remarks

If the currently active selector represents a virtual name, this function translates that virtual name to the corresponding physical name.

This function is useful in scenarios where an operation is only valid for a single repeated capability physical name. For example, attribute getters and functions that have output parameters can only return a single value, so the user can never invoke such operations on more than one repeated capability at a time. Thus, such operations must internally validate that only a single physical name is active when they are called. The ExpandSingleActiveSelector function is provided for this purpose.

Example

The following example demonstrates use of the ExpandSingleActiveSelector function.

C++
Copy
ViStatus _VI_FUNC acme4321_ConfigureMeasurement(ViSession Vi, ViReal64 Frequency, ViReal64 Bandwidth)
{
    // ...

    PhysicalName<Channel> channel;
    auto status = Channel::ExpandSingleActiveSelector(Vi, channel);
    ReturnOnError(status);

    // ...
}


SelectorStyleRepCap::GetActivePhysicalName

Returns a single PhysicalName object corresponding to the active selector.

static ViStatus GetActivePhysicalName(ViSession Vi, PhysicalName<T>& physicalName);
Parameters
Vi

[in] ViSession handle for the driver session.

physicalName

[out] The PhysicalName corresponding to the expansion of the active selector set by the most recent call to the SetActiveSelector function.

Return Value

Returns a VI_SUCCESS if the operation was successful or a failure ViStatus otherwise.

If more than one physical name is currently active (i.e. the number of elements returned by the GetActivePhysicalNames function is greater than one) then this function returns the error code IVIC_ERROR_BADLY_FORMED_SELECTOR.

Remarks

This function is useful in scenarios where an operation is only valid for a single repeated capability physical name. For example, attribute getters and functions that have output parameters can only return a single value, so the user can never invoke such operations on more than one repeated capability at a time. Thus, such operations must internally validate that only a single physical name is active when they are called. The GetActivePhysicalName function is provided for this purpose.


SelectorStyleRepCap::GetActivePhysicalNames

Returns the PhysicalNameList containing all of the PhysicalName objects for the expanded active selector.

static ViStatus GetActivePhysicalNames(ViSession Vi, PhysicalNameList<T>& physicalNames);
Parameters
Vi

[in] ViSession handle for the driver session.

physicalNames

[out] The PhysicalNameList containing the physical names resulting from the expansion of the active selector set by the most recent call to the SetActiveSelector function.

Return Value

Returns a VI_SUCCESS if the operation was successful or a failure ViStatus otherwise.

Remarks

See the discussion of the SetActiveSelector function and the ExpandSelector function for details on how selector strings are expanded into physical names.


SelectorStyleRepCap::GetActiveSelector

Returns the selector string that was last set by the SetActiveSelector function.

static ViStatus GetActiveSelector(ViSession Vi, ViInt32 nSelectorBufferSize, ViChar szSelector[]);
Parameters
Vi

[in] ViSession handle for the driver session.

nSelectorBufferSize

[in] Number of characters allocated by the caller in the szSelector parameter.

szSelector

[out] The active selector for the repeated capability as set by a previous call to the SetActiveSelector function. If the SetActiveSelector function has not yet been called by the client program, this function returns an empty string.

Return Value

Returns a VI_SUCCESS if the operation was successful or a failure ViStatus otherwise.

Remarks

Unlike parameter-style repeated capabilities which explicitly pass a RepCapIdentifier parameter to each function or attribute associated with the repeated capability, selector-style repeated capabilities operate on an active selector, which is a cached string that may accurately be thought of as a "hidden" or "implicit" RepCapIdentifier parameter. Client programs call the SetActiveSelector function and the driver caches the resulting physical names and uses it on subsequent calls to functions and attributes as if the client program had directly passed a RepCapIdentifier parameter to each function and attribute invocation.

The active selector retrieved here is the same literal value previously set via the SetActiveSelector function. That is to say, virtual names, lists, and ranges all appear as-specified without any of the expansion semantics performed by the ExpandActiveSelector function. Use the GetActivePhysicalNames function to retrieve the expanded active selector as a list of physical names.

Example

The following example demonstrates use of the GetActiveSelector function.

C++
Copy
ViStatus _VI_FUNC acme4321_get_ACTIVE_MARKER(ViSession Vi, ViConstString RepCapIdentifier, ViInt32 AttributeValueBufferSize, ViChar AttributeValue[])
{
    ValidateSession(Vi);
    ObtainLock(Vi);
    CheckForNull(Vi, AttributeValue);

    auto status = VI_SUCCESS;

    status = Marker::GetActiveSelector(Vi, AttributeValueBufferSize, AttributeValue);

    return status;
}


SelectorStyleRepCap::SetActiveSelector

Sets the active selector to use for subsequent operations on the repeated capability.

static ViStatus SetActiveSelector(ViSession Vi, ViConstString szSelector);
Parameters
Vi

[in] ViSession handle for the driver session.

szSelector

[out] The active selector to use for subsequent operations on the repeated capability.

Return Value

Returns a VI_SUCCESS if the operation was successful or a failure ViStatus otherwise.

See the documentation on the ExpandSelector function for additional details on the possible failure codes this function may return.

Remarks

Unlike parameter-style repeated capabilities which explicitly pass a RepCapIdentifier parameter to each function or attribute associated with the repeated capability, selector-style repeated capabilities operate on an active selector, which is a cached string that may accurately be thought of as a "hidden" or "implicit" RepCapIdentifier parameter. Client programs call the SetActiveSelector function and the driver caches the resulting physical names and uses it on subsequent calls to functions and attributes as if the client program had directly passed a RepCapIdentifier parameter to each function and attribute invocation.

The active selector set here is stored within the driver in two forms. First, it is stored in an unmodified form so that it can be retrieved exactly as the user specified. The GetActiveSelector function is used to retrieve the unmodified form. Next, the ExpandSelector function is called internally in order to translate any virtual names to physical names and to expand any lists of names or ranges of names. The result of this expansion is stored as a list of physical names that can be retrieved via the GetActivePhysicalNames function.

This function internally uses the ExpandSelector function to process the szSelector parameter. See that topic for more information on how the expansion is performed and the possible error codes that may be returned.

Important note Important

For dynamic repeated capabilities, where the list of supported physical names may change during the driver session, it is important to keep in mind that any calls to the RemovePhysicalNames function may affect the behavior of the driver in ways that may be confusing to the end user. Specifically, if the SetActiveSelector function is used to make a set of physical names active and then the RemovePhysicalNames function is used to remove one or more of those physical names, then runtime errors are likely, depending upon the specific details of the driver implementation. The list of physical names resulting from the expansion of the szSelector parameter is only validated at the time the SetActiveSelector function is called.

Example

The following example demonstrates use of the SetActiveSelector function.

C++
Copy
ViStatus _VI_FUNC acme4321_set_ACTIVE_MARKER(ViSession Vi, ViConstString RepCapIdentifier, ViConstString AttributeValue)
{
    ValidateSession(Vi);
    ObtainLock(Vi);

    auto status = VI_SUCCESS;

    status = Marker::SetActiveSelector(Vi, AttributeValue);

    return status;
}


Simulation and State Caching Functions

In This Section

CacheEntry Struct

GetCacheEntry Function

GetStringValueForSimulation Macro

GetterCacheManager Class

GetValueForSimulation Macro

SetterCacheManager Class


CacheEntry Struct

Nimbus provides automatic state caching support for attributes via the Attribute State Caching Editor. In some cases, the driver developer may wish to have more direct control of how the caching is performed. The CacheEntry class is used internally to manage cached attribute values and is available for driver developers to that wish to perform caching operations explicitly.

Each attribute for which state caching is enabled is stored on the DriverSession class. One CacheEntry instance is stored per attribute value. For attributes associated with a repeated capability, one CacheEntry instance is stored for the attribute per repeated capability physical name. The GetCacheEntry function is used to retrieve cache entries by attribute ID and physical name (if applicable).

In This Section

CacheEntry::HasValue

CacheEntry::Invalidate

CacheEntry::IsValid

CacheEntry::SetValid

CacheEntry::SetValue

CacheEntry::Value


CacheEntry::HasValue

Indicates if the specified value is in the cache and is valid.

bool HasValue(const T& value) const;
Parameters
value

[in] The value to test for equality against the cached value, if present. The data type T is that of the CacheEntry template instance.

Return Value

Returns true if the specified value is in the cache for this particular entry and if the entry is valid.

Example

The following example demonstrates use of the HasValue function.

C++
Copy
ViStatus _VI_FUNC acme4321_set_BANDWIDTH(ViSession Vi, ViConstString RepCapIdentifier, ViReal64 AttributeValue)
{
    auto status = VI_SUCCESS;

    // Retrieve the cache entry for the Bandwidth attribute
    //
    auto entry = GetCacheEntry<ViReal64>(Vi, ACME4321_ATTR_BANDWIDTH);

    // If the value is in the cache AND is valid, simply return since we don't need to send the instrument command
    //
    if (entry.HasValue(AttributeValue))
    {
        return status;
    }

    // If we get this far, then the new value is not in the cache, so we must communicate with the instrument to set the value
    //
    status = viPrintf(GetVisaSession(Vi), "SENS:BAND %0.15g\n", AttributeValue);
    ReturnOnError(status);

    // The new value was successfully sent to the instrument, so update the cache
    //
    entry.SetValue(AttributeValue);

    return status;
}


CacheEntry::Invalidate

Invalidates a cache entry so that the next set or get operation results in communication with the instrument.

void Invalidate();
Example

The following example demonstrates use of the Invalidate function.

C++
Copy
ViStatus _VI_FUNC acme4321_set_FREQUENCY(ViSession Vi, ViConstString RepCapIdentifier, ViReal64 AttributeValue)
{
    auto status = VI_SUCCESS;

    // We want to couple the frequency to the bandwidth, so we must invalidate the cached bandwidth
    // whenever the frequency changes.
    //

    // Retrieve the cache entry for the Bandwidth attribute
    //
    auto entry = GetCacheEntry<ViReal64>(Vi, ACME4321_ATTR_BANDWIDTH);

    // Invalidate the entry
    //
    entry.Invalidate();

    return status;
}


CacheEntry::IsValid

Indicates whether or not a cache entry is valid.

bool IsValid() const;
Return Value

Returns true if the cache entry is valid and false otherwise.

Example

The following example demonstrates use of the IsValid function.

C++
Copy
ViStatus _VI_FUNC acme4321_Configure(ViSession Vi, ViReal64 Frequency, ViReal64 Gain)
{
    auto status = VI_SUCCESS;

    // Retrieve the cache entry for the Bandwidth attribute
    //
    auto entry = GetCacheEntry<ViReal64>(Vi, ACME4321_ATTR_BANDWIDTH);

    if (entry.IsValid())
    {
        // ...
    }

    return status;
}


CacheEntry::SetValid

Sets the valid state of a cache entry to true.

void SetValid();
Example

The following example demonstrates use of the SetValid function.

C++
Copy
ViStatus _VI_FUNC acme4321_Configure(ViSession Vi, ViReal64 Bandwidth, ViReal64 Gain)
{
    auto status = viPrintf(GetVisaSession(Vi), "CONFIG:BAND %0.15g;CONFIG:GAIN %0.15g\n", Bandwidth, Gain);
    ReturnOnError(status);

    // Retrieve the cache entry for the Bandwidth attribute
    //
    auto entry = GetCacheEntry<ViReal64>(Vi, ACME4321_ATTR_BANDWIDTH);

    entry.SetValid();

    return status;
}


CacheEntry::SetValue

Updates the value for the cache entry. Note that SetValid must be called to set the entry's valid state to true.

void SetValue(const T& value);
Parameters
value

[in] The value to test for equality against the cached value, if present. The data type T is that of the CacheEntry template instance.

Example

The following example demonstrates use of the SetValue function.

C++
Copy
ViStatus _VI_FUNC acme4321_set_BANDWIDTH(ViSession Vi, ViConstString RepCapIdentifier, ViReal64 AttributeValue)
{
    auto status = VI_SUCCESS;

    // Retrieve the cache entry for the Bandwidth attribute
    //
    auto& entry = GetCacheEntry<ViReal64>(Vi, ACME4321_ATTR_BANDWIDTH);

    // If the value is in the cache AND is valid, simply return since we don't need to send the instrument command
    //
    if (entry.HasValue(AttributeValue))
    {
        return status;
    }

    // If we get this far, then the new value is not in the cache, so we must communicate with the instrument to set the value
    //
    status = viPrintf(GetVisaSession(Vi), "SENS:BAND %0.15g\n", AttributeValue);
    ReturnOnError(status);

    // The new value was successfully sent to the instrument, so update the cache
    //
    entry.SetValue(AttributeValue);
    entry.SetValid();

    return status;
}


CacheEntry::Value

Retrieves the value of the cache entry.

T Value() const;
Return Value

The cached value currently stored for the cache entry. The data type T is that of the CacheEntry template instance.

Example

The following example demonstrates use of the Value function.

C++
Copy
ViStatus _VI_FUNC acme4321_get_BANDWIDTH(ViSession Vi, ViConstString RepCapIdentifier, ViReal64* AttributeValue)
{
    auto status = VI_SUCCESS;

    // Retrieve the cache entry for the Bandwidth attribute
    //
    auto& entry = GetCacheEntry<ViReal64>(Vi, ACME4321_ATTR_BANDWIDTH);

    auto value = entry.Value();

    // ...

    return status;
}


GetCacheEntry Function

Retrieves a CacheEntry structure for the specified attribute on the specific repeated capability physical name.

template <typename T>
CacheEntry<T>& GetCacheEntry(ViSession Vi, ViAttr attributeId, const std::string& strQualifiedPhysicalName = std::string());
Parameters
Vi

[in] ViSession handle for the driver session.

attributeId

[in] The attribute ID of the cache entry to retrieve (e.g. ACME4321_ATTR_BANDWIDTH).

strQualifiedPhysicalName

[in] The qualified repeated capability physical name of the cache entry to retrieve for the specified attribute (e.g. Channel!!CH1). This parameter should be specified for attributes associated with a repeated capability. Note that the qualified physical name must always be used, even if the repeated capability associated with the attribute has not been configured to use qualified physical names via the Driver Settings Editor.

Return Value

The cache entry associated with the specified attribute ID and repeated capability physical name.

Remarks

This function is used in scenarios where the driver developer wishes to take direct control over the state caching functionality of the driver for specific attributes.

Example

The following example demonstrates use of the GetCacheEntry function.

C++
Copy
ViStatus _VI_FUNC acme4321_Configure(ViSession Vi, ViReal64 Frequency, ViReal64 Gain)
{
    auto status = VI_SUCCESS;

    // Retrieve the cache entry for the Bandwidth attribute
    //
    auto& entry = GetCacheEntry<ViReal64>(Vi, ACME4321_ATTR_BANDWIDTH);

    if (entry.IsValid())
    {
        // ...
    }

    return status;
}


GetStringValueForSimulation Macro

Returns a model-based string value to return from a function or attribute value when simulating.

#define GetStringValueForSimulation(Vi, bufferSize, buffer, ...)
Parameters
Vi

[in] ViSession handle for the driver session.

bufferSize

[int] The number of characters allocated by the caller in the buffer parameter.

buffer

[out] Simulated value chosen based from those supplied in the model-specific list of values in the variable argument parameter.

... (variable arguments)

[in] A variable argument list of model-value pairs. The function returns in the buffer parameter a value from this list based on matching the connected instrument model with one of the entries in this list.

Example

The following example demonstrates use of the GetStringValueForSimulation function.

C++
Copy
ViStatus _VI_FUNC acme4321_get_USER_NAME(ViSession Vi, ViConstString RepCapIdentifier, ViInt32 AttributeValueBufferSize, ViChar AttributeValue[])
{
    // ...

    if (SimulationEnabled(Vi))
    {
        if (!cacheManager.GetCachedValue(AttributeValueBufferSize, AttributeValue))
        {
            // The entries below indicate which values should be returned based upon the instrument model
            // being simulated.  The entry with no model specified (the one with value "Mark") will be chosen
            // if the model is something other than ModelA, ModelB, or ModelC.
            //
            GetStringValueForSimulation(
                Vi, AttributeValueBufferSize, AttributeValue,
                { "Mark" },
                { "ModelA", "Fred" },
                { "ModelB", "Tom" },
                { "ModelC", "Alice" },
            );
        }

        return VI_SUCCESS;
    }

    // ...
}


GetterCacheManager Class

As the name implies, the GetterCacheManager is used to manage cached values for attributes in IVI-C drivers. It is important to note that the Nimbus caching engine for IVI-C drivers is used for two purposes -- 1) to support the IVI-defined state caching features which drivers may optionally implement, and 2) to support simulation which all IVI drivers are required to implement. Because the same cache is used for both state caching and simulation, the GetterCacheManager appears in most attribute implementation code. Understanding the tasks it performs is useful in understanding the overall flow of Nimbus-generated attribute implementation code.

The GetterCacheManager simplifies simulation and state caching code by performing the following tasks:

  • Checks to see if either state caching or simulation is enabled and does nothing if neither are enabled.

  • Automatically retrieves the cache entry for the specified attribute. If the attribute is associated with a repeated capability, then the GetterCacheManager retrieves the cache entry for the physical name supplied in the attribute getter's RepCapIdentifier parameter.

  • Automatically updates the cached value and sets its cached state to valid upon function exit. This is done in the class destructor so that the cache will be properly updated when the function has multiple return locations.

  • Provides a GetCachedValue function which allows implementation code to easily implement simulation.

Using the GetterCacheManager without Repeated Capabilities

The following code shows how the GetterCacheManager is declared in a an attribute getter implementation. In this example, the ACME4321_ATTR_BANDWIDTH attribute is not associated with a repeated capability.

C++
Copy
ViStatus _VI_FUNC acme4321_get_BANDWIDTH(ViSession Vi, ViConstString RepCapIdentifier, ViReal64* AttributeValue)
{
    // ...

    // At this point, when the cacheManager variable is declared, the GetterCacheManager checks to
    // see if either state caching or simulation are enabled.  If enabled, then the constructor
    // retrieves the cache entry.
    //
    GetterCacheManager<ViReal64> cacheManager(Vi, ACME4321_ATTR_BANDWIDTH, *AttributeValue);

    if (SimulationEnabled(Vi))
    {
        if (!cacheManager.GetCachedValue(AttributeValue))
        {
            *AttributeValue = 3.14E6;
        }

        // Since the cacheManager destructor updates the cache, the AttributeValue will be stored
        // in the cache for simulation purposes at this point as well.
        //
        return VI_SUCCESS;
    }

    // ...

}   // Upon function exit, the final value of AttributeValue will be stored in the cache
Using the GetterCacheManager with Repeated Capabilities

The following code shows how the GetterCacheManager is declared in a an attribute getter implementation. In this example, the ACME4321_ATTR_FREQUENCY attribute is associated with a channel repeated capability.

C++
Copy
ViStatus _VI_FUNC acme4321_get_FREQUENCY(ViSession Vi, ViConstString RepCapIdentifier, ViReal64* AttributeValue)
{
    // ...

    PhysicalNameList<Channel> physicalNames;
    ReturnOnError(Channel::ExpandSingleSelector(Vi, RepCapIdentifier, physicalNames));

    // At this point, when the cacheManager variable is declared, the GetterCacheManager checks to
    // see if either state caching or simulation are enabled.  If enabled, then the constructor
    // retrieves the cache entry for the specific physical name supplied.
    //
    GetterCacheManager<ViReal64, Channel> cacheManager(Vi, physicalNames, ACME4321_ATTR_FREQUENCY, *AttributeValue);

    if (SimulationEnabled(Vi))
    {
        if (!cacheManager.GetCachedValue(AttributeValue))
        {
            *AttributeValue = 3.14E6;
        }

        // Since the cacheManager destructor updates the cache, the AttributeValue will be stored
        // in the cache for simulation purposes at this point as well.
        //
        return VI_SUCCESS;
    }

    // ...

}   // Upon function exit, the final value of AttributeValue will be stored in the cache for all physical names supplied


GetValueForSimulation Macro

Returns a model-based value to return from a function or attribute value when simulating.

#define GetValueForSimulation(Vi, pValueOut, ...)
Parameters
Vi

[in] ViSession handle for the driver session.

pValueOut

[out] Simulated value chosen based from those supplied in the model-specific list of values in the variable argument parameter.

... (variable arguments)

[in] A variable argument list of model-value pairs. The function returns in the pValueOut parameter a value from this list based on matching the connected instrument model with one of the entries in this list.

Example

The following example demonstrates use of the GetValueForSimulation function.

C++
Copy
ViStatus _VI_FUNC acme4321_get_BANDWIDTH(ViSession Vi, ViConstString RepCapIdentifier, ViReal64* AttributeValue)
{
    // ...

    if (SimulationEnabled(Vi))
    {
        if (!cacheManager.GetCachedValue(AttributeValue))
        {
            // The entries below indicate which values should be returned based upon the instrument model
            // being simulated.  The entry with no model specified (the one with value 1.0E9) will be chosen
            // if the model is something other than ModelA, ModelB, or ModelC.
            //
            GetValueForSimulation(
                Vi, AttributeValue,
                { 1.0E9 },
                { "ModelA", 2.0E9 },
                { "ModelB", 5.0E9 },
                { "ModelC", 7.0E9 },
            );
        }

        return VI_SUCCESS;
    }

    // ...
}


SetterCacheManager Class

As the name implies, the SetterCacheManager is used to manage cached values for attributes in IVI-C drivers. It is important to note that the Nimbus caching engine for IVI-C drivers is used for two purposes -- 1) to support the IVI-defined state caching features which drivers may optionally implement, and 2) to support simulation which all IVI drivers are required to implement. Because the same cache is used for both state caching and simulation, the SetterCacheManager appears in most attribute implementation code. Understanding the tasks it performs is useful in understanding the overall flow of Nimbus-generated attribute implementation code.

The SetterCacheManager simplifies simulation and state caching code by performing the following tasks:

  • Checks to see if either state caching or simulation is enabled and does nothing if neither are enabled.

  • Automatically retrieves the cache entry for the specified attribute. If the attribute is associated with a repeated capability, then the SetterCacheManager retrieves all cache entries for the physical names supplied in the attribute setter's RepCapIdentifier parameter.

  • Automatically updates the cached value and sets its cached state to valid upon function exit. This is done in the class destructor so that the cache will be properly updated when the function has multiple return locations.

  • Provides a NonCachedPhysicalNames function which allows implementation code to operate only upon those physical names for which a cache entry is not valid. This is important when determining which physical names should be operated upon in an attribute setter implementation.

Using the SetterCacheManager without Repeated Capabilities

The following code shows how the SetterCacheManager is declared in a an attribute setter implementation. In this example, the ACME4321_ATTR_BANDWIDTH attribute is not associated with a repeated capability.

C++
Copy
ViStatus _VI_FUNC acme4321_set_BANDWIDTH(ViSession Vi, ViConstString RepCapIdentifier, ViReal64 AttributeValue)
{
    // ...

    // At this point, when the cacheManager variable is declared, the SetterCacheManager checks to
    // see if either state caching or simulation are enabled.  If enabled, then the constructor
    // checks to see if the cache entry is valid and has the value passed in the AttributeValue
    // parameter.
    //
    SetterCacheManager<ViReal64> cacheManager(Vi, ACME4321_ATTR_BANDWIDTH, AttributeValue);

    if (SimulationEnabled(Vi))
    {
        // Since the cacheManager destructor updates the cache, the AttributeValue will be stored
        // in the cache for simulation purposes at this point as well.
        //
        return VI_SUCCESS;
    }

    // ...

}   // Upon function exit, the final value of AttributeValue will be stored in the cache
Using the SetterCacheManager with Repeated Capabilities

The following code shows how the SetterCacheManager is declared in a an attribute setter implementation. In this example, the ACME4321_ATTR_FREQUENCY attribute is associated with a channel repeated capability. When a repeated capability is involved, multiple cache entries must be managed by the SetterCacheManager class.

C++
Copy
ViStatus _VI_FUNC acme4321_set_FREQUENCY(ViSession Vi, ViConstString RepCapIdentifier, ViReal64 AttributeValue)
{
    // ...

    auto status = VI_SUCCESS;

    PhysicalNameList<Channel> physicalNames;
    ReturnOnError(Channel::ExpandSelector(Vi, RepCapIdentifier, physicalNames));

    // At this point, when the cacheManager variable is declared, the SetterCacheManager checks to
    // see if either state caching or simulation are enabled.  If enabled, then the constructor
    // checks to see if the cache entry for each physical name is valid and it stores the invalid
    // ones internally so that the code later in the implementation can discriminate.
    //
    SetterCacheManager<ViReal64, Channel> cacheManager(Vi, physicalNames, ACME4321_ATTR_FREQUENCY, AttributeValue);

    if (SimulationEnabled(Vi))
    {
        // Since the cacheManager destructor updates the cache, the AttributeValue will be stored
        // in the cache (for each physicalName) for simulation purposes at this point as well.
        //
        return VI_SUCCESS;
    }

    // Send a command to the instrument for each physical name whose cached value is not valid
    //
    for (const auto& physicalName : cacheManager.NonCachedPhysicalNames(Vi))
    {
        status = viPrintf(GetVisaSession(), "SENS:FREQ%s %0.15g", physicalName.Name(), AttributeValue);
        ReturnOnError(status);
    }

    // ...

}   // Upon function exit, the final value of AttributeValue will be stored in the cache for all physical names supplied


Validation Functions

In This Section

CheckForNull Macro

CheckForUnsupportedModel Macro

ObtainLock

ReturnOnError Macro

ValidateSession Macro


CheckForNull Macro

Returns from the current function with an error ViStatus if any of the supplied pointer arguments are null.

#define CheckForNull(Vi, ...)
Parameters
Vi

[in] ViSession handle for the driver session.

... (variable argument list)

[in] Comma-separated list of pointer variables to test against null.

Remarks

This macro is used to validate pointer arguments. If any of the arguments are null, then this macro will return from the current function with a ViStatus value of IVIC_ERROR_NULL_POINTER. Before returning, this function stores the error code and appropriately formatted error message in the driver session so that client code may retrieve both via the GetError function.

Example

The following example demonstrates use of the CheckForNull macro.

C++
Copy
ViStatus _VI_FUNC acme4321_ReadData(ViSession Vi, ViReal64* Frequency, ViReal64* Amplitude)
{
    ValidateSession(Vi);
      ObtainLock(Vi);
      CheckForNull(Vi, Frequency, Amplitude);

    // ...
}


CheckForUnsupportedModel Macro

Checks to see if the driver is executing against any of the models specified and returns from the current function with an appropriate ViStatus error code if an unsupported model is detected.

#define CheckForUnsupportedModel(Vi, unsupportedModels)
Parameters
Vi

[in] ViSession handle for the driver session.

unsupportedModels

[in] A comma-separated list of model names that are not supported by the current function.

Remarks

If the InstrumentModel function indicates that the driver is connected to any of the models specified by the list in the unsupportedModels parameter, then this macro will return from the current function with either an IVIC_ERROR_FUNCTION_NOT_SUPPORTED or IVIC_ERROR_ATTRIBUTE_NOT_SUPPORTED error code. It will also compose an error message of the form: "Function is not supported for instrument model 'ModelA'". and associate the error code and error message with the driver session so that the caller can use the GetError function to retrieve both.

Example

The following example demonstrates use of the CheckForUnsupportedModel macro.

C++
Copy
ViStatus _VI_FUNC acme4321_ConfigureSweep(ViSession Vi, ViReal64 StartFrequency, ViReal64 StopFrequency)
{
    CheckForUnsupportedModel(Vi, "ModelA, ModelC");

    // ...
}


ObtainLock

This macro obtains a thread-based lock for the specified session for the duration of the function in which it is declared.

#define ObtainLock(Vi)
Parameters
Vi

[in] ViSession handle for the driver session.

Remarks

This macro declares a local instance of a special SessionLock class. The constructor of the SessionLock class obtains a session lock on the session indicated by the Vi parameter. When the function containing the ObtainLock macro completes, the SessionLock destructor runs and the session is unlocked.

Example

The following example demonstrates use of the ObtainLock macro.

C++
Copy
ViStatus _VI_FUNC acme4321_ConfigureSweep(ViSession Vi, ViReal64 StartFrequency, ViReal64 StopFrequency)
{
    ObtainLock(Vi);

    // ...
}


ReturnOnError Macro

Returns from the current function using the supplied status parameter as the return value, if that parameter represents a failure status.

#define ReturnOnError(status)
Parameters
status

[in] ViStatus variable to test.

Remarks

This macro is useful for organizing a series of function calls that use ViStatus values as their return codes. It allows code to be written more "linearly", as opposed to using a series of nested if-else constructs.

Example

The following example demonstrates use of the ReturnOnError macro.

C++
Copy
ViStatus _VI_FUNC acme4321_ConfigureSweep(ViSession Vi, ViReal64 StartFrequency, ViReal64 StopFrequency)
{
    // ...

    auto status = VI_SUCCESS;

    status = viPrintf(GetVisaSession(Vi), "CONFIG:SWE %0.15lg,%0.15lg\n", StartFrequency, StopFrequency);
    ReturnOnError(status);

    // ...
}


ValidateSession Macro

Tests the specified session to ensure it represents a valid handle to an existing driver session created via the driver's init or InitWithOptions function.

#define ValidateSession(Vi)
Parameters
Vi

[in] ViSession variable to test.

Remarks

The macro returns from the current function with a ViStatus value of IVIC_ERROR_INVALID_SESSION_HANDLE if the supplied ViSession parameter is not valid.

Example

The following example demonstrates use of the ValidateSession macro.

C++
Copy
ViStatus _VI_FUNC acme4321_ConfigureSweep(ViSession Vi, ViReal64 StartFrequency, ViReal64 StopFrequency)
{
    ValidateSession(Vi);

    // ...
}


Adding Support for Multiple Instrument Models

Instruments are often designed in related families. Consequently, these instruments share many characteristics from a driver design and implementation perspective. Often identical SCPI command sets are available in more than one instrument, with differences arising in only specific measurement parameters, such as sweep speed, resolution, frequency, or bandwidth. Designing, developing, and implementing separate IVI drivers for each model in an instrument family would result in an intractable development and version management burden.

Nimbus allows a single driver to support multiple models of an instrument. The following driver features can all be made model-specific:

  • Method or property supported

  • Instrument command

  • Range-checking limits

  • Simulation values

Defining Instrument Models

The first step in building a multi-model driver is defining the list of supported models. This is done via the Models Page of the Driver Settings Editor. Models are defined within instrument families. This allows related models to be grouped together and family-specific behavior to be assigned to a group of instrument models. The list of models defined in the Models Page is used by Nimbus for a variety of purposes:

  • It establishes the list of models returned by the SUPPORTED_MODELS attribute.

  • During driver initialization, if the IdQuery parameter was set to true, the actual model detected is checked against this list of models. If the model detected is not in the list set on the Models Page, then the initialization function fails.

  • The model list is used in generating the IVI compliance information in the driver help file.

  • The model marked as the default model is used in simulation mode if no Model value is supplied in the OptionString parameter passed to Initialize.

Choosing Model Names

The model names defined in the Models Page of the Driver Settings Editor must match exactly the model string set by the InitializeIdentification (for IVI.NET), the InitializeIdentification function (for IVI-COM), or the GetIdentificationInfo (for IVI-C). If the detected model does not match, an error will be generated when initializing the driver. By default, during initialization, Nimbus will issue a *IDN? query and parse the result to determine the instrument model. In some cases, this may not be the desired behavior. For instance, some drivers might support a large number of specific instrument models that cannot practically be listed on the Models Page. Such drivers often choose to include "wildcard" characters in the model names. For instance, a model name such as Acme43XX could be used to respresent an entire series of instruments that start with "Acme43" and have a range of possible values for the last two characters in the model. Obviously, when querying the instrument for its model name, it will return a specific model and not Acme43XX. This requires one of two approaches for ensuring that the initialization of the driver succeeds.

  1. Override the function used to identify the connected instrument and to set the model string to one of the values defined on the Models Page of the Driver Settings Editor.

    For IVI.NET drivers, that function is the InitializeIdentification function.

    For IVI-COM drivers, that function is the InitializeIdentification function.

    For IVI-C drivers, that function is the GetIdentificationInfo function.

  2. Override the implementation of the function used to determine if the connected instrument is one that is supported by the driver.

    For IVI.NET drivers, that function is the CheckInstrumentSupported function.

    For IVI-COM drivers, that function is the InstrumentSupported method.

    For IVI-C drivers, that function is the InstrumentSupported method.

The Default Instrument Model

When the driver is initialized using a live instrument session, the model is determined by the implementation of the InitializeIdentification (for IVI.NET), the InitializeIdentification function (for IVI-COM), or the GetIdentificationInfo (for IVI-C). Typically, this performs a simple *IDN? query and parses the response to determine the connected model. However, in simulation mode, the driver obviously cannot issue queries to an instrument, yet a simulated instrument model must be established since many driver features may be model-specific. Nimbus provides three ways for the simulated model to be determined. These are listed below in order of precedence:

  1. A Model value can be supplied in the OptionsString parameter passed during initialization of the driver.

  2. If no Model value is passed as part of the OptionsString during initialization, Nimbus checks for a Model value supplied as a Configurable Initial Setting in the IVI Configuration Store.

  3. If no Model value is supplied during driver initialization and no Model value is found in the IVI Configuration Store, the driver falls back to use the default model specified by the driver developer on the Models Page of the Driver Settings Editor.

To specify the default instrument model for simulation

  1. From Solution Explorer, double-click the Driver Settings Editor node to bring up the Driver Settings Editor.

  2. Click on the Models tab.

  3. From within the list of defined models, right-click on the desired default model for simulation and choose Make Default Model. The default model appears in bold text.

Customizing Driver Behavior for Specific Models

Nimbus allows specific aspects of method and property implementations to be customized on a per-model and per-family basis. The following Item Editors within the Driver Designer include a special Models Window for defining model-specific behavior:

  • Method General Editor

  • Property General Editor

  • Property Range Checking Editor

  • Property Simulation Editor

  • Function General Editor (for IVI-C)

  • Attribute General Editor (for IVI-C)

  • Attribute Range Checking Editor (for IVI-C)

  • Attribute Simulation Editor (for IVI-C)

  • Enum Member General Editor

For each of the editors that support model-specific settings, the behavior of the Models Window is the same. When a method or property is first created, all models will use the same settings. When clicking on a specific model in the Models Window, all of the controls in the editor become read-only. Only by selecting the All Models node in the Models Window may any of the settings in an editor be changed.

The settings on a specific editor may be customized for a particular model by right-clicking the desired model in the Models Window and choosing Customize Settings.

Manual Model-Specific Customizations

In some cases, the desired model-specific behavior cannot be specified using one of the Item Editors mentioned above. Nimbus provides three functions that can be used in a method or property implementation to perform custom model-specific or family-specific logic.

For IVI.NET drivers, See the documentation in the Nimbus Class Library for details and examples of the following methods and properties:

  • InstrumentModel

  • InstrumentIsModel(String)

  • InstrumentInFamily(String)

For IVI-COM drivers, See the documentation in the Nimbus Template Library for details and examples of these three functions:

  • GetModel

  • InstrumentIsModel

  • InstrumentInFamily

For IVI-C drivers, See the documentation in the Nimbus Runtime Library for details and examples of these three functions:

  • InstruemntModel

  • InstrumentIsModel

  • InstrumentInFamily


Creating a Driver Help File

Nimbus provides a rich set of features for creating driver help files. Help templates allow the driver developer to control virtually every aspect of the help file appearance. A fully featured HTML help editor is provided for composing help content for driver methods, properties, enumerations, and more.

The topics in this section explain how driver help files are built and how they can be customized to meet specific driver requirements.

In This Section

Basics of Driver Help Files

Using the Help Editor

Working with Help Templates

Accessing the Project Properties

Building and Viewing the Help Content

Signing Microsoft Help Viewer Content

See Also

Other Resources

Using the Help Editor


Basics of Driver Help Files

This topic presents an overview of how Nimbus help files are created, managed, and customized. Other topics under the topic Creating a Driver Help File present detailed information on specific driver help issues.

Authoring Help Content

Nimbus constructs help files and other documentation artifacts from the content entered in the various Help Editors. Methods, properties, parameters, interfaces, enums, errors, and warnings all have a Help Editor that is accessed by selecting a specific item in the Driver Designer.

The content created using the Help Editors is stored in the Nimbus design file and ultimately used for several purposes. IVI drivers may be used in numerous IDEs, so the driver documentation must be rendered in several formats to create a complete user experience. Nimbus uses the help content from the Help Editors to automatically create the following:

  • HTML 1.0 help file (.chm)

    This is a standalone help file that is used by nearly all IDEs except for Visual Studio.

  • Microsoft Help Viewer help file (.mshc or .cab)

    This is a help file that is used by Visual Studio. It integrates with the Visual Studio local help so that driver help content appears alongside Visual Studio's own help content as well as the help content of other products that integrate with Visual Studio. Microsoft Help Viewer files may be digitally signed using a certificate (.cab) or distributed without being signed (.mshc). The topic Signing Microsoft Help Viewer Content explains how help file signing works.

  • XML IntelliSense file

    IVI drivers used within .NET programming languages, such as Visual C#, require a specially formatted XML file to present IntelliSense help as end users type code.

Since all of the help content is consolidated in a single location via the Help Editors, managing the various help artifacts is simple. Changing the content for a particular item in the Help Editor updates the help information for that item in all of the above locations.

The set of help file formats produced for an IVI driver is controlled via help project properties. The default settings chosen for new help projects can be controlled by per-user preferences.

The Driver Help Project

Every Nimbus driver solution includes a driver help project named as follows:

<projectName>Help

The driver help project serves two roles in IVI driver development:

  1. Its build process emits the help files discussed above.

  2. It houses the help template files used to control the look and feel of the driver help files.

Help File Appearance and Help Templates

The Template subfolder of the driver help project contains a number of files used to control the appearance of the driver HTML 1.0 Microsoft Help Viewer files. (For convenience, we will refer to all supported help file formats as simply the "driver help file", since they contain the same content and since the help template applies to them identically.) Collectively, these files are referred to as the help template and they are used to control nearly every aspect of the driver help file appearance.

Nimbus ships with one pre-built template:

  • Classic

    Generates a driver help file that mimics the classic MSDN help file appearance. Separate templates are maintained for each type of driver (IVI.NET, IVI-COM, and IVI-C). These are installed in the following folders:

    • NimbusInstallDir\HelpTemplates\Classic\IviNet

    • NimbusInstallDir\HelpTemplates\Classic\IviCom

    • NimbusInstallDir\HelpTemplates\Classic\IviC

When a new driver project is created with the New Project Wizard, Nimbus copies all of the files from the selected help template folder to the driver's help project folder. This allows help template customizations to be done on a per-driver basis, without affecting the pre-installed help templates.

To change the help template after a driver has been created

  1. From Solution Explorer, right click on the driver help project node and select Properties access the help project's properties.

  2. Click on the Template tab.

  3. Choose a template from the Available templates combo box. The list that appears contains the templates present in the NimbusInstallDir\HelpTemplates folder.

  4. Click the Switch to this template button.

    Caution note Caution

    This step deletes all of the files in the current driver help project's Template subfolder. Any customizations done to this point are lost. Make sure no files of interest remain in the help project's Templates subfolder before clicking the Switch to this template button.

    Note Note

    If your driver help project is integrated with a Visual Studio source control system, this operation automatically performs the necessary source code control operations to add, remove and otherwise update the help template files included in the driver help project.

Special note on IVI-COM Help Templates

IVI-COM help templates that include an IVI-C wrapper use template files from the IVI-C template for portions of the driver help file. The following folders within the IVI-C template are used by the IVI-COM help template:

  • IviCAttribute

  • IviCBranch

  • IviCCallbackFunction

  • IviCErrorsWarnings

  • IviCFunction

  • IviCLibrary

Customizing Help File Appearance

Nimbus provides complete flexibility in controlling nearly all aspects of the driver help file. Content and appearance can be controlled by customizing the help template. Everything from custom boilerplate content to vendor-specific branding can be implemented with the Nimbus help template customization features. The topic Working with Help Templates explains in detail how to control every aspect of driver help file appearance.

Important note Important

It is critical to never directly edit the pre-built help template files installed in the NimbusInstallDir\HelpTemplates folder. To customize a help template, you must first make a copy of the entire template and then edit the copy. Refer here for details on creating custom help templates.

See Also

Other Resources

Working with Help Templates
Building and Viewing the Help Content
Help Page, All Drivers Per-User Preferences
Accessing the Project Properties
Signing Microsoft Help Viewer Content


Using the Help Editor

The Help Editor allows you to enter raw HTML content for each portion of the help page for items such as methods, properties, enums, etc. The behavior of the Help Editor is very similar for each item type, so the information in this topic applies equally well to all item types (methods, properties, parameters, etc.).

Help Editor Basics

Each help page for an item, such as a method, is divided into independently editable regions termed fields. Available fields are listed along the top of the Help Editor. Every item has a Summary tab. Other fields, such as Return value or Remarks, appear long the top of the Help Editor when those fields are available for the selected item.

The Preview tab allows you to preview how the generated driver help will look based on the edits you're making and the selected help template, which is controlled by the help project properties.

For details on customizing help templates to add custom fields, see the topic Working with Help Templates.

Entering Help Content

Help content is entered using the Help Editor by selecting the field you wish to modify (which appear as separate tabs along the top of the Help Editor), and then using the editor to make the desired changes.

When editing the Summary and Return value fields, there are special limitations in what may be entered. First, the text is limited to 256 characters total. Secondly, a plain text editor is used to enter the help content.

For all other fields, such as the Remarks field, the native Visual Studio HTML editor is used. The reason plain text must be used for the Summary field is that this field is used in places that do not support HTML -- such as driver installers and XML IntelliSense files. See the topic Basics of Driver Help Files for details on where the driver help content is used.

The Visual Studio HTML editor is used to for editing the Remarks field as well as other fields (including those defined by help template customizations). An example entry is shown below.

XML
Copy
The <b>StartFrequency</b> property gets or sets the frequency at which the frequency sweep
will begin.  The units are Hz.
Important note Important

Even though the built-in Visual Studio HTML editor is used for editing HTML content, the contents of these fields must be XHTML, which is a stricter form of HTML. Among other things, this means that all HTML tags must be closed just like XML tags are. For example, instead of using <hr> to insert a horizontal separator, you must use <hr/> or <hr></hr>. If any XHTML rules are violated, the driver help previewerwill display an error, and the help project will fail to build.

Help content is required to be XHTML in order to integrate with the Microsoft Help Viewer that's used by Visual Studio.

Adding links to the help content

Nimbus supports adding help content with links to pages and other content. By using the standard HTML anchor tag (<a>), you can create the following kinds of links:

  • External links, such as to a support website.

  • Links to auto-generated pages, such as method and property help pages.

  • Links to fixed-content, boilerplate help pages.

Links to external content, such as web pages, is done in the standard fashion with standard URIs, such as www.pacificmindworks.com. Links to boilerplate pages is also simple in that only the name of the page (without any path information) is used as the URI in the <a> tag.

Since the help pages for Nimbus-generated content are created when the help project is built, the pages themselves are not actually available at development time. Thus, Nimbus supports a simple syntax for creating links to Nimbus-generated pages. The syntax for these links depends upon the type of driver under development. However, the simplest way to obtain a link to a particular item is to use the Copy help link to clipboard command available from the Driver Designer context menu.

To insert a link to a driver item:

  1. Within the Driver Designer, right-click on the item (interface, method, property, etc) that you wish to link to.

  2. Select Copy help link to clipboard.

  3. Navigate to the Remarks field or other HTML-enabled custom field for the item in which you wish to insert the link.

  4. Paste the clipboard contents at the desired location. Nimbus will have created a properly formatted HTML anchor tag for the item of interest. Note that the display text for the anchor tag must still be supplied.

Format for Help Links

Because the type system for IVI.NET drivers is much richer than that of either IVI-COM or IVI-C, it is difficult to use a help link format based on type name and type member names. Method overloading and .NET generics introduce considerable complexity into any name-based scheme for uniquely identifying IVI.NET items. Thus, Nimbus uses GUIDs to name the generated help HTML files. These GUIDS are persisted in the driver design file, so they are stable across builds and Visual Studio sessions. This also makes the GUIDs a logical candidate for creating IVI.NET help links.

Tip Tip

Because the GUIDs associated with IVI.NET items are maintained internally, the Copy help link to clipboard command mentioned earlier should be used to create IVI.NET driver help links.

For IVI-COM and IVI-C drivers, the Copy help link to clipboard is also the preferred way to create help links. However, because of the relative simplicity of the IVI-COM and IVI-C type systems, the help links for these drivers use simple type and member names. The example below demonstrates how to create some of these links and the table following the example specifies the syntax for all supported IVI-COM and IVI-C link types.

XML
Copy
<!-- Link to the Configure method on the IAcme4321Trigger interface -->
This method differs from the <a href="IAcme4321Trigger.Configure">Configure</a> method in that...

<!-- Link to the Acme4321TriggerMode enum -->
The <i>Mode</i> parameter can take on any value in the <a href="Acme4321TriggerMode">Acme4321TriggerMode</a> enum.

<!-- Link to the error and warnings page.  Note that all errors and warnings appear on a single page. -->
If the instrument cannot switch to <i>Mode</i>, the <a href="ErrorsAndWarnings">E_ACME4321_BAD_MODE</a> error is returned.

<!-- Link to an external website -->
For more information, see the whitepaper on our <a href="http://www.acme.com/support">website</a>.

The following table specifies the URI syntax for all supported IVI-COM and IVI-C link types.

Link Type | URI Syntax | Example
External link | Standard URI syntax | http://www.acme.com/support
Boilerplate page | Page name, including extension (no path) | AcmeDriverBasics.html
IVI-COM interface | Full interface name | IAcme4321Trigger
IVI-COM method | <interface>.<method> | IAcme4321Trigger.Configure IIviScopeMeasurement.Fetch
IVI-COM property | <interface>.<property> | IAcme4321Trigger.Source IIviScopeAcquisition.NumberOfAverages
IVI-COM enum | Full enum name | Acme4321TriggerSourceEnum IviScopeAcquisitionTypeEnum
IVI-COM error | Special string "ErrorsAndWarnings" All IVI-COM errors and warnings for a typelib appear on a single page. | ErrorsAndWarnings IviScope.ErrorsAndWarnings
IVI-COM warning | Special string "IviComErrorsAndWarnings" All IVI-COM errors and warnings for a typelib appear on a single page. | IviComErrorsAndWarnings IviScope.IviComErrorsAndWarnings
IVI-C function | Function name (no prefix) | ConfigureTrigger
IVI-C attribute | Attribute name (no prefix) | TRIGGER_SOURCE
IVI-C error | Special string "IviCErrorsAndWarnings" All IVI-C errors and warnings appear on a single page. | IviCErrorsAndWarnings
IVI-C warning | Special string "IviCErrorsAndWarnings" All IVI-C errors and warnings appear on a single page. | IviCErrorsAndWarnings
See Also

Other Resources

Adding Functionality to an IVI-COM Driver
Working with Help Templates


Working with Help Templates

Nimbus provides a great detail of flexibility in controlling the appearance and style of driver help files by customizing the help template. The first step in creating a custom help template is to always ensure you are working with a copy of the pre-built templates installed by Nimbus and not directly editing them.

The topics in this section explain how to customize the look and feel of driver help files using help templates.

In This Section

Using the Help Template Previewer

Changing the Table of Contents

Adding Boilerplate Pages

Editing Template Pages

Sharing Help Templates Across Projects


Using the Help Template Previewer

Nimbus provides a Help Template Previewer for selecting a help template to use for the current project and for previewing the results of applying that template. The Help Template Previewer is accessed by selecting the Template tab of the help project's properties.

The Help Template Previewer shows preview of a sample page for the template selected in the Available templates combo box. Use the Available templates combo box to view the different templates available. The choices shown will correspond to the pre-built template that ships with Nimbus ("Classic") as well as custom templates that have been placed in the following folder>

<ProgramData>\Pacific MindWorks\Nimbus\<version>\HelpTemplates

Use the Switch to this template button to change the current project to use the template selected in the Available templates combo box and currently displayed.

Caution note Caution

When you switch help templates for a project, the template files are copied from the templateHelpTemplates folder (or from the Visual Studio Extensions folder where Nimbus reside) to the driver's help project Template folder. This means that all customizations that might have been performed on the project's help template are lost. Before switching help templates, be sure that the current project template has no customizations that need to be saved elsewhere. See the topic Sharing Help Templates Across Projects.

Note Note

If your driver help project is integrated with a Visual Studio source control system, this operation automatically performs the necessary source code control operations to add, remove and otherwise update the help template files included in the driver help project.

See Also

Other Resources

Changing the Table of Contents
Adding Boilerplate Pages
Editing Template Pages
Sharing Help Templates Across Projects


Changing the Table of Contents

The driver help file table of contents is specified in a special XML file in the Template folder of the driver help project. This file is referred to as the help template manifest file, and it is always named Manifest.xml.

The code below is an excerpt from the manifest file for an IVI.NET driver:

XML
Copy
<!-- Manifest.xml -->
  <HelpTOC Resource="IviNetDriver.TocRoot.html">
    <HelpTOCNode Resource="GettingStarted.html">
      <HelpTOCNode Resource="IviBackgrounder.html">
        <HelpTOCNode Resource="InherentCapabilities.html"/>
        <HelpTOCNode Resource="Interchangeability.html"/>
        <HelpTOCNode Resource="InstrumentSpecificCapabilities.html"/>
        <HelpTOCNode Resource="IviSharedComponents.html"/>
        <HelpTOCNode Resource="RepeatedCapabilities.html"/>
        <HelpTOCNode Resource="LxiFundamentals.html"/>
      </HelpTOCNode>
      <HelpTOCNode Resource="Installation.html"/>
      <HelpTOCNode Resource="IviCompliance.html" Condition="NotNoClass" Output="IviCompliance.html"/>
      <HelpTOCNode Resource="IviComplianceNoClass.html" Condition="NoClass" Output="IviCompliance.html"/>
      <HelpTOCNode Resource="IviConfigStore.html"/>
    </HelpTOCNode>
    <HelpTOCNode Resource="IviNetDriver.html">
      <HelpTOCNode Resource="IviNetInitialize.html"/>

The <HelpTOC> element is the root of the help table of contents. Child <HelpTOCNode> elements are used to create a hierarchy of help topics. The Resource attribute refers to the HTML file that contains the content for the topic. The title is established by a special <MSHelp:TOCTitle> element within the HTML file itself.

Topics can be removed from the help file by simply deleting them from the manifest file. Alternatively, the help topics can be rearranged by simply moving the desired <HelpTOCNode> elements in the desired order.

Tip Tip

Nimbus installs the schema file (including documentation comments) for the manifest file. This provides IntelliSense support for available XML elements and attributes when editing the help template manifest file in Visual Studio.

Special Content Topics

Most of the help topics that appear in the final driver help file are not listed explicitly in the help template manifest file. For instance, the help topics for the driver methods and properties (or functions and attributes, in the case of IVI-C drivers) do not explicity appear in this XML file. These topics are far too numerous to include in the help template manifest file, so they are instead generated dynamically and placed under special topics that have a Content attribute.

The special content topics are included in the manifest file so that other topics can be arranged around them to produce the desired table of contents. The following code snippet shows all of the speical content topics for an IVI.NET driver.

XML
Copy
<!-- Manifest.xml -->

<!-- ... -->

    <HelpTOCNode Resource="IviNetDriverReference.html">
      <HelpTOCNode Title="Driver Hierarchy" Content="IviNetHierarchy"/>
      <HelpTOCNode Title="Driver Interfaces" Content="IviNetFlat"/>
      <HelpTOCNode Resource="IviNetCommandReference.html"/>
    </HelpTOCNode>

<!-- ... -->

Conditionally Including Help Topics

Help topics can be conditionally included by use of the Condition attribute. In the example below, the help topic for "AccessingRepCaps.html" will only be included in the help file if the condition "RepCap" is true. This particular condition is true as long as the driver includes one or more repeated capabilities. Similarly, the help topic for "IviNetClassCompliant-IviDCPwr.html" will only be included if the driver implements the IviDCPwr instrument class. Conditions are generally used when adding custom boilerplate help content.

XML
Copy
<!-- IviNetDriverHelpTemplate.xml -->

<HelpTOCNode Resource="IviNetClassCompliant-IviDCPwr.html" Condition="IviDCPwr" Output="IviNetClassCompliant.html"/>

<!-- ... -->

<HelpTOCNode Resource="AccessingRepCaps.html" Condition="RepCap"/>

The table below lists all of the pre-built conditions that can be used for conditionally including help file content:

Condition | Description
Lxi | True if the driver is compliant with the LXI Core 2016 base class.
NotLxi | True if the driver is not compliant with the LXI Core 2016 base class.
LxiClockSynchronization | True if the driver supports the LXI Clock Synchronization extended function.
LxiEventLogs | True if the driver supports the LXI Event Logs extended function.
LxiEventMessaging | True if the driver supports the LXI Event Messaging extended function.
LxiTimestampedData | True if the driver supports the LXI Timestamped Data extended function.
LxiWiredTriggerBus | True if the driver supports the LXI Wired Trigger Bus extended function.
RepCap | True if the driver has at least one repeated capability.
NotRepCap | True if the driver does not have any repeated capabilities.
NoClass | True if the driver does not implement an instrument class.
NotNoClass | True if the driver implements at least one instrument class.
IviCounter | True if the driver implements the IviCounter instrument class.
IviDCPwr | True if the driver implements the IviDCPwr instrument class.
IviDigitizer | True if the driver implements the IviDigitizer instrument class.
IviDmm | True if the driver implements the IviDmm instrument class.
IviDownconverter | True if the driver implements the IviDownconverter instrument class.
IviFgen | True if the driver implements the IviFgen instrument class.
IviPwrMeter | True if the driver implements the IviPwrMeter instrument class.
IviRFSigGen | True if the driver implements the IviRFSigGen instrument class.
IviScope | True if the driver implements the IviScope instrument class.
IviSpecAn | True if the driver implements the IviSpecAn instrument class.
IviSwtch | True if the driver implements the IviSwtch instrument class.
IviUpconverter | True if the driver implements the IviUpconverter instrument class.

Using the Output Attribute to Change Content File Names

When help pages are conditionally included as described in the previous section, it can be difficult or impossible to manage links to the conditionally included pages. For example, consider the following portion of a help template manifest file:

XML
Copy
<!-- Manifest.xml -->
<HelpTOC>
  <HelpTOCNode Resource="GettingStarted.html">
    <HelpTOCNode Resource="Installation.html"/>
    <HelpTOCNode Resource="IviComplianceWithClass.html" Condition="NotNoClass"/>
    <HelpTOCNode Resource="IviComplianceNoClass.html" Condition="NoClass"/>
    <HelpTOCNode Resource="IviConfigStore.html"/>
  </HelpTOCNode>

If the driver complies with at least one instrument class, the content file "IviComplianceWithClass.html" will be included in the help file. If the driver does not comply with any instrument class, the content file "IviComplianceNoClass.html" will be included in the help file. Other pages within the help file may wish to create a link to whichever of these two files was included. For instance, the first help topic "GettingStarted.html" is a parent of the two pages and likely needs to include a link to all of its child topics. Since links cannot be conditional, this presents a fundamental problem.

Nimbus provides the Output attribute to enable links to be created to conditionally included content. The Output attribute simply renames a content file from the name indicated by the Resource attribute to that specified with the Output attribute. Conditionally included topics use the Output attribute to "re-direct" multiple mutually exclusive topics to the same file name so that links can be created to the conditionally included topics.

The following example demonstrates use of the Output attribute.

XML
Copy
<!-- IviNetDriverHelpTemplate.xml -->
<HelpTOC>
  <HelpTOCNode Resource="GettingStarted.html">
    <HelpTOCNode Resource="Installation.html"/>
    <HelpTOCNode Resource="IviComplianceWithClass.html" Condition="NotNoClass"  Output="IviCompliance.html"/>
    <HelpTOCNode Resource="IviComplianceNoClass.html" Condition="NoClass" Output="IviCompliance.html"/>
    <HelpTOCNode Resource="IviConfigStore.html"/>
  </HelpTOCNode>

In the above example, the Output attribute has been used with the conditionally included topics "IviComplianceWithClass.html" and "IviComplianceNoClass.html". Irrespective of which of these topics is included in the help file, the resulting file name will be "IviCompliance.html". This allows other help pages to create links to the "IviCompliance.html" page without regard to the conditional inclusion logic.

See Also

Other Resources

Using the Help Template Previewer
Adding Boilerplate Pages
Editing Template Pages
Sharing Help Templates Across Projects


Adding Boilerplate Pages

A common help template customization is adding help pages to the driver help file. Because these specialized pages often discuss general topics, they are often reused across multiple driver projects. Hence, they are referred to as boilerplate help pages. Nimbus uses this terminology even if the help pages are only used in a single driver help project. The section below on replacement tags explains a special feature that is useful in authoring boilerplate content that will be shared amongst multiple drivers. The procedure for integrating boilerplate help pages is identical for shared pages and driver-specific pages.

Note Note

The procedure below uses the file names for IVI.NET driver help projects. The procedure and file names for IVI-COM and IVI-C driver help projects are similar.

To add help pages to a driver help file

  1. From Solution Explorer, navigate to the Template\Html\Boilerplate folder of the driver help project (<projectName>Help).

  2. To add an existing HTML file right click on the Boilerplate node, and choose Add Existing Item... and navigate to the desired file.

    To add a new HTML file right click on the Boilerplate node, and choose Add New Item... and choose HTML Page from the New Item Dialog.

  3. To ensure the style of the new page is consistent with other pages in the help template, it is generally easier to copy the content of another help page in the template and use it as a starting point for the new page.

  4. Add a <HelpTOCNode> to the help template manifest file (Manifest.xml) that points to the new page. Note that the Resource attribute just lists the file name.

  5. If the added page references a script file (.js) or a graphics file (such as a .jpg or a .bmp), perform the following steps:

    1. Add the file to either the Graphics, Icons, or Scripts subfolder of the help project's Template folder.

    2. In the Manifest.xml file, add an entry under the <AdditionalFiles> element, as in the example below:

      XML
      Copy
      <!-- Manifest.xml-->

<AdditionalFiles>

  <Binary OutputDir="Graphics" Resource="MyDiagram.jpg"/>
Using replacement tags in boilerplate help pages

If help pages are to be reused between different drivers, it is important to not hard-code into the pages any references to a specific driver, such as the project name or the driver output file name. Instead, special replacement tags can be used in the HTML itself and Nimbus will automatically replace the tags with the appropriate values for the driver when the help project is built.

The example HTML below uses the $$DRIVER_NAME$$ replacement tag in some introductory text. This would be replaced with a name such as Acme4321 when the help project is built.

XML
Copy
<!-- MyFile.html -->

<div class="introduction">
  <p>
    Because the $$DRIVER_NAME$$ driver is a standard .NET assembly, it may be accessed from
    COM-aware native applications written in languages such C++ and Visual Basic.
  </p>
</div>

Nimbus supplies a number of replacement tags that can be used when authoring help pages. The complete list of supported replacement tags for each type of IVI driver is given in the table below:

Replacement Tag | Driver Type | Description
$$INSTR_PREFIX$$ | IVI-COM, IVI-C | IVI-C prefix. Example: Acme
$$INSTR_PREFIX_UPPER$$ | IVI-COM, IVI-C | IVI-C prefix in all uppercase. Example: ACME
$$INSTR_PREFIX_LOWER$$ | IVI-COM, IVI-C | IVI-C prefix in all lowercase. Example: acme
$$PIA_FILENAME_NO_EXT$$ | IVI-COM, IVI-C | Name of the primary interop assembly file without the extension. Example: Acme.Acme4321.Interop
$$DRIVER_DLL_FILENAME_NO_EXT$$ | IVI-COM, IVI-C | Driver DLL filename without the extension. Example: Acme4321
$$SUPPORTED_MODELS$$ | All | Comma-separated list of supported instrument models.
$$IVI_CLASS_NAME$$ | All | Name of supported instrument class. Example: IviScope
$$IVI_CLASS_NAME_UPPER$$ | All | Name of supported instrument class in all uppercase. Example: IVISCOPE
$$IVI_CLASS_NAME_LOWER$$ | All | Name of supported instrument class in all lowercase. Example: iviscope
$$COMPANY$$ | All | Name of the driver vendor as listed in the Driver Settings Editor.
$$DRIVER_NAME$$ | All | Name of the driver. Example: Acme4321
$$DRIVER_NAMESPACE$$ | IVI.NET, IVI-COM | For IVI.NET, .NET namespace for the driver assembly. Example: Acme.Acme4321 For IVI-COM, .NET namespace for the driver's primary interop assembly. Example: Acme.Acme4321.Interop
$$DRIVER_DESCRIPTION$$ | All | Description text taken from the Driver Settings Editor.
$$VERSION_TWO_DIGIT$$ | All | Two-digit version number. Example: 5.1
$$VERSION_THREE_DIGIT$$ | All | Three-digit version number. Example: 5.1.2
$$VERSION_FOUR_DIGIT$$ | All | Four-digit version number. Example: 5.1.2.3
$$VERSION_MAJOR$$ | All | Major version number.
$$VERSION_MINOR$$ | All | Minor version number.
See Also

Other Resources

Adding Help Information


Editing Template Pages

Nimbus generates the driver help file by taking content entered via the Help Editor for a particular item (such as a method or property) and inserting it into the help template page for that item type. Each type of page generated by Nimbus has an HTML template file associated with it in one of the subfolders of Template\Html folder. This topic explains how the help template can be edited to control how Nimbus renders specific types of help pages.

Note Note

Editing the help template HTML files affects all pages of that type. For instance, editing the template page for IVI.NET methods (IviNetMethod.html) affects how the pages for all IVI.NET methods in the driver are rendered.

Understanding Help Template Pages
Note Note

The discussion below uses examples from IVI.NET drivers, but the procedures and techniques are very similar for IVI-COM and IVI-C drivers.

Since the help template contains both fixed HTML content intermixed with auto-generated content, the help template pages will contain replacement tags (identifiers enclosed in "$$") embedded in the HTML content. Also, note that since the help template resource file is an XML file, all of the HTML tags must be "escaped".

Important note Important

Even though help template pages have an extension of .html, the contents of those files must be XHTML. Among other things, this means that all HTML tags must be closed just like XML tags are. For example, instead of using <hr> to insert a horizontal separator, you must use <hr/> or <hr></hr>. If any XHTML rules are violated, the driver help previewer will display an error, and the help project will fail to build.

Help template files are required to be XHTML in order to be used by the Microsoft Help Viewer.

The following is help template page (IviNetMethod.html) used to generate IVI.NET methods. The template page is located under Template\Html\IviNetMethod.

XML
Copy
    <html xmlns:MSHelp="http://msdn.microsoft.com/mshelp" xmlns:ddue="http://ddue.schemas.microsoft.com/authoring/2003/5" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:msxsl="urn:schemas-microsoft-com:xslt">
  <head>
    <META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8" />
    <META NAME="save" CONTENT="history" />
    <title>$$METHOD_NAME$$ Method</title>
$$STYLESHEET$$
    <xml>
      <MSHelp:TOCTitle Title="$$METHOD_NAME$$ Method " />
      <MSHelp:RLTitle Title="$$PARENT_NAME$$.$$METHOD_NAME$$ Method  ($$NAMESPACE_NAME$$)" />
      <MSHelp:Keyword Index="A" Term="M:$$NAMESPACE_NAME$$.$$PARENT_NAME$$.$$METHOD_NAME$$" />
      <MSHelp:Keyword Index="K" Term="$$METHOD_NAME$$ method" />
      <MSHelp:Keyword Index="K" Term="$$PARENT_NAME$$.$$METHOD_NAME$$ method" />
      <MSHelp:Keyword Index="F" Term="$$METHOD_NAME$$" />
      <MSHelp:Keyword Index="F" Term="$$PARENT_NAME$$.$$METHOD_NAME$$" />
      <MSHelp:Keyword Index="F" Term="$$NAMESPACE_NAME$$.$$PARENT_NAME$$.$$METHOD_NAME$$" />
$$METHOD_INDEX_VALUES$$
      <MSHelp:Attr Name="DocSet" Value="$$DOCSET$$" />
      <MSHelp:Attr Name="DevLang" Value="VB" />
      <MSHelp:Attr Name="DevLang" Value="CSharp" />
      <MSHelp:Attr Name="DevLang" Value="C++" />
      <MSHelp:Attr Name="Locale" Value="en-us" />
      <MSHelp:Attr Name="TopicType" Value="kbSyntax" />
      <MSHelp:Attr Name="TopicType" Value="apiref" />
      <MSHelp:Attr Name="Abstract" Value="$$METHOD_SUMMARY$$" />
    </xml>
    <!-- begin: Microsoft Help 1.0 -->
    <meta name="Microsoft.Help.Id" content="" />
    <meta name="Microsoft.Help.TocParent" content="" />
    <meta name="Microsoft.Help.TocOrder" content="" />
    <meta name="Microsoft.Help.ContentType" content="" />
    <meta name="Microsoft.Help.SelfBranded" content="true" />
    <meta name="Microsoft.Help.Locale" content="en-us" />
    <meta name="Microsoft.Help.TopicLocale" content="en-us" />
    <!--$$Microsoft.Help.F1$$-->
    <!--$$Microsoft.Help.Keywords$$-->
    <!-- end: Microsoft Help 1.0 -->
  </head>
  <body>
    <input type="hidden" id="userDataCache" class="userDataStyle" />
    <input type="hidden" id="hiddenScrollOffset" />
    <div id="header">
      <table id="topTable" cellpadding="0" cellspacing="0">
        <tr>
          <td colspan="2" height="10">&nbsp;</td>
        </tr>
        <tr id="headerTableRow1">
          <td align="left">
            <span id="runningHeaderText">$$RUNNING_HEAD$$</span>
          </td>
          <td align="right">
            <span id="nimbusHeaderText">$$NIMBUS_HEADER$$</span>
          </td>
        </tr>
        <tr>
          <td colspan="2" height="10">&nbsp;</td>
        </tr>
        <tr id="headerTableRow2">
          <td align="left">
            <span id="nsrTitle">$$PARENT_NAME$$<span class="cs">.</span><span class="vb">.</span><span class="cpp">::</span><span class="nu">.</span>$$METHOD_NAME$$ Method </span>
          </td>
        </tr>
        <tr id="headerTableRow3">
          <td align="left">
          <a href="$$PARENT_LINK$$">$$PARENT_NAME$$</a>  <a href="#seeAlsoToggle" onclick="OpenSection(seeAlsoToggle)">See Also</a>  <span id="headfb" class="feedbackhead" /></td>
        </tr>
      </table>
      <table id="gradientTable">
        <tr>
          <td class="nsrBottom" background="../icons/gradient.gif" />
        </tr>
      </table>
    </div>

    <!-- Main section (everything below first separator line) -->
    <div id="mainSection">

      <!-- Main body (between header separator line and footer separator line) -->
      <div id="mainBody">
        <div id="allHistory" class="saveHistory" onsave="saveAll()" onload="loadAll()">
        <font color="DarkGray"></font>
        <p />
        </div>

        <!-- Summary -->
        <div class="summary">
          <p>$$METHOD_SUMMARY$$</p>
        </div>
        <p />
        <b>Namespace:</b>
        $$NAMESPACE_NAME$$<br/>
        <b>Assembly:</b>
        <a href="$$ASSEMBLY_LINK$$" tabindex="0">$$ASSEMBLY_NAME$$</a> (in $$ASSEMBLY_FILE_NAME$$)

        <!-- Syntax -->
        <h1 class="heading"><span onclick="ExpandCollapse(syntaxToggle)" style="cursor:default;" onkeypress="ExpandCollapse_CheckKey(syntaxToggle, event)" tabindex="0">
          <img id="syntaxToggle" onload="OnLoadImage(event)" class="toggle" name="toggleSwitch" src="../icons/collapse_all.gif" />Syntax</span>
        </h1>
        <div id="syntaxSection" class="section" name="collapseableSection" style="">
          <div id="syntaxCodeBlocks" class="code">
$$METHOD_SYNTAX$$
          </div>

$$TYPE_PARAMETER_DESCRIPTIONS$$

$$METHOD_PARAMETER_DESCRIPTIONS$$

$$METHOD_RETURNS$$
        </div>

$$CustomField.IviNetMethod.Remarks$$

$$METHOD_COMMANDS$$

$$METHOD_REQUIREMENTS$$

        <!-- See also -->
        <h1 class="heading">
          <span onclick="ExpandCollapse(seeAlsoToggle)" style="cursor:default;" onkeypress="ExpandCollapse_CheckKey(seeAlsoToggle, event)" tabindex="0">
          <img id="seeAlsoToggle" onload="OnLoadImage(event)" class="toggle" name="toggleSwitch" src="../icons/collapse_all.gif" />See Also</span>
        </h1>
        <div id="seeAlsoSection" class="section" name="collapseableSection" style="">
          <h4 class="subHeading">Reference</h4>
          <div class="seeAlsoStyle"><a href="$$PARENT_LINK$$">$$PARENT_NAME$$ $$PARENT_TYPE_KIND$$</a></div>
          <div class="seeAlsoStyle"><a href="$$ASSEMBLY_LINK$$" tabindex="0">$$ASSEMBLY_NAME$$ Assembly</a></div>
        </div>

      </div>

$$FOOTER$$

    </div>
  </body>
</html>

The content of the help template can be edited to include any arbitrary HTML, as long as you adhere to the more stringent formatting requirements for XHTML mentiond above. This can be used to implement custom branding or any other desired appearance affect or to inject custom content into all pages of a particular type.

Replacement Tags in Help Template Pages

The help template page contains two types of replacement tags (enclosed in "$$"). The find kind of tag that can be used in a help template page are custom fields. These all begin with $$CustomField and allow you to inject variable, developer-specified help content into a help page. Custom fields are discussed in the next section.

The second kind of replacement tags are those that appear in all capital letters, such as $$METHOD_SYNTAX$$. These tags are automatically replaced by Nimbus-generated content. For example, the $$METHOD_SYNTAX$$ tag is replaced by the Nimbus-generated method signature. The driver developer does not explicitly enter the content for these tags in any editor. Rather, Nimbus infers this content from other information in the driver.

In many cases, the Nimbus-generated replacement tags are formatted using other HTML pages in one of the subfolders of the Template\Html folder. Editing these "child" template pages entries provides fine-grained control over the help page formatting and content. For example, the following is the template file for the "Return Value" section of the IVI.NET method help template page. Note that the name of these template files of help template pages all begin with the name of the "parent" page ("IviNetMethod.html" in the example below).

XML
Copy
<!-- Html\IviNetMethod\IviNetMethod.Returns.html -->

<!-- Return value -->
<h4 class="subHeading">
    Return Value</h4>
<br />
<p>
    $$RETURNS$$</p>
Adding Content with Custom Fields

The help template pages include special replacement tags known as custom fields. These specially named tags are replaced by content that the driver developer enters for that field in the Help Editors. Custom fields have names in the following form:

CustomField.<pageType>.<fieldName>.html

For IVI.NET drivers, <pageType> can be replaced with any of the following values:

  • IviNetAssembly

  • IviNetClass

  • IviNetConstructor

  • IviNetDelegate

  • IviNetEnum

  • IviNetEvent

  • IviNetInterface

  • IviNetMethod

  • IviNetProperty

  • IviNetStruct

For IVI-COM drivers, <pageType> can be replaced with any of the following values:

  • IviComMethod

  • IviComProperty

  • IviComInterface

  • IviComEnum

  • IviComClass

  • IviComNamespace

  • IviCFunction

  • IviCAttribute

For IVI-C drivers, <pageType> can be replaced with any of the following values:

  • IviCFunction

  • IviCAttribute

When a custom field is defined, Nimbus does two things:

  1. It updates the help editor for the pageType specified so that an editable field called fieldName appears.

  2. When the help project is built, it replaces all occurrences of custom field replacement tags with the help editor content entered for those custom fields.

Tip Tip

Nimbus actually uses custom fields for some of the standard sections of help pages. For instance, the Remarks and Units sections that appear on many help pages are implemented using custom fields. Searching the various help template files for instances of "CustomField" will yield numerous examples of how custom fields can be defined and used in help template pages.

To add a custom field to a help template page

  1. Add a new HTML file to one of the subfolders of the Html\Templates folder of the driver help project. Be sure to name the file using the desired page type and the desired field name as you want it to appear in the help editor. For example, the HTML file for the pre-defined Remarks custom field for IVI.NET property pages is named "CustomField.IviNetProperty.Remarks". The contents of this file are as follows:

    XML
    Copy
    <!-- \Html\IviNetProperty\CustomField.IviNetProperty.Remarks.html -->

<!-- Remarks -->
<h1 class="heading">
    <span onclick="ExpandCollapse(remarksToggle)" style="cursor: default;" onkeypress="ExpandCollapse_CheckKey(remarksToggle, event)"
        tabindex="0">
        <img id="remarksToggle" onload="OnLoadImage(event)" class="toggle" name="toggleSwitch"
            src="../icons/collapse_all.gif" />Remarks</span>
</h1>
<div id="remarksSection" class="section" name="collapseableSection" style="">
    <p>
        $$CUSTOM_FIELD_VALUE$$</p>
</div>

  2. Add any desired fixed HTML content inside the new template page.

  3. Place the $$CUSTOM_FIELD_VALUE$$ tag within the HTML content at the location where you want the content from the help editor to be inserted. Note in the example above that the $$CUSTOM_FIELD_VALUE$$ tag is embedded in a <div> tag that appears after <span> and <img> tags.

  4. Insert the replacement tag for the custom field (e.g. the custom field name enclosed in "$$") at the desired location in the appropriate help template page. For example, the pre-defined Remarks custom field appears within the help template property page as shown below (the entire help template page is not shown):

    XML
    Copy
    <!-- Template\Html\IviNetProperty\IviNetProperty.html -->

<!-- ... -->

$$PROPERTY_PARAMETER_DESCRIPTIONS$$

          <h4 class="subHeading">Property Value</h4>
          <p>$$PROPERTY_SUMMARY$$</p>
        </div>

$$CustomField.IviNetProperty.Remarks$$

<!-- ... -->
See Also

Other Resources

Using the Help Template Previewer
Changing the Table of Contents
Adding Boilerplate Pages
Sharing Help Templates Across Projects


Sharing Help Templates Across Projects

One of the chief motivations for customizing a driver help file using templates is the ability to re-use those templates across other driver projects. Since the help template is simply a collection of files, making help templates available to other driver project involves nothing more than copying the help template files to a special folder that Nimbus recognizes.

To create a shared help template

  1. Create a new driver project or open an existing project that can be used to perform the desired help template customizations.

    Important note Important

    Always edit help template files within a specific driver project, as each driver project contains its own private copy of the help template files. It is critical to never directly edit the pre-built help templates that ship with Nimbus.

  2. Perform the desired help template modifications. Take care to use replacement tags for things like the driver name and driver output file names, rather than hardcoding names for a specific driver. See the topics under the Working with Help Templates for details on customizing help templates.

  3. Build the driver help file and make sure it appears as desired.

  4. Locate the folder where the custom Nimbus help templates are stored.

    <ProgramData>\Pacific MindWorks\Nimbus\<version>\HelpTemplates

  5. Create a new folder in this directory that indicates the name of your custom help template. The name of this folder will be displayed in the Template tab of the help project properties, which is used to switch betweeen driver help templates.

  6. Create a subdirectory below your new template directory named either IviNet, IviCom, or IviC, depending upon the driver type for which you have created your custom template.

  7. Copy the entire contents Template folder of the driver help file project and paste it into the IviNet, IviCom, or IviC folder below your custom template folder.

For example, if you follow the above procedure in order to create a custom help template named Acme Help for an IVI.NET driver, you should end up with a directory path as follows:

<ProgramData>\Pacific MindWorks\Nimbus\<version>\HelpTemplates\Acme Help\IviNet

The contents of that folder which will match the contents of your driver help project's Template folder.

See Also

Other Resources

Using the Help Template Previewer
Changing the Table of Contents
Adding Boilerplate Pages
Editing Template Pages


Accessing the Project Properties

Various aspects of Nimbus-generated help files are controlled via the driver help project's properties.

To access the driver help project properties

  1. From Solution Explorer, right click on the driver help project node and choose Properties.

  2. A tabbed document window appears with various settings on each tab.

    The remaining topics in this section provide a detailed explanation of the properties available on each tab.

In This Section

General Page, Driver Help Project Properties

Template Page, Driver Help Project Properties


General Page, Driver Help Project Properties

Each driver help project is associated with a single driver project contained within the same Visual Studio solution. The driver project associated with the help project is shown in the Driver field on this page.

Building the driver help project produces any combination of three different Microsoft help formats, which are explained below. The generated driver help content is automatically deployed by the driver installer project (if any) associated with the same driver.

Help formats
Help 1.x (chm)

This setting controls whether or not a self-contained .chm file will be generated. When enabled, the associated driver installer (if any) will deploy this file to the end-user machine.

To preview the generated help content from within Visual Studio, right click on the help project node in the Solution Explorer and select View Help 1.x (.chm).

Help Viewer

This setting controls whether or not driver help content will be generated for the Microsoft Help Viewer , which is used by Visual Studio. When enabled, the associated driver installer (if any) will integrate the driver help content into the Microsoft Help Viewer on the end-user's machine.

Register content with Help Viewer on build

This setting controls whether or not the driver help content will be automatically registered with the Microsoft Help Viewer on your machine whenever the driver help project is built. This setting has no effect on the end-user's machine.

To preview the generated help content from within Visual Studio, right click on the help project node in the Solution Explorer and selecting View in Help Viewer.

Sign content with a code-signing certificate

Enables signing sign of the help content to be integrated with the Microsoft Help Viewer. Signed help content can be silently installed without the Microsoft Help Viewer without displaying a security warning to the end-user. Refer here for more information on signing Microsoft Help Viewer content.

Certificate thumbprint

The certificate thumbprint of the code-signing certificate to use for signing the help content.

Use the Browse button to bring up a dialog that can be used to conveniently select the thumbprint from certificates installed on the local machine.

Note Note

You can use per-user preferences to control the default values of these project properties for new driver help projects created by Nimbus.

See Also

Other Resources

Signing Microsoft Help Viewer Content
Help Page, All Drivers Per-User Preferences
Microsoft Help Viewer


Template Page, Driver Help Project Properties

This page allows you to select the help template that will control the look and feel of the generated driver help content.

Nimbus provides a Help Previewer for selecting a help template to use for the current project and for previewing the results of applying that template. The Help Previewer is accessed by right clicking on the driver help project node in the Solution Explorer, selecting Properties and then going to the General tab.

Each tab shows a sample page for each of the different kinds of pages. Use the Available templates combo box to view the different templates available.

Help template selection
Available templates

The list of available driver help templates is listed here.

This list includes the template defined within the driver help project, help templates installed by Nimbus, and any custom driver help templates you may have created. The choices shown will correspond to the templates present in the HelpTemplates subfolder of the Nimbus installation folder.

A preview of the selected template is displayed below. Changing the selected help template has no effect on the help project until you press the Switch to this template button.

Note Note

If an error is detected in the selected help template, the help previewer will display an error page until the error is corrected.

Switch to this template

Pressing this button causes the driver help project to be updated to use the selected template.

Caution note Caution

When you switch help templates for a project, the template files from the appropriate NimbusInstallDir\HelpTemplates folder are copied over the files in the driver's help project Template folder. This means that all customizations that might have been performed on the project's help template are lost. Before switching help templates, be sure that the current project template has no customizations that need to be saved elsewhere.

Note Note

IVI-COM help templates that include an IVI-C wrapper use template files from the IVI-C template for portions of the driver help file. The following folders within the IVI-C template are used by the IVI-COM help template:

  • IviCAttribute

  • IviCBranch

  • IviCCallbackFunction

  • IviCErrorsWarnings

  • IviCFunction

  • IviCLibrary

See Also

Other Resources

Working with Help Templates
Help Template Previewer Errors


Help Template Previewer Errors

If the help template previewer that's displayed on the driver help project properties Template tab encounters an error, the previewer will present an error control similar to the one shown in Figure 1.

Figure 1: Help Template Preview Error View
03BB 9 F 72-6649-4 F 49-8802-E 7 A 8998FE 216

Once you have corrected the problem in the selected template, the help template previewer will automatically revert back to displaying a preview of the selected help template.

See Also

Other Resources

Template Page, Driver Help Project Properties
Working with Help Templates


Building and Viewing the Help Content

If Nimbus created the driver help project when the driver solution was created (a setting that can be controlled via per-user preferences), the driver help project will not be built automatically whenever you build the driver solution.

Building the driver help

  1. Right click on the driver help project in the Solution Explorer.

  2. Select Build.

If you add a help project to a solution at a later time, Visual Studio will automatically include that project in the default build configuration, and the driver help project will be built each time the solution is built. To change this, right click on the root solution node in the Solution Explorer, select Configuration Manager, and exclude the driver help project from the default build configuration.

Whenever a driver help project is built, the resulting help file(s) will be located in the <solutionFolder>\build directory.

Note Note

The exact set of help files produced by the build depends on the help file formats selected on the General tab of the help project properties.

Viewing the driver help

  1. Right click on the driver help project in Solution Explorer.

  2. The following commands will appear in the context menu:

    • View Help 1.x

    • View in Help Viewer

    Only those help formats selected in the help project properties will be enabled.

  3. Select the help format you wish to view.

Special Considerations for Microsoft Help Viewer Compatibility

When the Help Viewer radio checkbox is checked in the help project properties, additional validation is performed during the build process. This validation is done to ensure compatibility with the Microsoft Help Viewer. The Microsoft Help Viewer requires XHTML content, which is stricter than HTML. Consequently, content entered using the Visual Studio HTML editor embedded in the Nimbus Help Editor may not be valid XHTML. If invalid content is supplied to the Help Library Manager when merging help into the Visual Studio content store, then the Help Library Manager will fail and send errors to the Windows Event Log. That log reports only the first error, out of potentially hundreds that could exist in an IVI driver. Additionally, the file name of the HTML file in which the error occurred is not given. Consequently, debugging help content errors can be extraordinarily difficult using only the Windows Event Log.

Note Note

The validation for Help Viewer compatibility is only performed when the Help Viewer radio checkbox is checked in the help project properties. The validation is not required, and thus not performed, when building only the Help 1 (.chm) format.

To faciliate debugging help content errors, Nimbus provides validation before the Help Library Manager is invoked. Any errors detected are reported in the Errors List and the Output window as with other types of Visual Studio projects. However, it is important to note that the file in which the actual error is reported is an automatically generated file, since driver help files are ultimately composed of HTML fragments from various pieces of the help template. To automatically navigate to the exact location of the error, you can double-click the error in the Output window. Double-clicking the entry in the Errors List will NOT open the file.

Important note Important

To navigate to help build errors, use the Output window to double-click on the specific error. The Errors List does not allow for direct navigation.

See Also

Other Resources

General Page, Driver Help Project Properties
Using Per-User Preferences
Help Page, All Drivers Per-User Preferences


Signing Microsoft Help Viewer Content

In order for help content to be viewed within the Microsoft Help Viewer, it must first be integrated into the local help library store. This integration step is performed by a separate application from Microsoft called the Help Library Manager, and may be performed automatically by Nimbus whenever a driver help project is built. Whether or not Nimbus runs the Help Library Manager to perform this integration is controlled via help project properties. If enabled, help content registration happens whenever the driver help project is built.

When the Help Library Manager runs, it will display a modal Security Alert dialog box if the help content being registered by Nimbus is not signed using a valid certificate. The driver help build operation will not complete until you respond to this dialog box by confirming that you trust the source of the content and wish to proceed. In order to prevent this dialog box from being displayed whenever a driver help project is built, you must provide Nimbus with the certificate thumbprint that uniquely identifies the certificate within your computer's local certificate store.

The steps outlined below explain how to use the Microsoft MMC snap-in to import a certificate into your local certificate store and then locate the thumbprint that can be used by Nimbus to access that certificate.

Signing Microsoft Help Viewer Driver Help Content

  1. Use the Microsoft MMC snap-in to import a certificate into your local per-user certificate store.

  2. After importing the certifiate, use the Microsoft MMC snap-in to retrieve the thumbprint of the certificate

  3. Once you have the certificate thumbprint copied to your clipboard, use the Visual Studio Solution Explorer to bring up the help project properties for the driver help project you wish to configure.

  4. Paste the retrieved thumbprint value into the Certificate thumbprint field on the General tab. A certificate thumbprint is an alphanumeric string of 40 characters.

    Note Note

    Note that per-user preferences for help projects can be used to configure the certificate thumbprint value once so that Nimbus can automatically supply the correct value for new driver help projects.

Once a valid certificate thumbprint has been provided for a driver help project, the Help Library Manager will no longer display any modal dialog boxes when the driver help project is built.

See Also

Other Resources

General Page, Driver Help Project Properties
Help Page, All Drivers Per-User Preferences
Import Certificates Using MMC (MSDN)
Retrieve the Thumbprint of a Certificate Using MMC (MSDN)


Creating a Driver Installer

The IVI Foundation imposes a considerable number of specific requirements for IVI.NET driver installers. Driver installers must properly register with the IVI Configuration Store. They must also meet the IVI requirements for installation on 64-bit operating systems. All of these requirements must be met in addition to the basic requirements imposed by COM and .NET.

All Nimbus drivers utilize WiX (Windows Installer XML) for creating driver installer packages. The topics in this section explain how Nimbus uses WiX and how driver installers may be customized to meet specific driver requirements.

In This Section

Basics of Driver Installers

Using the Setup Designer

Accessing Driver Settings

Roundtripping The Setup Project

Creating 64-Bit Driver Installers

Ensuring Proper COM Registration (IVI-COM only)

Installing Help Viewer Content

Distributing Driver Source Code

Building the Driver Installer

Manually Customizing The Driver Installer

Learning More About WiX


Basics of Driver Installers

This topic presents an overview of how Nimbus driver installers are created, managed, and customized. Other topics under the topic Creating a Driver Installer present detailed information on specific installer issues.

The Driver Setup Project and WiX

If you have Nimbus create a driver setup project as part of creating a new driver solution, the setup project will be named as follows:

<projectName>Setup

Driver setup projects added to a solution after the fact can be named arbitrarily.

This driver setup project produces an MSI installer package (.msi) when it is built. It does this by use of an installer tool called WiX (Windows Installer XML) . WiX is a toolset that builds Windows installation packages from XML source code. WiX is in wide use today, particularly within Microsoft where it is used to produce the installers for such large-scale projects as Microsoft Office, Visual Studio, and SQL Server. This technology is particularly amenable to driver installers because it exposes the full power of Windows Installer technology and because its XML source format allows for both manual modifications and automated code-generation and roundtripping, such as that performed by Nimbus.

For links to helpful WiX resources, see the topic Learning More About WiX. When working with WiX directly, keep in mind that there are several versions of WiX available. Nimbus currently uses WiX version 3.9.

Nimbus automatically installs WiX in the NimbusInstallDir\Tools\Wix3 folder, so a separate download and installation is not necessary. The WiX command-line programs installed by Nimbus are invoked automatically by the driver setup project. These programs process the XML source files in the driver setup project. The table below lists each file in a driver setup project.

Caution note Caution

All of the files listed below appear in the driver setup project, and are therefore easily accessed from within the Visual Studio Solution Explorer. You will typically not need to edit these files directly using Visual Studio's XML editor, although that capability exists for advanced scenarios where manual customization is desired.

File

Description

Setup.wxs

The main WiX source file. This file contains the product declarations, files and components, and features comprising the driver installer. Double click this file in the Solution Explorer to launch the Nimbus Driver Setup Designer. To view and edit the WiX XML in this file, right click on this file in the Solution Explorer and select View Code.

Caution note Caution

Using the Visual Studio XML editor to modify the WiX source for this file is an advanced operation. Refer to the documentation on manual customization for more information.

DriverEULA.rtf

End-user license agreement that appears in one of the setup dialog pages. It also gets installed with the driver.

This file should be customized by the developer to meet the appropriate corporate legal standards.

Readme.txt

Readme file installed with the driver.

Important note Important

Nimbus generates only a template Readme.txt file with fields for the required IVI compliance information. This information needs to be manually populated by the driver developer before shipping the driver. Once complete, this file can be used to perform the required registration of the driver on the IVI Foundation web site.

Images\*.*

Series of graphics files (.bmp, .ico) used in various places by the installer.

Important note Important

These files may be replaced for custom branding or other purposes, but it is critical they be replaced with files that have precisely the same image size.

Internal\*.*

Standard file and folder definitions used by driver installers.

Caution note Caution

Although these files may be modified using Visual Studio's XML file editor, doing so is an advanced operation. Refer to the documentation on manual customization for more information.

Policy Files\*.xml (IVI.NET and IVI-COM only)

Policy files for implementing backwards compatibility with previous versions of the driver. Nimbus automatically adds one of these for each compatible version listed in the General Property Page. Building the setup project creates policy file DLLs from these XML files. The resulting policy file DLLs are automatically integrated into the driver installer.

Default Behavior of the Driver Installer

Nimbus automatically generates a fully IVI-compliant and fully functional IVI driver installer. In many cases, the driver installer project can simply be built and the resulting .msi package used as is. By default, the driver installer does all of the following:

  1. Checks for the presence of the minimum version of the IVI Shared Components, as specified in the General Page of the Driver Setup Project Properties, and aborts if not found.

  2. For IVI.NET drivers, the installer checks for the presence of the minimum version of the IVI.NET Shared Components, as specified in the General Page of the Driver Setup Project Properties, and aborts if not found.

  3. For IVI-COM and IVI-C drivers, the installer checks for the presence of another version of the same driver and alerts the user if one is found.

    For IVI.NET drivers, the installer deploys the driver side-by-side with any other version of the same IVI.NET driver on the system. The policy files deployed with the driver ensure that applications built against earlier versions of the IVI.NET driver will load the latest version when they execute. This side-by-side deployment is the approach recommended by the IVI Foundation and the same approach employed by the IVI Shared Component installer.

  4. Installs files as listed in the sections below, based on driver type.

  5. Creates a Start Menu item named "<company>\<driverName>" and adds links to the following items:

    • Driver help file, if available (<driverName>.chm).

    • Readme file.

  6. Updates the IVI Configuration Store with the information specified in the driver's IVI Config Store XML file (<driverName>.xml).

  7. Merges the driver help with the Visual Studio help, if the Visual Studio help is installed.

IVI.NET Driver Files Installed

The table below lists the files that are installed as part of the IVI.NET driver:

File

Install Location

Description

<driverName>.<frameworkShortVersion>.dll

e.g.: Acme.Acme4321.Fx20.dll

<IviInstallDir>\Microsoft.NET\Framework32\<frameworkVersion>\<driverName> <driverThreeDigitVersion>

e.g.: C:\Program Files (x86)\IVI Foundation\IVI\Microsoft.NET\Framework32\v2.0.50727\Acme.Acme4321 0.1

AND

Global Assembly Cache (GAC)

IVI.NET driver assembly.

<driverName>.<frameworkShortVersion>.xml

e.g.: Acme.Acme4321.Fx20.xml

<IviInstallDir>\Microsoft.NET\Framework32\<frameworkVersion>\<driverName> <driverThreeDigitVersion>

Visual Studio IntelliSense file (only if you XML documentation is enabled on the driver assembly project's property page).

Policy.X.X.<driverName>.dll

Global Assembly Cache (GAC)

Policy file for .NET versioning. There will be one of these for each compatible version listed in the General Page of the Driver Setup Project Properties.

Source\*.*

<IviInstallDir>\Microsoft.NET\Framework32\<frameworkVersion>\<driverName> <driverThreeDigitVersion>\Source

Driver sources files. End users will have the option of installing driver source when they run the driver installer.

<driverName>.chm

<IviInstallDir>\Microsoft.NET\Framework32\<frameworkVersion>\<driverName> <driverThreeDigitVersion>\Help

HTML 1.0 driver help file and index (if HTML 1.0 help has been enabled on the General Page of the Driver Setup Project Properties).

<driverName>.HxS

<driverName>Collection*.*

h2reg.ini

<IviInstallDir>\Microsoft.NET\Framework32\<frameworkVersion>\<driverName> <driverThreeDigitVersion>\Help

<driverName>.msha

<driverName>.mshc or <driverName>.cab

<IviInstallDir>\Microsoft.NET\Framework32\<frameworkVersion>\<driverName> <driverThreeDigitVersion>\Help

Microsoft Help Viewer driver help file for use with Visual Studio. (if Microsoft Help Viewer help has been enabled on the General Page of the Driver Setup Project Properties).

The actual name of this file depends on whether or the help is signed with a certificate. Signed help files will have an extension of .mshc, while signed help files will have an extension of .cab. Refer to Signing Microsoft Help Viewer Content for instructions on how to sign help files. Regardless of whether or not the driver help file is signed, it is integrated into the Microsoft Help Viewer local content database by the driver installer.

IVI-COM Driver Files Installed

The table below lists the files that are installed as part of the IVI-COM driver:

File

Install Location

Description

<driverName>.dll

<IviInstallDir>\Bin

IVI-COM driver DLL.

If an IVI-C wrapper is included with the driver, then this DLL is NOT named <driverName>.dll. Rather, the driver is named according to the IVI-C prefix -- <prefix>.dll.

<assemblyPrefix>.<driverName>.Interop.dll

<IviInstallDir>\Bin\Primary Interop Assemblies

AND

Global Assembly Cache (GAC)

.NET interop assembly.

The <assemblyPrefix> can be set from the .NET Page of the Driver Settings Editor.

<assemblyPrefix>.<driverName>.Interop.xml

<IviInstallDir>\Bin\Primary Interop Assemblies

XML IntelliSense file for using the driver in .NET environments.

Policy.X.X.<assemblyPrefix>.<driverName>.Interop.dll

Global Assembly Cache (GAC)

Policy file for .NET versioning. There will be one of these for compatible version listed in the General Page of the Project Properties.

Source\*.*

<IviInstallDir>\Drivers\<driverName>\Source

Driver sources files.

If an IVI-C wrapper is included with the driver, then the install location will use the IVI-C prefix in the install path instead of <driverName>.

<driverName>.chm

<IviInstallDir>\Drivers\<driverName>

HTML 1.0 driver help file and index.

If an IVI-C wrapper is included with the driver, then the install location will use the IVI-C prefix in the install path instead of <driverName>.

<driverName>.HxS

<driverName>Collection*.*

h2reg.ini, h2reg.exe

<IviInstallDir>\Drivers\<driverName>

<driverName>.msha

<driverName>.mshc or <driverName>.cab

<IviInstallDir>\Drivers\<prefix>

Microsoft Help Viewer driver help file for use with Visual Studio. (if Microsoft Help Viewer help has been enabled on the General Page of the Driver Setup Project Properties).

The actual name of this file depends on whether or the help is signed with a certificate. Signed help files will have an extension of .mshc, while signed help files will have an extension of .cab. Refer to for instructions on how to sign help files. Regardless of whether or not the driver help file is signed, it is integrated into the Microsoft Help Viewer local content database by the driver installer.

If a MATLAB® wrapper has been included with the driver via the MATLAB Page of the Driver Settings Editor, then Nimbus automatically integrates additional files with the driver installer. The root folder for the installed MATLAB files is:

<IviInstallDir>\\Components\MATLAB\+instrument\+driver

IVI-C Driver Files Installed

The IVI-C driver files installed are the same for standalone IVI-C drivers and for IVI-C wrappers built on top of an IVI-COM driver.

File

Install Location

Description

<prefix>.h

<IviInstallDir>\Include

IVI-C header file containing IVI-C function and attribute definitions.

<prefix>.lib

<IviInstallDir>\Lib\Msc

IVI-C import library.

<prefix>.fp

<IviInstallDir>\Drivers\<prefix>

Function panel file containing hierarchy of IVI-C functions.

<prefix>.sub

<IviInstallDir>\Drivers\<prefix>

Attribute information file containing hierarchy of IVI-C attributes.

Source\*.*

<IviInstallDir>\Drivers\<prefix>\Source

Driver sources files.

<prefix>.chm

<IviInstallDir>\Drivers\<prefix>

HTML 1.0 driver help file and index.

<prefix>.HxS

<prefix>Collection*.*

h2reg.ini, h2reg.exe

<IviInstallDir>\Drivers\<prefix>

<driverName>.msha

<prefix>.mshc or <prefix>.cab

<IviInstallDir>\Drivers\<prefix>

Microsoft Help Viewer driver help file for use with Visual Studio. (if Microsoft Help Viewer help has been enabled on the General Page of the Driver Setup Project Properties).

The actual name of this file depends on whether or the help is signed with a certificate. Signed help files will have an extension of .mshc, while signed help files will have an extension of .cab. Refer to for instructions on how to sign help files. Regardless of whether or not the driver help file is signed, it is integrated into the Microsoft Help Viewer local content database by the driver installer.

See Also

Other Resources

Manually Customizing The Driver Installer
Signing Microsoft Help Viewer Content


Using the Setup Designer

Nimbus provides a Driver Setup Designer for customizing the driver installer without directly editing the WiX source files. The designer automates some of the more common driver installer customization tasks. For instance, adding a set of example programs can easily be done with the Setup Designer.

The Setup Designer is accessed via the Setup Designer node in Solution Explorer. The designer presents a tree view in the left pane representing the set of folders on the target machine. The grid view in the right pane displays the items the installer will deploy in the folder selected in the tree view.

Many of the folders in the tree view are shown in gray. These folders cannot be edited as most are part of the standard IVI folder structure, which can only be modified by the IVI Shared Component installer -- not by IVI driver installers.

The Setup Designer only modifies the Setup.wxs file within the driver setup project. Other required WiX source files are also present within the Internal project folder, but the Setup Designer only reads those files.

Caution note Caution

Although Visual Studio will allow you to easily view and modify WiX source files (.wxs and .wxl) directly, doing so is an advanced operation and should be done with great care to make sure your solution is checked in under a source code control system, or you have backed up the WiX source files before manually modifying them.

The following types of customizations can be performed with the Setup Designer. More advanced customizations might require directly editing the other setup project files, such as the Setup.wxs. The topic Learning More about WiX provides useful links to WiX resources for understanding how to work with WiX installers.

  • Adding individual files to the target machine.

  • Adding a hierarchy of folders and files to the target machine.

  • Adding shortcuts to the Start Menu folder to the target machine.

  • Installing .NET assemblies in the global assembly cache (GAC).

To add a single file or flat list of files to be installed on the target machine

  1. Right-click on one of the editable folders in the tree view. Often, the only folders to which files may be added are the driver's own folders -- named <driverName> and shown in bold.

  2. Choose Add Files.

  3. The standard Windows Add Files dialog appears.

  4. Choose the files to be added and click Open.

  5. The Setup Designer displays the added files in the right-side grid view.

To add a hierarchy of files and folders to be installed on the target machine

  1. Right-click on one of the editable folders in the tree view under. Often, the only folders to which files may be added are the driver's own folders -- named <driverName> and shown in bold.

  2. Choose Add Folder.

  3. The standard Windows folder browse dialog appears.

  4. Choose the root folder of the items to be added and click OK.

  5. A special dialog appears showing a flattened list of the files that will be added. Note that even though the list is displayed as a flat list of files, the Setup Designer will preserve the actual hierarchy when the files are actually added.

  6. Use the check boxes next to each file in the list to include or exclude individual files. The Exclude text box near the bottom of the dialog can be used to filter out files based on file extension.

  7. Once the desired set of files are checked, click OK.

  8. The Setup Designer displays the added folders in the tree view on the left along with the contents of the selected folder in the grid view on the right.

To add items to the Start Menu

  1. Right-click on a folder in the tree view on the left or on a file in the grid view on the right.

  2. Choose Create Shortcut to ....

  3. The Setup Designer creates a shortcut to the specified folder or file.

  4. Drag and drop the shortcut to the desired location under the Start Menu.

To add one or more .NET assemblies to the GAC

  1. Right-click on the Global Assembly Cache node in the tree view.

  2. Choose Add Files.

  3. The standard Windows Add Files dialog appears. Note that only .NET assemblies can be added to the GAC.

  4. Choose the files to be added and click Open.

  5. The Setup Designer displays the added files in the right-side grid view.

See Also

Other Resources

Manually Customizing The Driver Installer


Accessing Driver Settings

Certain aspects of Nimbus-generated driver installers are controlled via the driver setup project's project properties.

To access the driver setup project properties

  1. From Solution Explorer, right click on the driver setup project node and choose Properties.

  2. A tabbed document window appears with various settings on each tab.

    The remaining topics in this section provide a detailed explanation of the properties available on each tab.

In This Section

General Page, Driver Installer Project Properties


General Page, Driver Installer Project Properties

Installer settings
Driver

The name of the driver associated with this driver installer project. This is a read-only field.

Minimal IVI version

The setting specifies the minimum version of the IVI Shared Components the driver requires. Nimbus will update the driver installer so that it automatically checks the end-user system for the presence of an IVI Shared Components version that is equal to or greater than this value. The value is also used in generating the driver's IVI compliance information in the help file.

The latest version of the IVI Shared Components along with the revision history can be downloaded here .

Minimal IVI.NET version (IVI.NET only)

The setting specifies the minimum version of the IVI.NET Shared Components the driver requires. Nimbus will update the driver installer so that it automatically checks the end-user system for the presence of an IVI.NET Shared Components version that is equal to or greater than this value. The value is also used in generating the driver's IVI compliance information in the help file.

The latest version of the IVI.NET Shared Components along with the revision history can be downloaded here .

Create a 32-bit installer

This option enables creation of a 32-bit driver installer. If the Create a 64-bit installer checkbox is also checked, then the resulting 32-bit installer will refuse to install on a 64-bit operating system. Otherwise, the resulting installer will run on both 32-bit and 64-bit operating systems.

See the topic Creating 64-Bit Driver Installers for more details on the implications of building 32-bit and 64-bit installers.

Create a 64-bit installer

This option enables creation of a 64-bit driver installer. The exact behavior of the resulting installer depends upon the state of the Create a 32-bit installer checkbox. When a 32-bit installer will also be created, the setup project must be compiled twice -- once with the x86 configuration selected and once with the x64 configuration selected. When checked, the Create a 64-bit installer option results in a 32-bit driver installer that will refuse to install when run on a 64-bit operating system. When cleared (the default), the Create a 64-bit installer option produces a 32-bit driver installer that will work on both 32- and 64-bit operating systems.

IVI-COM and IVI-C drivers must also be built twice (x86 and x64) when this option is checked (and the 32-bit option is also checked).

IVI.NET drivers may need to be built twice depending upon if bitness specific IVI.NET drivers are being deployed or if Any CPU drivers are being built. See the discussion of the Platform to deploy options below.

There are a number of implications to enabling this option. See the topic Creating 64-Bit Driver Installers for details.

Distribute driver source code with installer

When checked, this option instructs Nimbus to add a feature to the driver installer that allows the end user to install the driver source code. By default, the source code will still not be installed, but the user will have the ability to choose Custom install when running the installer. The custom install screen will offer the user the option to installer the driver source code. If selected by the end user, the driver source code will be installed one of the following folders, based on driver type:

  • For IVI.NET: <IviInstallDir>\Microsoft.NET\Framework32\v2.0.50727\<driverNamespace> <driverThreeDigitVersion>\Source

    Note Note

    The Framework32 folder will be Framework64 when deploying to the 64-bit Program Files folder. Also, the v2.0.50727 folder will change based on the .NET Framework against which the driver is built.

  • For IVI-COM: <IviInstallDir>\Drivers\<driverName>\Source

  • For IVI-C: <IviInstallDir>\Drivers\<prefix>\Source

Create a policy file to automatically upgrade each of the following previous driver versions

The version numbers listed here are used to specify previous versions of the driver with which the current version is compatible. This information is used to create .NET version policy files for seamlessly upgrading .NET client applications to the latest version of the driver. Note that only the major and minor digits of the version number are used by policy files.

For each version number specified here, Nimbus will automatically add an XML file to the setup project with a name in the following format:

Policy.<major>.<minor>.<driverNamespace>.config

Example: Policy.3.2.Acme.Acme4321.config

At build time, these XML files are compiled into policy file DLLs that are automatically integrated into the resulting driver installer and deployed into the global assembly cache.

Platform to deploy to 32-bit Program Files Folder (IVI.NET only)

IVI.NET drivers can be built as bitness-independent assemblies (Any CPU) or as bitness-specific assemblies (x86 or x64). This setting controls which build of the IVI.NET driver is deployed in the 32-bit Program Files folder on the target machine.

If AnyCPU is selected, then the driver installer will take the IVI.NET assembly from the driver project's bin\Debug folder and deploy it to the 32-bit Program Files folder. If x86 is selected, then the driver installer will take the IVI.NET assembly from the driver project's bin\x86\Debug folder and deploy it to the 32-bit Program Files folder.

Platform to deploy to 64-bit Program Files Folder (IVI.NET only)

IVI.NET drivers can be built as bitness-independent assemblies (Any CPU) or as bitness-specific assemblies (x86 or x64). This setting controls which build of the IVI.NET driver is deployed in the 64-bit Program Files folder on the target machine.

If AnyCPU is selected, then the driver installer will take the IVI.NET assembly from the driver project's bin\Debug folder and deploy it to the 64-bit Program Files folder. If x64 is selected, then the driver installer will take the IVI.NET assembly from the driver project's bin\x64\Debug folder and deploy it to the 64-bit Program Files folder.


Roundtripping The Setup Project

Setup Roundtripping Basics

As a driver project is modified, Nimbus performs code roundtripping on the setup project files to keep them in sync with the driver itself. This roundtripping is done in real time so that the setup project can be built at any time with the assurance that it contains the latest updates. Manual modifications of the setup project files is typically only needed when custom features are required.

A variety of actions performed on the driver using the various editors can trigger Nimbus updates to the setup project files. The table below lists some (but not all) of the automatic code roundtripping that Nimbus performs on an IVI-COM setup project. IVI.NET setup projects and IVI-C setup projects perform similar roundtripping operations, though, obviously the exact details vary with driver type.

IVI-COM Driver Project Change | Setup Roundtripping Performed
Child interface added | The new interface and its GUID must be added to the registry on the target machine.
Enum added | The new enum and its GUID must be added to the registry on the target machine.
Repeated capability added | A new COM coclass must be registered on the target machine along with all of all of the interfaces it supports.
New compatible versions added | .NET policy files for each compatible version must be installed on the target machine.
IVI-C wrapper enabled | All of the IVI-C related files (.fp, .sub, .lib, .h) must be installed on the target machine.
64-bit support enabled | A new set of files is generated to produce a 64-bit installer. The 32-bit installer is modified so that it only works on 32-bit machines.
IVI-C prefix changed | All of the entries for the IVI-C related files (.fp, .sub, .lib, .h) are renamed.
Avoiding Setup Roundtripping Failures

Failures can occur during roundtripping if the setup project files are not in a state that is expected by Nimbus. Care must be taken if manual modifications are performed on setup project files. Here are some tips to avoid roundtripping failures.

  • Always ensure the WiX files are in well-formed XML. Nimbus loads the file content in an XML document. If it fails to load as XML, roundtripping will fail.

  • Do not rename the WiX files. Nimbus relies upon on the files being named as they are in the originally generated setup project.

  • Do not rename the existing component IDs, directory IDs or file IDs in the WiX files. Nimbus locates the elements that must be modified based on these IDs.


Creating 64-Bit Driver Installers

Nimbus includes support for creating 64-bit installers that fully comply with the IVI Foundation specifications for 64-bit driver installers. The generation of a 64-bit driver installer is controlled by two settings -- the Create a 64-bit installer and Create a 32-bit installer check boxex on the General Page of the Project Properties. Though enabling this feature is simple, several implications must be carefully considered.

Creating Both 32-Bit and 64-Bit Driver Installers

This section applies when a 32-bit driver is being created. For details on creating 64-bit-only installers, see the section below.

When 64-bit support is enabled and 32-bit support IS enabled, the following are true:

  1. Two IVI nodes appear in the Setup Designer, indicating that there are two distinct installation trees on the target machine. Consequently, installer customizations must be done independently for the 32-bit and 64-bit installation trees.

  2. Building the setup project produces two .msi packages -- one for use on a 32-bit machine and one for use on a 64-bit machine.

  3. Before attempting to build the setup project, the driver MUST be built twice -- once with a 32-bit target and once with a 64-bit target.

    Important note Important

    If the 32-bit build and the 64-bit build of the driver are not both performed before the setup project is built, then the setup project build will fail.

  4. The generation of the 32-bit installer is affected by the decision to generate a 64-bit installer. The 32-bit installer is modified so that it cannot be installed on a 64-bit machine. This is done as per the IVI Foundation specifications, and is intended to prevent end users from unknowningly using a 32-bit installer on a 64-bit machine when a 64-bit installer is actually available.

    Important note Important

    32-bit installers generated when the 64-bit support check box is checked will NOT install on a 64-bit machine.

  5. Any additional DLLs or EXEs added to the 64-bit installer (i.e. support binarys or example programs) MUST be compiled as native 64-bit. The 64-bit installer places all driver files in the native 64-bit folders, not in the WoW64 (Windows-on-Windows 64-bit) folders

When 64-bit support is NOT enabled and 32-bit support IS enabled, the following are true:

  1. A single IVI node appears in the Setup Designer, indicating that there is a single installation tree on the target machine, whether the target machine is 32-bit or 64-bit.

  2. Building the setup project produces a single 32-bit .msi package.

  3. Before attempting to build the setup project, the driver must be built with a 32-bit target.

  4. The installer can be used on either a 32-bit machine or a 64-bit machine. When used on a 64-bit machine, the driver files will be installed in the WoW64 (Windows-on-Windows 64-bit) folders.

Creating 64-Bit-Only Driver Installers

This section applies when a 32-bit driver is NOT being created. These drivers can only run on 64-bit systems.

When 64-bit support is enabled and 32-bit support is NOT enabled, the following are true:

  1. A single IVI node appears in the Setup Designer, indicating that there is a single installation tree on the 64-bit target machine.

  2. Building the setup project produces a single 64-bit .msi package.

  3. The resulting installer will refuse to run on a 32-bit operating system.

  4. Any additional DLLs or EXEs added to the 64-bit installer (i.e. support binarys or example programs) MUST be compiled as native 64-bit. The 64-bit installer places all driver files in the native 64-bit folders, not in the WoW64 (Windows-on-Windows 64-bit) folders


Ensuring Proper COM Registration (IVI-COM only)

COM Registration Basics

One of the main tasks performed by an IVI driver installer is registration of various bits of COM infrastructure. Specifically, every class, enum, and interface in the driver must have an entry in the registry of the target machine. The COM runtime relies upon all of these entries to be complete and correct, else the driver will not operate properly.

There are two basic ways to perform COM registration for an IVI driver -- using the driver installer and using COM self-registration.

COM self-registration relies upon a pair of special functions present in all COM components -- including all IVI-COM drivers. These functions are DllRegisterServer and DllUnregisterServer and they contain the code necessary to run special registration scripts that add (or remove) the appropriate registry entries from the target machine. COM self-registration is performed by running the regsvr32.exe command-line utility and passing in the name of the driver DLL. This regsvr32.exe utility simply invokes the DllRegisterServer function. Passing in the /u flag to regsvr32.exe invokes the DllUnregisterServer to remove the driver's COM registration entries.

Though COM self-registration can be convenient, it is frought with problems that make it unsuitable for most general driver deployment scenarios. Not least amongst these disadvantages are its inability to perform reliable rollbacks and its lack of support for per-user registration. Consequently, IVI drivers should never rely upon COM self-registration for end-user deployment scenarios. Rather, the driver installer is constructed to explicitly register each COM enum, interface, and class using MSI infrastructure.

Caution note Caution

Never modify an IVI driver installer to use COM self-registration.

COM Self-Registration and the Driver Build Process

Although the previous section emphasized the importance of avoiding COM self-registration for driver deployment, it does prove to be useful for testing an IVI driver on a Nimbus developer machine. Each time the driver project is compiled, the regsvr32.exe command is run to perform the required COM registration of the driver. This enables the driver developer to immediately run unit tests or other test applications, without having to build and run the driver installer.

Running the driver installer in order to perform testing is not only extraordinarily inconvenient, it is also a VERY dangerous practice. This is because a single set of COM registry entries (those associated with the driver) are being manipulated by two different mechanisms that know nothing about one another -- COM self-registration and the Windows Installer infrastructure. If both of these mechanisms are used on the same machine, the registry could become corrupt and inexplicable errors are likely to occur. Since the COM self-registration is built into the driver compilation process and is, for all intents and purposes, required on the developer machine, it is imperative that the driver installer NEVER be run on a machine on which the same driver has been compiled. The driver installer must be tested on a separate machine. This rule is so important that it bears repeating.

Caution note Caution

NEVER run a driver installer on a Nimbus developer machine that has been used to compile that same driver. The registry entries associated with the driver could become corrupt. IVI driver installers MUST always be tested on a dedicated test machine -- not on the same machine on which they were developed.

Per-User COM Registration

COM objects are typically registered in the machine-wide registry hive. Since per-machine settings present greater security concerns, this typically meant that registering a COM object required administrator privileges.

Beginning with Visual Studio 2008, an additional option is available for COM registration -- per-user COM registration. Indeed, for Visual Studio 2008 it is important to note that per-user COM registration is the default mode. As the name implies, per-user COM registration places the COM object's registry entries in the per-user registry hive. This means that administrator privileges are not required when using per-user COM registration.

Since per-user COM objects do not require administrator privileges to register, the operating system uses different rules to load them. These rules are intended to keep a per-user COM object which may have been installed by a relatively low privileged user from getting loaded into an application that is running with high privileges. Consequently, it is possible that per-user COM objects are not visible to certain applications running on a machine. The table below summarizes the loading policy. Note that the table shows the loading policies as of Windows Vista SP1.

UAC Setting | Application Privileges | Per-User COM Visible
Disabled | Not Elevated | Visible
Disabled | Elevated | Visible
Enabled | Not Elevated | Visible
Enabled | Elevated | Not Visible


Installing Help Viewer Content

Nimbus generates all of the necessary code in the setup project to properly install the driver help content in the Microsoft Help Viewer that is used for integrated Visual Studio help. The amount of time needed to install the Help Viewer content can vary a great deal depending upon the amount and nature of driver help content, the speed of the end user machine, and the amount of help content already present in the end user machine's help library store.

To deal with the potential need to support longer help viewer installation times, Nimbus defines a special property in the Internal\Common.wxs file in the setup project. The property appears as follows:

XML
Copy
<Property Id="HELPVIEWER_TIMEOUT" Value="60000" Secure="yes" />

This defines the HELPVIEWER_TIMEOUT property (in milliseconds) with a default value of 60000 milliseconds (or 1 minute). The code just below this Property element passes this value to the custom action that performs the help content installation (and uninstallation):

XML
Copy
<CustomAction Id="CA_REGISTER_HELP3" BinaryKey="IviDriverActions" DllEntry="InstallHelp3Content" Execute="deferred" Impersonate="no"/>
<CustomAction Id="CA_REGISTER_HELP3.SetCustomActionData" Property="CA_REGISTER_HELP3" Value="HV_TIMEOUT=[HELPVIEWER_TIMEOUT];HELP_SOURCE_MEDIA_PATH=[Ivi$(var.Bitness)DriverFolder]$(var.Help3OutputFileBaseName).msha"/>

<CustomAction Id="CA_UNREGISTER_HELP3" BinaryKey="IviDriverActions" DllEntry="UninstallHelp3Content" Execute="deferred" Impersonate="no"/>
<CustomAction Id="CA_UNREGISTER_HELP3.SetCustomActionData" Property="CA_UNREGISTER_HELP3" Value="HV_TIMEOUT=[HELPVIEWER_TIMEOUT];HELP_SOURCE_MEDIA_PATH=[Ivi$(var.Bitness)DriverFolder]$(var.Help3OutputFileBaseName).msha"/>

If your driver is large and/or includes a large amount of help content, then you may want to increase the value of the Property element to one more suitable for your particular driver.

However, it is important to keep in mind that end-user machine conditions will actually determine the required timeout value, so it is possible that the timeout value selected at build time may still be inadequate for some users. In such cases, the HELPVIEWER_TIMEOUT property may be directly supplied at installation time by running msiexec from the command line. The following command installs the driver from the command line and specifies a timeout value of 90000 milliseconds for the HELPVIEWER_TIMEOUT property:

msiexec /i Acme4301.msi HELPVIEWER_TIMEOUT=90000


Distributing Driver Source Code

By default, Nimbus-generated driver installers include a Source Code feature that the end-user can use to optionally install the driver's source code in addition to the standard IVI driver components. When the end user runs the driver installer, a feature selection dialog like the one shown in Figure 1 will be displayed.

Figure 1: The Default Driver Installer Feature Dialog
78142990-F 1 E 9-4040-8875-057DF 8 C 8 B 3DF

The end user may choose to include the source code feature at this time (opt in model), or they may choose to use the Windows Add/Remove Programs Change command to install the driver source at a later time.

Follow the instructions below to modify the driver installer so that the source code feature is enabled by default (opt out model), or remove the source code feature from the driver installer altogether.

Remove the source feature completely

  1. Open the General Page of the setup project's Project Properties.

  2. Uncheck the checkbox labeled Distribute driver source code with installer.

Caution note Caution

The steps below involve manual modification of the WiX source code for the driver installer. Before proceding, make sure your solution is checked into a source code control system, or make a backup copy of your solution.

Enable the source feature by default (opt out model)

  1. Expand the driver setup project node in the Solution Explorer.

  2. Right click on Setup.wxs and select View Code.

  3. Locate the <Feature> element that has an Id attribute equal to SourceFeature.

  4. Change the Level attribute of that <Feature> to 3 (the default value is 100).

  5. Save and close Setup.wxs.

  6. Verify that you can build the driver setup project, and open the driver setup designer (by double clicking on Setup.wxs) without error before making any further modifications to the driver setup project.


Building the Driver Installer

If Nimbus created the IVI.NET driver setup project when the IVI.NET driver solution was created (a setting that can be controlled via per-user preferences), the driver setup project will not be built automatically whenever you build the IVI.NET driver solution.

Building the driver installer

  1. Right click on the driver setup project in the Solution Explorer.

  2. Select Build.

If you add a setup project to a solution at a later time, Visual Studio will automatically include that project in the default build configuration, and the driver setup project will be built each time the solution is built. To change this, right click on the root solution node in the Solution Explorer, select Configuration Manager, and exclude the driver setup project from the default build configuration.

Whenever a driver setup project is built, the resulting .msi file will be located in the <solutionFolder>\build\<configuration>\<platform> directory, where <configuration> is the active build configuration (e.g. debug or release) and <platform> is the active build platform (e.g. x86 or x64).

See Also

Other Resources

Using Per-User Preferences
Using Per-User Preferences


Manually Customizing The Driver Installer

While the Nimbus Driver Setup Designer facilitates the most commonly required installer modifications, you may occassionally wish to modify your driver installer in a way that's not yet directly supported by the designer. Because the setup designer is just manipulating the WiX source files that are part of the driver setup project, you can always resort to manually editing the WiX source files directly.

Caution note Caution

Before making any modifications to WiX source files directly, be sure your solution is checked into a source code control system, or make a backup copy of your driver setup project (or entire solution) before proceeding. Directly modifying the WiX source files should only be done by individuals who are already comfortable with WiX. Refer here to learn more about WiX.

See Also

Other Resources

Using the Setup Designer


Learning More About WiX

Windows Installer XML (WiX) is the core technology used by Nimbus to build driver installers for both 32-bit and 64-bit environments. WiX is a freely available toolset that builds Windows installation packages from XML source code and is in widespread use today for some of the largest commercial source-code-base products, such as Microsoft Office, Visual Studio, and SQL Server.

Note Note

Nimbus currently uses WiX version 3.11.

There are a variety of resources available for WiX, including complete documentation, blogs, mailing lists, etc. These can all be located from the WiX Home Page.

An excellent WiX Tutorial is also available here.

In addition, the original team that developed WiX offers commerical-grade support, guaranteed response times on bug fixes and features as well as custom WiX development services through FireGiant.

Contact FireGiant at contact@firegiant.com for additional information.

See Also

Other Resources

Windows Installer XML (WiX)
FireGiant


Getting Assistance

Technical Support

Each license of Nimbus includes one year of direct email technical support, as well as free upgrades for both major and minor releases of the product.

For all technical support issues, please send email to:

support@pacificmindworks.com

Feature Requests

Pacific MindWorks is always seeking to improve the quality and usability of our Nimbus product. Please feel free to offer feature suggestions and other comments through our support email address: support@pacificmindworks.com


Copyright

Information in this document, including URL and other Internet Web site references, is subject to change without notice. Unless otherwise noted, the example companies, organizations, products, domain names, e-mail addresses, logos, people, places and events depicted herein are fictitious, and no association with any real company, organization, product, domain name, e-mail address, logo, person, place or event is intended or should be inferred. Complying with all applicable copyright laws is the responsibility of the user. Without limiting the rights under copyright, no part of this document may be reproduced, stored in or introduced into a retrieval system, or transmitted in any form or by any means (electronic, mechanical, photocopying, recording, or otherwise), or for any purpose, without the express written permission of Pacific MindWorks.

Pacific MindWorks may have patents, patent applications, trademarks, copyrights, or other intellectual property rights covering subject matter in this document. Except as expressly provided in any written license agreement from Pacific MindWorks, the furnishing of this document does not give you any license to these patents, trademarks, copyrights, or other intellectual property.


IVI-C Driver Walkthrough

In this walkthrough, you will create a simple IVI-COM driver along with a help file and installer.

This walkthrough will consist of the eight main steps:

  1. Creating the IVI-C driver project

  2. Adding a function

  3. Implementing a function using an instrument command

  4. Adding an attribute that uses an enumerated type

  5. Compiling the driver

  6. Testing the driver

  7. Creating the help file

  8. Creating the driver installer

Creating the IVI-C Driver Project

We'll create a new driver project called Acme4321. Nimbus is completely integrated with Microsoft Visual Studio, so the process of creating an IVI-C driver project begins with the same steps required to create any Visual Studio project.

To create the Acme4321 driver

  1. Open Visual Studio.

  2. From the File menu, chooseNew Project.

  3. Select IVI-C Driver from the list of project types.

  4. In the Name box, enter Acme4321.

  5. Click OK.

    The New IVI-C Driver Wizard appears.

  6. On the General Page, specify the following:

    • For Prefix, enter acme4321.

    • For Instrument manufacturer, enter Acme Corporation.

    • For Driver vendor, enter Pacific MindWorks.

    • For Instrument model, enter Acme4321.

    • For Instrument class, leave the selection at none.

  7. On the Instrument I/O Page, specify the following:

    • Check the Enable VISA-based I/O check box.

    • Check the Generate direct I/O functions and attributes check box.

    • Leave all other settings on this page at their default values.

  8. On the LXI Compliance Page, leave the Conformance combo box at its default value of none.

  9. On the Projects Page, enable the following:

    • Create unit test

    • Create help project

    • Create setup project

    • Create C++ application

  10. Click Finish to create the project.

    The Driver Designer should automatically open. If it does not, then double-click the Driver Designer node in Solution Explorer. The project has been created and you are now ready to add some functions and properties to your Acme4321 driver.

Adding a Function

When you add new functionality to a driver, you organize the functions and attributes in a hierarchy, grouping them in interfaces.

To add a Configure function with parameters:

  1. Expand the Acme4321 root node to reveal the functions and attributes already added to your driver by Nimbus.

    All of the functions and attributes in the driver at this point are shown greyed out to indicate that they cannot be modified. This is because all of these functions and attributes are part of the IVI-defined inherent capabilities.

    Notice that there is an Instrument Specific node that is empty. This is the portion of the hierarchy we will use to add the functionality of our driver that is specific to our instrument.

  2. Right-click on the Instrument Specific node and choose Add Function.

    A new function node is added to the hierarchy with a default name, and the node enters edit mode.

  3. Change the function name to Configure.

  4. Note that a parameter named Vi of type ViSession is automatically added to the function as the first parameter. All IVI-C driver functions must include a ViSession parameter to represent the driver session. Nimbus automatically adds this parameter and makes it read-only so that it cannot mistakently be modified.

  5. Right click on the Configure function and choose Add Parameter.

    A new parameter is added to the function with a default name, and the node enters edit mode.

  6. Change the parameter name to NumRecords and hit Enter.

    Note that the parameter is added with a default data type of ViReal64.

  7. Change the data type of the NumRecords parameter using the Item Editor. This is done by right-clicking on the Type text box and choosing Int32 from the context menu of available types.

  8. Add a second parameter by right-clicking the Configure function again, choosing Add Parameter.

    For the parameter name, enter Enabled and hit Enter. Note that Nimbus automatically infers the desired Boolean parameter type from the name of the parameter.

  9. Finally, we'll add a third parameter and enter both the parameter name and data type by typing directly into the node label while it is in edit mode.

  10. Right-click the Configure function and choose Add Parameter.

  11. Type the name TriggerSource followed by a colon followed by string.

Implementing a function using an instrument command

Although Nimbus supports developing drivers for any type of instrument -- register-based, message-based, or custom I/O devices, special features are provided that make message-based IVI driver development particularly efficient. Every function or attribute can be implemented by associating an instrument command with the function or attribute. Nimbus can be instructed to automatically format the runtime value of function parameters into the instrument command string. The section of the walkthrough will present some of the automatic instrument command formatting features provided by Nimbus.

To implement a function using an instrument command:

  1. From the tree view, select the Configure function under the Instrument Specific node.

  2. From the Item Editor, change the Implementation style to be Instrument command. This enables the Command text box.

  3. In the Command text box, enter the following command:

    ACQ:CONFIG {NumRecords},{Enabled}; TRIG:SOUR {TriggerSource}

    The above command uses parameter tags enclosed in curly braces ({ }) to insert the runtime value of parameters into the command. Notice that when you type a left curly brace ({), Nimbus presents an IntelliSense context menu from which you can select the desired parameter to use in the instrument command.

  4. Nimbus generates all of the code needed to format the instrument command and send the result to the instrument. Several commands are available from the IVI-C Designer to inspect the generated code.

    Right-click on the Configure function and select Go to Implementation.

  5. Nimbus navigates to the acme4321.cpp file. For the Configure function, the command is formatted and sent by the following section of code in the function implementation:

    C++
    Copy
    status = viPrintf(GetVisaSession(Vi), "ACQ:CONFIG %ld,%s; TRIG:SOUR %s\n", NumRecords, strEnabled.c_str(), TriggerSource);

    A complete discussion of instrument command formatting is provided in the topic Working With Instrument Commands.

  6. The implementation of the Configure function needs to be modified so that it works in simulation mode -- that is, when no device is physically available. (This is important for steps later in this walkthrough.) For this, Nimbus has already created an if-statement block of code designated for just this purpose. It currently returns the error IVIC_ERROR_FUNCTION_NOT_SUPPORTED and it marked with a TODO block. If simulation is enabled, then we will simply return from the function so that the viPrintf function does not attempt to perform any I/O.

    Modify the implementation of Configure to the following:

    C++
    Copy
    if (SimulationEnabled(Vi))
{
    return VI_SUCCESS;
}
Adding an attribute that uses an enumerated type

Enumerated types are commonly used as attribute types and parameter types. Nimbus provides special support for defining enums and using them in function and attribute instrument commands.

To define a attribute that uses an enum:

  1. We start by defining the enum itself. From the IVI-C Designer, right-click on the Enums node and choose Add Enum.

    A new enum node is added with a default name and the node enters edit mode.

  2. For the name, simply enter TriggerSource and hit Enter.

    Creating an enum in an IVI-C driver does not physically create an enumerated type anywhere in the driver. It simply serves as a pseudo type which can be used to group together a set of related constant values. The constant values are defined when we create enum members for this enum, as we will do shortly.

  3. We need to add three enum members to the TriggerSource. Right-click on the TriggerSource and choose Add Enum Member.

    A new enum member is added to the enum with a default name and the enum member enters edit mode.

  4. Enter Internal for the member name and hit Enter.

  5. Right-click again on the TriggerSource and add two more members -- External and Software.

  6. We now need to add an attribute that uses the new enum. Right-click on the Instrument Specific node and select Add Attribute.

    Enter SweepSource for the attribute name followed by a colon followed by TriggerSource. This adds a attribute named SweepSource of type TriggerSource.

  7. With the SweepSource attribute selected in the tree view, change the Implementation style in the Item Editor to Instrument command.

  8. For the Setter command, enter the following command that will be sent to the device when the attribute value is written:

    TRIG:SOUR {value}

    For the Getter command, enter the following query that will be sent to the device when the attribute value is read:

    TRIG:SOUR?

    The setter command instructs Nimbus to take the value of the attribute and place it in the command in place of the {value} parameter tag. For reads from the instrument, first the Getter command is sent, and then Nimbus reads from the device and parses the response according to the Getter response specified. For the SweepSource attribute, leave the Getter response set to {value}, which simply means that the device responds by sending a value that Nimbus will parse into one of the allowed TriggerSource values.

  9. In order to translate the enum values to and from instrument command and respone strings, the Enum Member Editor is used to map each enum member to a command string.

    Select each of the three enum members and enter for the Command textbox INT for Internal, EXT for External, and SW for Software. These strings are stored within a special map managed by Nimbus in the driver project's Enums.h file.

Compiling the Driver

To compile the driver:

  1. The first step in compiling a Nimbus driver is to properly setting the build configuration. This typicall has to be done once the first time a new driver is compiled. However, adding, removing, or even uloading projects from a solution can cause the Configuration Manager settings to get modified.

    Important note Important

    Adding, removing, or unloading projects from a driver solution can modify the Configuration Manager settings. The tasks explained here may need to be performed again after such operations.

  2. From Solution Explorer, right click on the solution and choose Configuration Manager. The Configuration Manager Dialog Box appears.

  3. From the Configuration Manager dialog, choose the x86 platform from the Action solution platform combo box.

  4. Make sure that the Platform column setting and Build column setting for each project is set according to the table below. (Note the list of projects that appears depends upon the driver options chosen.)

    Project

    Platform

    Build

    Acme4321CDriver

    Win32

    Checked

    Acme4321CDriverConsoleApplication

    Win32

    Checked

    Acme4321CDriverUnitTest

    Win32

    Checked

    Acme4321CDriverHelp

    Any CPU

    Unchecked

    Acme4321CDriverSetup

    x86

    Unchecked

  5. Make sure x86 is selected in the Solution Platforms combo box.

    Also make sure Debug is selected in the Solution Configurations combo box.

  6. From the Build menu, select Build Solution.

    This will perform a 32-bit compilation of the driver project, the unit test projects, and the client application project.

    For the Debug build we performed in this step, the output files will be placed in the following folder:

    • <build>\Debug\x86

  7. The driver is now ready to use in an application. The build process registers the driver with the IVI Configuration Store. You can use a 3rd-party IVI browsers, such as Measurement Automation Explorer® (MAX) from National Instruments®.

Testing the driver

With the driver compiled and ready to use, the next task is to use the Visual Studio integrated unit testing tools.

To run the driver unit tests

  1. From the Test menu, choose Windows and then select Test Explorer. The Test Explorer window appears.

  2. Within Test Explorer Right-click on the ATTR_SWEEPSOURCE attribute and choose Open Test.

  3. Visual Studio navigates to the C++ unit test function for the SweepSource attribute. The test code for this function sets the value of the attribute, reads back the value in the instrument, and then compares the value set to the value read to ensure that the attribute worked. It repeats this sequence for each of the three members of the TriggerSource.

  4. Go to the top of the UnitTest.cpp file within the unit test project.

    The top of the unit test contains two important functions delineated by the TEST_METHOD_INITIALIZE and TEST_METHOD_CLEANUP functions. These functions are called before and after (respectively) each TEST_METHOD in the unit test. These functions used to perform any required initialization and cleanup. At a minimum, the TEST_METHOD_INITIALIZE function must invoke the driver's InitWithOptions function, while the TEST_METHOD_CLEANUP function must call the driver's close function.

  5. Typically, within the TEST_METHOD_INITIALIZE, the g_resourceDesc variable is set to a valid I/O resource descriptor or to a valid logical name configured in the IVI Configuration Store. For purposes of this walkthrough, we need not set the g_resourceDesc, as we will be operating the driver in simulation mode.

    Modify the OptionsString parameter in the call to InitWithOptions to run the driver in simulation mode, as follows:

    C#
    Copy
    auto status = acme4321_InitWithOptions(g_resourceDesc, VI_TRUE, VI_TRUE, "QueryInstrStatus=True, Simulate=True, DriverSetup= ", &g_session);

  6. From the Build menu, choose Build Acme4321CDriverUnitTest.

  7. From the Test Explorer, right-click the ATTR_SWEEPSOURCE node and choose Run Selection.

    The test succeeds because automatically Nimbus generates code for the driver in simulation mode that remembers the last value set and returns that value when queried. This behavior is what most users would expect for IVI-C driver attributes operating in simulation mode. Additionally, this same test works equally well in live mode when communicating with an instrument because the instrument should also be storing the state of each instrument variable and returning that state when queried.

Creating the Help File

Nimbus provides powerful and flexible features for creating driver help files. Help file templates allow complete control over help file styling and content so that custom branding and other styling requirements can easily be incorporated.

One of the most compelling aspects of the Nimbus help editing features is that they provide a single place to enter help content that is used in many places. This greatly simplifies driver documentation management. For instance, the Summary field in the Help Editor is used in all of the following places:

  • Microsoft Help Viewer help content (for use with Visual Studio).

  • The Help 1.0 (.chm) help file (for standalone viewing and viewing in non-Microsoft IDEs).

  • The IVI-C function panel file (.fp)

  • The IVI-C attribute information file (.sub)

To enter help content for a function:

  1. From the IVI-C Designer, select the Configure function.

  2. Click on the Help tab at the bottom of the Item Editor to bring up the Help Editor.

    The Summary tab (listed at the top of the Item Editor) should be the active tab.

  3. Enter the following in the Summary field:

    Configures the device acquisition.

  4. Click on the Remarks tab. This will activate the standard Visual Studio HTML editor. The HTML editor allows use of any arbitrary HTML formatting tags.

    In the HTML editor for the Remarks field, enter the following within the <body> tag that's already been provided:

    XML
    Copy
    <html>
<body>
<p>
    This function configures the device acquisition.  The <i>NumRecords</i>
    parameter controls how many sweeps are performed.
</p>
<p>
    Call the <b>Configure</b> function before invoking the acquisition with the
    <b>Initiate</b> function.
</p>
</body>
</html>
    Important note Important

    Even though the built-in Visual Studio HTML editor is used for editing HTML content, the contents of these fields must be XHTML, which is a stricter form of HTML. Among other things, this means that all HTML tags must be closed just like XML tags are. For example, instead of using <hr> to insert a horizontal separator, you must use <hr/> or <hr></hr>. If any XHTML rules are violated, the driver help previewer will display an error, and the help project will fail to build.

    Help content is required to be XHTML in order to be used by the Microsoft Help Viewer that's used by Visual Studio.

  5. Click on the Preview tab in the Help Editor to instantly view the newly entered help content. The formatted HTML text entered for the Remarks field is rendered just as it will appear in the compiled driver help file.

    Note that Nimbus automatically includes an Instrument Command section on the help page for the function. This feature of driver help files is very useful for end users accustomed to direct SCPI (or other messaging protocol) programming.

  6. The layout and styling of the driver help file is completely customizable via Nimbus Help Templates. Nimbus ships with one pre-built help template that mimics the classic format of MSDN help.

    From Solution Explorer, right-click on the Acme4321Help project and choose Properties. The Template page shows a preview of each type of help page for the currently active help template. You can easily choose another help template from the Available templates combo box.

    See the topic Working with Help Templates for a complete discussion of driver help file customization using templates.

  7. From Solution Explorer, right-click on the Acme4321CDriverHelp project and choose Properties.

    For the purpose of this walkthrough, check the Help 1.x (.chm) help format, but leave the other options cleared. The options on this page are described in detailed here.

  8. From Solution Explorer, right-click on the Acme4321CDriverHelp project and choose Build. While the build is in progress, the Visual Studio Output window will display the progress of the help project build.

  9. Once the build completes, right-click on the Acme4321CDriverHelp project in the Solution Explorer and select View Help 1.x (.chm). This will open the newly built driver help file in the Help 1.x viewer.

  10. In the help viewer, click on the Contents tab and then expand the Getting Started node. Note that several boilerplate help pages have been included in the driver's help file, which are described in more detail here.

  11. Expand the Acme4321 IVI-C Driver node in the help viewer, then Reference, and finally Hierarchy. This is where all of the dynamically generated help for the driver functions and properties will appear.

  12. Click on the Configure node in the help viewer table of content. Note that the help documentation entered for the Configure function appears in the generated help file.

Creating the driver installer

The final task in developing a Nimbus IVI driver is creating the driver installer. The IVI specifications impose a number of detailed requirements for IVI driver installers. Nimbus uses Windows Installer XML (WiX) as the underlying technology for building driver installers. The WiX toolset is in widespread use, expecially within Microsoft where it is used to produce the installers for such large-scale projects as Microsoft Office, Visual Studio, and SQL Server.

WiX installers consist of a series of XML files that get compiled in the Acme4321CDriverSetup project. Nimbus manages the XML files for you as you add functionality to your IVI driver.

Nimbus also provides a powerful and easy-to-use graphical designer for customizing a driver installer, such as for installing example programs or other dependent files outside the control of Nimbus.

To customize the driver installer

  1. From Solution Explorer, expand the Acme4321CDriverSetup project node. Note that several files have already been added to this project:

    • Images\*.*

      This folder contains icon and graphic files that are used by the driver installer.

    • Internal\*.wx?

      This folder contains WiX source files that define the required folder structure required for IVI-C driver installers by the IVI standards, as well as localizable string resources used on driver installer screens.

    • EULA.rtf

      The contents of this license agreement file will be displayed on a driver installer screen when the driver installer is run on end-user machines. You must not remove this file. The EULA.rtf file is essentially empty, providing a place for you to enter the specifics of your driver's end-user license agreement.

    • Readme.txt

      A starter template for a standard IVI-C driver readme file.

    • Setup.wxs

      This WiX source file defines the overall layout of the driver installer, and is the file that's modified by the integrated driver setup designer.

  2. Double click on Setup.wxs in the Solution Explorer to launch the driver setup designer.

  3. The Setup Designer shows the standard IVI folders present on any system with the IVI Shared Components. These standard folders are shown in gray to indicate that they cannot be modified by a driver installer. The Setup Designer also shows the Acme4321 driver folders under which the driver files will be deployed on the target machine.

  4. Navigate to a folder on disk with some files and subfolders and click OK. A dialog box titled Select Files to Add will be displayed. Check and uncheck files to be included in the driver installer as desired. Press OK when you're done.

    Note that the selected folder, its files, and any subfolders and files chosen are now displayed in the Setup Designer tree view. This folder structure will be created on the end-user system by the driver installer.

  5. From the Setup Designer tree view, right-click the Examples folder and choose Add and then select Add Folder...

    The standard Windows Add Folder Dialog appears.

  6. Navigate to a folder on disk with some files and subfolders and click OK.

  7. Return to the Setup.wxs file and note how Nimbus has automatically added the appropriate WiX entries to integrate the selected items with the driver installer.

  8. Right-click on the Acme4321CDriverSetup project and choose Build.

  9. When the build has completed, navigate to the <solutionFolder>\build\debug\x86 directory below the driver solution folder and note that an .msi installer package named Acme4321.msi has been created.

    Caution note Caution

    Never run a driver installer on the same machine on which the driver was compiled. The registry entries associated with the driver could become corrupt. IVI-COM driver installers must ALWAYS be tested on a separate test machine.

Next Steps

This walkthrough has illustrated how to create a simple IVI-C driver, implement, test and document functions and properties. We have also shown how to create and customize an IVI-compliant driver installer. You might want to explore the following topics:

  • Understanding the Nimbus User Interface

  • Adding Functionality to an IVI-C Driver

  • Adding Support for Multiple Instrument Models

  • Implementing Driver Functions and Attributes

  • Developing an IVI-C Driver


Merging Repeated Capabilities

When two repeated capabilities exist in a driver, it may be the case that the two repeated capabilities represent the same physical entity on the device. In such cases, the repeated capabilities may be merged into a single repeated capability.

Consider the case of a driver that supports the IviScope instrument class. The driver will contain a repeated capability called "Channel", since this repeated capability is defined in the IviScope instrument class. If the driver developer adds support for the IviDigitizer instrument class, then Nimbus will create an additional repeated capability called "IviDigitizerChannel", since the IviDigitizer instrument also defines a repeated capability called "Channel". (Nimbus adds the "IviDigitizer" prefix to the repeated capability name to distinguish it from the one defined in the IviScope instrument class.) The result is a driver with two separate repeated capabilities -- one called "Channel", representing the repeated capability defined in IviScope, and another called "IviDigitizerChannel" representing the repeated capability defined in IviDigitizer. In most cases, these represent the same physical channel on the instrument. The Merge command should then be used to combine these two repeated capabilities into one.

When two repeated capabilities are merged, Nimbus does the following:

  1. Moves any methods or properties on the source repeated capability to the target repeated capability. Note that this is only done automatically for collection-style repeated capabilities. Methods and properties on parameter or selector-style repeated capabilities must be manually moved to the target repeated capability before executing the Merge command.

  2. Changes the associated repeated capability of all methods and properties on the source repeated capability to be associated with the target repeated capability.

  3. Deletes the source repeated capability along with any physical names defined on the repeated capability.

Note Note

Only repeated capabilities of the same style can be merged. For instance, you cannot merge a collection-style repeated capability with a parameter-style repeated capability

To merge two repeated capabilities:

  1. From Solution Explorer, double-click on the Driver Settings Editor node to bring up the Driver Settings Editor.

  2. Select the Repeated Capabilities page and right-click on the source repeated capability that you wish to merge. This is the repeated capability that will be deleted.

  3. Select Merge and then choose the target repeated capability.

    Caution note Caution

    This operation will result in the source repeated capability being deleted from the driver, so you will be prompted to confirm that you wish to proceed.

See Also

Other Resources

Repeated Capabilities


IVI-COM Driver Walkthrough

In this walkthrough, you will create a simple IVI-COM driver along with a help file and installer.

This walkthrough will consist of the eight main steps:

  1. Creating the IVI-COM driver project

  2. Adding a method

  3. Implementing a method using the Instrument Command Editor

  4. Adding a property that uses an enumerated type

  5. Compiling the driver

  6. Testing the driver

  7. Creating the help file

  8. Designing an IVI-C wrapper

  9. Creating the driver installer

Creating the IVI-COM Driver Project

We'll create a new driver project called Acme4321. Nimbus is completely integrated with Microsoft Visual Studio, so the process of creating an IVI-COM driver project begins with the same steps required to create any Visual Studio project.

To create the Acme4321 driver

  1. Open Visual Studio.

  2. From the File menu, chooseNew Project.

  3. Select IVI-COM Driver from the list of project types.

  4. In the Name box, enter Acme4321.

  5. Click OK.

    The New IVI-COM Driver Wizard appears.

  6. On the General Page, specify the following:

    • For Instrument manufacturer, enter Acme Corporation.

    • For Driver vendor, enter Pacific MindWorks.

    • For .NET assembly name prefix, enter MindWorks.

    • For Instrument model , enter Acme4321.

  7. On the IVI Instrument Classes Page, leave all instrument classes unchecked.

  8. On the LXI Compliance Page, select the None radio button.

  9. On the Features Page, specify the following:

    • Enable the IVI-C wrapper check box and set the Prefix to acme.

    • Enable the MATLAB wrapper check box.

  10. On the Projects Page, enable only the following:

    • Create IVI-COM help project

    • Create IVI-COM setup project

    • Create IVI-COM unit test

    • Create IVI-C unit test

    Leave the other check boxes unchecked.

  11. Click Finish to create the project.

    The Driver Designer should automatically open. If it does not, then double-click the Driver Designer node in Solution Explorer. The project has been created and you are now ready to add some methods and properties to your Acme4321 driver.

Adding a Method

When you add new functionality to a driver, you organize the methods and properties in a hierarchy, grouping them in interfaces.

To add a Configure method with parameters:

  1. Expand the Acme4321 type library node and then expand the Hierarchy node to reveal the methods and properties already added to your driver by Nimbus.

    All of the methods and properties in the driver at this point are shown greyed out to indicate that they cannot be modified. This is because all of these methods are inherited from the IVI-defined IIviDriver interface.

  2. Right-click on the Hierarchy node and choose Add Method.

    A new method node is added to the hierarchy with a default name, and the node enters edit mode.

  3. Change the method name to Configure.

  4. Right click on the Configure method and choose Add Parameter.

    A new parameter is added to the hierarchy with a default name, and the node enters edit mode.

  5. Change the parameter name to NumRecords and hit Enter.

    Note that the parameter is added with a default data type of Double.

  6. Change the data type of the NumRecords parameter using the Item Editor. This is done by right-clicking on the Type text box and choosing Int32 from the context menu of available types.

  7. Add a second parameter by right-clicking the Configure method again, choosing Add Parameter.

    For the parameter name, enter Enabled and hit Enter. Note that Nimbus automatically infers the desired Boolean parameter type from the name of the parameter.

  8. Finally, we'll add a third parameter and enter both the parameter name and data type by typing directly into the node label while it is in edit mode.

  9. Right-click the Configure method and choose Add Parameter.

  10. Type the name TriggerSource followed by a colon followed by string.

Implementing a Method Using the Instrument Command Editor

Although Nimbus supports developing drivers for any type of instrument -- register-based, message-based, or custom I/O devices, special features are provided that make message-based IVI driver development particularly efficient. Every method or property can be implemented by associating an instrument command with the method or property. Nimbus can be instructed to automatically format the runtime value of method parameters into the instrument command string. The section of the walkthrough will present some of the automatic instrument command formatting features provided by Nimbus.

To implement a method using an instrument command:

  1. From the tree view, select the Configure method under the Hierarchy node.

  2. From the Item Editor, change the Implementation style to be Instrument Command. This enables the Command text box.

  3. In the Command text box, enter the following command:

    ACQ:CONFIG {NumRecords},{Enabled}; TRIG:SOUR {TriggerSource}

    The above command uses parameter tags enclosed in curly braces ({ }) to insert the runtime value of parameters into the command. Notice that when you type a left curly brace ({), Nimbus presents an IntelliSense context menu from which you can select the desired parameter to use in the instrument command.

  4. Each parameter used in the instrument command can be formatted in a variety of ways. The easiest way to specify the formatting of command parameters is to use the Instrument Command Editor. Invoke the Instrument Command Editor by clicking on the editor icon at the far right of the Command text box.

  5. Select the NumRecords parameter in the Parameters listbox. Nimbus provides a variety of numeric formatting options, such hex or binary, variable field width, and right/left justification with optional padding.

    See the topic Using the Instrument Command Editor for detailed information on the various parameter formatting options available.

  6. Next, select the Enabled parameter. The Instrument Command Editor displays a table that allows you to enter an arbitrary string to associate with the two possible values for the boolean parameter -- VARIANT_TRUE and VARIANT_FALSE.

    Enter ON for the value VARIANT_TRUE and OFF for the value VARIANT_FALSE.

  7. Click OK to close the Instrument Command Editor.

  8. Nimbus generates all of the code needed to format the instrument command according to the settings chosen in the Instrument Command Editor. Several commands are available from the IVI-COM Designer to inspect the generated code.

    Right-click on the Configure method and select Go to Forwarding Shim.

  9. Nimbus navigates to the ForwardingShims.nimbus.cpp file. This Nimbus-managed file generates important pre-processing and post-processing code for each method and property in the driver. One of its main tasks is to format the instrument command. For the Configure method, the command formatting is performed by the following section of code in the shim:

    C++
    Copy
    CString strCmd;
hr = CFormattedIo::Printf(strCmd, pT->GetRoot(), _T("ACQ:CONFIG %d,%{VARIANT_BOOL}s; TRIG:SOUR %$Bs"), NumRecords, Enabled, TriggerSource);

    A complete discussion of instrument command formatting is provided in the topic Working With Instrument Commands.

  10. Return to the IVI-COM Designer. Right-click on the Configure method and choose Go to Implementation.

  11. Nimbus navigates to the CoAcme4321.nimbus.cpp. The implementation of the Configure method in this file includes only a call to the InstrPrintCommand function. InstrPrintCommand sends the string formatted in the shim to the device.

  12. The implementation of the Configure method needs to be modified so that it works in simulation mode -- that is, when no device is physically available. (This is important for steps later in this walkthrough.) For this, we must use the Nimbus Template Library function GetSimulate to determine if the driver is operating in simulation mode. If it is, we will simply return from the function so that the InstrPrintCommand function does not attempt to perform any I/O.

    Modify the implementation of Configure to the following:

    C++
    Copy
    HRESULT hr = S_OK;

if (GetSimulate())
    return hr;

hr = InstrPrintCommand();

return hr;
Adding a Property That Uses an Enumerated Type

Enumerated types are commonly used as property types and parameter types. Nimbus provides special support for defining enums and using them in method and property instrument commands.

To define a property that uses an enum:

  1. We start by defining the enum itself. From the IVI-COM Designer, right-click on the Enums node and choose Add Enum.

    A new enum node is added with a default name and the node enters edit mode.

  2. For the name, simply enter TriggerSource and hit Enter.

    This adds an enum named Acme4321TriggerSourceEnum. By convention, enum names in IVI drivers begin with the driver name (Acme4321, in this case) and end with Enum. For convenience, Nimbus allows you to enter just the short name (TriggerSource) for the enum and Nimbus adds the standard enum prefix and suffix.

  3. We need to add three enum members to the Acme4321TriggerSourceEnum. Right-click on the Acme4321TriggerSourceEnum and choose Add Enum Member.

    A new enum member is added to the enum with a default name and the enum member enters edit mode.

  4. Enter Internal for the member name and hit Enter. Notice that Nimbus automatically adds a member with the fully-qualified name Acme4321TriggerSourceInternal.

  5. Right-click again on the Acme4321TriggerSourceEnum and add two more members -- External and Software.

  6. We now need to add a property that uses the new enum. Right-click on the Hierarchy node and select Add Property.

    Enter SweepSource for the property name followed by a colon followed by TriggerSource. This adds a property named SweepSource of type Acme4321TriggerSourceEnum.

  7. With the SweepSource property selected in the tree view, change the Implementation style in the Item Editor to Instrument Command.

  8. For the Setter command, enter the following command that will be sent to the device when the property value is written:

    TRIG:SOUR {value}

    For the Getter command, enter the following query that will be sent to the device when the property value is read:

    TRIG:SOUR?

    The setter command instructs Nimbus to take the value of the property and place it in the command in place of the {value} parameter tag. For reads from the instrument, first the Getter command is sent, and then Nimbus reads from the device and parses the response according to the Getter response specified. For the SweepSource property, leave the Getter response set to {value}, which simply means that the device responds by sending a value that Nimbus will parse into one of the allowed Acme4321TriggerSourceEnum values.

  9. In order to translate the enum values to and from instrument command and respone strings, the Instrument Command Editor is used to map each enum member to a command string.

    Click on the editor icon at the right end of the Setter command text box.

  10. The Instrument Command Editor displays a table with the short name of the three enum members we defined -- Internal, External, and Software.

    In the Instrument Command column of the table, enter the command INT for Internal, EXT for External, and SW for Software.

  11. For the unit tests used later in this walkthrough to work properly, we need to configure the simulation behavior of the SweepSource property.

    With the SweepSource property selected in the tree view, click the Simulation tab in the Item Editor and click the Last value set radio button.

Compiling the Driver

To compile the driver:

  1. The first step in compiling a Nimbus driver is to properly setting the build configuration. This typicall has to be done once the first time a new driver is compiled. However, adding, removing, or even uloading projects from a solution can cause the Configuration Manager settings to get modified.

    Important note Important

    Adding, removing, or unloading projects from a driver solution can modify the Configuration Manager settings. The tasks explained here may need to be performed again after such operations.

  2. From Solution Explorer, right click on the solution and choose Configuration Manager. The Configuration Manager Dialog Box appears.

  3. From the Configuration Manager dialog, choose the x86 platform from the Action solution platform combo box.

  4. Make sure that the Platform column setting and Build column setting for each project is set according to the table below. (Note the list of projects that appears depends upon the driver options chosen.)

    Project

    Platform

    Build

    Acme4321CppConsoleApplication

    Win32

    Checked

    Acme4321CsConsoleApplication

    x86

    Checked

    Acme4321CWrapperConsoleApplication

    Win32

    Checked

    Acme4321CWrapperUnitTest

    Win32

    Checked

    Acme4321Driver

    Win32

    Checked

    Acme4321Help

    Any CPU

    Unchecked

    Acme4321Setup

    x86

    Unchecked

    Acme4321UnitTest

    x86

    Checked

  5. Make sure x86 is selected in the Solution Platforms combo box.

    Also make sure Debug is selected in the Solution Configurations combo box.

  6. From the Build menu, select Build Solution.

    This will perform a 32-bit compilation of the driver project, the unit test projects, and the client application projects. It will also generate the MATLAB® wrapper.

    For the Debug build we performed in this step, the output files will be placed in the following folder:

    • <solutionFolder>\build\Debug\x86

  7. The driver is now ready to use in an application. The build process registers the driver with the IVI Configuration Store. You can use a 3rd-party IVI browsers, such as Measurement Automation Explorer® (MAX) from National Instruments®.

Testing the Driver

With the driver compiled and ready to use, the next task is to use the Visual Studio integrated unit testing tools.

To run the driver unit tests

  1. From the Test menu, choose Windows and then select Test View.

  2. The Test View window appears docked with Solution Explorer. Change the Group By combo box to Class Name. This will show all of the test classes for the IVI-COM driver. One test class is created for each interface implemented by the IVI-COM driver.

  3. Expand the test class node for the IAcme4321Test class, right-click on the SweepSource property and choose Open Test.

  4. Visual Studio navigates to the C# unit test method for the SweepSource property. The test code for this method sets the value of the property, reads back the value in the instrument, and then compares the value set to the value read to ensure that the property worked. It repeats this sequence for each of the three members of the Acme4321TriggerSourceEnum.

  5. Go to the top of the IAcme4321Test test class. Right-click on the BaseTest base class and click Go To Definition.

    The definition of the BaseTest class is opened. This class is the base class for all test classes in the unit test project. It serves a very important purpose -- it houses the _Init and _Close methods. The _Init method is executed before each test method. Correspondingly, the _Close is executed after each test method.

    These methods are used to perform any required initialization and cleanup. At a minimum, the _Init method must invoke the driver's Initialize method, while the _Close method must call the driver's Close method.

  6. Typically, within the _Init, the logicalName variable is set to a valid I/O resource descriptor or to a valid logical name configured in the IVI Configuration Store. For purposes of this walkthrough, we need not set the logicalName, as we will be operating the driver in simulation mode.

    Modify the driverSetup variable to run the driver in simulation mode, as follows:

    C#
    Copy
    driverSetup = "Simulate=True";

  7. From the Build menu, choose Build Acme4321UnitTest.

  8. From the Driver Test View, right-click the Acme4321UnitTest node and choose Run Selection.

    The Driver Results View opens in the lower portion of the IDE and shows the status of the unit test methods as they execute. Nimbus generates working code for all of the IVI inherent capabilities.

Creating the Help File

Nimbus provides powerful and flexible features for creating driver help files. Help file templates allow complete control over help file styling and content so that custom branding and other styling requirements can easily be incorporated.

One of the most compelling aspects of the Nimbus help editing features is that they provide a single place to enter help content that is used in many places. This greatly simplifies driver documentation management. For instance, the Summary field in the Help Editor is used in all of the following places:

  • The .NET interop assembly help (for IntelliSense support in .NET languages, such as C# and Visual Basic.NET).

  • Microsoft Help Viewer help content (for use with the Visual Studio).

  • The Help 1.0 (.chm) help file (for standalone viewing and viewing in non-Microsoft IDEs).

  • The COM type library (for COM-aware environments, such as Visual Basic 6 and many others).

  • The MATLAB wrapper files.

To enter help content for a method:

  1. From the IVI-COM Designer, select the Configure method.

  2. Click on the Help tab at the bottom of the Item Editor to bring up the Help Editor.

    The Summary tab (listed at the top of the Item Editor) should be the active tab.

  3. Enter the following in the Summary field:

    Configures the device acquisition.

  4. Click on the Remarks tab. This will activate the standard Visual Studio HTML editor. The HTML editor allows use of any arbitrary HTML formatting tags.

    In the HTML editor for the Remarks field, enter the following within the <body> tag that's already been provided:

    XML
    Copy
    <html>
<body>
<p>
    This method configures the device acquisition.  The <i>NumRecords</i>
    parameter controls how many sweeps are performed.
</p>
<p>
    Call the <b>Configure</b> method before invoking the acquisition with the
    <b>Initiate</b> method.
</p>
</body>
</html>
    Important note Important

    Even though the built-in Visual Studio HTML editor is used for editing HTML content, the contents of these fields must be XHTML, which is a stricter form of HTML. Among other things, this means that all HTML tags must be closed just like XML tags are. For example, instead of using <hr> to insert a horizontal separator, you must use <hr/> or <hr></hr>. If any XHTML rules are violated, the driver help previewer will display an error, and the help project will fail to build.

    Help content is required to be XHTML in order to be used by the Microsoft Help Viewer that's used by Visual Studio.

  5. Click on the Preview tab in the Help Editor to instantly view the newly entered help content. The formatted HTML text entered for the Remarks field is rendered just as it will appear in the compiled driver help file.

    Note that Nimbus automatically includes an Instrument Command section on the help page for the method. This feature of driver help files is very useful for end users accustomed to direct SCPI (or other messaging protocol) programming.

  6. The layout and styling of the driver help file is completely customizable via Nimbus Help Templates. Nimbus ships with one pre-built help template that mimics the classic format of MSDN help.

    From Solution Explorer, right-click on the Acme4321Help project and choose Properties. The Template page shows a preview of each type of help page for the currently active help template. You can easily choose another help template from the Available templates combo box.

    See the topic Working with Help Templates for a complete discussion of driver help file customization using templates.

  7. From Solution Explorer, right-click on the Acme4321Help project and choose Properties.

    For the purpose of this walkthrough, check the Help 1.x (.chm) help format, but leave the other options cleared. The options on this page are described in detailed here.

  8. From Solution Explorer, right-click on the Acme4321Help project and choose Build. While the build is in progress, the Visual Studio Output window will display the progress of the help project build.

  9. Once the build completes, right-click on the Acme4321Help project in the Solution Explorer and select View Help 1.x (.chm). This will open the newly built driver help file in the Help 1.x viewer.

  10. In the help viewer, click on the Contents tab and then expand the Getting Started node. Note that several boilerplate help pages have been included in the driver's help file, which are described in more detail here.

  11. Expand the Acme4321 IVI-COM Driver node in the help viewer, then Reference, Driver Hierarchy, and finally IAcme4321. This is where all the dynamically generated help for the main driver interface's methods, properties and events will appear.

  12. Click on the Configure node in the help viewer table of content. Note that the help documentation entered for the Configure method appears in the generated help file.

Designing an IVI-C wrapper

One of the most powerful features of Nimbus is the ability to develop a fully compliant IVI-C driver using the same code base as the IVI-COM driver. This greatly simplifies driver development and maintenance.

To develop an IVI-C wrapper:

  1. From Solution Explorer, double-click the Driver Settings Editor node.

    The Driver Settings Editor appears.

  2. Select the IVI-C tab and make sure that IVI-C wrapper generation is enabled. If not, click the Add button to enable it.

  3. Nimbus automatically generates and manages the required IVI-C files -- specifically, the header file (.h), the function panel file (.fp), and the attribute information file (.sub). These files can be examined in the Acme4321Driver folder on disk. If you have LabWindows/CVI installed, you can double-click the .fp file to view the function panels generated for the driver.

  4. With IVI-C wrapper generation enabled, the IVI-C tab in the Driver Designer now becomes available. Select the IVI-C tab to view the hierarchy of IVI-C functions and attributes that correspond to the IVI-COM methods and properties in the driver.

  5. In the tree view of the IVI-C tab, expand the Acme4321 node to locate the Configure function. Note the Info Panel displays the IVI-COM Configure method associated with the IVI-C function.

    Click on the IVI-COM Configure method in the Info Panel to quickly navigate to the IVI-COM view.

  6. IVI-C functions and attributes are automatically maintained in terms of IVI-COM methods and properties. When a new IVI-COM method is added to the driver, a corresponding IVI-C function is automatically added with the proper IVI-C types and parameters. Similarly, when an IVI-COM property is added, a new IVI-C attribute is created and associated with the property.

    From the IVI-COM Configure method, right-click and choose Rename. Enter ConfigureAcquisition as the new method name.

    Right-click on the ConfigureAcquisition method and select Go to IVI-C Function. Note that the IVI-C function has also been renamed to ConfigureAcquisition so that it remains "in-sync" with the IVI-COM method.

  7. From the IVI-C tab, right-click on the ConfigureAcquisition function and click Go to Implementation.

    Nimbus opens the auto-generated Acme4321.nimbus.cpp file and navigates to the implementation of the ConfigureAcquisition function. Notice how Nimbus automatically generates all of the necessary code to invoke the underlying IVI-COM method -- converting IVI-C parameters to their IVI-COM counterparts and even translating errors in the IVI-COM driver to IVI-C format via the TranslateHRESULT function.

    Nimbus also offers the ability to disable the auto-generated implementation of any IVI-C function or attribute. By selecting the Manual radio button in the IVI-C Item Editor Nimbus will add an empty stub implementation of an IVI-C function or attribute to a user-managed Acme4321.cpp file. This allows complete control of the IVI-C implementation.

Creating the Driver Installer

The final task in developing a Nimbus IVI driver is creating the driver installer. The IVI specifications impose a number of detailed requirements for IVI driver installers. Nimbus uses Windows Installer XML (WiX) as the underlying technology for building driver installers. The WiX toolset is in widespread use, expecially within Microsoft where it is used to produce the installers for such large-scale projects as Microsoft Office, Visual Studio, and SQL Server.

WiX installers consist of a series of XML files that get compiled in the Acme4321Setup project. Nimbus manages the XML files for you as you add functionality to your IVI driver. For instance, as new interfaces and repeated capabilities are added to the driver, Nimbus automatically updates the WiX source XML files to include new registry entries for the COM interfaces and classes.

Nimbus also provides a powerful and easy-to-use graphical designer for customizing a driver installer, such as for installing example programs or other dependent files outside the control of Nimbus.

To customize the driver installer

  1. From Solution Explorer, expand the Acme4321Setup project node. Note that several files have already been added to this project:

    • Images\*.*

      This folder contains icon and graphic files that are used by the driver installer.

    • Internal\*.wx?

      This folder contains WiX source files that define the required folder structure required for IVI-COM driver installers by the IVI standards, as well as localizable string resources used on driver installer screens.

    • EULA.rtf

      The contents of this license agreement file will be displayed on a driver installer screen when the driver installer is run on end-user machines. You must not remove this file. The EULA.rtf file is essentially empty, providing a place for you to enter the specifics of your driver's end-user license agreement.

    • Readme.txt

      A starter template for a standard IVI-COM driver readme file.

    • Setup.wxs

      This WiX source file defines the overall layout of the driver installer, and is the file that's modified by the integrated driver setup designer.

  2. Double click on Setup.wxs in the Solution Explorer to launch the driver setup designer.

  3. The Setup Designer shows the standard IVI folders present on any system with the IVI Shared Components. These standard folders are shown in gray to indicate that they cannot be modified by a driver installer. The Setup Designer also shows the Acme4321 driver folders under which the driver files will be deployed on the target machine.

  4. Navigate to a folder on disk with some files and subfolders and click OK. A dialog box titled Select Files to Add will be displayed. Check and uncheck files to be included in the driver installer as desired. Press OK when you're done.

    Note that the selected folder, its files, and any subfolders and files chosen are now displayed in the Setup Designer tree view. This folder structure will be created on the end-user system by the driver installer.

  5. From the Setup Designer tree view, right-click the Examples folder and choose Add and then select Add Folder...

    The standard Windows Add Folder Dialog appears.

  6. Navigate to a folder on disk with some files and subfolders and click OK.

  7. Return to the Setup.wxs file and note how Nimbus has automatically added the appropriate WiX entries to integrate the selected items with the driver installer.

  8. Right-click on the Acme4321Setup project and choose Build.

  9. When the build has completed, navigate to the <solutionFolder>\build\Debug\x86 directory below the driver solution folder and note that an .msi installer package named Acme4321Setup.msi has been created.

    Caution note Caution

    Never run a driver installer on the same machine on which the driver was compiled. The registry entries associated with the driver could become corrupt. IVI-COM driver installers must ALWAYS be tested on a separate test machine.

Next Steps

This walkthrough has illustrated how to create a simple IVI-COM driver, implement, test and document methods and properties. We have also shown how to create and customize an IVI-compliant driver installer. You might want to explore the following topics:

  • Understanding the Nimbus User Interface

  • Adding Functionality to an IVI-COM Driver

  • Adding Support for Multiple Instrument Models

  • Implementing an IVI-COM Driver

  • Developing an IVI-C Driver

  • Creating a MATLAB Wrapper


IVI.NET Driver Walkthrough

In this walkthrough, you will create a simple IVI.NET driver along with a help file and installer.

This walkthrough will consist of the following nine main steps:

  1. Creating the IVI.NET driver project

  2. Defining an enumerated type

  3. Adding a method

  4. Implementing a method using the Instrument Command Editor

  5. Adding a property that uses an enumerated type

  6. Building the driver

  7. Testing the driver

  8. Creating the help file

  9. Creating the driver installer

Creating the IVI.NET Driver Project

We'll create a new driver project called Acme4321. Nimbus is completely integrated with Microsoft Visual Studio, so the process of creating an IVI.NET driver project begins with the same steps required to create any Visual Studio project.

To create the Acme4321 driver

  1. Open Visual Studio.

  2. From the File menu, chooseNew Project.

  3. Select IVI.NET Projects from the list of installed project templates shown on the left.

  4. Select IVI.NET Driver from the list of project types shown on the right.

  5. In the Name box, enter Acme4321.

  6. Click Next.

    The IVI.NET Driver Wizard appears.

  7. On the General Page, specify the following:

    • For Instrument manufacturer, enter Acme Corporation.

    • For Driver vendor, enter Pacific MindWorks.

    • For .NET assembly name prefix, enter Acme.

    • For Instrument model , enter Acme4321.

  8. Press Next.

  9. On the IVI Instrument Classes Page, leave all instrument classes unchecked.

  10. Press Next.

  11. On the LXI Compliance Page, select the None radio button.

  12. Press Next.

  13. On the Projects Page, check each of the available project types except Create IVI.NET Visual Basic console application.

  14. Click Finish to create the project.

    The Visual Studio Solution Explorer will automatically open, showing each of the following projects:

    • Acme4321

      This is the Nimbus Project, which manages each of the other related projects in the solution for this driver.

    • Acme4321CsConsoleApplication

      A sample C# console application that can be used to exercise the driver, or be released as sample code.

    • Acme4321Driver

      The standard C# class library assembly project that will contain all of the code for this driver.

    • Acme4321Help

      The driver help project that will build the help file(s) for this driver.

    • Acme4321Setup

      The driver setup project that you'll use to customize and build the installer for the driver.

    • Acme4321UnitTest

      The standard Visual Studio unit test project that will be used to test the driver.

  15. In the Solution Explorer, double click the Driver Designer node that's displayed under the Acme4321Nimbus Project.

    The Nimbus driver designer appears.

Defining an Enumerated Type

Enumerated types are commonly used as property types and parameter types. Nimbus provides special support for defining enums and using them in method and property instrument commands.

To define an enum:

  1. Expand the Acme.Acme4321 assembly node in the driver designer. This will reveal the following child nodes:

    • Hierarchy

      This is the main designer node under which most of the driver modifications described below will be performed.

    • Interfaces

      This node lists the interfaces defined in the driver assembly.

    • Classes

      This node lists the classes defined in the driver assembly.

    • Structs

      This node lists the structures defined in the driver assembly.

    • Delegates

      This node lists the delegates defined in the driver assembly.

    • Enums

      This node lists the enumeration types defined in the driver assembly. You'll be using this momentarily to define a custom enum.

    • Exceptions

      This node lists the exception classes defined in the driver assembly.

  2. Right-click on the Enums node and choose Add Enum.

    A new enum node is added with a default name and the node enters edit mode.

  3. For the name, simply enter TriggerSource and hit Enter.

  4. We need to add three enum members to the TriggerSource. Right-click on the TriggerSource and choose Add Enum Member.

    A new enum member is added to the enum with a default name and the enum member enters edit mode.

  5. Enter Internal for the member name and hit Enter. This will complete the addition of the new enum member, and display the Enum Member Editor.

  6. Enter INT for the Command value shown in the Enum Member Editor. This value will be used by Nimbus if whenever automatic instrument command formatting is leveraged by the driver developer.

  7. Right-click again on the TriggerSource and add an enum member named External. Set its instrument Command value to EXT.

  8. Finally, add an enum member named Software. Set its instrument Command value to SW.

Adding a Method

When you add new functionality to a driver, you organize the methods and properties in a hierarchy, which corresponds to interfaces that Nimbus will create and manage.

To add a Configure method with parameters:

  1. Expand the Hierarchy node in the driver designer to reveal the methods and properties already added to your driver by Nimbus when the driver solution was created.

    Methods and properties shown greyed out indicate that they cannot be modified. This is because those methods and properties are inherited from the IVI-defined IIviDriver interface.

  2. Right-click on the Hierarchy node and choose Add Method.

    A new method node is added to the hierarchy with a default name, and the node enters edit mode.

  3. Enter the following as the name and signature of the new method and then press the Enter key:

    Configure(int numRecords, bool enabled)

  4. Expand the newly created Configure node and notice that Nimbus automatically created both the numRecords and enabled parameters requested above.

  5. Right-click on the Configure method node and select Add Parameter.

    A new parameter node is added to the Configure method with a default name, and the node enters edit mode.

  6. Enter the following as the name and signature of the new parameter and then press the Enter key:

    source : TriggerSource

    If you are prompted to resolve the ambiguity between two different TriggerSource types, pick the instrument-specific one -- the one defined in the Acme4321 assembly.

    Note Note

    The source parameter could have been added at the same time as the numRecords and enabled parameters when the Configure method was initially created. It was only added as a separate step here in order to demonstrate the Add Parameter command.

    Existing parameter names (and their types) can also be changed by clicking on a parameter node in the driver designer, and then using the parameter item editor on the right to rename the parameter or change its type.

Implementing a Method Using the Instrument Command Editor

Although Nimbus supports developing drivers for any type of instrument -- register-based, message-based, or custom I/O devices, special features are provided that make message-based IVI.NET driver development particularly efficient. Every method or property can be implemented by associating an instrument command with the method or property. Nimbus can be instructed to automatically format the runtime value of method parameters into the instrument command string. This section of the walkthrough will present some of the automatic instrument command formatting features provided by Nimbus.

To implement a method using an instrument command:

  1. Select the Configure method node in the IVI.NET Driver Designer.

  2. From the Item Editor, change the Implementation style to be Instrument Command. This enables the Command text box.

  3. In the Command text box, enter the following command (although you could copy/paste this command, don't do so at this time so that a feature of this editor can be demonstrated):

    ACQ:CONFIG {numRecords},{enabled}; TRIG:SOUR {source}

    The above command uses parameter tags enclosed in curly braces ({ }) to insert the runtime value of parameters into the command. Notice that when you type a left curly brace ({), Nimbus presents an IntelliSense context menu from which you can select the desired parameter to use in the instrument command.

  4. Right-click on the Configure method node and select Go to Implementation.

    Nimbus will open the source file containing the method's implementation (Acme4321.cs), and then navigate to the location within that source file where that method resides. It should look as shown below:

    C#
    Copy
    [DriverMethod]
public void Configure(int numRecords, bool enabled, TriggerSource source)
{
    if (this.Session.InitOptions.SimulationEnabled)
    {
        throw new NotImplementedException();  // TODO
    }

    this.IO.FormattedIO.PrintfAndFlush("ACQ:CONFIG %d,%s; TRIG:SOUR %s", numRecords, enabled, source);
}

  5. The implementation of the Configure method needs to be modified so that it works in simulation mode -- that is, when no device is physically available. (This is important for steps later in this walkthrough.) The driver designer has already generated the code necessary to test the SimulationEnabled property, which will return true if the driver is being used in simulation mode. But the designer has left the remainder of the simulation-mode implementation for the developer to complete. Since the designer doesn't know what's appropriate, it always generates code to raise a NotImplementedException exception. All we need to do is replace the boilerplate code with something more appropriate.

    Delete the TODO comment and replace the throw new NotImplementedException(); statement with a simple return; statement. These changes allow the Configure method to operate when the driver is used in simulation mode.

    The Configure method should now look as follows:

    C#
    Copy
    [DriverMethod]
public void Configure(int numRecords, bool enabled, TriggerSource source)
{
    if (this.Session.InitOptions.SimulationEnabled)
    {
        return;
    }

    this.IO.FormattedIO.PrintfAndFlush("ACQ:CONFIG %d,%s; TRIG:SOUR %s", numRecords, enabled, source);
}

  6. Each parameter used in the instrument command is formatted according to its data type and Nimbus configuration options. Note that the numRecords parameter will be formatted using the %d format specifier, while both the enabled and source parameters will be formatted using the %s format specifier.

  7. Because the source parameter is an enumerated type (TriggerSource), the Command values previously configured for each of its three enum members will be sent to the instrument based on the value of the source parameter. For example, if the source parameter value is TriggerSource.External, the instrument command value will be TRIG:SOUR EXT.

    The formatting used for numeric and boolean values is configured at the Nimbus project level.

    Right click on the Acme4321 project in the Solution Explorer and select Driver Settings Editor. This will display the IVI.NET Driver Settings.

  8. Click on the I/O tab. This will display the instrument command formatting editor.

  9. Note that format specifiers for integer and floating point data types have been provided (%d and %0.15g, respectively). Also note that the default values to use for booleans have been provided (1 and 0 for true and false, respectively).

    Change the Boolean True field from 1 to ON.

    Change the Boolean False field from 0 to OFF.

    Note Note

    The boolean values fields can contain a comma-separated list of values to use, for example ON,1,ENABLED and OFF,0,DISABLED. When more than one value is present, the first value will be used by Nimbus when formatting boolean values to be sent to an instrument. When Nimbus is parsing responses coming back from an instrument, any of the values expressed will be used to convert instrument responses into boolean values.

    Additional information on instrument command formatting can be found here.

Adding a Property That Uses an Enumerated Type

Enumerated types are commonly used as property types as well as for parameter types.

To define a property that uses an enum:

  1. We've already defined the TriggerSource enum type, so to define a property that uses that type, simply right-click on the Hierarchy node in the driver designer, and select Add Property.

    Enter the following and then press the Enter key:

    SweepSource : TriggerSource

    The General tab of the property item editor will appear to the right.

  2. With the SweepSource property selected in the tree view, change the Implementation style in the Item Editor to Instrument Command.

  3. For the Setter command, enter the following command that will be sent to the device when the property value is written:

    TRIG:SOUR {value}

    For the Getter command, enter the following query that will be sent to the device when the property value is read:

    TRIG:SOUR?

    The setter command instructs Nimbus to take the value of the property and place it in the command in place of the {value} parameter tag. For reads from the instrument, first the Getter command is sent, and then Nimbus reads from the device and parses the response according to the Getter response specified. For the SweepSource property, leave the Getter response set to {value}, which simply means that the device responds by sending a value that Nimbus will parse into one of the allowed TriggerSource values.

  4. Right click on the newly created SweepSource property node in the driver designer and select Go to Implementation. Nimbus should navigate you to the implementation of the new SweepSource property, which should look as follows:

    C#
    Copy
    [DriverProperty]
[Simulation(SimulationMode.LastValue, Default = "Internal")]
public TriggerSource SweepSource
{
    get
    {
        this.IO.FormattedIO.PrintfAndFlush("TRIG:SOUR?");
        Acme.Acme4321.TriggerSource value;
        this.IO.FormattedIO.Scanf("%s", out value);

        return value;
    }
    set
    {
        this.IO.FormattedIO.PrintfAndFlush("TRIG:SOUR %s", value);
    }
}

    Node that, unlike it did for the Configure method, the Nimbus driver designer did not generate any boilerplate code that needs to be replaced before using this property. The implementation of both the property getter and setter is completely filled in and requires no further updates.

    Furthermore, simulation support has been enabled by default via the use of the SimulationAttribute attribute. This is accomplished automatically by the Nimbuscode weaver, which is discussed in detail here.

Building the Driver

To build the driver:

  1. The first step in compiling a Nimbus driver is properly setting the build configuration. This only has to be done once the first time a new driver project is created, and is described in more detail here.

  2. From Solution Explorer, right click on the solution and choose Configuration Manager. The Configuration Manager Dialog Box appears.

  3. From the Active solution platform combo box, choose <Edit...>. The Edit Solution Platforms dialog box appears.

  4. The following shows the list of platforms will be listed:

    • Any CPU

    • Mixed Platforms

    • x64

    • x86

  5. Remove all platforms except for Mixed Platforms.

  6. Close the Edit Solution Platforms dialog.

  7. Back in the Configuration Manager dialog, make sure that the Platform column setting and Build column setting for each project is set according to the table below.

    Project

    Platform

    Build

    Acme4321CsConsoleApplication

    x86

    Checked

    Acme4321Driver

    Any CPU

    Checked

    Acme4321Help

    Any CPU

    Unchecked

    Acme4321Setup

    x86

    Unchecked

    Acme4321UnitTest

    Any CPU

    Checked

  8. After making the above changes to both the Debug and Release configurations, close the Configuration Manager dialog.

  9. Make sure Mixed Platforms is selected in the Solution Platforms combo box.

    Also make sure Debug is selected in the Solution Configurations combo box.

  10. From the Build menu, select Build Solution. You can also initiate the build by right-clicking on the Solution node in the Solution Explorer and choosing Build Solution.

  11. The driver is now ready to use in an application. The build process automatically registers the driver with the IVI Configuration Store. You can use a 3rd-party IVI browser, such as Measurement Automation Explorer® (MAX) from National Instruments® to view the IVI Configuration Store.

Testing the Driver

Nimbus-generated driver unit test projects integrate directly into Visual Studio's unit testing environment. As you use the Nimbus driver designer, Nimbus creates, deletes and updates unit test methods for each driver method, property and event, which can then be executed using Visual Studio's unit testing framework.

To run the driver unit tests

  1. From the Visual Studio Test menu, choose Windows and then select Test View.

  2. The Test View window appears docked within Solution Explorer, and will display all of the unit test methods Nimbus has already created for the driver.

    Pull down the Group By combo box within the Test View and select Class Name. This will organize the unit test methods according to the unit test classes in which those test methods are defined. Nimbus creates one unit test class per interface defined within the driver project. The following unit test classes should be visible:

    • IAcme4321Test

    • IIviDriverIdentityTest

    • IIviDriverOperationTest

    • IIviDriverTest

    • IIviDriverUtilityTest

  3. Expand the test class node for the IAcme4321Test class, right-click on the SweepSource property and choose Open Test.

  4. Nimbus navigates to the C# unit test method for the SweepSource property. The test code for this method sets the value of the property, reads back the value in the instrument, and then compares the value set to the value read to ensure that the property worked. It repeats this sequence for each of the three members of the TriggerSource.

    Also note that the unit test method has a [TestMethod] attribute applied. This is a standard Visual Studio attribute that Nimbus uses to mark this method as a unit test method for the Visual Studio unit testing engine.

  5. Go to the top of the IAcme4321Test test class source file.

    Notice that the following two methods are defined: _Init, and _Close. The _Init method has a [TestInitialize] attribute applied, and the _Close method has a [TestCleanup] attribute applied. Those attributes are standard Visual Studio attributes that instruct the Visual Studio unit test engine to invoke those methods before and after each unit test method is executed.

    The _Init and _Close methods do most of their work by delegating to the implementation of implementation inherited from their base class, BaseTest.

  6. Right-click on the BaseTest base class and click Go To Definition. This will take you to the core implementation of the _Init and _Close methods.

  7. Typically, within the _Init, the logicalName variable is set to a valid I/O resource descriptor or to a valid logical name configured in the IVI Configuration Store. For purposes of this walkthrough, we can leave the value of the logicalName as it was set when Nimbus created the unit test project (Acme4321UnitTest), as we will be operating the driver in simulation mode.

    Modify the initOptions variable to run the driver in simulation mode by changing the value of the Simulate operation to True, as shown below:

    C#
    Copy
    var initOptions = "QueryInstrStatus=True, Simulate=True, DriverSetup= ";

  8. From the Build menu, choose Build Acme4321UnitTest.

  9. From the Test View, right-click the IAcme4321UnitTest node and choose Run Selection.

    The Test Results View opens in the lower portion of the Visual Studio IDE, and shows the status of the unit test methods as they execute. Verify that the SweepSource and Configure_Int32_Boolean_TriggerSource unit tests passed.

  10. Return to the Test View and select all 5 unit test classes. Right-click on any one of them and choose Run Selection. This will execute the entire suite of unit test methods that Nimbus has generated for the driver, which includes working code for all of the IVI inherent capabilities.

    You should expect the Test Results window to list the following 3 unit test methods as having failed. The Error Message column next to each should indicate that each test failed because the test is not implemented.

    • Warning

    • InterchangeCheckWarning

    • Coercion

  11. Right-click on the Warning test in the Test Results view and select Open Test. This will take you to the location of the Nimbus-generated unit test method for the Warning event defined on the IVI.NET-defined IIviDriverOperation interface.

    Because Nimbus doesn't know how to appropriately implement a unit test for the Warning event, it generates the following boilerplate implementation:

    C#
    Copy
    [TestMethod]
public void Warning()
{
    Assert.Fail("Test not implemented.");
}

    Note that the Coercion and InterchangeCheckWarning unit test methods are similarly implemented.

  12. For the purposes of this walkthrough, simply delete the call to Assert.Fail from the Warning, Coercion and InterchangeCheckWarning unit test methods. Each of those unit test methods should now be empty.

  13. In the Test Results view, click the Run button. Because you've made a change to the unit test source code, Visual Studio will automatically rebuild the unit test project, and then execute just the 3 unit test methods that failed. They should now pass.

Creating the Help File

Nimbus provides powerful and flexible features for creating driver help files. Help file templates allow complete control over help file styling and content so that custom branding and other styling requirements can easily be incorporated.

One of the most compelling aspects of the Nimbus help editing features is that they provide a single place to enter help content that is used in many places. This greatly simplifies driver documentation management. For instance, the Summary field in the Help Editor is used in all of the following places:

  • Autmatically generated XML documentation files for IntelliSense support in .NET languages, such as C# and Visual Basic.

  • Microsoft Help Viewer help content (for use with the Visual Studio).

  • The Help 1.0 (.chm) help file (for standalone viewing and viewing in non-Microsoft IDEs).

To enter help content for a method:

  1. From the IVI.NET Driver Designer, select the Configure method.

  2. Click on the Help tab at the bottom of the Item Editor to bring up the Help Editor.

    The Summary tab (listed at the top of the Item Editor) should be the active tab.

  3. Enter the following in the Summary field:

    Configures the device acquisition.

  4. Click on the Remarks tab. This will activate the standard Visual Studio HTML editor. The HTML editor allows use of any arbitrary HTML formatting tags.

    In the HTML editor for the Remarks field, enter the following within the <body> tag that's already been provided:

    XML
    Copy
    <p>
    This method configures the device acquisition.
</p>
<p>
    Call the <b>Configure</b> method before invoking the acquisition with the <b>Initiate</b> method.
</p>
    Important note Important

    Even though the built-in Visual Studio HTML editor is used for editing HTML content, the contents of these fields must be XHTML, which is a stricter form of HTML. Among other things, this means that all HTML tags must be closed just like XML tags are. For example, instead of using <hr> to insert a horizontal separator, you must use <hr/> or <hr></hr>. If any XHTML rules are violated, the driver help previewer will display an error, and the help project will fail to build.

    Help content is required to be XHTML in order to be used by the Microsoft Help Viewer that's used by Visual Studio.

  5. Click on the Preview tab in the Help Editor to instantly view the newly entered help content. The formatted HTML text entered for the Remarks field is rendered just as it will appear in the compiled driver help file.

    Note that Nimbus automatically includes an Instrument Command section on the help page for the method. This feature of driver help files is very useful for end users accustomed to direct SCPI (or other messaging protocol) programming.

  6. The layout and styling of the driver help file is completely customizable via Nimbus Help Templates. Nimbus ships with one pre-built help template that mimic the standard help format of Visual Studio.

    From Solution Explorer, right-click on the Acme4321Help project and choose Properties. The Template page shows a preview of each type of help page for the currently active help template. You can easily choose another help template from the Available templates combo box.

    See the topic Working with Help Templates for a complete discussion of driver help file customization using templates.

  7. Finish documenting the Configure method by providing help documentation for its three parameters:

    1. Click on the numRecords parameter node below the Configure method node in the driver designer.

    2. Click on the Help tab in the Item Editor.

    3. Enter the following into the Summary tab:

      The number of sweeps to perform.

    4. Repeat the above steps to enter documentation for the enabled and source parameters to the Configure method. Enter arbitrary Summary information for each.

  8. From Solution Explorer, right-click on the Acme4321Help project and choose Properties.

    For the purpose of this walkthrough, check the Help 1.x (.chm) help format, but leave the other options cleared. The options on this page are described in detailed here.

  9. From Solution Explorer, right-click on the Acme4321Help project and choose Build. While the build is in progress, the Visual Studio Output window will display the progress of the help project build.

  10. Once the build completes, right-click on the Acme4321Help project in the Solution Explorer and select View Help 1.x (.chm). This will open the newly built driver help file in the Help 1.x viewer.

  11. In the help viewer, click on the Contents tab and then expand the Getting Started node. Note that several boilerplate help pages have been included in the driver's help file, which are described in more detail here.

  12. Expand the Acme4321 IVI.NET Driver node in the help viewer, then Reference, Driver Hierarchy, and finally IAcme4321. This is where all the dynamically generated help for the main driver interface's methods, properties and events will appear.

  13. Click on the Configure node in the help viewer table of content. Note that the help documentation entered for the Configure method and its parameters using the driver designer appears in the generated help file.

Creating the Driver Installer

The final task in developing a Nimbus IVI.NET driver is creating the driver installer. The IVI.NET specifications impose a number of detailed requirements for IVI driver installers. Nimbus uses Windows Installer XML (WiX) as the underlying technology for building driver installers. The WiX toolset is in widespread use, expecially within Microsoft where it is used to produce the installers for such large-scale projects as Microsoft Office, Visual Studio, and SQL Server.

WiX installers consist of a series of XML files that get compiled in the Acme4321Setup project. Nimbus manages the XML files for you as you add functionality to your IVI.NET driver. For instance, when you use the help project properties to enable or disable different help formats, the Nimbus-generated driver setup project will automatically update the WiX source XML files to reflect set of help files and shortcuts that should be installed on end-user systems by the driver installer.

Nimbus also provides a powerful and easy-to-use graphical designer for customizing a driver installer, such as for installing example programs or other dependent files outside the control of Nimbus.

To customize the driver installer

  1. From Solution Explorer, expand the Acme4321Setup project node. Note that several files have already been added to this project:

    • Images\*.*

      This folder contains icon and graphic files that are used by the driver installer.

    • Internal\*.wx?

      This folder contains WiX source files that define the required folder structure required for IVI.NET driver installers by the IVI.NET standards, as well as localizable string resources used on driver installer screens.

    • DriverEULA.rtf

      The contents of this license agreement file will be displayed on the driver installer screen when the driver installer is run on end-user machines. You must not remove this file, as the installer source code directly references it. It is is essentially empty, providing a place for you to enter the specifics of your driver's end-user license agreement.

    • Readme.txt

      A starter template for a standard IVI.NET driver readme file.

    • Setup.wxs

      This WiX source file defines the overall layout of the driver installer, and is the file that's modified by the integrated driver setup designer.

  2. Double click on Setup.wxs in the Solution Explorer to launch the driver setup designer.

  3. The Setup Designer shows the standard IVI.NET folders present on any system with the IVI Shared Components. IVI.NET standard folders that cannot be modified by the driver installer are shown in gray. The Setup Designer also shows the Acme4321 driver folders under which the driver files will be deployed on the target machine.

  4. From the Setup Designer tree view, right-click the Examples folder and choose Add and then select Add Folder...

    The standard Windows Add Folder Dialog appears.

  5. Navigate to a folder on disk with some files and subfolders and click OK. A dialog box titled Select Files to Add will be displayed. Check and uncheck files to be included in the driver installer as desired. Press OK when you're done.

    Note that the selected folder, its files, and any subfolders and files chosen are now displayed in the Setup Designer tree view. This folder structure will be created on the end-user system by the driver installer.

  6. Right-click on the Acme4321Setup project and choose Build.

  7. When the build has completed, navigate to the <solutionFolder>\build\Debug\x86 directory below the driver solution folder and note that an .msi installer package named Acme4321Setup.msi has been created.

    Caution note Caution

    Never run a driver installer on the same machine on which the driver was compiled. The registry entries associated with the driver could become corrupt. IVI.NET driver installers must ALWAYS be tested on a separate test machine.

Next Steps

This walkthrough has illustrated how to create a simple IVI.NET driver, implement, test and document methods and properties. We have also shown how to create and customize an IVI.NET-compliant driver installer. You might want to explore the following topics:

  • Understanding the Nimbus User Interface

  • Adding Functionality to an IVI.NET Driver

  • Adding Support for Multiple Instrument Models

  • Implementing Driver Methods and Properties

  • Understanding Nimbus Code Weaving

  • State Caching Overview

  • Using Per-User Preferences

See Also

Other Resources

Visual Studio Projects for an IVI.NET Driver
Testing an IVI.NET Driver
Creating a Driver Help File
Creating a Driver Installer
Accessing Driver Settings
Working With Instrument Commands