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

Background

The AxsunOCTCapture library and API captures a high-bandwidth image stream from an Axsun Ethernet/PCIe DAQ board and provides additional image management and display functionality to custom client applications.

The primary functions of the AxsunOCTCapture library (or simply the "Capture library") are:

  • Open a network interface (Ethernet-connected DAQ) or DMA interface (PCIe-connected DAQ, WINDOWS ONLY).
  • Wait for streamed image data arriving on the open interface from the DAQ board.
  • Capture and enqueue streamed image data into RAM (the "Main Image Buffer").
  • Retrieve individual images from the Main Image Buffer, perform JPEG decompression (if necessary, Ethernet only), and copy the images to the client application's RAM for subsequent manupulation by the user.

Some secondary functions of the Capture library include:

  • (WINDOWS ONLY) Change DAQ imaging modes and read/write FPGA registers (PCIe-connected DAQ only; use AxsunOCTControl or AxsunOCTControl_LW to change DAQ imaging modes or read/write FPGA registers via an Ethernet-connected DAQ).
  • (WINDOWS ONLY) Direct-to-screen OpenGL-based display of captured OCT images.
    • Avoids memory copy associated with image retrieval to a client application.
    • Includes colormap selection, brightness & contrast adjustment, and image cropping.
    • Includes polar->cartesian scan conversion for displaying rotationally-scanned OCT images.
  • Save and Load image buffers to/from disk for off-line storage.
  • Export images as individual JPEG, PNG, BMP, or raw binary files.
  • (WINDOWS ONLY) Interface to the National Instruments family of multifunction USB DAQ devices to control two-axis galvanometer raster scan patterns and other auxiliary digital and analog output.

C API Usage Guidelines

AxsunOCTCapture is written in C++ and exposes a Standard C interface to insure maximum portability for client application integration. See relevant Axsun Knowledge Base pages at https://docs.axsun.com/axsun-technologies-knowledge-base/guides/integrated-engine/installing-software#image-capture-tool-and-axsunoctcapture for installation instructions of AxsunOCTCapture dependencies.

Naming Conventions: C function names in this library begin with "ax". Enumerated types begin with "Ax". Struct type definitions end with "_t".

Error Handling: Functions usually return an error code as defined in the AxErr enum. Check that returned values indicate NO_AxERROR after function calls. Sample code shown below and in the linked examples eschews robust error handling in favor of readability.

Thread Safety: Confine AxsunOCTCapture library calls to a single thread or insure serialization at the client application level. Calling AxsunOCTCapture functions concurrently could result in undefined behavior. axGetImageInfo(), axRequestImage(), and axGetStatus() are safe to call from within the New Image event callback.

Project Configuration: Include the AxsunOCTCapture.h header file in your project and link to AxsunOCTCapture.dll (or libaxsunoctcapture.so or libAxsunOCTCapture.dylib on Linux or macOS). On Windows, you must also link to the include library AxsunOCTCapture.lib. Insure that your include search path is correctly pointing to the location of AxsunOCTCapture.h and AxsunCommonEnums.h. To get started, copy the .c or .cpp source code from one of the linked examples into your project and modify as appropriate.

Image Capture Session

Follow these basic steps to use the capture library in your C-based client application. C and C++ usage examples are provided in AxsunOCTCapture_C_example.c and AxsunOCTCapture_Cpp_example.cpp. The Capture library uses an "opaque pointer" design pattern to manage the creation, functionality, and destruction of a Capture session (https://en.wikipedia.org/wiki/Opaque_pointer).

1) Open a new AxsunOCTCapture session using axStartSession() and select a capture interface using axSelectInterface():

AOCHandle session = NULL;                                       // declare a handle (opaque pointer) for the session
AxErr returnValue = axStartSession(&session, 100);              // the "100" argument indicates a desired Main Image Buffer size of 100 MB
returnValue = axSelectInterface(session, GIGABIT_ETHERNET);     // a session supports either the PCI_EXPRESS or the GIGABIT_ETHERNET interface.

2) Call functions from the AxsunOCTCapture library as desired within your application workflow, using the generated session handle as the first argument. To get status information about the Main Image Buffer, use the axGetStatus() function. First declare variables and then send pointers to those variables with the "address-of" operator (&) as the arguments to axGetStatus():

uint32_t imaging, last_packet, last_frame, last_image, dropped_packets, frames_since_sync;      // declare variables
returnValue = axGetStatus(      session,                                                        // the session handle created using axStartSession()
                                &imaging,                                                       // is DAQ in Live Imaging, Burst Record, or Idle/Off state?
                                &last_packet,                                                   // the number of the last packet enqueued in the buffer
                                &last_frame,                                                    // the number of the last frame enqueued in the buffer
                                &last_image,                                                    // the number of the last image enqueued in the buffer
                                &dropped_packets,                                               // the number of packets dropped since the last Imaging off/on cycle
                                &frames_since_sync);                                            // the number of frames (256 A-lines) enqueued since the last Image_sync trigger

This paradigm is used for getting information about images in the Main Image Buffer using axGetImageInfo(). This paradigm is used to retrieve or display an image in the Main Image Buffer using axRequestImage(). The client application can retreive or display images from the Main Image Buffer using a polling-based approach as shown in AxsunOCTCapture_Cpp_example.cpp or using a callback-based approach as shown in AxsunOCTCapture_Cpp_example_NewImageCallback.cpp.

3) Call axStopSession() to release resources prior to quitting:

returnValue = axStopSession(session);

PCIe DAQ Controls

(WINDOWS ONLY) Follow these basic steps to use the PCIe control functions in your C-based client application. C and C++ usage examples are provided in AxsunOCTCapture_C_example.c and AxsunOCTCapture_Cpp_example.cpp. If you connect to the DAQ via the Ethernet interface, use the AxsunOCTControl library or AxsunOCTControl_LW library for this functionality.

1) Open a Capture session as shown above but select the PCI_EXPRESS interface using the axSelectInterface() function:

returnValue = axSelectInterface(session, PCI_EXPRESS);

2) Use the axImagingCntrlPCIe() function to select among DAQ imaging modes: Image-On (Live), Image-On (Burst Record), Image-Off (Idle):

returnValue = axImagingCntrlPCIe(session, -1);          // Live mode
returnValue = axImagingCntrlPCIe(session, 1000);        // Burst Record mode (1000 images)
returnValue = axImagingCntrlPCIe(session, 0);           // Idle mode

3) The pipeline mode and channel can be selected with axPipelineMode() and an argument selected from the AxPipelineMode and AxChannelMode enums:

returnValue = axPipelineMode(session, EIGHT_BIT, CHAN_1);       // set pipeline mode to 8-bit processed data from Channel 1
returnValue = axPipelineMode(session, RAW_DATA, CHAN_2);        // set pipeline mode to 16-bit raw ADC data from Channel 2

Scanner Control

(WINDOWS ONLY) Follow these basic steps to control galvo scanner waveforms in your C-based client application. A C++ usage example is provided in axScanCmd_Test.cpp. (Note: scanner control functionality does not require a Capture session to be initialized; however, axStopSession() will release scanner control resources.)

1) Scanner control functionality is accessed via a single function, axScanCmd(), the first argument of which is always a AxScannerCommand to indicate the desired operation, and additional arguments are used for some specific scanner commands or can otherwise be set to 0 or NULL.

int number_of_devices = (int)axScanCmd(COUNT_DEVICES, 0, NULL, NULL, NULL);     // initialize scanner resources and count number of connected devices
scan_params_t scan_pattern{ 0 };                                            // create a scan parameters structure for a rectangular raster pattern
scan_pattern.X_increments = 2000;                                           // populate some details of the scan parameters structure
scan_pattern.Y_increments = 2000;                                           // ...
scan_pattern.X_range = 3.0;                                                 // ...
scan_pattern.Y_range = 3.0;                                                 // ...
returnValue = axScanCmd(SET_RECT_PATTERN, 0, &scan_pattern, NULL, NULL)     // program this rectangular raster scan to the device
returnValue = axScanCmd(CONTINUOUS_LINE_SCAN, 0, NULL, NULL, NULL);         // execute a continuous line scan along the X dimension
returnValue = axScanCmd(SETUP_BURST_RASTER, 0, NULL, NULL, NULL);           // move scanner to start of 2D raster scan and wait for START_BURST_RASTER command
returnValue = axScanCmd(START_BURST_RASTER, 0, NULL, NULL, NULL);           // execute 2D raster scan once
returnValue = axScanCmd(WAIT_BURST, 10, NULL, NULL, NULL)                   // wait for 2D raster scan to complete (function blocks until scan completed or timeout expires)
returnValue = axScanCmd(DESTROY_SCAN, 0, NULL, NULL, NULL);                 // release scanner control resources

2) If desired, a callback function can be registered using axRegisterScannerConnectCallback() to execute whenever a scanner device is connected or disconnected from the library:

void MyCallback(void* user_data) { printf("In MyCallback!"); }
returnValue = axRegisterScannerConnectCallback(MyCallback, NULL);       // register "MyCallback" to be executed on device connect and disconnect