MX Foundation 4
mil1553_bc_rt_data_assignment.c
/*****************************************************************************
//
// File:
// mil1553_bc_rt_data_assignment.c
//
// Copyright (c) MAX Technologies Inc. 1988-2016, All Rights Reserved.
// CONFIDENTIAL AND PROPRIETARY INFORMATION WHICH IS THE
// PROPERTY OF MAX TECHNOLOGIES INC.
//
// This example demonstrates the usage of buffer assignments for BC and RT,
// periodic update message with asynchronous events, IRIG-B timebase, and
// fixed delay between messages of the frame.
//
// Hardware requirements:
// - MAXT Flex1553-PCIe or FlexMulti or 500 series carrier with IPM-1553-MRT
//
*****************************************************************************/
#include "../../inc/example.h"
#define LOCAL
#define LOOPBACK
uint32 eventHandler(HMXF_HANDLE asyncEvent, void* pParam);
typedef struct
{
HMXF_BUFFER bcBuffer0;
HMXF_BUFFER bcBuffer1;
HMXF_BUFFER rtBuffer;
union
{
struct
{
}data;
uint64 reserved[2];
}u;
}
EVENT_INFO;
int main(void)
{
HMXF_SERVER server;
HMXF_DEVICE device=0;
HMXF_MODULE module=0;
HMXF_CHANNEL bc=0;
HMXF_CHANNEL bm=0;
HMXF_CHANNEL rt4=0;
HMXF_CHANNEL rt5=0;
HMXF_BUFFER acq1553Buffer=0;
HMXF_BUFFER bcBuffer0=0;
HMXF_BUFFER bcBuffer1=0;
HMXF_BUFFER bcBuffer2=0;
HMXF_BUFFER rt4Buffer0=0;
HMXF_BUFFER rt4Buffer1=0;
HMXF_BUFFER rt5Buffer0=0;
HMXF_BUFFER rt5Buffer1=0;
uint32 rc;
uint32 txDataSize=0;
uint32 rxDataSize=0;
uint64 rxAcqStatus;
uint64 msgCount;
uint64 byteCount;
uint64 rxRec;
uint64 loop=0;
uint32 data;
char errorString[200];
uint64 rate;
uint64 last=0, moduleCount=0;
uint64 irigbStatus=0;
HMXF_ASYNCEVENT asyncEvent=0;
EVENT_INFO eventInfo;
#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\r");
rc = mxfSystemInit(server);
}
// Get handle of first device
if(!rc)
rc = mxfSystemDeviceGet(server, 0, &device);
// Get handle of first module
// Try with MXF_MODULE_MIL1553MRT_EH and if not found, try with MXF_MODULE_MIL1553MRT
if(!rc)
rc = mxfDeviceModuleAllGet(device, MXF_MODULE_MIL1553MRT_EH, 1, &moduleCount, &module);
if (!rc && !moduleCount)
rc = mxfDeviceModuleAllGet(device, MXF_MODULE_MIL1553MRT, 1, &moduleCount, &module);
// Get handle of first MIL1553 Bus controller channel
if(!rc)
rc = mxfModuleChannelGet(module, 1, &bc);
// Get handle of first MIL1553 Bus monitor channel
if(!rc)
rc = mxfModuleChannelGet(module, 0, &bm);
// Get handle of MIL1553 remote terminal 4 channel
if(!rc)
rc = mxfModuleChannelGet(module, 2+4, &rt4);
// Get handle of MIL1553 remote terminal 5 channel
if(!rc)
rc = mxfModuleChannelGet(module, 2+5, &rt5);
#ifdef LOOPBACK
if(!rc)
rc = mxfAttributeUint64Set(bm, KMXF_MIL1553_TX_RX_TEST_LB, VMXF_ENABLE);
#endif
// Allocate 4KB buffer for bc data buffer 0
if(!rc)
{
txDataSize = 4096;
rc = mxfTxPeriodicUpdateMsgBufferAlloc(bc, 0, txDataSize, &bcBuffer0, NULL);
// Host allocation
if(!rc)
{
bcData0 = (MXF_MIL1553_DATAREC*)malloc(txDataSize);
if(!bcData0)
rc = MAXT_ERROR_MEM;
}
}
// Allocate 4KB buffer for bc data buffer 1
if(!rc)
{
txDataSize = 4096;
rc = mxfTxPeriodicUpdateMsgBufferAlloc(bc, 1, txDataSize, &bcBuffer1, NULL);
// Host allocation
if(!rc)
{
bcData1 = (MXF_MIL1553_DATAREC*)malloc(txDataSize);
if(!bcData1)
rc = MAXT_ERROR_MEM;
}
}
// Allocate 0KB buffer for bc data buffer 2
if(!rc)
{
txDataSize = 0;
rc = mxfTxPeriodicUpdateMsgBufferAlloc(bc, 2, txDataSize, &bcBuffer2, NULL);
}
// Allocate 4KB buffer for rt4 data buffer
if(!rc)
{
txDataSize = 4096;
// RX 0-31 --> 0-31
// TX 0-31 --> 32-63
// MODE-CODE 0-31 --> 64-95
// RT 4 SA 1 RX
rc = mxfTxPeriodicUpdateMsgBufferAlloc(rt4, 1, txDataSize, &rt4Buffer0, NULL);
// RT 4 SA 30 RX
if(!rc)
rc = mxfTxPeriodicUpdateMsgBufferAlloc(rt4, 30, txDataSize, &rt4Buffer1, NULL);
}
// Allocate 4KB buffer for rt5 data buffer
if(!rc)
{
txDataSize = 4096;
// RT 5 SA 1 RX
rc = mxfTxPeriodicUpdateMsgBufferAlloc(rt5, 1, txDataSize, &rt5Buffer0, NULL);
// RT 5 SA 1 TX
if(!rc)
rc = mxfTxPeriodicUpdateMsgBufferAlloc(rt5, 33, txDataSize, &rt5Buffer1, NULL);
// Host allocation
if(!rc)
{
rtData = (MXF_MIL1553_DATAREC*)malloc(txDataSize);
if(!rtData)
rc = MAXT_ERROR_MEM;
}
}
// Allocate 10KB buffer for 1553 acquisition data
if(!rc)
{
rxDataSize = 10*1024;
rc = mxfRxAcqBufferAlloc(bm, rxDataSize, &acq1553Buffer, NULL);
// Host allocation
if(!rc)
{
rxData = (MXF_MIL1553_DATAREC*)malloc(rxDataSize);
if(!rxData)
rc = MAXT_ERROR_MEM;
}
}
// Configure IRIG-B
// Enable IRIG-B generator
if(!rc)
{
printf("Configuring IRIG-B\n");
rc = mxfAttributeUint64Set(device, KMXF_DEVICE_IRIGB_GEN_ENABLE, TRUE);
}
// Enable IRIG-B internal loopback
if(!rc)
rc = mxfAttributeUint64Set(device, KMXF_DEVICE_IRIGB_GEN_LOOPBACK_ENABLE, TRUE);
// Set IRIG-B input to device input
if(!rc)
rc = mxfAttributeUint64Set(device, KMXF_DEVICE_IRIGB_INPUT, VMXF_DEVICE_IRIGB_INPUT_DEVICE);
// Set IRIG-B signal to digital
if(!rc)
rc = mxfAttributeUint64Set(device, KMXF_DEVICE_IRIGB_INPUT_SIGNAL, VMXF_DEVICE_IRIGB_INPUT_SIGNAL_DIGITAL);
// Wait IRIG-B signal locked
if(!rc)
{
do
{
rc = mxfDeviceIrigbStatusGet(device, &irigbStatus);
}while(!rc && (irigbStatus!=MXF_IRIGB_STATUS_NO_SIGNAL) && (irigbStatus!=MXF_IRIGB_STATUS_LOCKED));
}
// Set timebase to IRIG-B nsec
if(!rc)
{
if(irigbStatus == MXF_IRIGB_STATUS_LOCKED)
rc = mxfSystemTimeBaseSet(server, MXF_TIMEBASE_IRIGB_NSEC);
else
{
printf("No IRIG-B signal found\n\r");
rc = mxfSystemTimeBaseSet(server, MXF_TIMEBASE_COMPUTER_NSEC);
}
}
// Set the minor frame #0 using 5 Commands
if(!rc)
{
memset(minorFrame, 0, sizeof(minorFrame));
// Command #0 : Address 4, Subaddress 1, RX, 4 words
rc = mxfMIL1553CommandCompose(4, 1, MXF_MIL1553_COMMAND_DIR_RX, 4, &minorFrame[0].command);
minorFrame[0].modulo = 1;
minorFrame[0].buffer = bcBuffer0; // link command to bcBuffer0
// Command #1 : Address 5, Subaddress 1, RX, 4 words
if(!rc)
{
rc = mxfMIL1553CommandCompose(5, 1, MXF_MIL1553_COMMAND_DIR_RX, 4, &minorFrame[1].command);
minorFrame[1].modulo = 1;
minorFrame[1].buffer = bcBuffer0; // link command to bcBuffer0
minorFrame[1].delay = 8000; // send command 1 msec after preceding command
minorFrame[1].options = MXF_MIL1553_TXPERIODIC_MJRFRAME_MSG_OPT_DELAY;
}
// Command #2 : Address 4, Subaddress 30, RX, 4 words
if(!rc)
{
rc = mxfMIL1553CommandCompose(4, 30, MXF_MIL1553_COMMAND_DIR_RX, 4, &minorFrame[2].command);
minorFrame[2].modulo = 1;
minorFrame[2].buffer = bcBuffer1; // link command to bcBuffer1
minorFrame[2].delay = 8000; // send command 1 msec after preceding command
minorFrame[2].options = MXF_MIL1553_TXPERIODIC_MJRFRAME_MSG_OPT_DELAY;
}
// Command #3 : Address 4, Subaddress 30, TX, 4 words
if(!rc)
{
rc = mxfMIL1553CommandCompose(4, 30, MXF_MIL1553_COMMAND_DIR_TX, 4, &minorFrame[3].command);
minorFrame[3].modulo = 1;
minorFrame[3].buffer = bcBuffer2; // link command to bcBuffer2
minorFrame[3].delay = 8000; // send command 1 msec after preceding command
minorFrame[3].options = MXF_MIL1553_TXPERIODIC_MJRFRAME_MSG_OPT_DELAY;
}
// Command #4 : Address 5, Subaddress 1, TX, 4 words
if(!rc)
{
rc = mxfMIL1553CommandCompose(5, 1, MXF_MIL1553_COMMAND_DIR_TX, 4, &minorFrame[4].command);
minorFrame[4].modulo = 1;
minorFrame[4].buffer = bcBuffer2; // link command to bcBuffer2
minorFrame[4].delay = 8000; // send command 1 msec after preceding command
minorFrame[4].options = MXF_MIL1553_TXPERIODIC_MJRFRAME_MSG_OPT_DELAY;
}
if(!rc)
rc = mxfMIL1553TxPeriodicMajorFrameSet(bc, 0, 0, 5, minorFrame, NULL);
}
// Set default data for bc buffer 0
if(!rc)
{
txRec1553 = (MXF_MIL1553_DATAREC *)bcData0;
memset(txRec1553, 0, sizeof(MXF_MIL1553_DATAREC));
txRec1553->repeatCount = 1;
txRec1553->dataSize = 10; //10 bytes (command + 4 words)
txRec1553->data[0] = 0x0000; //Not used
txRec1553->data[1] = 0x0000;
txRec1553->data[2] = 0x1111;
txRec1553->data[3] = 0x2222;
txRec1553->data[4] = 0x3333;
rc = mxfMIL1553TxPeriodicUpdateMsgWrite(bcBuffer0, 1, bcData0);
}
// Set default data for bc buffer 1
if(!rc)
{
txRec1553 = (MXF_MIL1553_DATAREC *)bcData1;
memset(txRec1553, 0, sizeof(MXF_MIL1553_DATAREC));
txRec1553->repeatCount = 1;
txRec1553->dataSize = 10; //10 bytes (command + 4 words)
txRec1553->data[0] = 0x0000; //Not used
txRec1553->data[1] = 0x1234;
txRec1553->data[2] = 0x5678;
txRec1553->data[3] = 0x9ABC;
txRec1553->data[4] = 0xDEF0;
rc = mxfMIL1553TxPeriodicUpdateMsgWrite(bcBuffer1, 1, bcData1);
}
// Set default data for rt5 buffer 1
if(!rc)
{
txRec1553 = (MXF_MIL1553_DATAREC *)rtData;
memset(txRec1553, 0, sizeof(MXF_MIL1553_DATAREC));
txRec1553->repeatCount = 1;
txRec1553->dataSize = 10; //10 bytes (command + 4 words)
txRec1553->data[0] = 0x0000; //Not used
txRec1553->data[1] = 0xAAAA;
txRec1553->data[2] = 0xBBBB;
txRec1553->data[3] = 0xCCCC;
txRec1553->data[4] = 0xDDDD;
rc = mxfMIL1553TxPeriodicUpdateMsgWrite(rt5Buffer1, 1, rtData);
}
if(!rc)
{
printf("Starting RT 4\n\r");
rc = mxfMIL1553RtSubsystemEnableSet(rt4, MXF_MIL1553_MSGTYPE_RX, 1, MXF_MIL1553_BUS_A, rt4Buffer0);
if(!rc)
rc = mxfMIL1553RtSubsystemEnableSet(rt4, MXF_MIL1553_MSGTYPE_RX, 30, MXF_MIL1553_BUS_A, rt4Buffer1);
// link RT4 SA30 TX buffer to RT4 SA30 RX buffer (data wrap-around)
if(!rc)
rc = mxfMIL1553RtSubsystemEnableSet(rt4, MXF_MIL1553_MSGTYPE_TX, 30, MXF_MIL1553_BUS_A, rt4Buffer1);
if(!rc)
rc = mxfMIL1553RtEnableSet(rt4, TRUE);
}
if(!rc)
{
printf("Starting RT 5\n\r");
rc = mxfMIL1553RtSubsystemEnableSet(rt5, MXF_MIL1553_MSGTYPE_RX, 1, MXF_MIL1553_BUS_A, rt5Buffer0);
if(!rc)
rc = mxfMIL1553RtSubsystemEnableSet(rt5, MXF_MIL1553_MSGTYPE_TX, 1, MXF_MIL1553_BUS_A, rt5Buffer1);
if(!rc)
rc = mxfMIL1553RtEnableSet(rt5, TRUE);
}
// attach async event handler
if(!rc)
{
eventInfo.u.data.rtData = rtData;
eventInfo.u.data.bcData0 = bcData0;
eventInfo.u.data.bcData1 = bcData1;
eventInfo.bcBuffer0 = bcBuffer0;
eventInfo.bcBuffer1 = bcBuffer1;
eventInfo.rtBuffer = rt5Buffer1;
rc = mxfAsyncEventHandlerInit(server, eventHandler, &eventInfo, &asyncEvent);
}
// set event condition on TX periodic update message threshold for RT5
if(!rc)
{
memset(&condition, 0, sizeof(condition));
condition.condID = MXF_ASYNCEVENT_COND_TXPERIODIC_UPDATEMSG_BUFFER_THRESHOLD;
rc = mxfAsyncEventConditionsSet(asyncEvent, TRUE, 1, &condition);
}
// set event condition on TX periodic update message threshold for BC
if(!rc)
{
memset(&bcCondition, 0, sizeof(bcCondition));
bcCondition.condID = MXF_ASYNCEVENT_COND_TXPERIODIC_UPDATEMSG_BUFFER_THRESHOLD;
rc = mxfAsyncEventConditionsSet(asyncEvent, TRUE, 1, &bcCondition);
}
// Select BC buffers and RT buffer for async events
if(!rc)
rc = mxfAsyncEventTxPeriodicUpdateMsgSelectSet(asyncEvent, rt5, MXF_MSG_SELECT_ONLY, 1, &rt5Buffer1);
if(!rc)
rc = mxfAsyncEventTxPeriodicUpdateMsgSelectSet(asyncEvent, bc, MXF_MSG_SELECT_ONLY, 1, &bcBuffer0);
if(!rc)
rc = mxfAsyncEventTxPeriodicUpdateMsgSelectSet(asyncEvent, bc, MXF_MSG_SELECT_ADD, 1, &bcBuffer1);
// Start BM acquisition
if(!rc)
rc = mxfRxAcqStart(acq1553Buffer, MXF_RXACQ_FLAG_DEFAULT, 0, 0);
// Start the major frame
if(!rc)
rc = mxfMIL1553TxPeriodicMajorFrameStart(bc, 0, 50*1000*1000, NULL); //50 msec
if(!rc)
{
mxfSleep(2000);
}
// Read and display received messages
if(!rc)
{
loop=0;
do
{
rc = mxfMIL1553RxAcqRead(acq1553Buffer, 0, rxDataSize, &rxAcqStatus, &msgCount, &byteCount, rxData);
rxRec1553 = (MXF_MIL1553_DATAREC*)rxData;
for(rxRec=0; !rc && rxRec<msgCount; rxRec++)
{
rate = last?((rxRec1553->timeTag - last)/1000000):0;//msec
last = rxRec1553->timeTag;
printf("%012llu ", rxRec1553->timeTag);
printf("%03llu ", rate);
printf("%08X ", rxRec1553->control);
printf("%04u ", (rxRec1553->dataSize/2)-1);
for(data=0; data < min(8, rxRec1553->dataSize/2); data++)
{
printf("%04X ", rxRec1553->data[data]);
}
printf("\n\r");
// Get next msg
mxfMIL1553NextDataRecordPtrGet(rxRec1553, &rxRec1553);
}
mxfSleep(100);
loop++;
}
while(loop < 20);
}
// Clear the major frame
// Stop acquisition
mxfRxAcqStop(acq1553Buffer);
// Stop and Clear message queues
printf("Stopping BC and RTs\n\r");
mxfMIL1553RtEnableSet(rt4, FALSE);
mxfMIL1553RtEnableSet(rt5, FALSE);
// Disable conditions and detach event handler
mxfAsyncEventConditionsSet(asyncEvent, FALSE, 1, &condition);
mxfAsyncEventConditionsSet(asyncEvent, FALSE, 1, &bcCondition);
mxfRxAcqClear(acq1553Buffer);
// Free buffers
if(bcData0)
free(bcData0);
if(bcData1)
free(bcData1);
if(rtData)
free(rtData);
if(rxData)
free(rxData);
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(bcBuffer0)
{
if (rc)
printf("Free buffer failed !\n\r");
}
if(bcBuffer1)
{
if (rc)
printf("Free buffer failed !\n\r");
}
if(bcBuffer2)
{
if (rc)
printf("Free buffer failed !\n\r");
}
if(rt4Buffer0)
{
if (rc)
printf("Free buffer failed !\n\r");
}
if(rt4Buffer1)
{
if (rc)
printf("Free buffer failed !\n\r");
}
if(rt5Buffer0)
{
if (rc)
printf("Free buffer failed !\n\r");
}
if(rt5Buffer1)
{
if (rc)
printf("Free buffer failed !\n\r");
}
if(acq1553Buffer)
{
rc = mxfRxAcqBufferFree(acq1553Buffer);
if (rc)
printf("Free buffer failed !\n\r");
}
// Unload MX Foundation library
printf("\n\rPress enter to terminate\n\r");
getchar();
return 0;
}
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 rt5 buffer 1
if(pendingList.condition.txPeriodicUpdateMsgBufferThreshold.buffer == eventInfo->rtBuffer)
{
txRec1553 = (MXF_MIL1553_DATAREC *)eventInfo->u.data.rtData;
memset(txRec1553, 0, sizeof(MXF_MIL1553_DATAREC)*(size_t)pendingList.condition.txPeriodicUpdateMsgBufferThreshold.almostFull);
for(rec=0; rec<pendingList.condition.txPeriodicUpdateMsgBufferThreshold.almostFull; rec++)
{
txRec1553->repeatCount = 1;
txRec1553->dataSize = 10; //10 bytes (command + 4 words)
txRec1553->data[0] = 0x0000; //Not used
txRec1553->data[1] = (uint16)rec;
txRec1553->data[2] = (uint16)rec;
txRec1553->data[3] = (uint16)rec;
txRec1553->data[4] = (uint16)rec;
mxfMIL1553NextDataRecordPtrGet(txRec1553, &txRec1553);
}
}
else if(pendingList.condition.txPeriodicUpdateMsgBufferThreshold.buffer == eventInfo->bcBuffer0) // Set data for BC buffer 0
{
txRec1553 = (MXF_MIL1553_DATAREC *)eventInfo->u.data.bcData0;
memset(txRec1553, 0, sizeof(MXF_MIL1553_DATAREC)*(size_t)pendingList.condition.txPeriodicUpdateMsgBufferThreshold.almostFull);
for(rec=0; rec<pendingList.condition.txPeriodicUpdateMsgBufferThreshold.almostFull; rec++)
{
txRec1553->repeatCount = 1;
txRec1553->dataSize = 10; //10 bytes (command + 4 words)
txRec1553->data[0] = 0x0000; //Not used
txRec1553->data[1] = 0x1111 * (uint16)rec;
txRec1553->data[2] = 0x1111 * (uint16)rec;
txRec1553->data[3] = 0x1111 * (uint16)rec;
txRec1553->data[4] = 0x1111 * (uint16)rec;
mxfMIL1553NextDataRecordPtrGet(txRec1553, &txRec1553);
}
}
else if(pendingList.condition.txPeriodicUpdateMsgBufferThreshold.buffer == eventInfo->bcBuffer1) // Set data for BC buffer 1
{
txRec1553 = (MXF_MIL1553_DATAREC *)eventInfo->u.data.bcData1;
memset(txRec1553, 0, sizeof(MXF_MIL1553_DATAREC)*(size_t)pendingList.condition.txPeriodicUpdateMsgBufferThreshold.almostFull);
for(rec=0; rec<pendingList.condition.txPeriodicUpdateMsgBufferThreshold.almostFull; rec++)
{
txRec1553->repeatCount = 1;
txRec1553->dataSize = 10; //10 bytes (command + 4 words)
txRec1553->data[0] = 0x0000; //Not used
txRec1553->data[1] = (rec % 2)?0xACDC:0xCAFE;
txRec1553->data[2] = (rec % 2)?0xACDC:0xCAFE;
txRec1553->data[3] = (rec % 2)?0xACDC:0xCAFE;
txRec1553->data[4] = (rec % 2)?0xACDC:0xCAFE;
mxfMIL1553NextDataRecordPtrGet(txRec1553, &txRec1553);
}
}
break;
}
}
if(rc)
printf("event handler rc=0x%08x\n\r", rc);
return rc;
}
Updated 03/30/2022