AxsunOCTCapture 3.8.2
Captures and buffers streamed imaged data from the Axsun Ethernet/PCIe DAQ and displays or retrieves images to a client application on request.
axScanCmd_example.cpp

This is example source code showing how to use the AxsunOCTCapture scanner command API in a C++ client application (Windows only).

// axScanCmd_example.cpp
//
// NOTES:
//
// 1. AxsunOCTCapture functions are Standard C and do NOT throw C++ exceptions, but rather
// return an error status of type AxErr. Calls to AxsunOCTCapture functions in this
// example program are typically wrapped in an "if (status != OK) throw AxErr" fashion
// and contained in a try/catch block in order to make the behavior exception-based.
//
// 2. The intent of this example program is to exemplify the capabilities of the
// AxsunOCTCapture library. Program structure is simplified for readability and is not
// intended for "production" use as-is.
//
#include <iostream>
#include <string>
#include <chrono>
#include <vector>
using namespace std::chrono_literals;
using std::cout;
using std::cin;
using std::string;
// Get error message as a C++ std::string (convert from char* that ANSI C interface uses)
string GetErrorStringCpp(AxErr e) {
char errormsg[512];
axGetErrorString(e, errormsg);
return errormsg; // calls std::string(char*) constructor automatically based on the function return type
}
// Wrap the DESTROY_SCAN command in a C++ class so that it will be called automatically
// in the destructor when the object goes out of scope (we won't have to remember to do it explicitly)
class ScannerSession {
public:
ScannerSession() {}
~ScannerSession() {
}
};
// function to call when scanner is connected or disconnected
void DeviceConnectedCallback(void * user_data) {
try {
// count the devices
int32_t devices = static_cast<int32_t>(axScanCmd(AxScannerCommand::COUNT_DEVICES, 0, NULL, NULL, NULL));
if (devices < 0) throw static_cast<AxErr>(devices); // return value < 0 indicates AxErr error occurred
cout << "Total devices connected: " << devices << '\n';
// get each device's serial and model number and print it along with its index
for (int index = 0; index < devices; index++) {
int32_t serialno = static_cast<int32_t>(axScanCmd(AxScannerCommand::GET_DEVICE_SERIALNO, index, NULL, NULL, NULL));
int32_t modelno = static_cast<int32_t>(axScanCmd(AxScannerCommand::GET_DEVICE_MODEL_NUMBER, index, NULL, NULL, NULL));
if (serialno > 0 && modelno > 0)
cout << "USB-" << std::dec << modelno << " (" << std::hex << serialno << ") is device index " << std::dec << index << '\n';
else throw static_cast<AxErr>(devices); // return value < 0 indicates AxErr error occurred
}
cout << '\n';
}
catch (AxErr& e) {
cout << "***** ERROR: " << GetErrorStringCpp(e) << "\n\n";
}
}
int main(int argc, char* argv[])
{
try {
cout << "Welcome to the AxsunOCTCapture DAQmx Scanner Control example application.\n";
AxErr retval{ AxErr::NO_AxERROR };
ScannerSession mySession; // construct ScannerSession class instance
axRegisterScannerConnectCallback(DeviceConnectedCallback, NULL);
// declare some variables for our user interaction loop
bool running = true;
char which_command;
// prompt the user for a character, interpret this as a command, and then execute it if recognized
// examples are given for several common device functions; additional functions in the library can be added following the same pattern
while (running) {
cout << "Type a character and press enter to execute a command.\n>> ";
cin >> which_command;
try {
switch (which_command) {
case '?':
cout << "\n***** COMMAND LIST *****\n";
cout << "(see matrix in AxsunOCTCapture.h for supported devices and functions)\n\n";
cout << "L\tList connected device serial numbers using axScanCmd(GET_DEVICE_SERIALNO, ..);\n";
cout << "D\tMake device at index 1 active using axScanCmd(SELECT_DEVICE, 1, ..);\n";
cout << "P\tSet scan parameters using axScanCmd(set_rect_pattern, ..);\n";
cout << "1\tStart continuous 1D linear scanning using axScanCmd(CONTINUOUS_LINE_SCAN, ..);\n";
cout << "2\tStart continuous 2D raster scanning using axScanCmd(CONTINUOUS_RASTER_SCAN, ..);\n";
cout << "S\tStop scanning using axScanCmd(STOP_AT_POSITION, ..);\n";
cout << "I\tSet internal sample clock using axScanCmd(SET_SAMPLE_CLOCK, 1, ..);\n";
cout << "E\tSet external sample clock using axScanCmd(SET_SAMPLE_CLOCK, 0, ..);\n";
cout << "B\tPrepare for burst raster scan using axScanCmd(SETUP_BURST_RASTER, ..);\n";
cout << "R\tStart burst raster scan using axScanCmd(START_BURST_RASTER, ..);\n";
cout << "M\tSet maximum analog output voltage to 1.0V using axScanCmd(SET_MAX_VOLTAGE, 1.0, ..);\n";
cout << "W\tSet square wave synthesizer to 7200 Hz using axScanCmd(SET_SQUAREWAVE_OUTPUT, 7200, ..);\n";
cout << "X\tTurn square wave synthesizer off using axScanCmd(SET_SQUAREWAVE_OUTPUT, 0.0, ..);\n";
cout << "N\tTurn general purpose digital output ON using axScanCmd(SET_DIGITAL_OUTPUT, 1.0, ..);\n";
cout << "F\tTurn general purpose digital output OFF using axScanCmd(SET_DIGITAL_OUTPUT, 0.0, ..);\n";
cout << "A\tSet auxiliary analog output to 2.5 Vdc using axScanCmd(SET_AUX_DC_ANALOG_OUTPUT, 2.5, ..);\n";
cout << "O\tTurn auxiliary analog DC output OFF using axScanCmd(SET_AUX_DC_ANALOG_OUTPUT, 0.0, ..);\n";
cout << "T\tLoad an external scan pattern using axScanCmd(LOAD_EXT_PATTERN, 0.0, ..);\n";
cout << "U\tSet max limit on auxiliary analog DC output to 1.0V using axScanCmd(SET_AUX_DC_ANALOG_MAX, 1.0, ..);\n";
cout << "?\tList command options.\n";
cout << "Q\tQuit this program.\n\n";
break;
case '1':
retval = axScanCmd(AxScannerCommand::CONTINUOUS_LINE_SCAN, 0, NULL, NULL, NULL); if (retval != AxErr::NO_AxERROR) throw retval;
cout << "Linear scan started.\n";
break;
case '2':
retval = axScanCmd(AxScannerCommand::CONTINUOUS_RASTER_SCAN, 0, NULL, NULL, NULL); if (retval != AxErr::NO_AxERROR) throw retval;
cout << "Raster scan started.\n";
break;
case 's':
case 'S':
{
scan_params_t scan_pattern{ 0 };
scan_pattern.X_shift = 1.0; // uses X_shift and Y_shift to define the stop position
scan_pattern.Y_shift = -1.0;
retval = axScanCmd(AxScannerCommand::STOP_AT_POSITION, 0, &scan_pattern, NULL, NULL); if (retval != AxErr::NO_AxERROR) throw retval;
cout << "Scan stopped at (" << scan_pattern.X_shift << "," << scan_pattern.Y_shift << ").\n";
break;
}
case 'p':
case 'P':
{
scan_params_t scan_pattern{ 0 };
scan_pattern.X_increments = 1000;
scan_pattern.Y_increments = 4;
scan_pattern.X_range = 3.0;
scan_pattern.Y_range = 3.0;
retval = axScanCmd(AxScannerCommand::SET_RECT_PATTERN, 0, &scan_pattern, NULL, NULL); if (retval != AxErr::NO_AxERROR) throw retval;
cout << "Scan parameters set.\n";
break;
} // scope limit for scan_pattern
case 'l':
case 'L':
{
DeviceConnectedCallback(NULL); // just do the same thing that the callback function does: list the connected devices
break;
} // scope limit for devices
case 'd':
case 'D':
retval = axScanCmd(AxScannerCommand::SELECT_DEVICE, 1, NULL, NULL, NULL); if (retval != AxErr::NO_AxERROR) throw retval;
cout << "Selected active device: " << std::hex << static_cast<int32_t>(axScanCmd(AxScannerCommand::GET_DEVICE_SERIALNO, 0, NULL, NULL, NULL)) << '\n';
break;
case 'e':
case 'E':
retval = axScanCmd(AxScannerCommand::SET_SAMPLE_CLOCK, 0, NULL, NULL, NULL); if (retval != AxErr::NO_AxERROR) throw retval;
cout << "Selected external sample clock. \n";
break;
case 'i':
case 'I':
retval = axScanCmd(AxScannerCommand::SET_SAMPLE_CLOCK, 1, NULL, NULL, NULL); if (retval != AxErr::NO_AxERROR) throw retval;
cout << "Selected internal 100 kHz sample clock. \n";
break;
case 'm':
case 'M':
retval = axScanCmd(AxScannerCommand::SET_MAX_VOLTAGE, 1.0, NULL, NULL, NULL); if (retval != AxErr::NO_AxERROR) throw retval;
cout << "Maxiumum analog output voltage has been set. \n";
break;
case 'b':
case 'B':
retval = axScanCmd(AxScannerCommand::SETUP_BURST_RASTER, 0, NULL, NULL, NULL); if (retval != AxErr::NO_AxERROR) throw retval;
cout << "Burst raster setup and waiting for START_BURST_RASTER command. \n";
break;
case 'w':
case 'W':
retval = axScanCmd(AxScannerCommand::SET_SQUAREWAVE_OUTPUT, 7200, NULL, NULL, NULL); if (retval != AxErr::NO_AxERROR) throw retval;
cout << "Square wave synthesizer configured for 7200 Hz. \n";
break;
case 'x':
case 'X':
retval = axScanCmd(AxScannerCommand::SET_SQUAREWAVE_OUTPUT, 0.0, NULL, NULL, NULL); if (retval != AxErr::NO_AxERROR) throw retval;
cout << "Square wave synthesizer off. \n";
break;
case 'n':
case 'N':
retval = axScanCmd(AxScannerCommand::SET_DIGITAL_OUTPUT, 1.0, NULL, NULL, NULL); if (retval != AxErr::NO_AxERROR) throw retval;
cout << "General purpose digital output ON. \n";
break;
case 'f':
case 'F':
retval = axScanCmd(AxScannerCommand::SET_DIGITAL_OUTPUT, 0.0, NULL, NULL, NULL); if (retval != AxErr::NO_AxERROR) throw retval;
cout << "General purpose digital output OFF. \n";
break;
case 'r':
case 'R':
{
retval = axScanCmd(AxScannerCommand::START_BURST_RASTER, 0, NULL, NULL, NULL); if (retval != AxErr::NO_AxERROR) throw retval;
cout << "Burst raster started... \n";
retval = axScanCmd(AxScannerCommand::WAIT_BURST, 10, NULL, NULL, NULL); if (retval != AxErr::NO_AxERROR) throw retval; // wait for 10 seconds and then timeout
cout << "Burst raster completed.\n";
break;
}
case 'a':
case 'A':
{
retval = axScanCmd(AxScannerCommand::SET_AUX_DC_ANALOG_OUTPUT, 2.5, NULL, NULL, NULL); if (retval != AxErr::NO_AxERROR) throw retval;
cout << "Auxiliary analog output set to 2.5 Vdc.\n";
break;
}
case 'o':
case 'O':
{
retval = axScanCmd(AxScannerCommand::SET_AUX_DC_ANALOG_OUTPUT, 0.0, NULL, NULL, NULL); if (retval != AxErr::NO_AxERROR) throw retval;
cout << "Auxiliary analog output disabled.\n";
break;
}
case 'u':
case 'U':
{
retval = axScanCmd(AxScannerCommand::SET_AUX_DC_ANALOG_MAX, 1.0, NULL, NULL, NULL); if (retval != AxErr::NO_AxERROR) throw retval;
cout << "Auxiliary analog output limit set to 1.0V.\n";
break;
}
case 't':
case 'T':
{
// create and populate an ext_pattern_t struct
constexpr auto x_increments{ 4000u };
constexpr auto y_increments{ 20u };
ext_pattern_t my_pattern{};
my_pattern.ext_X_increments = x_increments;
my_pattern.ext_Y_increments = y_increments;
auto pattern1D = std::vector<double>(2 * x_increments, 0.0);
auto pattern2D = std::vector<double>(2 * x_increments * y_increments, 0.0);
my_pattern.linear_pattern = pattern1D.data();
my_pattern.raster_pattern = pattern2D.data();
retval = axScanCmd(AxScannerCommand::LOAD_EXT_PATTERN, 0.0, NULL, &my_pattern, NULL); if (retval != AxErr::NO_AxERROR) throw retval;
cout << "External scan pattern loaded.\n";
break;
}
case 'q':
case 'Q':
cout << "Quitting.\n";
running = false;
break;
default:
cout << "Command not recognized. Enter '?' to list options.\n";
} // switch
} // try
catch (AxErr& e) {
cout << "***** ERROR: " << GetErrorStringCpp(e) << "\n\n";
} // catch
}
} // try (NOTE: myInstance goes out of scope here and its destructor calls DESTROY_SCAN to release resources)
catch (AxErr& e) {
cout << "***** ERROR: " << GetErrorStringCpp(e) << " Program terminating.\n";
}
catch (...) {
cout << "***** UNKNOWN ERROR. Program terminating.\n";
}
}
AxErr
Error codes returned from AxsunOCTCapture or AxsunOCTControl_LW functions. Use axGetErrorString() in ...
Definition: AxsunCommonEnums.h:40
This header file contains all exported function prototypes, structures, and enums necessary for integ...
@ START_BURST_RASTER
Definition: AxsunOCTCapture.h:319
@ DESTROY_SCAN
Definition: AxsunOCTCapture.h:305
@ WAIT_BURST
Definition: AxsunOCTCapture.h:321
@ SET_DIGITAL_OUTPUT
Definition: AxsunOCTCapture.h:333
@ SET_AUX_DC_ANALOG_MAX
Definition: AxsunOCTCapture.h:341
@ GET_DEVICE_SERIALNO
Definition: AxsunOCTCapture.h:325
@ COUNT_DEVICES
Definition: AxsunOCTCapture.h:329
@ SET_SAMPLE_CLOCK
Definition: AxsunOCTCapture.h:323
@ CONTINUOUS_LINE_SCAN
Definition: AxsunOCTCapture.h:311
@ CONTINUOUS_RASTER_SCAN
Definition: AxsunOCTCapture.h:313
@ SELECT_DEVICE
Definition: AxsunOCTCapture.h:327
@ GET_DEVICE_MODEL_NUMBER
Definition: AxsunOCTCapture.h:345
@ SETUP_BURST_RASTER
Definition: AxsunOCTCapture.h:317
@ SET_SQUAREWAVE_OUTPUT
Definition: AxsunOCTCapture.h:335
@ SET_RECT_PATTERN
Definition: AxsunOCTCapture.h:307
@ STOP_AT_POSITION
Definition: AxsunOCTCapture.h:315
@ SET_MAX_VOLTAGE
Definition: AxsunOCTCapture.h:331
@ SET_AUX_DC_ANALOG_OUTPUT
Definition: AxsunOCTCapture.h:339
@ LOAD_EXT_PATTERN
Definition: AxsunOCTCapture.h:309
AxErr __cdecl axScanCmd(AxScannerCommand scan_command, double misc_scalar, const scan_params_t *scan_parameters, ext_pattern_t *external_scan_pattern, void *RFU)
Control analog output waveform generation for 2 channel (X-Y) scanners. (Windows OS only)
void __cdecl axGetErrorString(AxErr errorcode, char *message_out)
Get a description of a specific AxErr error code.
AxErr __cdecl axRegisterScannerConnectCallback(AxConnectScannerCallbackFunction_t callback_function, void *userData)
Registers a callback function to be executed following a scanner (DAQmx) device connection or disconn...
Structure for passing a user-generated scan pattern to axScanCmd(LOAD_EXT_PATTERN,...
Definition: AxsunOCTCapture.h:373
uint32_t ext_X_increments
Definition: AxsunOCTCapture.h:375
Structure for passing raster scan pattern parameters to axScanCmd(SET_RECT_PATTERN,...
Definition: AxsunOCTCapture.h:351
double X_shift
Definition: AxsunOCTCapture.h:361
uint32_t X_increments
Definition: AxsunOCTCapture.h:353