#include "TriggerOverEthernet.h"
void PrintHeader()
{
MosPrintf(MIL_TEXT("[EXAMPLE NAME]\n\n"));
MosPrintf(MIL_TEXT("TriggerOverEthernet\n\n"));
MosPrintf(MIL_TEXT("[SYNOPSIS]\n\n"));
MosPrintf(
MIL_TEXT("This program enumerates GigE Vision devices that support trigger\n")\
MIL_TEXT("over Ethernet and that are physically connected to a Matrox\n")\
MIL_TEXT("ConcordPoE board that supports TOE functionality. The GigE\n")\
MIL_TEXT("Vision devices will be set-up in triggered mode using the\n")\
MIL_TEXT("action command packet or the software trigger packet as trigger\n")\
MIL_TEXT("source. The Matrox ConcordPoE will be set-up in such a way as to\n")\
MIL_TEXT("send periodic trigger over Ethernet packets to the GigE Vision\n")\
MIL_TEXT("devices in order to trigger frame capture.\n")\
MIL_TEXT("\nPress <Enter> to start.\n\n")\
);
}
MIL_DOUBLE TriggerFrequency = 10.0;
bool ForceSoftwareTriggerPackets = false;
#define FREQ_TO_PERIOD_IN_NS(N) ((1.0 / N) * 1E9)
MIL_INT MFTYPE ProcessingFunction(MIL_INT HookType, MIL_ID HookId, void* HookDataPtr);
void SetupToEUsingActions(MIL_ID MilConcordPoESystem, const std::vector<ToEDevice>& Devices);
void SetupToEUsingSoftware(MIL_ID MilConcordPoESystem, const std::vector<ToEDevice>& Devices);
int MosMain(void)
{
MIL_ID MilApplication = M_NULL,
MilConcordPoESystem = M_NULL,
MilGigESystem = M_NULL;
PrintHeader();
MosGetch();
MappAlloc(M_DEFAULT, &MilApplication);
MsysAlloc(M_SYSTEM_GIGE_VISION, M_DEV0, M_DEFAULT, &MilGigESystem);
MsysAlloc(M_SYSTEM_CONCORD_POE, M_DEV0, M_DEFAULT, &MilConcordPoESystem);
if (!(MsysInquire(MilConcordPoESystem, M_BOARD_TYPE, M_NULL) & M_TOE))
{
MsysFree(MilConcordPoESystem);
MilConcordPoESystem = M_NULL;
}
bool UseActionCapableDevices = !ForceSoftwareTriggerPackets;
std::vector<ToEDevice> Devices = FindToEDevices(MilConcordPoESystem, MilGigESystem, UseActionCapableDevices);
if (Devices.empty() && !ForceSoftwareTriggerPackets)
{
UseActionCapableDevices = false;
Devices = FindToEDevices(MilConcordPoESystem, MilGigESystem, UseActionCapableDevices);
}
if (Devices.empty())
{
MosPrintf(MIL_TEXT("No compatible ToE %s have been found.\n"),
(MilConcordPoESystem == M_NULL ? MIL_TEXT("systems") : MIL_TEXT("devices")));
MosPrintf(MIL_TEXT("Press <enter> to quit.\n"));
MosGetch();
if (MilConcordPoESystem)
{
MsysFree(MilConcordPoESystem);
}
MappFreeDefault(MilApplication, MilGigESystem, M_NULL, M_NULL, M_NULL);
return 0;
}
MosPrintf(MIL_TEXT("Found %d compatible devices using %s:\n"), (int)Devices.size(),
UseActionCapableDevices ? MIL_TEXT("ACTION COMMAND PACKETS") : MIL_TEXT("SOFTWARE TRIGGER PACKETS"));
for (size_t i = 0; i < Devices.size(); i++)
{
MosPrintf(MIL_TEXT("%.2d\t%s %s\n"), (int)i, Devices[i].Vendor.c_str(), Devices[i].Model.c_str());
Devices[i].Allocate();
if (UseActionCapableDevices)
{
Devices[i].GetActionSelectorInfo();
}
}
MosPrintf(MIL_TEXT("\nPress <enter> to continue.\n"));
MosGetch();
MsysControl(MilConcordPoESystem, M_TIMER1 + M_TIMER_DELAY, FREQ_TO_PERIOD_IN_NS(TriggerFrequency) /2);
MsysControl(MilConcordPoESystem, M_TIMER1 + M_TIMER_DURATION, FREQ_TO_PERIOD_IN_NS(TriggerFrequency) / 2);
MsysControl(MilConcordPoESystem, M_TIMER1 + M_TIMER_TRIGGER_SOURCE, M_CONTINUOUS);
if (UseActionCapableDevices)
{
SetupToEUsingActions(MilConcordPoESystem, Devices);
}
else
{
SetupToEUsingSoftware(MilConcordPoESystem, Devices);
}
for (size_t i = 0; i < Devices.size(); i++)
{
MdigProcess(Devices[i].MilDigitizerId, Devices[i].GrabBufList,
BUFFERING_SIZE_MAX, M_START, M_DEFAULT, ProcessingFunction, &Devices[i]);
}
MosPrintf(MIL_TEXT("Press <Enter> to start transmission of ToE packets and frame capture.\n"));
MosGetch();
if (UseActionCapableDevices)
MsysControl(MilConcordPoESystem, M_GC_ACTION0 + M_TRIGGER_STATE, M_ENABLE);
else
MsysControl(MilConcordPoESystem, M_GC_TRIGGER_SOFTWARE0 + M_TRIGGER_STATE, M_ENABLE);
MsysControl(MilConcordPoESystem, M_TIMER1 + M_TIMER_STATE, M_ENABLE);
MosPrintf(MIL_TEXT("Press <Enter> to stop the grab.\n\n"));
MosGetch();
MsysControl(MilConcordPoESystem, M_TIMER1 + M_TIMER_STATE, M_DISABLE);
if (UseActionCapableDevices)
MsysControl(MilConcordPoESystem, M_GC_ACTION0 + M_TRIGGER_STATE, M_DISABLE);
else
MsysControl(MilConcordPoESystem, M_GC_TRIGGER_SOFTWARE0 + M_TRIGGER_STATE, M_DISABLE);
MosSleep(250);
for (size_t i = 0; i < Devices.size(); i++)
{
MIL_INT ProcessFrameCount = 0;
MIL_DOUBLE ProcessFrameRate = 0;
MdigProcess(Devices[i].MilDigitizerId, Devices[i].GrabBufList,
BUFFERING_SIZE_MAX, M_STOP, M_DEFAULT, ProcessingFunction, &Devices[i]);
MdigInquire(Devices[i].MilDigitizerId, M_PROCESS_FRAME_COUNT, &ProcessFrameCount);
MdigInquire(Devices[i].MilDigitizerId, M_PROCESS_FRAME_RATE, &ProcessFrameRate);
MosPrintf(MIL_TEXT("%d frames grabbed at %.1f frames/sec (%.1f ms/frame).\n"),
(int)ProcessFrameCount, ProcessFrameRate, 1000.0 / ProcessFrameRate);
}
MosPrintf(MIL_TEXT("\nInter-frame jitter measurements (in nanoseconds):\n"));
PrintInterfameJitter(Devices, TriggerFrequency);
if (!UseActionCapableDevices)
{
MosPrintf(MIL_TEXT("\nNOTE: SOFTWARE TRIGGER PACKETS were used so inter-frame jitter can increase significantly.\n"));
}
MosPrintf(MIL_TEXT("\nPress <Enter> to end.\n\n"));
MosGetch();
for (size_t i = 0; i < Devices.size(); i++)
{
Devices[i].Free();
}
MsysFree(MilConcordPoESystem);
MsysFree(MilGigESystem);
MappFree(MilApplication);
return 0;
}
void SetupToEUsingActions(MIL_ID MilConcordPoESystem, const std::vector<ToEDevice>& Devices)
{
MosPrintf(MIL_TEXT("\nSetting-up GigE Vision devices and the Matrox ConcordPoE board.\n\n"));
MIL_INT64 DeviceKey = 0x56781234, GroupKey = 0x24, GroupMask = 0xFFFFFFFF;
MsysControl(MilConcordPoESystem, M_GC_ACTION0 + M_GC_ACTION_DEVICE_KEY, DeviceKey);
MsysControl(MilConcordPoESystem, M_GC_ACTION0 + M_GC_ACTION_GROUP_KEY, GroupKey);
MsysControl(MilConcordPoESystem, M_GC_ACTION0 + M_GC_ACTION_GROUP_MASK, GroupMask);
MsysControl(MilConcordPoESystem, M_GC_ACTION0 + M_TRIGGER_SOURCE, M_TIMER1);
for (size_t i = 0; i < Devices.size(); i++)
{
MdigControlFeature(Devices[i].MilDigitizerId, M_FEATURE_VALUE, MIL_TEXT("ActionSelector"), M_TYPE_INT64, &Devices[i].ActionNumber);
MdigControlFeature(Devices[i].MilDigitizerId, M_FEATURE_VALUE, MIL_TEXT("ActionDeviceKey"), M_TYPE_INT64, &DeviceKey);
MdigControlFeature(Devices[i].MilDigitizerId, M_FEATURE_VALUE, MIL_TEXT("ActionGroupKey"), M_TYPE_INT64, &GroupKey);
MdigControlFeature(Devices[i].MilDigitizerId, M_FEATURE_VALUE, MIL_TEXT("ActionGroupMask"), M_TYPE_INT64, &GroupMask);
MdigControlFeature(Devices[i].MilDigitizerId, M_FEATURE_VALUE, MIL_TEXT("TriggerSelector"), M_TYPE_STRING, MIL_TEXT("FrameStart"));
MdigControlFeature(Devices[i].MilDigitizerId, M_FEATURE_VALUE, MIL_TEXT("TriggerSource"), M_TYPE_STRING, Devices[i].TriggerSource);
MdigControlFeature(Devices[i].MilDigitizerId, M_FEATURE_VALUE, MIL_TEXT("TriggerMode"), M_TYPE_STRING, MIL_TEXT("On"));
MsysControl(MilConcordPoESystem, M_GC_ACTION0 + M_ADD_DESTINATION, Devices[i].MilDigitizerId);
}
}
void SetupToEUsingSoftware(MIL_ID MilConcordPoESystem, const std::vector<ToEDevice>& Devices)
{
MosPrintf(MIL_TEXT("\nSetting-up GigE Vision devices and the Matrox ConcordPoE board.\n\n"));
MsysControl(MilConcordPoESystem, M_GC_TRIGGER_SOFTWARE0 + M_TRIGGER_SOURCE, M_TIMER1);
MsysControl(MilConcordPoESystem, M_GC_TRIGGER_SOFTWARE0 + M_GC_TRIGGER_SELECTOR, MIL_TEXT("FrameStart"));
for (size_t i = 0; i < Devices.size(); i++)
{
MdigControlFeature(Devices[i].MilDigitizerId, M_FEATURE_VALUE, MIL_TEXT("TriggerSelector"), M_TYPE_STRING, MIL_TEXT("FrameStart"));
MdigControlFeature(Devices[i].MilDigitizerId, M_FEATURE_VALUE, MIL_TEXT("TriggerSource"), M_TYPE_STRING, MIL_TEXT("Software"));
MdigControlFeature(Devices[i].MilDigitizerId, M_FEATURE_VALUE, MIL_TEXT("TriggerMode"), M_TYPE_STRING, MIL_TEXT("On"));
MsysControl(MilConcordPoESystem, M_GC_TRIGGER_SOFTWARE0 + M_ADD_DESTINATION, Devices[i].MilDigitizerId);
}
}
#define STRING_LENGTH_MAX 20
#define STRING_POS_X 20
#define STRING_POS_Y 20
MIL_INT MFTYPE ProcessingFunction(MIL_INT HookType, MIL_ID HookId, void* HookDataPtr)
{
ToEDevice &Device = *(ToEDevice*)HookDataPtr;
MIL_ID ModifiedBufferId;
MIL_DOUBLE TimeStamp = 0;
MIL_TEXT_CHAR Text[STRING_LENGTH_MAX] = { MIL_TEXT('\0'), };
MdigGetHookInfo(HookId, M_MODIFIED_BUFFER + M_BUFFER_ID, &ModifiedBufferId);
MdigGetHookInfo(HookId, M_GC_CAMERA_TIME_STAMP, &TimeStamp);
Device.ProcessedImageCount++;
MosSprintf(Text, STRING_LENGTH_MAX, MIL_TEXT("%d"),
(int)Device.ProcessedImageCount);
MgraText(M_DEFAULT, ModifiedBufferId, STRING_POS_X, STRING_POS_Y, Text);
MbufCopy(ModifiedBufferId, Device.MilImageDisp);
if (Device.TimeStamp != 0)
{
MIL_DOUBLE Delta = TimeStamp - Device.TimeStamp;
if (Delta > Device.DeltaMax)
{
Device.DeltaMax = Delta;
}
if (Delta < Device.DeltaMin)
{
Device.DeltaMin = Delta;
}
}
Device.TimeStamp = TimeStamp;
return 0;
}