MX Foundation 4
discrete_event_handler.c
/******************************************************************************
//
// File:
// discrete_event_handler.c
//
// Copyright (c) MAX Technologies Inc. 1988-2015, All Rights Reserved.
// CONFIDENTIAL AND PROPRIETARY INFORMATION WHICH IS THE
// PROPERTY OF MAX TECHNOLOGIES INC.
//
// This example demonstrates how to read discrete input from event handler
// and to write to discrete output.
//
// Hardware requirements:
// - MAXT Flex or MAXT 500 series carrier with IPM with discrete channel.
//
*******************************************************************************/
#include "example.h"
#define LOCAL
typedef struct
{
uint64 rxBufferSize;
MXF_DISCRETE_DATAREC* rxHostBuffer;
FILE* fp;
}
EVENT_INFO;
uint32 eventHandler(HMXF_HANDLE asyncEvent, void* param);
uint32 ReadDiscreteInput(HMXF_BUFFER bufferRx, EVENT_INFO* eventInfo);
int main(void)
{
uint32 rc;
uint64 channelCount=0;
uint64 msgCount;
HMXF_SERVER server;
HMXF_DEVICE device=0;
HMXF_MODULE module=0;
HMXF_CHANNEL rx=0;
HMXF_CHANNEL tx=0;
HMXF_BUFFER bufferRx=0;
HMXF_BUFFER bufferTx=0;
HMXF_ASYNCEVENT asyncEvent=0;
EVENT_INFO eventInfo;
char errorString[200];
uint64 moduleType=0;
uint32 edge=0x0010;
// Connect to services and initialize environment
#ifdef LOCAL
rc = mxfServerConnect("0.0.0.0", "", "", FALSE, &server);
#else
rc = mxfServerConnect("192.168.0.1", "admin", "admin", FALSE, &server);
#endif
// Initialize MX Foundation library
if(!rc)
{
printf("Starting ...\n");
rc = mxfSystemInit(server);
};
// Get handle of discrete input channel
if (!rc)
rc = mxfChannelAllGet(server, MXF_CLASS_DISCRETE, MXF_SCLASS_RX_CHANNEL, MXF_MODULE_ALL, 1, &channelCount, &rx);
// Get handle of discrete output channel
if(!rc && channelCount)
rc = mxfChannelAllGet(server, MXF_CLASS_DISCRETE, MXF_SCLASS_TX_CHANNEL, MXF_MODULE_ALL, 1, &channelCount, &tx);
if(!rc && !channelCount)
rc = MAXT_ERROR_NOT_FOUND;
if(!rc)
rc = mxfChannelInfoGet(rx, &device, &module);
// configure discrete input
if(!rc)
rc = mxfAttributeUint64Set(rx, KMXF_DISCRETE_RX_EDGE_FALLING, 0xff);
if(!rc)
rc = mxfAttributeUint64Set(rx, KMXF_DISCRETE_RX_EDGE_RISING, 0xff);
if (!rc)
rc = mxfAttributeUint64Get(module, KMXF_MODULE_TYPE, &moduleType);
if(!rc)
{
if(moduleType == MXF_MODULE_DIOFIFO_EH)
{
rc = mxfAttributeUint64Set(rx, KMXF_DISCRETE_RX_PULSE_WIDTH_FILTER, 100);
}
else
{
rc = mxfAttributeUint64Set(rx, KMXF_DISCRETE_DIRECTION, 0x00ff);
}
}
memset(&eventInfo, 0, sizeof(eventInfo));
// Allocate 10KB buffer for rx data
if(!rc)
{
eventInfo.rxBufferSize = 10*1024;
// Device allocation
rc = mxfRxAcqBufferAlloc(rx, eventInfo.rxBufferSize, &bufferRx, NULL);
// Host allocation
if(!rc)
{
eventInfo.rxHostBuffer = (MXF_DISCRETE_DATAREC*)malloc((size_t)eventInfo.rxBufferSize);
if(!eventInfo.rxHostBuffer)
rc = MAXT_ERROR_MEM;
}
}
// Set timebase to RTC nsec
if(!rc)
rc = mxfSystemTimeBaseSet(server, MXF_TIMEBASE_DEVICE_NSEC);
// Configure acquisition asynchronous event condition
if(!rc)
{
eventInfo.fp = fopen("discrete_log.txt", "w+t");
rc = mxfAsyncEventHandlerInit(server, &eventHandler, &eventInfo, &asyncEvent);
}
if(!rc)
{
condition.reserved = 0;
condition.condID = MXF_ASYNCEVENT_COND_RXACQ_BUFFER_THRESHOLD;
condition.condition.rxAcqBufferThreshold.buffer = bufferRx;
rc = mxfAsyncEventConditionsSet(asyncEvent, TRUE, 1, &condition);
}
// Start acquisition
if(!rc)
rc = mxfRxAcqStart(bufferRx, MXF_RXACQ_FLAG_DEFAULT, 0, 0);
if(!rc)
printf("Acquisition started\n");
if(!rc)
{
uint32 pulseCount;
uint64 timer=0;
memset(dioRec, 0, sizeof(dioRec));
// Allocate buffer for 300 discrete tx data
rc = mxfTxAperiodicBufferAlloc(tx, MXF_TXAPERIODIC_PRIORITY_NORMAL, 300*sizeof(MXF_DISCRETE_DATAREC), &bufferTx, NULL);
if(!rc)
rc = mxfDeviceTimerGet(device, &timer);
if(!rc)
{
// Fill the queue with; (2*100ms requests) => 10 records/secs => 300 records for the next 30 secs (max)
for(pulseCount=0; !rc && pulseCount<149-1; pulseCount++)
{
timer += (uint64)100*1000*1000; // 100 msec
dioRec[0].repeatCount= 1;
dioRec[0].control= 0;
dioRec[0].timeTag = timer;
dioRec[0].edge = edge;
dioRec[0].data = 0x0010;
timer += 100*1000*1000; // +100 msec
dioRec[1].repeatCount= 1;
dioRec[1].control= 0;
dioRec[1].timeTag = timer;
dioRec[1].edge = edge;
dioRec[1].data = 0x0000;
rc = mxfDiscreteTxAperiodicWrite(bufferTx, MXF_TXAPERIODIC_FLAG_USE_RECORD_ABSOLUTE_TIME, 0, 2, dioRec);
if (rc)
{
printf("mxfDiscreteTxAperiodicWrite() error; rc=0x%08x, pulse count=%u\n", rc, pulseCount);
break;
}
}
if(!rc)
{
do
{
rc = mxfTxAperiodicBufferStatusGet(bufferTx, &msgCount, NULL, NULL);
} while(!rc && (msgCount != 0));
}
}
}
// Wait a little
if(!rc)
mxfSleep(300);
// Stop acquisition
if(!rc)
rc = mxfRxAcqStop(bufferRx);
// Disable asynchronous event condition
if(!rc)
rc = mxfAsyncEventConditionsSet(asyncEvent, FALSE, 1, &condition);
// Clear the queue and terminate
if (!rc)
rc = mxfAsyncEventPendingClear(asyncEvent);
if(!rc)
// Clear what not sent yet (do not wait that queue is empty).
if(!rc)
mxfTxAperiodicClear(bufferTx, MXF_TXAPERIODIC_CLEAR_OPT_HWFIFO);
// Read last messages
if(!rc)
rc = ReadDiscreteInput(bufferRx, &eventInfo);
printf("\n");
// Close log file
if(eventInfo.fp)
fclose(eventInfo.fp);
// free buffers
if(eventInfo.rxHostBuffer)
free(eventInfo.rxHostBuffer);
if(rc)
{
if(mxfSystemErrorStringGet(server, rc, sizeof(errorString), errorString))
sprintf (errorString,"ERROR # 0x%08X", rc);
printf("%s\n\r", errorString);
}
// Free all buffers and terminate
if (bufferRx)
{
rc = mxfRxAcqBufferFree(bufferRx);
if (rc)
printf("Free buffer failed !\n\r");
}
if (bufferTx)
{
rc = mxfTxAperiodicBufferFree(bufferTx);
if (rc)
printf("Free buffer failed !\n\r");
}
// Unload MX Foundation library
printf("\nPress a key to terminate\n");
getchar();
return rc;
}
uint32 eventHandler(HMXF_HANDLE asyncEvent, void* param)
{
uint32 rc;
uint64 count;
// get asynchronous event information
rc = mxfAsyncEventPendingGet(asyncEvent, 1, &count, &pendingInfo);
if(!rc && count)
{
if(pendingInfo.condID == MXF_ASYNCEVENT_COND_RXACQ_BUFFER_THRESHOLD)
{
// Read discrete input
rc = ReadDiscreteInput(pendingInfo.condition.rxAcqBufferThreshold.buffer, (EVENT_INFO*)param);
printf("+");
}
}
if(rc)
printf("event handler rc=0x%08x\n", rc);
return rc;
}
uint32 ReadDiscreteInput(HMXF_BUFFER bufferRx, EVENT_INFO* eventInfo)
{
uint32 rc;
uint64 status, msgCount, byteCount, msg;
rc = mxfDiscreteRxAcqRead(bufferRx, 0, eventInfo->rxBufferSize, &status, &msgCount, &byteCount, eventInfo->rxHostBuffer);
rxRec = eventInfo->rxHostBuffer;
for (msg=0; msg<msgCount && !rc; msg++)
{
fprintf(eventInfo->fp, "%"PRIu64": 0x%04x 0x%04x\n\r", rxRec->timeTag, rxRec->data, rxRec->edge);
fflush(eventInfo->fp);
rc = mxfDiscreteNextDataRecordPtrGet(rxRec, &rxRec);
}
return rc;
}
Updated 10/23/2023