MX Foundation 4
multi.c
/*****************************************************************************
//
## File:
## multi.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 the basic usage of MIL-STD-1553, ARINC 429,
// ASYNC, CSDB, Discrete and HDLC for transmission and reception at the same time.
//
// Hardware requirements:
// - MAXT FlexMulti-1553, FlexMulti-629-4, FlexMulti-429 or FlexMulti-664
//
*****************************************************************************/
#include "example.h"
#define ADDRESS 5
#define SUBADDRESS 3
#define ALMOST_FULL 10
#define ALMOST_EMPTY 5
#define MIL1553_IDX 0
#define A429_IDX 1
#define CSDB_IDX 2
#define ASYNC_IDX 3
#define DISCRETE_IDX 4
#define HDLC_IDX 5
#define BUFFER_SIZE 1*1024*1024 // 1MB
#define RATE 250*1000*1000 // 250msec
//#define LOCAL
//#define LOOPBACK
#define MIL1553
#define A429
#define CSDB
#define ASYNC
#define DISCRETE
#define HDLC
typedef struct
{
HMXF_CHANNEL txChannel;
HMXF_CHANNEL rxChannel;
HMXF_BUFFER txBuffer;
HMXF_BUFFER rxBuffer;
HMXF_SCHED sched;
}
EVENT_INFO_CHANNEL;
typedef struct
{
EVENT_INFO_CHANNEL channel[6];
void* hostBuffer;
void* reserved;
}
EVENT_INFO;
uint32 initHandler(HMXF_SERVER server, uint64 deviceIndex, uint64 moduleIndex, uint64 channelIndex, uint64 attrib, uint64* value);
uint32 eventHandler(HMXF_HANDLE asyncEvent, void* pParam);
#ifdef MIL1553
uint32 startMil1553(HMXF_DEVICE device, HMXF_ASYNCEVENT asyncEvent, EVENT_INFO_CHANNEL *eventInfoChn);
uint32 stopMil1553(HMXF_ASYNCEVENT asyncEvent, EVENT_INFO_CHANNEL *eventInfoChn);
#endif
#ifdef A429
uint32 startA429(HMXF_DEVICE device, HMXF_ASYNCEVENT asyncEvent, EVENT_INFO_CHANNEL *eventInfoChn);
uint32 stopA429(HMXF_ASYNCEVENT asyncEvent, EVENT_INFO_CHANNEL *eventInfoChn);
#endif
#ifdef CSDB
uint32 startCSDB(HMXF_DEVICE device, HMXF_ASYNCEVENT asyncEvent, EVENT_INFO_CHANNEL *eventInfoChn);
uint32 stopCSDB(HMXF_ASYNCEVENT asyncEvent, EVENT_INFO_CHANNEL *eventInfoChn);
#endif
#ifdef ASYNC
uint32 startASYNC(HMXF_DEVICE device, HMXF_ASYNCEVENT asyncEvent, EVENT_INFO_CHANNEL *eventInfoChn);
uint32 stopASYNC(HMXF_ASYNCEVENT asyncEvent, EVENT_INFO_CHANNEL *eventInfoChn);
#endif
#ifdef DISCRETE
uint32 startDiscrete(HMXF_DEVICE device, HMXF_ASYNCEVENT asyncEvent, EVENT_INFO_CHANNEL *eventInfoChn);
uint32 stopDiscrete(HMXF_ASYNCEVENT asyncEvent, EVENT_INFO_CHANNEL *eventInfoChn);
#endif
#ifdef HDLC
uint32 startHDLC(HMXF_DEVICE device, HMXF_ASYNCEVENT asyncEvent, EVENT_INFO_CHANNEL *eventInfoChn);
uint32 stopHDLC(HMXF_ASYNCEVENT asyncEvent, EVENT_INFO_CHANNEL *eventInfoChn);
#endif
int main(void)
{
uint32 rc;
uint64 deviceCount=0;
HMXF_SERVER server;
HMXF_DEVICE device=0;
MXF_DEVICE_INFO deviceInfo;
EVENT_INFO eventInfo;
HMXF_ASYNCEVENT asyncEvent=0;
char errorString[200];
#ifdef LOCAL
rc = mxfServerConnect("0.0.0.0", "", "", FALSE, &server);
#else
rc = mxfServerConnect("192.168.0.1", "admin", "admin", FALSE, &server);
#endif
if(rc!=MAXT_SUCCESS)
{
printf("Failed to connect; rc=0x%08x", rc);
getchar();
return 0;
}
printf("\n\rStarting\n\r");
memset(&eventInfo, 0, sizeof(eventInfo));
// Get handle of first device
if(!rc)
{
rc = mxfSystemDeviceAllGet(server, MXF_DEVICE_ALL, 1, &deviceCount, &device);
if(!rc && (deviceCount == 0))
rc = MAXT_ERROR_DEVICE_NOT_DETECTED;
}
// Get the device info to be used in init handler
if(!rc)
rc = mxfDeviceInfoGet(device, &deviceInfo);
// initialize init callback handler to set IPM-ASYNC-EH first TX and RX channel to CSDB
// and IPM-MULTI-EH first TX and RX channel to HDLC
rc = mxfSystemInitAttributeUint64CallbackHandler(server, &initHandler);
// Initialize MX Foundation library
if (!rc)
rc = mxfSystemInit(server);
// Set timebase to RTC nsec
if(!rc)
rc = mxfSystemTimeBaseSet(server, MXF_TIMEBASE_DEVICE_NSEC);
// Host allocation
if(!rc)
{
eventInfo.hostBuffer = malloc(BUFFER_SIZE);
if(!eventInfo.hostBuffer)
rc = MAXT_ERROR_MEM;
}
// Set asynchronous event handler
if(!rc)
rc = mxfAsyncEventHandlerInit(server, eventHandler, &eventInfo, &asyncEvent);
// Start transmission and acquisition
#ifdef MIL1553
if(!rc)
rc = startMil1553(device, asyncEvent, &eventInfo.channel[MIL1553_IDX]);
#endif
#ifdef A429
if(!rc)
rc = startA429(device, asyncEvent, &eventInfo.channel[A429_IDX]);
#endif
#ifdef CSDB
if(!rc)
rc = startCSDB(device, asyncEvent, &eventInfo.channel[CSDB_IDX]);
#endif
#ifdef ASYNC
if(!rc)
rc = startASYNC(device, asyncEvent, &eventInfo.channel[ASYNC_IDX]);
#endif
#ifdef DISCRETE
if(!rc)
rc = startDiscrete(device, asyncEvent, &eventInfo.channel[DISCRETE_IDX]);
#endif
#ifdef HDLC
if(!rc)
rc = startHDLC(device, asyncEvent, &eventInfo.channel[HDLC_IDX]);
#endif
if(!rc)
mxfSleep(10000);
#ifdef MIL1553
// Stop transmission and acquisition
if(!rc)
rc = stopMil1553(asyncEvent, &eventInfo.channel[MIL1553_IDX]);
#endif
#ifdef A429
if(!rc)
rc = stopA429(asyncEvent, &eventInfo.channel[A429_IDX]);
#endif
#ifdef CSDB
if(!rc)
rc = stopCSDB(asyncEvent, &eventInfo.channel[CSDB_IDX]);
#endif
#ifdef ASYNC
if(!rc)
rc = stopASYNC(asyncEvent, &eventInfo.channel[ASYNC_IDX]);
#endif
#ifdef DISCRETE
if(!rc)
rc = stopDiscrete(asyncEvent, &eventInfo.channel[DISCRETE_IDX]);
#endif
#ifdef HDLC
if(!rc)
rc = stopHDLC(asyncEvent, &eventInfo.channel[HDLC_IDX]);
#endif
// Terminate asynchronous event handler
if(asyncEvent)
if(rc)
{
if(mxfSystemErrorStringGet(server, rc, sizeof(errorString), errorString))
sprintf (errorString,"ERROR # 0x%08X", rc);
printf("%s\n\r", errorString);
}
// Free buffer
if(eventInfo.hostBuffer)
free(eventInfo.hostBuffer);
printf("\n\rPress a key to terminate\n\r");
getchar();
return 0;
}
uint32 initHandler(HMXF_SERVER server, uint64 deviceIndex, uint64 moduleIndex, uint64 channelIndex, uint64 attrib, uint64* value)
{
HMXF_DEVICE device;
MXF_DEVICE_INFO deviceInfo;
uint32 rc;
server=server;
deviceIndex=deviceIndex;
if(attrib == KMXF_CHANNEL_CLASS)
{
rc = mxfSystemDeviceGet(server, deviceIndex, &device);
if (!rc)
rc = mxfDeviceInfoGet(device, &deviceInfo);
if(!rc && (deviceInfo.modules[moduleIndex].type == MXF_MODULE_ASYNC_EH))
{
// Set IPM-ASYNC-EH first TX and RX channel to CSDB
if ((channelIndex == 0) || (channelIndex == deviceInfo.modules[moduleIndex].txCount))
{
*value = MXF_CLASS_CSDB;
return TRUE;
}
}
else
{
// Set IPM-MULTI-EH first TX and RX channel to HDLC
if ((channelIndex == 0) || (channelIndex == 8))
{
*value = MXF_CLASS_HDLC;
return TRUE;
}
else if ((channelIndex == 4) || (channelIndex == 12))
{
*value = MXF_CLASS_CLOCK;
return TRUE;
}
}
}
return FALSE;
}
uint32 startMil1553(HMXF_DEVICE device, HMXF_ASYNCEVENT asyncEvent, EVENT_INFO_CHANNEL *eventInfoChn)
{
uint32 rc;
HMXF_MODULE module;
uint64 count;
rc = mxfDeviceModuleAllGet(device, MXF_MODULE_MIL1553MRT_EH, 1, &count, &module);
if(!rc && !count)
rc = MAXT_ERROR_NOT_FOUND;
// Get handle of first MIL1553 Bus controller channel
if(!rc)
rc = mxfModuleChannelGet(module, 1, &eventInfoChn->txChannel);
// Get handle of first MIL1553 Bus monitor channel
if(!rc)
rc = mxfModuleChannelGet(module, 0, &eventInfoChn->rxChannel);
#ifdef LOOPBACK
if(!rc)
rc = mxfAttributeUint64Set(eventInfoChn->rxChannel, KMXF_MIL1553_TX_RX_TEST_LB, VMXF_ENABLE);
#endif
// Flex allocation for MIL1553 BC
if(!rc)
rc = mxfTxPeriodicUpdateMsgBufferAlloc(eventInfoChn->txChannel, 0, BUFFER_SIZE, &eventInfoChn->txBuffer, NULL);
// Flex allocation for MIL1553 BM
if(!rc)
rc = mxfRxAcqBufferAlloc(eventInfoChn->rxChannel, BUFFER_SIZE, &eventInfoChn->rxBuffer, NULL);
// Set the minor frame #0 using 1 command
if(!rc)
{
memset(minorFrame, 0, sizeof(minorFrame));
// Command #0 : Address 5, Subaddress 3, RX, 4 words
rc = mxfMIL1553CommandCompose(ADDRESS, SUBADDRESS, MXF_MIL1553_COMMAND_DIR_RX, 4, &minorFrame[0].command);
minorFrame[0].modulo = 1;
minorFrame[0].buffer = eventInfoChn->txBuffer;
}
if(!rc)
rc = mxfMIL1553TxPeriodicMajorFrameSet(eventInfoChn->txChannel, 0, 0, 1, minorFrame, NULL);
// Start message queue
if(!rc)
{
printf("Starting MIL1553\n\r");
}
// set event condition on TX periodic update message threshold for RT5
if(!rc)
{
memset(&eventInfoChn->txCondition, 0, sizeof(eventInfoChn->txCondition));
eventInfoChn->txCondition.condID = MXF_ASYNCEVENT_COND_TXPERIODIC_UPDATEMSG_BUFFER_THRESHOLD;
eventInfoChn->txCondition.condition.txPeriodicUpdateMsgBufferThreshold.almostEmpty = ALMOST_EMPTY;
eventInfoChn->txCondition.condition.txPeriodicUpdateMsgBufferThreshold.almostFull = ALMOST_FULL;
eventInfoChn->txCondition.condition.txPeriodicUpdateMsgBufferThreshold.channel = eventInfoChn->txChannel;
rc = mxfAsyncEventConditionsSet(asyncEvent, TRUE, 1, &eventInfoChn->txCondition);
}
// Select BC buffer for async event
if(!rc)
rc = mxfAsyncEventTxPeriodicUpdateMsgSelectSet(asyncEvent, eventInfoChn->txChannel, MXF_MSG_SELECT_ONLY, 1, &eventInfoChn->txBuffer);
// set event condition on RX acquisition buffer threshold
if(!rc)
{
memset(&eventInfoChn->rxCondition, 0, sizeof(eventInfoChn->rxCondition));
eventInfoChn->rxCondition.condID = MXF_ASYNCEVENT_COND_RXACQ_BUFFER_THRESHOLD;
eventInfoChn->rxCondition.condition.rxAcqBufferThreshold.almostEmpty = ALMOST_EMPTY;
eventInfoChn->rxCondition.condition.rxAcqBufferThreshold.almostFull = ALMOST_FULL;
eventInfoChn->rxCondition.condition.rxAcqBufferThreshold.buffer = eventInfoChn->rxBuffer;
rc = mxfAsyncEventConditionsSet(asyncEvent, TRUE, 1, &eventInfoChn->rxCondition);
}
// Start acquisition
if(!rc)
rc = mxfRxAcqStart(eventInfoChn->rxBuffer, MXF_RXACQ_FLAG_DEFAULT, 0, 0);
// Start the major frame with 250 msec rate
if(!rc)
rc = mxfMIL1553TxPeriodicMajorFrameStart(eventInfoChn->txChannel, 0, RATE, NULL);
return rc;
}
uint32 startA429(HMXF_DEVICE device, HMXF_ASYNCEVENT asyncEvent, EVENT_INFO_CHANNEL *eventInfoChn)
{
uint32 rc;
HMXF_MODULE module;
HMXF_SCHED_MSG msgSched=0;
uint64 count;
// Get handle of first A429 TX and RX channel
rc = mxfDeviceModuleAllGet(device, MXF_MODULE_A429_EH, 1, &count, &module);
if (!rc && !count)
rc = MAXT_ERROR_NOT_FOUND;
if(!rc)
rc = mxfModuleChannelGet(module, 0, &eventInfoChn->txChannel);
if(!rc)
{
rc = mxfModuleChannelAllGet(module, MXF_CLASS_A429, MXF_SCLASS_RX_CHANNEL, 1, &count, &eventInfoChn->rxChannel);
if (!rc && !count)
rc = MAXT_ERROR_NOT_FOUND;
}
#ifdef LOOPBACK
if(!rc)
rc = mxfAttributeUint64Set(eventInfoChn->rxChannel, KMXF_A429_TX_RX_TEST_LB, VMXF_ENABLE);
#endif
// Flex allocation for A429 TX
if(!rc)
rc = mxfTxPeriodicUpdateMsgBufferAlloc(eventInfoChn->txChannel, 0, BUFFER_SIZE, &eventInfoChn->txBuffer, NULL);
// Flex allocation for A429 RX
if(!rc)
rc = mxfRxAcqBufferAlloc(eventInfoChn->rxChannel, BUFFER_SIZE, &eventInfoChn->rxBuffer, NULL);
// Start message queue
if(!rc)
{
printf("Starting A429\n\r");
}
// set event condition on TX periodic update message threshold for label 5
if(!rc)
{
memset(&eventInfoChn->txCondition, 0, sizeof(eventInfoChn->txCondition));
eventInfoChn->txCondition.condID = MXF_ASYNCEVENT_COND_TXPERIODIC_UPDATEMSG_BUFFER_THRESHOLD;
eventInfoChn->txCondition.condition.txPeriodicUpdateMsgBufferThreshold.almostEmpty = ALMOST_EMPTY;
eventInfoChn->txCondition.condition.txPeriodicUpdateMsgBufferThreshold.almostFull = ALMOST_FULL;
eventInfoChn->txCondition.condition.txPeriodicUpdateMsgBufferThreshold.channel = eventInfoChn->txChannel;
rc = mxfAsyncEventConditionsSet(asyncEvent, TRUE, 1, &eventInfoChn->txCondition);
}
// Select buffer for async event
if(!rc)
rc = mxfAsyncEventTxPeriodicUpdateMsgSelectSet(asyncEvent, eventInfoChn->txChannel, MXF_MSG_SELECT_ONLY, 1, &eventInfoChn->txBuffer);
// set event condition on RX acquisition buffer threshold
if(!rc)
{
memset(&eventInfoChn->rxCondition, 0, sizeof(eventInfoChn->rxCondition));
eventInfoChn->rxCondition.condID = MXF_ASYNCEVENT_COND_RXACQ_BUFFER_THRESHOLD;
eventInfoChn->rxCondition.condition.rxAcqBufferThreshold.almostEmpty = ALMOST_EMPTY;
eventInfoChn->rxCondition.condition.rxAcqBufferThreshold.almostFull = ALMOST_FULL;
eventInfoChn->rxCondition.condition.rxAcqBufferThreshold.buffer = eventInfoChn->rxBuffer;
rc = mxfAsyncEventConditionsSet(asyncEvent, TRUE, 1, &eventInfoChn->rxCondition);
}
// Set the Periodic Scheduler
if(!rc)
rc = mxfTxPeriodicScheduleNew(eventInfoChn->txChannel, &eventInfoChn->sched);
// Set scheduling values: Rate=250 ms, Phase=0 us
if(!rc)
rc = mxfTxPeriodicScheduleMsgAdd(eventInfoChn->sched, RATE, 0, &msgSched);
// Define the number of buffer for the list and link to it
if(!rc)
rc = mxfTxPeriodicScheduleBufferListAdd(msgSched, 1, 0, &eventInfoChn->txBuffer);
// Start acquisition
if(!rc)
rc = mxfRxAcqStart(eventInfoChn->rxBuffer, MXF_RXACQ_FLAG_DEFAULT, 0, 0);
// Run the schedule
if(!rc)
rc = mxfTxPeriodicScheduleRun(eventInfoChn->sched);
return rc;
}
uint32 startCSDB(HMXF_DEVICE device, HMXF_ASYNCEVENT asyncEvent, EVENT_INFO_CHANNEL *eventInfoChn)
{
uint32 rc;
HMXF_MODULE module;
HMXF_SCHED_MSG msgSched=0;
MXF_CSDB_DATAREC recTXCsdb[1];
HMXF_BUFFER txSyncBuffer=0;
HMXF_BUFFER txBuffer[2];
uint64 count;
// Get handle of first CSDB TX and RX channel
rc = mxfDeviceModuleAllGet(device, MXF_MODULE_ASYNC_EH, 1, &count, &module);
if (!rc && !count)
rc = MAXT_ERROR_NOT_FOUND;
if(!rc)
rc = mxfModuleChannelGet(module, 0, &eventInfoChn->txChannel);
if(!rc)
{
rc = mxfModuleChannelAllGet(module, MXF_CLASS_CSDB, MXF_SCLASS_RX_CHANNEL, 1, &count, &eventInfoChn->rxChannel);
if (!rc && !count)
rc = MAXT_ERROR_NOT_FOUND;
}
#ifdef LOOPBACK
if(!rc)
rc = mxfAttributeUint64Set(eventInfoChn->rxChannel, KMXF_CSDB_TX_RX_TEST_LB, VMXF_ENABLE);
#endif
// Flex allocation for CSDB TX
if(!rc)
rc = mxfTxPeriodicUpdateMsgBufferAlloc(eventInfoChn->txChannel, 0, BUFFER_SIZE, &eventInfoChn->txBuffer, NULL);
if(!rc)
rc = mxfTxPeriodicUpdateMsgBufferAlloc(eventInfoChn->txChannel, 1, BUFFER_SIZE, &txSyncBuffer, NULL);
// Flex allocation for CSDB RX
if(!rc)
rc = mxfRxAcqBufferAlloc(eventInfoChn->rxChannel, BUFFER_SIZE, &eventInfoChn->rxBuffer, NULL);
// Start message queue
if(!rc)
{
printf("Starting CSDB\n\r");
}
// set event condition on TX periodic update message threshold for label 5
if(!rc)
{
memset(&eventInfoChn->txCondition, 0, sizeof(eventInfoChn->txCondition));
eventInfoChn->txCondition.condID = MXF_ASYNCEVENT_COND_TXPERIODIC_UPDATEMSG_BUFFER_THRESHOLD;
eventInfoChn->txCondition.condition.txPeriodicUpdateMsgBufferThreshold.almostEmpty = ALMOST_EMPTY;
eventInfoChn->txCondition.condition.txPeriodicUpdateMsgBufferThreshold.almostFull = ALMOST_FULL;
eventInfoChn->txCondition.condition.txPeriodicUpdateMsgBufferThreshold.channel = eventInfoChn->txChannel;
rc = mxfAsyncEventConditionsSet(asyncEvent, TRUE, 1, &eventInfoChn->txCondition);
}
// Select buffer for async event
if(!rc)
rc = mxfAsyncEventTxPeriodicUpdateMsgSelectSet(asyncEvent, eventInfoChn->txChannel, MXF_MSG_SELECT_ONLY, 1, &eventInfoChn->txBuffer);
// set event condition on RX acquisition buffer threshold
if(!rc)
{
memset(&eventInfoChn->rxCondition, 0, sizeof(eventInfoChn->rxCondition));
eventInfoChn->rxCondition.condID = MXF_ASYNCEVENT_COND_RXACQ_BUFFER_THRESHOLD;
eventInfoChn->rxCondition.condition.rxAcqBufferThreshold.almostEmpty = ALMOST_EMPTY;
eventInfoChn->rxCondition.condition.rxAcqBufferThreshold.almostFull = ALMOST_FULL;
eventInfoChn->rxCondition.condition.rxAcqBufferThreshold.buffer = eventInfoChn->rxBuffer;
rc = mxfAsyncEventConditionsSet(asyncEvent, TRUE, 1, &eventInfoChn->rxCondition);
}
// Set the Periodic Scheduler
if(!rc)
rc = mxfTxPeriodicScheduleNew(eventInfoChn->txChannel, &eventInfoChn->sched);
// Add one message to scheduler, Rate=250 ms, Phase=0 us
if(!rc)
rc = mxfTxPeriodicScheduleMsgAdd(eventInfoChn->sched, RATE, 0, &msgSched);
// Add two records to the message
if(!rc)
{
txBuffer[0] = txSyncBuffer;
txBuffer[1] = eventInfoChn->txBuffer;
rc = mxfTxPeriodicScheduleBufferListAdd(msgSched, 2, 0, txBuffer);
}
// Set default data for sync block
if(!rc)
{
// SYNC block
recTXCsdb[0].timeTag = 0;
recTXCsdb[0].control = 0;
recTXCsdb[0].repeatCount = 1;
recTXCsdb[0].reserved = 0;
recTXCsdb[0].data[0] = 0xA5;
recTXCsdb[0].data[1] = 0xA5;
recTXCsdb[0].data[2] = 0xA5;
recTXCsdb[0].data[3] = 0xA5;
recTXCsdb[0].data[4] = 0xA5;
recTXCsdb[0].data[5] = 0xA5;
}
if(!rc)
rc = mxfCSDBTxPeriodicUpdateMsgWrite(txSyncBuffer, 1, &recTXCsdb[0]);
// Start acquisition
if(!rc)
rc = mxfRxAcqStart(eventInfoChn->rxBuffer, MXF_RXACQ_FLAG_DEFAULT, 0, 0);
// Run the schedule
if(!rc)
rc = mxfTxPeriodicScheduleRun(eventInfoChn->sched);
return rc;
}
uint32 startASYNC(HMXF_DEVICE device, HMXF_ASYNCEVENT asyncEvent, EVENT_INFO_CHANNEL *eventInfoChn)
{
uint32 rc;
HMXF_MODULE module;
uint64 count;
// Get handle of first ASYNC TX and RX channel
rc = mxfDeviceModuleAllGet(device, MXF_MODULE_ASYNC_EH, 1, &count, &module);
if (!rc && !count)
rc = MAXT_ERROR_NOT_FOUND;
if (!rc)
rc = mxfModuleChannelGet(module, 1, &eventInfoChn->txChannel);
if (!rc)
{
rc = mxfModuleChannelAllGet(module, MXF_CLASS_ASYNC_ENHANCED, MXF_SCLASS_RX_CHANNEL, 1, &count, &eventInfoChn->rxChannel);
if (!rc && !count)
rc = MAXT_ERROR_NOT_FOUND;
}
#ifdef LOOPBACK
if(!rc)
rc = mxfAttributeUint64Set(eventInfoChn->rxChannel, KMXF_ASYNCEH_TX_RX_TEST_LB, VMXF_ENABLE);
#endif
// Set TX minimum string gap to 4 bit
if(!rc)
rc = mxfAttributeUint64Set(eventInfoChn->txChannel, KMXF_ASYNCEH_TX_STRING_GAP, 4*4);
// Flex allocation for ASYNC TX
if(!rc)
rc = mxfTxAperiodicBufferAlloc(eventInfoChn->txChannel, MXF_TXAPERIODIC_PRIORITY_NORMAL, BUFFER_SIZE, &eventInfoChn->txBuffer, NULL);
// Flex allocation for ASYNC RX
if(!rc)
rc = mxfRxAcqBufferAlloc(eventInfoChn->rxChannel, BUFFER_SIZE, &eventInfoChn->rxBuffer, NULL);
// set event condition on RX acquisition buffer threshold
if(!rc)
{
memset(&eventInfoChn->rxCondition, 0, sizeof(eventInfoChn->rxCondition));
eventInfoChn->rxCondition.condID = MXF_ASYNCEVENT_COND_RXACQ_BUFFER_THRESHOLD;
eventInfoChn->rxCondition.condition.rxAcqBufferThreshold.almostEmpty = ALMOST_EMPTY;
eventInfoChn->rxCondition.condition.rxAcqBufferThreshold.almostFull = ALMOST_FULL;
eventInfoChn->rxCondition.condition.rxAcqBufferThreshold.buffer = eventInfoChn->rxBuffer;
rc = mxfAsyncEventConditionsSet(asyncEvent, TRUE, 1, &eventInfoChn->rxCondition);
}
// Start acquisition
if(!rc)
{
printf("Starting ASYNC\n\r");
rc = mxfRxAcqStart(eventInfoChn->rxBuffer, MXF_RXACQ_FLAG_DEFAULT, 0, 0);
}
// set event condition on TX aperiodic buffer threshold
if(!rc)
{
memset(&eventInfoChn->txCondition, 0, sizeof(eventInfoChn->txCondition));
eventInfoChn->txCondition.condID = MXF_ASYNCEVENT_COND_TXAPERIODIC_BUFFER_THRESHOLD;
eventInfoChn->txCondition.condition.txAperiodicBufferThreshold.almostEmpty = ALMOST_EMPTY;
eventInfoChn->txCondition.condition.txAperiodicBufferThreshold.almostFull = ALMOST_FULL;
eventInfoChn->txCondition.condition.txAperiodicBufferThreshold.buffer = eventInfoChn->txBuffer;
rc = mxfAsyncEventConditionsSet(asyncEvent, TRUE, 1, &eventInfoChn->txCondition);
}
return rc;
}
uint32 startDiscrete(HMXF_DEVICE device, HMXF_ASYNCEVENT asyncEvent, EVENT_INFO_CHANNEL *eventInfoChn)
{
uint32 rc;
HMXF_MODULE module;
uint64 moduleCount;
// Get handle of first Discrete TX and RX channel
rc = mxfDeviceModuleAllGet(device, MXF_MODULE_DIOFIFO_EH, 1, &moduleCount, &module);
if(!rc)
rc = mxfModuleChannelGet(module, 0, &eventInfoChn->txChannel);
if(!rc)
rc = mxfModuleChannelGet(module, 1, &eventInfoChn->rxChannel);
#ifdef LOOPBACK
if(!rc)
rc = mxfAttributeUint64Set(eventInfoChn->rxChannel, KMXF_DISCRETE_TX_RX_TEST_LB, VMXF_ENABLE);
#endif
// Flex allocation for Discrete TX
if(!rc)
rc = mxfTxAperiodicBufferAlloc(eventInfoChn->txChannel, MXF_TXAPERIODIC_PRIORITY_NORMAL, BUFFER_SIZE, &eventInfoChn->txBuffer, NULL);
// Flex allocation for Discrete RX
if(!rc)
rc = mxfRxAcqBufferAlloc(eventInfoChn->rxChannel, BUFFER_SIZE, &eventInfoChn->rxBuffer, NULL);
// set event condition on RX acquisition buffer threshold
if(!rc)
{
memset(&eventInfoChn->rxCondition, 0, sizeof(eventInfoChn->rxCondition));
eventInfoChn->rxCondition.condID = MXF_ASYNCEVENT_COND_RXACQ_BUFFER_THRESHOLD;
eventInfoChn->rxCondition.condition.rxAcqBufferThreshold.almostEmpty = ALMOST_EMPTY;
eventInfoChn->rxCondition.condition.rxAcqBufferThreshold.almostFull = ALMOST_FULL;
eventInfoChn->rxCondition.condition.rxAcqBufferThreshold.buffer = eventInfoChn->rxBuffer;
rc = mxfAsyncEventConditionsSet(asyncEvent, TRUE, 1, &eventInfoChn->rxCondition);
}
// Start acquisition
if(!rc)
{
printf("Starting Discrete\n\r");
rc = mxfRxAcqStart(eventInfoChn->rxBuffer, MXF_RXACQ_FLAG_DEFAULT, 0, 0);
}
// set event condition on TX aperiodic buffer threshold
if(!rc)
{
memset(&eventInfoChn->txCondition, 0, sizeof(eventInfoChn->txCondition));
eventInfoChn->txCondition.condID = MXF_ASYNCEVENT_COND_TXAPERIODIC_BUFFER_THRESHOLD;
eventInfoChn->txCondition.condition.txAperiodicBufferThreshold.almostEmpty = ALMOST_EMPTY;
eventInfoChn->txCondition.condition.txAperiodicBufferThreshold.almostFull = ALMOST_FULL;
eventInfoChn->txCondition.condition.txAperiodicBufferThreshold.buffer = eventInfoChn->txBuffer;
rc = mxfAsyncEventConditionsSet(asyncEvent, TRUE, 1, &eventInfoChn->txCondition);
}
return rc;
}
uint32 startHDLC(HMXF_DEVICE device, HMXF_ASYNCEVENT asyncEvent, EVENT_INFO_CHANNEL *eventInfoChn)
{
uint32 rc;
HMXF_MODULE module;
uint64 count;
// Get handle of first Discrete TX and RX channel
rc = mxfDeviceModuleAllGet(device, MXF_MODULE_MULTI_EH, 1, &count, &module);
if(!rc && count)
rc = mxfModuleChannelAllGet(module, MXF_CLASS_HDLC, MXF_SCLASS_TX_CHANNEL, 1, &count, &eventInfoChn->txChannel);
if (!rc && count)
rc = mxfModuleChannelAllGet(module, MXF_CLASS_HDLC, MXF_SCLASS_RX_CHANNEL, 1, &count, &eventInfoChn->rxChannel);
// If module or channel not found, return an error
if (!rc && !count)
rc = MAXT_ERROR_NOT_FOUND;
#ifdef LOOPBACK
if(!rc)
rc = mxfAttributeUint64Set(eventInfoChn->rxChannel, KMXF_HDLC_TX_RX_TEST_LB, VMXF_ENABLE);
#endif
// Flex allocation for HDLC TX
if(!rc)
rc = mxfTxAperiodicBufferAlloc(eventInfoChn->txChannel, MXF_TXAPERIODIC_PRIORITY_NORMAL, BUFFER_SIZE, &eventInfoChn->txBuffer, NULL);
// Flex allocation for HDLC RX
if(!rc)
rc = mxfRxAcqBufferAlloc(eventInfoChn->rxChannel, BUFFER_SIZE, &eventInfoChn->rxBuffer, NULL);
// set event condition on RX acquisition buffer threshold
if(!rc)
{
memset(&eventInfoChn->rxCondition, 0, sizeof(eventInfoChn->rxCondition));
eventInfoChn->rxCondition.condID = MXF_ASYNCEVENT_COND_RXACQ_BUFFER_THRESHOLD;
eventInfoChn->rxCondition.condition.rxAcqBufferThreshold.almostEmpty = ALMOST_EMPTY;
eventInfoChn->rxCondition.condition.rxAcqBufferThreshold.almostFull = ALMOST_FULL;
eventInfoChn->rxCondition.condition.rxAcqBufferThreshold.buffer = eventInfoChn->rxBuffer;
rc = mxfAsyncEventConditionsSet(asyncEvent, TRUE, 1, &eventInfoChn->rxCondition);
}
// Start acquisition
if(!rc)
{
printf("Starting HDLC\n\r");
rc = mxfRxAcqStart(eventInfoChn->rxBuffer, MXF_RXACQ_FLAG_DEFAULT, 0, 0);
}
// set event condition on TX aperiodic buffer threshold
if(!rc)
{
memset(&eventInfoChn->txCondition, 0, sizeof(eventInfoChn->txCondition));
eventInfoChn->txCondition.condID = MXF_ASYNCEVENT_COND_TXAPERIODIC_BUFFER_THRESHOLD;
eventInfoChn->txCondition.condition.txAperiodicBufferThreshold.almostEmpty = ALMOST_EMPTY;
eventInfoChn->txCondition.condition.txAperiodicBufferThreshold.almostFull = ALMOST_FULL;
eventInfoChn->txCondition.condition.txAperiodicBufferThreshold.buffer = eventInfoChn->txBuffer;
rc = mxfAsyncEventConditionsSet(asyncEvent, TRUE, 1, &eventInfoChn->txCondition);
}
return rc;
}
uint32 stopMil1553(HMXF_ASYNCEVENT asyncEvent, EVENT_INFO_CHANNEL *eventInfoChn)
{
uint32 rc;
printf("Stopping MIL1553\n\r");
// Stop the major frame
rc = mxfTxPeriodicMajorFrameStop(eventInfoChn->txChannel, 0, 0);
// Stop acquisition
if(!rc)
rc = mxfRxAcqStop(eventInfoChn->rxBuffer);
// disable event condition
if(!rc)
rc = mxfAsyncEventConditionsSet(asyncEvent, FALSE, 1, &eventInfoChn->txCondition);
if(!rc)
rc = mxfAsyncEventConditionsSet(asyncEvent, FALSE, 1, &eventInfoChn->rxCondition);
return rc;
}
uint32 stopA429(HMXF_ASYNCEVENT asyncEvent, EVENT_INFO_CHANNEL *eventInfoChn)
{
uint32 rc;
printf("Stopping A429\n\r");
// Stop the schedule
rc = mxfTxPeriodicScheduleFree(eventInfoChn->sched);
// Stop acquisition
if(!rc)
rc = mxfRxAcqStop(eventInfoChn->rxBuffer);
// disable event condition
if(!rc)
rc = mxfAsyncEventConditionsSet(asyncEvent, FALSE, 1, &eventInfoChn->txCondition);
if(!rc)
rc = mxfAsyncEventConditionsSet(asyncEvent, FALSE, 1, &eventInfoChn->rxCondition);
return rc;
}
uint32 stopCSDB(HMXF_ASYNCEVENT asyncEvent, EVENT_INFO_CHANNEL *eventInfoChn)
{
uint32 rc;
printf("Stopping CSDB\n\r");
// Stop the schedule
rc = mxfTxPeriodicScheduleFree(eventInfoChn->sched);
// Stop acquisition
if(!rc)
rc = mxfRxAcqStop(eventInfoChn->rxBuffer);
// disable event condition
if(!rc)
rc = mxfAsyncEventConditionsSet(asyncEvent, FALSE, 1, &eventInfoChn->txCondition);
if(!rc)
rc = mxfAsyncEventConditionsSet(asyncEvent, FALSE, 1, &eventInfoChn->rxCondition);
return rc;
}
uint32 stopASYNC(HMXF_ASYNCEVENT asyncEvent, EVENT_INFO_CHANNEL *eventInfoChn)
{
uint32 rc;
printf("Stopping ASYNC\n\r");
// disable event condition
rc = mxfAsyncEventConditionsSet(asyncEvent, FALSE, 1, &eventInfoChn->txCondition);
if(!rc)
rc = mxfAsyncEventConditionsSet(asyncEvent, FALSE, 1, &eventInfoChn->rxCondition);
// Stop acquisition
if(!rc)
rc = mxfRxAcqStop(eventInfoChn->rxBuffer);
return rc;
}
uint32 stopDiscrete(HMXF_ASYNCEVENT asyncEvent, EVENT_INFO_CHANNEL *eventInfoChn)
{
uint32 rc;
printf("Stopping Discrete\n\r");
// disable event condition
rc = mxfAsyncEventConditionsSet(asyncEvent, FALSE, 1, &eventInfoChn->txCondition);
if(!rc)
rc = mxfAsyncEventConditionsSet(asyncEvent, FALSE, 1, &eventInfoChn->rxCondition);
// Stop acquisition
if(!rc)
rc = mxfRxAcqStop(eventInfoChn->rxBuffer);
return rc;
}
uint32 stopHDLC(HMXF_ASYNCEVENT asyncEvent, EVENT_INFO_CHANNEL *eventInfoChn)
{
uint32 rc;
printf("Stopping HDLC\n\r");
// disable event condition
rc = mxfAsyncEventConditionsSet(asyncEvent, FALSE, 1, &eventInfoChn->txCondition);
if(!rc)
rc = mxfAsyncEventConditionsSet(asyncEvent, FALSE, 1, &eventInfoChn->rxCondition);
// Stop acquisition
if(!rc)
rc = mxfRxAcqStop(eventInfoChn->rxBuffer);
return rc;
}
uint32 eventHandler(HMXF_HANDLE asyncEvent, void* pParam)
{
EVENT_INFO* eventInfo=(EVENT_INFO*)pParam;
uint32 rc=0;
uint64 eventCount;
uint64 rec;
// Get pending event
rc=mxfAsyncEventPendingGet(asyncEvent, 1, &eventCount, &pendingList);
if(!rc)
{
switch(pendingList.condID)
{
case MXF_ASYNCEVENT_COND_TXPERIODIC_UPDATEMSG_BUFFER_THRESHOLD:
{
// Set data for MIL1553 BC buffer
if(pendingList.condition.txPeriodicUpdateMsgBufferThreshold.buffer == eventInfo->channel[MIL1553_IDX].txBuffer)
{
MXF_MIL1553_DATAREC *txRec = (MXF_MIL1553_DATAREC *)eventInfo->hostBuffer;
memset(txRec, 0, BUFFER_SIZE);
for(rec=0; rec<pendingList.condition.txPeriodicUpdateMsgBufferThreshold.almostFull; rec++)
{
txRec->repeatCount = 1;
txRec->dataSize = 10; //10 bytes (command + 4 words)
txRec->data[0] = 0x0000; //Not used
txRec->data[1] = (uint16)rec;
txRec->data[2] = (uint16)rec;
txRec->data[3] = (uint16)rec;
txRec->data[4] = (uint16)rec;
}
rc = mxfTxPeriodicUpdateMsgWrite(pendingList.condition.txPeriodicUpdateMsgBufferThreshold.buffer, rec, eventInfo->hostBuffer);
}
else if(pendingList.condition.txPeriodicUpdateMsgBufferThreshold.buffer == eventInfo->channel[A429_IDX].txBuffer) // Set data for A429 TX buffer
{
MXF_A429_DATAREC *txRec = (MXF_A429_DATAREC *)eventInfo->hostBuffer;
memset(txRec, 0, BUFFER_SIZE);
for(rec=0; rec<pendingList.condition.txPeriodicUpdateMsgBufferThreshold.almostFull; rec++)
{
txRec->repeatCount = 1;
mxfA429ArwCompose(ADDRESS, SUBADDRESS, rec, 0, VMXF_A429_PARITY_ODD, &txRec->data);
}
rc = mxfTxPeriodicUpdateMsgWrite(pendingList.condition.txPeriodicUpdateMsgBufferThreshold.buffer, rec, eventInfo->hostBuffer);
}
else if(pendingList.condition.txPeriodicUpdateMsgBufferThreshold.buffer == eventInfo->channel[CSDB_IDX].txBuffer) // Set data for CSDB TX buffer
{
MXF_CSDB_DATAREC *txRec = (MXF_CSDB_DATAREC *)eventInfo->hostBuffer;
memset(txRec, 0, BUFFER_SIZE);
for(rec=0; rec<pendingList.condition.txPeriodicUpdateMsgBufferThreshold.almostFull; rec++)
{
txRec->repeatCount = 1;
txRec->data[0] = (uint8)rec;
txRec->data[1] = (uint8)rec;
txRec->data[2] = (uint8)rec;
txRec->data[3] = (uint8)rec;
txRec->data[4] = (uint8)rec;
txRec->data[5] = (uint8)rec;
}
rc = mxfTxPeriodicUpdateMsgWrite(pendingList.condition.txPeriodicUpdateMsgBufferThreshold.buffer, rec, eventInfo->hostBuffer);
}
break;
}
case MXF_ASYNCEVENT_COND_TXAPERIODIC_BUFFER_THRESHOLD:
{
// Set data for ASYNC TX buffer
if(pendingList.condition.txAperiodicBufferThreshold.buffer == eventInfo->channel[ASYNC_IDX].txBuffer)
{
MXF_ASYNCEH_DATAREC *txRec = (MXF_ASYNCEH_DATAREC *)eventInfo->hostBuffer;
int i;
memset(txRec, 0, BUFFER_SIZE);
for(rec=0; rec<pendingList.condition.txAperiodicBufferThreshold.almostFull; rec++)
{
txRec->repeatCount = 1;
txRec->dataSize = 10; //10 bytes
for(i=0; i<10; i++)
txRec->data[i] = (uint8)rec;
}
rc = mxfTxAperiodicWrite(pendingList.condition.txAperiodicBufferThreshold.buffer, MXF_TXAPERIODIC_FLAG_DEFAULT, RATE*rec, rec, eventInfo->hostBuffer);
}
else if(pendingList.condition.txPeriodicUpdateMsgBufferThreshold.buffer == eventInfo->channel[DISCRETE_IDX].txBuffer) // Set data for Discrete TX buffer
{
MXF_DISCRETE_DATAREC *txRec = (MXF_DISCRETE_DATAREC *)eventInfo->hostBuffer;
static uint64 timer=0;
if(timer == 0)
{
uint64 device;
rc = mxfChannelInfoGet(eventInfo->channel[DISCRETE_IDX].txChannel, &device, NULL);
if(!rc)
rc = mxfDeviceTimerGet(device, &timer);
if(rc)
break;
}
memset(txRec, 0, BUFFER_SIZE);
for(rec=0; rec<pendingList.condition.txAperiodicBufferThreshold.almostFull; rec++)
{
txRec->timeTag = timer;
txRec->repeatCount = 1;
txRec->data = (uint8)rec;
txRec->edge = 0x00ff;
timer += RATE;
}
rc = mxfTxAperiodicWrite(pendingList.condition.txAperiodicBufferThreshold.buffer, MXF_TXAPERIODIC_FLAG_USE_RECORD_ABSOLUTE_TIME, 0, rec, eventInfo->hostBuffer);
}
else if(pendingList.condition.txPeriodicUpdateMsgBufferThreshold.buffer == eventInfo->channel[HDLC_IDX].txBuffer) // Set data for HDLC TX buffer
{
MXF_HDLC_DATAREC *txRec = (MXF_HDLC_DATAREC *)eventInfo->hostBuffer;
uint64 i;
memset(txRec, 0, BUFFER_SIZE);
for(rec=0; rec<pendingList.condition.txAperiodicBufferThreshold.almostFull; rec++)
{
txRec->repeatCount = 1;
txRec->dataSize = 20; //20 bytes
for(i=0; i<txRec->dataSize/2; i++)
txRec->data[i] = (uint16)rec;
}
rc = mxfTxAperiodicWrite(pendingList.condition.txAperiodicBufferThreshold.buffer, MXF_TXAPERIODIC_FLAG_DEFAULT, RATE*rec, rec, eventInfo->hostBuffer);
}
break;
}
case MXF_ASYNCEVENT_COND_RXACQ_BUFFER_THRESHOLD:
{
uint64 rxAcqStatus, msgCount, byteCount;
rc = mxfRxAcqRead(pendingList.condition.rxAcqBufferThreshold.buffer, 0, BUFFER_SIZE, &rxAcqStatus, &msgCount, &byteCount, eventInfo->hostBuffer);
if(rc)
break;
// Get data for MIL1553 BM buffer
if(pendingList.condition.rxAcqBufferThreshold.buffer == eventInfo->channel[MIL1553_IDX].rxBuffer)
{
MXF_MIL1553_DATAREC *rxRec = (MXF_MIL1553_DATAREC *)eventInfo->hostBuffer;
uint64 data;
for(rec=0; !rc && rec<msgCount; rec++)
{
printf("MIL1553 --> %012llu ", rxRec->timeTag);
printf("%08X ", rxRec->control);
printf("%04u ", (rxRec->dataSize/2)-1);
for(data=0; data < min(8, rxRec->dataSize/2); data++)
{
printf("%04X ", rxRec->data[data]);
}
printf("\n\r");
}
}
else if(pendingList.condition.rxAcqBufferThreshold.buffer == eventInfo->channel[A429_IDX].rxBuffer) // Get data for A429 RX buffer
{
MXF_A429_DATAREC *rxRec = (MXF_A429_DATAREC *)eventInfo->hostBuffer;
for(rec=0; !rc && rec<msgCount; rec++)
{
printf("A429 --> %012llu ", rxRec->timeTag);
printf("%08X ", rxRec->control);
printf("%08X \n\r", rxRec->data);
}
}
else if(pendingList.condition.rxAcqBufferThreshold.buffer == eventInfo->channel[CSDB_IDX].rxBuffer) // Get data for CSDB RX buffer
{
MXF_CSDB_DATAREC *rxRec = (MXF_CSDB_DATAREC *)eventInfo->hostBuffer;
uint64 data;
for(rec=0; !rc && rec<msgCount; rec++)
{
printf("CSDB --> %012llu ", rxRec->timeTag);
printf("%08X ", rxRec->control);
for(data=0; data < 6; data++)
{
printf("%02X ", rxRec->data[data]);
}
printf("\n\r");
}
}
else if(pendingList.condition.rxAcqBufferThreshold.buffer == eventInfo->channel[ASYNC_IDX].rxBuffer) // Get data for ASYNC RX buffer
{
MXF_ASYNCEH_DATAREC *rxRec = (MXF_ASYNCEH_DATAREC *)eventInfo->hostBuffer;
uint64 data;
for(rec=0; !rc && rec<msgCount; rec++)
{
printf("ASYNC --> %012llu ", rxRec->timeTag);
printf("%08X ", rxRec->control);
printf("%04u ", rxRec->dataSize);
for(data=0; data < rxRec->dataSize; data++)
{
printf("%02X ", rxRec->data[data]);
}
printf("\n\r");
}
}
else if(pendingList.condition.rxAcqBufferThreshold.buffer == eventInfo->channel[DISCRETE_IDX].rxBuffer) // Get data for Discrete RX buffer
{
MXF_DISCRETE_DATAREC *rxRec = (MXF_DISCRETE_DATAREC *)eventInfo->hostBuffer;
for(rec=0; !rc && rec<msgCount; rec++)
{
printf("DISCRETE --> %012llu ", rxRec->timeTag);
printf("%02X ", (uint8)rxRec->edge);
printf("%02X \n\r", (uint8)rxRec->data);
}
}
else if(pendingList.condition.txPeriodicUpdateMsgBufferThreshold.buffer == eventInfo->channel[HDLC_IDX].rxBuffer) // Get data for HDLC RX buffer
{
MXF_HDLC_DATAREC *rxRec = (MXF_HDLC_DATAREC *)eventInfo->hostBuffer;
uint64 data;
for(rec=0; !rc && rec<msgCount; rec++)
{
printf("HDLC --> %012llu ", rxRec->timeTag);
printf("%08X ", rxRec->control);
printf("%04u ", (rxRec->dataSize/2));
for(data=0; data < min(8, rxRec->dataSize/2); data++)
{
printf("%04X ", rxRec->data[data]);
}
printf("\n\r");
}
}
break;
}
}
}
if(rc)
printf("event handler rc=0x%08x\n\r", rc);
return rc;
}
Updated 10/23/2023