Events

Background

Coaxlink cards generate different kinds of events:

New buffer events: events indicating that a buffer has been filled by a data stream.
Data stream events: events related to a data stream and its frame store.
Camera and illumination controller events: events related to the real-time control (performed by a device) of a camera and its illumination devices.
I/O toolbox events: events (coming from the interface) related to digital I/O lines and other I/O tools.
CoaXPress interface events: events (also coming from the interface) related to the CoaXPress interface.

New buffer events are standard in GenTL. They occur when a buffer is filled by the frame grabber. Information attached to new buffer events include the handle of the buffer and a timestamp.

The other types of events are restricted to Coaxlink and can be viewed as categories of specific events. For example, in the CIC category of events, we have:

CameraTriggerRisingEdge (start of camera trigger)
CameraTriggerFallingEdge (end of camera trigger)
StrobeRisingEdge (start of light strobe)
StrobeFallingEdge (end of light strobe)
AllowNextCycle (CIC is ready for next camera cycle)
...

and in the I/O toolbox category of events, we have:

LIN1 (line input tool 1)
LIN2 (line input tool 2)
MDV1 (multiplier/divider tool 1)
...

Counters

Coaxlink firmware counts each occurrence of each event (except new buffer events) and makes this counter available in a GenApi feature named EventCount. Each event has its own counter, and the value of EventCount depends on the selected event:

// select the CameraTriggerRisingEdge event
grabber.setString<DeviceModule>("EventSelector", "CameraTriggerRisingEdge");
// read the value of the counter  
int64_t counter = grabber.getInteger<DeviceModule>("EventCount");

or, using the selected feature notation:

// read the value of the CameraTriggerRisingEdge counter  
int64_t counter = grabber.getInteger<DeviceModule>("EventCount[CameraTriggerRisingEdge]");

Notifications

As we've just seen, when an event occurs, a dedicated counter is incremented. Coaxlink can also notify the application of this event by having Euresys::EGrabber execute a user-defined callback function. But first, it is required to enable notifications of one or more events:

grabber.setString<DeviceModule>("EventSelector", "CameraTriggerRisingEdge");
grabber.setInteger<DeviceModule>("EventNotification", true);
grabber.setString<DeviceModule>("EventSelector", "CameraTriggerFallingEdge");
grabber.setInteger<DeviceModule>("EventNotification", true);
...

or:

grabber.setInteger<DeviceModule>("EventNotification[CameraTriggerRisingEdge]", true);
grabber.setInteger<DeviceModule>("EventNotification[CameraTriggerFallingEdge]", true);
...           

Using a configuration script, it is easy to enable notifications for all events:

function  enableAllEvents(p) {                            // 1  
    var events =  p.$ee('EventSelector');                 // 2  
    for (var e of events) {  
        p.set('EventNotification['  + e +  ']',  true);   // 3  
    }  
}  

var grabber = grabbers[0];  
enableAllEvents(grabber.InterfacePort);                   // 4  
enableAllEvents(grabber.DevicePort);                      // 5  
enableAllEvents(grabber.StreamPort);                      // 6
1. Define a helper function named enableAllEvents and taking as argument a module (or port) p.
2. Use the $ee function to retrieve the list of values EventSelector can take. This is the list of events generated by module p. (ee stands for enum entry.)
3. For each event, enable notifications. (The + operator concatenates strings, so if e is 'LIN1', the expression 'EventNotification[' + e + ']' evaluates to 'EventNotification[LIN1]'.)
4. Call the enableAllEvents function defined in step 1 for the interface module. This will enable notifications for all events in the I/O toolbox and CoaXPress interface categories.
5. Likewise, enable notifications for all events coming from the device module (CIC events).
6. Finally, enable notifications for all data stream events.

Callback functions

When an event occurs, and event notification is enabled for that event, Euresys::EGrabber executes one of several callback functions.

These callback functions are defined in overridden virtual methods:

class MyGrabber : public Euresys::EGrabber<>
{
    public:
        ...

    private:
        // callback function for new buffer events  
        virtual  void onNewBufferEvent(const NewBufferData& data) {
            ...
        }

        // callback function for data stream events  
        virtual  void onDataStreamEvent(const DataStreamData &data) {
            ...
        }

        // callback function for CIC events  
        virtual  void onCicEvent(const CicData &data) {
            ...
        }

        // callback function for I/O toolbox events  
        virtual  void onIoToolboxEvent(const IoToolboxData &data) {
            ...
        }

        // callback function for CoaXPress interface events  
        virtual  void onCxpInterfaceEvent(const CxpInterfaceData &data) {
            ...
        }
};

As you can see, a different callback function can be defined for each category of events.

In .NET, callback functions are defined by creating delegates rather than overriding virtual methods. An example will be given in the chapter about the .NET assembly.

Event identification

When an event is notified to the application, the callback function that is executed indicates the category of that event. The actual event that occurred is identified by a numerical ID, called numid, and defined in include/GenTL_v1_5_EuresysCustom.h:

enum EVENT_DATA_NUMID_CUSTOM_LIST
{
// EVENT_CUSTOM_IO_TOOLBOX
EVENT_DATA_NUMID_IO_TOOLBOX_LIN1                    = ...  /* Line Input Tool 1 */
EVENT_DATA_NUMID_IO_TOOLBOX_LIN2                    = ...  /* Line Input Tool 2 */
EVENT_DATA_NUMID_IO_TOOLBOX_MDV1                    = ...  /* Multiplier/Divider Tool 1 */
...
// EVENT_CUSTOM_CXP_INTERFACE
EVENT_DATA_NUMID_CXP_INTERFACE_CRC_ERROR_CXP_A      = ...  /* Detected CRC error on CXP connector A */
EVENT_DATA_NUMID_CXP_INTERFACE_CRC_ERROR_CXP_B      = ...   /* Detected CRC error on CXP connector B */ */
...
// EVENT_CUSTOM_CIC
EVENT_DATA_NUMID_CIC_CAMERA_TRIGGER_RISING_EDGE     = ...  /* Start of camera trigger */
EVENT_DATA_NUMID_CIC_CAMERA_TRIGGER_FALLING_EDGE    = ...  /* End of camera trigger */
EVENT_DATA_NUMID_CIC_STROBE_RISING_EDGE             = ...  /* Start of light strobe */
EVENT_DATA_NUMID_CIC_STROBE_FALLING_EDGE            = ...  /* End of light strobe */
...
// EVENT_CUSTOM_CXP_DEVICE
EVENT_DATA_NUMID_CXP_DEVICE_LINK_TRIGGER            = ...  /* LinkTrigger N received from CoaXPress device */     
...
// EVENT_CUSTOM_DATASTREAM
EVENT_DATA_NUMID_DATASTREAM_START_OF_CAMERA_READOUT = ...  /* Start of camera readout */
EVENT_DATA_NUMID_DATASTREAM_END_OF_CAMERA_READOUT   = ...  /* End of camera readout */
...
//CUSTOM_DEVICE_ERROR
EVENT_DATA_NUMID_DEVICE_ERROR_STREAM_PACKET_SIZE_ERROR      = ...  /* Stream packet size error */
EVENT_DATA_NUMID_DEVICE_ERROR_STREAM_PACKET_FIFO_OVERFLOW   = ...  /* Stream packet FIFO overflow */
...}; 

For reference, the following table lists the relationships between:

the module generating events
the category of events
the name of the callback function
the data type passed to the callback function
the common numid prefix
Module Category Callback function Data type numid prefix
Data stream New Buffer onNewBufferEvent NewBufferData -
Data stream Data Stream onDataStreamEvent DataStreamData EVENT_DATA_NUMID_DATASTREAM_
Device CIC onCicEvent CicData EVENT_DATA_NUMID_CIC_
Interface I/O Toolbox onIoToolboxEvent IoToolboxData EVENT_DATA_NUMID_IO_TOOLBOX_
Interface CXP Interface onCxpInterfaceEvent CxpInterfaceData EVENT_DATA_NUMID_CXP_INTERFACE_
Device Remote Device onRemoteDeviceEvent RemoteDeviceData -
Device Device Error onDeviceErrorEvent DeviceErrorData EVENT_DATA_NUMID_DEVICE_ERROR_
Device CXP Device onCxpDeviceEvent CxpDeviceData EVENT_DATA_NUMID_CXP_DEVICE_
There is only one event in the new buffer event category, so we don't need a numid there.
A simple naming scheme is followed: a category of events named some category has a callback function named onSomeCategoryEvent which takes as argument a SomeCategoryData structure, and uses EVENT_DATA_NUMID_SOME_CATEGORY_ as common numid prefix.

Examples

We'll soon show a few complete example programs illustrating events and callbacks, but there is one more thing we need to explain before we can do that: the context in which callback functions are executed. This is the subject of the next section.