AxsunOCTControl_LW 0.9.7.0
A light-weight & cross-platform alternative to the .NET-based AxsunOCTControl.dll.
AxsunOCTControl_LW_Test.cpp

This is example source code showing how to use the AxsunOCTControl_LW API in a C++ client application, including context construction/destruction (axOpen.. & axClose..), callback function registration, opening of communication interfaces, and sending a variety of commands to Laser and DAQ devices with user interaction. Several additional helper functions are also provided for conversion from char* or enums into std::string for console output.

// AxsunOCTControl_LW_Test.cpp
// Copyright 2020 Axsun Technologies
#include <iostream> // for std::cin & std::cout
#include <string>
#include <memory> // for std::unique_ptr
#include <vector>
// frequently used std:: library members
using std::cout;
using std::cin;
using std::string;
// Convert AxDevType enum into string
string AxDevTypeString(AxDevType device) {
switch (device) {
case AxDevType::LASER: return "Laser";
case AxDevType::EDAQ: return "EDAQ";
case AxDevType::CLDAQ: return "CLDAQ";
default: return "Unknown";
}
}
// Convert AxConnectionType enum into string
string AxConnectTypeString(AxConnectionType connection) {
switch (connection) {
case AxConnectionType::USB: return "USB";
case AxConnectionType::RS232: return "RS-232";
case AxConnectionType::RS232_PASSTHROUGH: return "via EDAQ";
case AxConnectionType::ETHERNET: return "Ethernet";
default: return "Unknown";
}
}
// Get error message as a C++ std::string (convert from char* that C interface uses)
string GetErrorStringCpp(AxErr e) {
char errormsg[256];
axGetErrorExplained(e, errormsg);
return errormsg; // calls std::string(char*) constructor automatically based on the function return type
}
// Function which counts the connected devices and then prints some details about them to std::cout.
// It is safe to call these library functions from the callback function (executed in a background thread).
void PrintConnectedDevices() {
uint32_t count = axCountConnectedDevices(); // how many devices are connected now?
cout << "\nTotal devices connected: " << count << "\n";
if (count > 0) { // if any devices are connected,
AxErr retval;
for (auto i = 0; i < count; i++) { // print out their connection type, device type, serial number, and firmware version
AxConnectionType connection_type;
retval = axConnectionType(&connection_type, i);
if (retval != AxErr::NO_AxERROR) throw retval;
AxDevType device_type;
retval = axDeviceType(&device_type, i);
if (retval != AxErr::NO_AxERROR) throw retval;
uint32_t major, minor, patch;
retval = axFirmwareVersion(&major, &minor, &patch, i);
if (retval != AxErr::NO_AxERROR) throw retval;
char serial_no[40];
retval = axSerialNumber(serial_no, i);
cout << AxDevTypeString(device_type) << " (" << AxConnectTypeString(connection_type) << ")\tFW: v" << major << "." << minor << "." << patch << "\tSN: " << serial_no << "\t";
if (device_type == AxDevType::EDAQ) {
uint32_t build;
retval = axFPGAVersion(&major, &minor, &patch, &build, i);
if (retval != AxErr::NO_AxERROR) throw retval;
cout << "\tFPGA: v" << major << "." << minor << "." << patch << "." << build;
}
cout << "\n";
}
cout << "\n";
}
}
// Function which is executed via callback when a device connects or disconnects.
void ConnectedCallbackFunc(void* userData) {
try {
// Callback function is useful for maintaining a list of the connected devices at the application level.
PrintConnectedDevices();
// NOTE: calling this print function from the callback is not a thread-safe use of std::cout.
// It is convienient for example code, but production code should avoid this approach.
}
catch (AxErr e) { cout << "***** ERROR: " << GetErrorStringCpp(e) << " in callback function.\n"; }
}
// Wrap the axOpen.. and axClose.. commands in a C++ class so that the axClose.. command will be called automatically in the destructor
class AOCTLW {
public:
AOCTLW(uint32_t open_all_interfaces) {
AxErr retval = axOpenAxsunOCTControl(open_all_interfaces);
if (retval != AxErr::NO_AxERROR) throw retval;
}
~AOCTLW() {
}
};
int main()
{
try {
AxErr retval;
// Create an instance of our AOCTLW class, whose constructor calls axOpenAxsunOCTControl().
// When this object goes out of scope, the desctructor will automatically call axCloseAxsunOCTControl().
AOCTLW myInstance(0); // the 0 argument here prevents communication interfaces from being automatically opened
// report the current library version
uint32_t major, minor, patch, build;
retval = axLibraryVersion(&major, &minor, &patch, &build);
if (retval != AxErr::NO_AxERROR) throw retval;
cout << "Using AxsunOCTControl_LW library version: " << major << "." << minor << "." << patch << "." << build << "\n\n";
// tells library to execute this callback function when a device connect or disconnect event happens; userData pointer also available in callback
retval = axRegisterConnectCallback(ConnectedCallbackFunc, nullptr);
if (retval != AxErr::NO_AxERROR) throw retval;
// opens the Ethernet network interface (for Ethernet DAQ connectivity only)
if (retval != AxErr::NO_AxERROR) throw retval;
// opens the USB interface (for Laser or DAQ connectivity)
retval = axUSBInterfaceOpen(1);
if (retval != AxErr::NO_AxERROR) throw retval;
/*
// un-comment this block to open a RS-232 serial interface
retval = axSerialInterfaceOpen(true, "/dev/tty.usbserial-A9015L62"); // example for Linux or macOS
retval = axSerialInterfaceOpen(true, "COM8"); // example for Windows
if (retval) throw retval;
*/
// 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 'd':
case 'D':
cout << "axSetLaserEmission(...) for LASER OFF\n";
retval = axSetLaserEmission(0, 0);
if (retval != AxErr::NO_AxERROR) throw retval;
break;
case 'e':
case 'E':
cout << "axSetLaserEmission(...) for LASER ON\n";
retval = axSetLaserEmission(1, 0);
if (retval != AxErr::NO_AxERROR) throw retval;
break;
case 'f':
case 'F':
{
cout << "axGetFPGARegisterRange(0..63)\n";
auto regvals = std::make_unique<uint16_t[]>(64);
retval = axGetFPGARegisterRange(0, 63, regvals.get(), 64*2, 0);
if (retval != AxErr::NO_AxERROR) throw retval;
for (auto i = 0; i < 64; i++) {
cout << "Reg " << i << " =\t" << std::hex << regvals[i] << std::dec << "\n";
}
}
break;
case 'h':
case 'H':
cout << "axHomeVDL(...)\n";
retval = axHomeVDL(0);
if (retval != AxErr::NO_AxERROR) throw retval;
break;
case 'i':
case 'I':
PrintConnectedDevices();
break;
case 'l':
case 'L':
cout << "axImagingCntrlEthernet(...) for LIVE IMAGING\n";
retval = axImagingCntrlEthernet(-1, 0);
if (retval != AxErr::NO_AxERROR) throw retval;
break;
case 'o':
case 'O':
cout << "axImagingCntrlEthernet(...) for IDLE\n";
retval = axImagingCntrlEthernet(0, 0);
if (retval != AxErr::NO_AxERROR) throw retval;
break;
case 't':
case 'T':
cout << "axTECState(...) ";
AxTECState state;
retval = axGetTECState(&state, 1, 0);
if (retval != AxErr::NO_AxERROR) throw retval;
cout << "State of Primary TEC: " << state << "\n";
break;
case 'a':
case 'A':
cout << "axSetFPGADataArray(...) ";
{
std::vector<uint16_t> pattern(1024, 500);
retval = axSetFPGADataArray(37, pattern.data(), pattern.size(), 0);
}
cout << "Retval: " << static_cast<int32_t>(retval) << "\n";
break;
case 'c':
case 'C':
cout << "axSetFPGADataArray(...) ";
{
std::vector<uint16_t> pattern(1024, 0);
retval = axSetFPGADataArray(37, pattern.data(), pattern.size(), 0);
}
cout << "Retval: " << static_cast<int32_t>(retval) << "\n";
break;
case '?':
cout << "\n***** COMMAND LIST *****\n";
cout << "D\tLASER: axSetLaserEmission(false); // Laser OFF\n";
cout << "E\tLASER: axSetLaserEmission(true); // Laser ON\n";
cout << "H\tLASER: axHomeVDL();\n";
cout << "T\tLASER: axGetTECState();\n";
cout << "F\tDAQ: axGetFPGARegisterRange(...);\n";
cout << "L\tDAQ: axImagingCntrlEthernet(-1); // Imaging ON - Live\n";
cout << "O\tDAQ: axImagingCntrlEthernet(0); // Imaging OFF - Idle\n";
cout << "A\tDAQ: axSetFPGADataArray(...); // Load Test Pattern\n";
cout << "C\tDAQ: axSetFPGADataArray(...); // Clear Test Pattern\n";
cout << "\nI\tGet info on connected devices.\n";
cout << "?\tList command options.\n";
cout << "Q\tQuit this program.\n\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
} // while loop
} // try (NOTE: myInstance goes out of scope here and its destructor calls axCloseAxsunOCTControl() to release resources)
catch (AxErr e) {
cout << "***** ERROR: " << static_cast<int32_t>(e) << " (" << 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:34
This header file defines the usage of the AxsunOCTControl_LW "lightweight" library in a C or C++ appl...
AxErr axGetFPGARegisterRange(const uint32_t start_regnum, const uint32_t end_regnum, uint16_t *regvals, const uint32_t bytes_allocated, uint32_t which_DAQ)
Gets (i.e. reads) current values in a range of FPGA registers.
AxTECState
Laser TEC states.
Definition: AxsunOCTControl_LW_C.h:50
AxErr axSetLaserEmission(uint32_t emission_state, uint32_t which_laser)
Enables or disables swept laser emission.
AxConnectionType
Definition: AxsunOCTControl_LW_C.h:34
@ RS232_PASSTHROUGH
Definition: AxsunOCTControl_LW_C.h:37
@ RS232
Definition: AxsunOCTControl_LW_C.h:38
@ USB
Definition: AxsunOCTControl_LW_C.h:36
@ ETHERNET
Definition: AxsunOCTControl_LW_C.h:39
AxErr axFPGAVersion(uint32_t *major, uint32_t *minor, uint32_t *patch, uint32_t *build, uint32_t which_device)
Gets the device FPGA version.
AxErr axConnectionType(AxConnectionType *connection_type, uint32_t which_device)
Gets the device connection interface (e.g. USB, Ethernet, RS-232).
AxDevType
Definition: AxsunOCTControl_LW_C.h:42
@ LASER
Definition: AxsunOCTControl_LW_C.h:44
@ CLDAQ
Definition: AxsunOCTControl_LW_C.h:45
@ EDAQ
Definition: AxsunOCTControl_LW_C.h:46
AxErr axNetworkInterfaceOpen(uint32_t interface_status)
Opens, resets, or closes the Ethernet network interface.
AxErr axUSBInterfaceOpen(uint32_t interface_status)
Opens, resets, or closes the USB interface.
AxErr axSerialNumber(char *serial_number, uint32_t which_device)
Gets the device serial number string.
AxErr axDeviceType(AxDevType *device_type, uint32_t which_device)
Gets the device type (e.g. Laser, EDAQ).
AxErr axSetFPGADataArray(const uint32_t regnum, const uint16_t *data_array, const uint32_t number_of_words, uint32_t which_DAQ)
Sets (i.e. writes) a FPGA register with an array of multiple values.
AxErr axHomeVDL(uint32_t which_laser)
Starts the VDL home operation.
void axGetErrorExplained(AxErr errornum, char *error_string)
Gets a string which explains an error code in a more verbose fashion.
AxErr axOpenAxsunOCTControl(uint32_t open_all_interfaces)
Opens the AxsunOCTControl context for subsequent device communication.
AxErr axFirmwareVersion(uint32_t *major, uint32_t *minor, uint32_t *patch, uint32_t which_device)
Gets the device firmware version.
uint32_t axCountConnectedDevices()
Counts the number of devices successfully connected and enumerated by AxsunOCTControl.
AxErr axCloseAxsunOCTControl()
Closes an AxsunOCTControl context previously opened with axOpenAxsunOCTControl().
AxErr axImagingCntrlEthernet(int16_t number_of_images, uint32_t which_DAQ)
Control the DAQ operational mode (Live Imaging, Burst Recording, or Imaging Off) when using the Ether...
AxErr axGetTECState(AxTECState *TEC_state, uint32_t which_TEC, uint32_t which_laser)
Gets the current state of a Laser Thermo-Electric Cooler (TEC).
AxErr axLibraryVersion(uint32_t *major, uint32_t *minor, uint32_t *patch, uint32_t *build)
Gets the library version.
AxErr axRegisterConnectCallback(AxConnectCallbackFunctionC_t callback_function, void *userData)
Registers a callback function to be executed following a device connection or disconnection event.