MX Foundation 4
Asynchronous Events

An application can register condition(s) to be monitored by the firmware.

When a callback handler is defined, the condition(s) are reported to the application asynchronously from the firmware to the handler.

The way to define a handler is as follows:

After this registration, the application can read acquisition data as usual and/or received asynchronous events through the callback handler.

The receive queue can also be read from the callback handler if necessary.

List of conditions

The event conditions that can be monitored are as follows:

Condition Description
MXF_ASYNCEVENT_COND_RX_MSG Specific message available in the buffer.
MXF_ASYNCEVENT_COND_RX_ERROR Receive errors on the RX port.
MXF_ASYNCEVENT_COND_RXACQ_BUFFER_THRESHOLD Acquisition buffer threshold exceeded.

Callback Handler

ar429_rx_event_handler.c
ar429_buffer_threshold.c
The function below illustrates how to define an asynchronous callback handler for trapping ARINC 429 RX conditions.

uint32 asyncEventHandler(HMXF_ASYNCEVENT asyncEvent, void *param)
{
HMXF_CHANNEL channel;
uint64 i, maxCount=64, pendingCount, status;
uint32 rc=MAXT_SUCCESS;
uint64 dev, mod, port;
// Builds the list of pending events to process
rc = mxfAsyncEventPendingGet(asyncEvent, maxCount, &pendingCount, pendingList);
for (i=0; i < pendingCount && !rc; i++)
{
switch ( pendingList[i].condID )
{
case MXF_ASYNCEVENT_COND_RXACQ_BUFFER_THRESHOLD:
{
MXF_A429_DATAREC *recPtr=rec429;
HMXF_BUFFER buffer;
uint64 status;
uint64 msgCount, byteCount;
uint32 label, sdi, data, ssm, parity;
uint64 msg;
uint32 rc=MAXT_SUCCESS;
buffer = pendingList[i].condition.rxAcqBufferThreshold.buffer;
// The buffer is almost full, we should then read the data with mxfA429RxAcqRead().
rc = mxfA429RxAcqRead(buffer, 0, BUFFER_SIZE, &status, &msgCount, &byteCount, rec429);
for (msg=0; msg<msgCount && !rc; msg++)
{
rc = mxfA429ArwDecompose(recPtr->data, &label, &sdi, &data, &ssm, &parity);
if(!rc)
{
printf("%02llu: Timetag %llu - ARINC word=[%03llo,%lld,%05llX,%lld,%s]\n",
msg, recPtr->timeTag, label, sdi, data, ssm, (parity==VMXF_A429_PARITY_ODD)?"ODD":"EVEN");
if(!rc)
rc = mxfA429NextDataRecordPtrGet(recPtr, &recPtr);
}
}
break;
}
case MXF_ASYNCEVENT_COND_RX_MSG:
{
HMXF_BUFFER sampBuffer;
uint32 label, sdi, data, ssm, parity;
channel = pendingList[i].condition.rxMsg.channel;
label = pendingList[i].condition.rxMsg.msg.a429.label;
sdi = pendingList[i].condition.rxMsg.msg.a429.sdi;
// An event was generated when the data on the specific (label,sdi) was received.
// Reads the last data received.
rc = mxfRxSamplingBufferGet(channel, &sampBuffer);
if(!rc)
rc = mxfA429RxSamplingSingleRead(sampBuffer, MXF_RXSAMPLING_FLAG_DEFAULT, label, sdi, &rec429);
if(!rc)
{
rc = mxfA429ArwDecompose(rec429.data, &label, &sdi, &data, &ssm, &parity);
if(!rc)
{
printf("Timetag %llu - ARINC word=[%03llo,%lld,%05llX,%lld,%s]\n",
rec429.timeTag, label, sdi, data, ssm, (parity==VMXF_A429_PARITY_ODD)?"ODD":"EVEN");
}
}
break;
}
case MXF_ASYNCEVENT_COND_RX_ERROR:
// A receive error was detected
channel = pendingList[i].condition.rxErr.channel;
status = pendingList[i].condition.rxErr.status;
rc = mxfChannelLocationGet(channel, &dev, &mod, &port);
if(!rc)
printf("Status 0x%08llx received on channel %llu.%llu.%llu\n", status, dev, mod, port);
break;
default:
printf("Unknown condID 0x%llx)", pendingList[i].condID);
break;
}
}
return rc;
}

Registering Conditions

ar429_rx_event_handler.c
ar429_buffer_threshold.c

In the example below a condition handler is defined to monitor conditions, and an ARINC 429 RX acquisition channel is started to receive data.

#define BUFFER_SIZE 1*1024*1024 // 1 MB
#define TX_LABEL 5
#define TX_SDI 0
HMXF_SERVER server;
HMXF_CHANNEL rxChannel;
HMXF_ASYNCEVENT asyncEvent=0;
MXF_ASYNCEVENT_CONDITION asyncEventInfo[2];
MXF_A429_DATAREC *hostBuffer=NULL;
...
// Allocates host buffer
if(!rc)
{
hostBuffer = (MXF_A429_DATAREC *)malloc(BUFFER_SIZE);
if(!hostBuffer)
rc = MAXT_ERROR_MEM;
}
// Sets the event handler
if(!rc)
rc = mxfAsyncEventHandlerInit(server, &asyncEventHandler, hostBuffer, &asyncEvent);
// Sets the RX async event conditions
if(!rc)
{
asyncEventInfo[0].condID = MXF_ASYNCEVENT_COND_RX_MSG;
asyncEventInfo[0].condition.rxMsg.channel = rxChannel;
asyncEventInfo[1].condID = MXF_ASYNCEVENT_COND_RX_ERROR;
asyncEventInfo[1].condition.rxErr.channel = rxChannel;
rc = mxfAsyncEventConditionsSet(asyncEvent, TRUE, 2, &asyncEventInfo[0]);
}
// Monitors a specific label/sdi
if (!rc)
{
msgid.label = LABEL;
msgid.sdi = SDI;
msgid.reserved[0] = 0;
msgid.reserved[1] = 0;
rc = mxfA429AsyncEventRxMsgSelectSet(asyncEvent, rxChannel, MXF_MSG_SELECT_ADD, 1, &msgid);
}
...
// Terminates async event handler
if(!rc)
rc = mxfAsyncEventConditionsSet(asyncEvent, FALSE, 2, asyncEventInfo);
if(!rc)
if(hostBuffer)
free(hostBuffer);
...
Updated 10/23/2023