MX Foundation 4
mil1553_aperiodic_frame.c
/*****************************************************************************
//
## File:
## mil1553_aperiodic_frame.c
//
// Copyright (c) MAX Technologies Inc. 1988-2019, All Rights Reserved.
// CONFIDENTIAL AND PROPRIETARY INFORMATION WHICH IS THE
// PROPERTY OF MAX TECHNOLOGIES INC.
//
// This example demonstrates the usage of major frame and aperiodic
// transmission with MIL-STD-1553 BC channel, message filtering on BM channel
// and MIL-STD-1760 checksum generation and verification.
//
// Hardware requirements:
// - MAXT Flex1553-PCIe (FX1553-4) or FlexMulti 1553 (FM1553-4)
//
*****************************************************************************/
#include "example.h"
#define LOCAL
//#define LOOPBACK
int main(void)
{
uint32 rc;
uint64 deviceCount = 0;
uint64 moduleCount = 0;
HMXF_SERVER server;
HMXF_DEVICE device = 0;
HMXF_MODULE module[2];
HMXF_CHANNEL bc = 0;
HMXF_CHANNEL bm = 0;
HMXF_CHANNEL rt4 = 0;
HMXF_CHANNEL rt5 = 0;
HMXF_BUFFER bcLowAperBuffer = 0;
HMXF_BUFFER bcHighAperBuffer = 0;
HMXF_BUFFER bcBuffer0 = 0;
HMXF_BUFFER bcBuffer1 = 0;
HMXF_BUFFER bcBufferTx = 0;
HMXF_BUFFER rt4Buffer = 0;
HMXF_BUFFER rt5Buffer = 0;
HMXF_BUFFER bmBuffer = 0;
uint64 startTime = 0;
uint64 txBufferSize = 0, rxBufferSize = 0;
MXF_MIL1553_DATAREC* txBuffer = NULL;
MXF_MIL1553_DATAREC* rxBuffer = NULL;
uint64 rxAcqStatus = 0;
uint64 msgCount;
uint64 byteCount;
uint64 rxRec;
uint32 data;
uint32 checksumError = 0;
char errorString[200];
// 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\r");
rc = mxfSystemInit(server);
}
//Get a FM1553-4 or FX1553-4 device handle
if (!rc)
rc = mxfSystemDeviceAllGet(server, MXF_DEVICE_FLEXMULTI_1553, 1, &deviceCount, &device);
if (!rc && !deviceCount)
rc = mxfSystemDeviceAllGet(server, MXF_DEVICE_FLEX1553_PCIE, 1, &deviceCount, &device);
// Get a MIL1553 module handle
if (!rc && deviceCount)
{
rc = mxfDeviceModuleAllGet(device, MXF_MODULE_MIL1553MRT_EH, 2, &moduleCount, module);
//If not a FM1553-4 or FX1553-4 , return an error
if (moduleCount != 2)
{
printf("This example only works for FM1553-4 or FX1553-4\n");
rc = MAXT_ERROR_MODEL;
}
}
//If no device found, return an error
else if (!rc && !deviceCount)
rc = MAXT_ERROR_MODEL;
// Get bus controller channel
if (!rc)
rc = mxfModuleChannelGet(module[0], 1, &bc);
// Get bus monitor channel
if (!rc)
rc = mxfModuleChannelGet(module[0], 0, &bm);
// Get remote terminal 4 channel
if (!rc)
rc = mxfModuleChannelGet(module[0], 2 + 4, &rt4);
// Get remote terminal 5 channel
if (!rc)
rc = mxfModuleChannelGet(module[0], 2 + 5, &rt5);
#ifdef LOOPBACK
if (!rc)
rc = mxfAttributeUint64Set(bm, KMXF_MIL1553_TX_RX_TEST_LB, VMXF_ENABLE);
#endif
// Allocate 4KB buffer for tx data
if (!rc)
{
txBufferSize = 4096;
// Device allocation
rc = mxfTxAperiodicBufferAlloc(bc, MXF_TXAPERIODIC_PRIORITY_LOW, txBufferSize, &bcLowAperBuffer, NULL); // Low priority aperiodic
if (!rc)
rc = mxfTxAperiodicBufferAlloc(bc, MXF_TXAPERIODIC_PRIORITY_HIGH, txBufferSize, &bcHighAperBuffer, NULL); // High priority aperiodic
if (!rc)
rc = mxfTxPeriodicUpdateMsgBufferAlloc(bc, 0, txBufferSize, &bcBuffer0, NULL); // BC buffer for RT4 SA1 RX
if (!rc)
rc = mxfTxPeriodicUpdateMsgBufferAlloc(bc, 1, txBufferSize, &bcBuffer1, NULL); // BC buffer for RT4 SA2 RX
if (!rc)
rc = mxfTxPeriodicUpdateMsgBufferAlloc(bc, 2, txBufferSize, &bcBufferTx, NULL); // BC buffer for TX command
if (!rc)
rc = mxfTxPeriodicUpdateMsgBufferAlloc(rt4, 0, txBufferSize, &rt4Buffer, NULL); // RT buffer for RT4 SA1 TX
if (!rc)
rc = mxfTxPeriodicUpdateMsgBufferAlloc(rt5, 1, txBufferSize, &rt5Buffer, NULL); // RT buffer for RT5 SA1 TX
// Host allocation
if (!rc)
{
txBuffer = (MXF_MIL1553_DATAREC*)malloc((size_t)txBufferSize);
if (!txBuffer)
rc = MAXT_ERROR_MEM;
}
}
// Allocate 10KB buffer for rx data
if (!rc)
{
rxBufferSize = 10 * 1024;
// Device allocation
rc = mxfRxAcqBufferAlloc(bm, rxBufferSize, &bmBuffer, NULL);
if (!rc)
rc = mxfRxAcqBufferStatusGet(bmBuffer, NULL, NULL, NULL, &rxBufferSize);
// Host allocation
if (!rc)
{
rxBuffer = (MXF_MIL1553_DATAREC*)malloc((size_t)rxBufferSize);
if (!rxBuffer)
rc = MAXT_ERROR_MEM;
}
}
// Set timebase to RTC nsec
if (!rc)
rc = mxfSystemTimeBaseSet(server, MXF_TIMEBASE_DEVICE_NSEC);
// Set BM acquisition mode
if (!rc)
rc = mxfRxAcqModeSet(bmBuffer, MXF_RXACQ_MODE_LINEAR);
// Enable checksum verification RT4 SA1 RX
if (!rc)
rc = mxfMIL1553MsgChecksumEnableSet(bm, MXF_MIL1553_MSGTYPE_RX, 4, 1, TRUE);
// Enable checksum verification RT4 SA1 TX
if (!rc)
rc = mxfMIL1553MsgChecksumEnableSet(bm, MXF_MIL1553_MSGTYPE_TX, 4, 1, TRUE);
// Enable checksum verification RT4 SA2 RX
if (!rc)
rc = mxfMIL1553MsgChecksumEnableSet(bm, MXF_MIL1553_MSGTYPE_RX, 4, 2, TRUE);
// Enable checksum generation RT4 SA1 TX
if (!rc)
rc = mxfMIL1553MsgChecksumEnableSet(rt4, MXF_MIL1553_MSGTYPE_TX, 0, 1, TRUE);
// Deselect acquisition of RT4 SA2 TX
if (!rc)
{
msgid.type = MXF_MIL1553_MSGTYPE_TX;
msgid.address = 4;
msgid.subAddress = 2;
msgid.reserved = 0;
rc = mxfMIL1553RxAcqMsgSelectSet(bmBuffer, MXF_MSG_DESELECT, 1, &msgid);
}
// Start BM acquisition
if (!rc)
rc = mxfRxAcqStart(bmBuffer, MXF_RXACQ_FLAG_DEFAULT, 0, 0);
// Set the minor frame #0 using 4 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].options = MXF_MIL1553_TXPERIODIC_MJRFRAME_MSG_OPT_CHECKSUM_ENABLE;
minorFrame[0].buffer = bcBuffer0;
// Command #1 : Address 4, Subaddress 2, RX, 4 words
if (!rc)
{
rc = mxfMIL1553CommandCompose(4, 2, MXF_MIL1553_COMMAND_DIR_RX, 4, &minorFrame[1].command);
minorFrame[1].modulo = 1;
minorFrame[1].delay = 80000; // send command 10 msec after preceding command
// Checksum generation is disabled, but checksum verification is enabled, will cause a checksum error with BM
minorFrame[1].options = MXF_MIL1553_TXPERIODIC_MJRFRAME_MSG_OPT_DELAY;
minorFrame[1].buffer = bcBuffer1;
}
// Command #2 : Address 4, Subaddress 1, TX, 4 words
if (!rc)
{
rc = mxfMIL1553CommandCompose(4, 1, MXF_MIL1553_COMMAND_DIR_TX, 4, &minorFrame[2].command);
minorFrame[2].modulo = 1;
minorFrame[2].delay = 80000; // send command 10 msec after preceding command
minorFrame[2].options = MXF_MIL1553_TXPERIODIC_MJRFRAME_MSG_OPT_DELAY;
minorFrame[2].buffer = bcBufferTx;
}
// Command #3 : Address 4, Subaddress 2, TX, 4 words
if (!rc)
{
rc = mxfMIL1553CommandCompose(4, 2, MXF_MIL1553_COMMAND_DIR_TX, 4, &minorFrame[3].command);
minorFrame[3].modulo = 1;
minorFrame[3].delay = 80000; // send command 10 msec after preceding command
minorFrame[3].options = MXF_MIL1553_TXPERIODIC_MJRFRAME_MSG_OPT_DELAY;
minorFrame[3].buffer = bcBufferTx;
}
// 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].delay = 80000; // send command 10 msec after preceding command
minorFrame[4].options = MXF_MIL1553_TXPERIODIC_MJRFRAME_MSG_OPT_DELAY;
minorFrame[4].buffer = bcBufferTx;
}
if (!rc)
rc = mxfMIL1553TxPeriodicMajorFrameSet(bc, 0, 0, 5, minorFrame, NULL);
}
// Set default data for BC RT4 SA1 RX
if (!rc)
{
rec1553 = (MXF_MIL1553_DATAREC*)txBuffer;
memset(rec1553, 0, sizeof(MXF_MIL1553_DATAREC));
rec1553->repeatCount = 1;
rec1553->dataSize = 10; //10 bytes (command + 4 words)
rec1553->data[0] = 0x0000; //Not used
rec1553->data[1] = 0x0000;
rec1553->data[2] = 0x1111;
rec1553->data[3] = 0x2222;
rec1553->data[4] = 0x3333;
rc = mxfMIL1553TxPeriodicUpdateMsgWrite(bcBuffer0, 1, txBuffer);
}
// Set default data for BC RT4 SA2 RX
if (!rc)
{
rec1553 = (MXF_MIL1553_DATAREC*)txBuffer;
memset(rec1553, 0, sizeof(MXF_MIL1553_DATAREC));
rec1553->repeatCount = 1;
rec1553->dataSize = 10; //10 bytes (command + 4 words)
rec1553->data[0] = 0x0000; //Not used
rec1553->data[1] = 0x1234;
rec1553->data[2] = 0x5678;
rec1553->data[3] = 0x9ABC;
rec1553->data[4] = 0xDEF0;
rc = mxfMIL1553TxPeriodicUpdateMsgWrite(bcBuffer1, 1, txBuffer);
}
// Set default data for RT4 SA1 TX
if (!rc)
{
rec1553 = (MXF_MIL1553_DATAREC*)txBuffer;
memset(rec1553, 0, sizeof(MXF_MIL1553_DATAREC));
rec1553->repeatCount = 1;
rec1553->dataSize = 10; //10 bytes (command + 4 words)
rec1553->data[0] = 0x0000; //Not used
rec1553->data[1] = 0xAAAA;
rec1553->data[2] = 0xBBBB;
rec1553->data[3] = 0xCCCC;
rec1553->data[4] = 0xDDDD;
rc = mxfMIL1553TxPeriodicUpdateMsgWrite(rt4Buffer, 1, txBuffer);
}
if (!rc)
{
printf("Starting RT 4\n\r");
rc = mxfMIL1553RtSubsystemEnableSet(rt4, MXF_MIL1553_MSGTYPE_TX, 1, MXF_MIL1553_BUS_A, rt4Buffer);
if (!rc)
rc = mxfMIL1553RtEnableSet(rt4, TRUE);
}
if (!rc)
{
printf("Starting RT 5\n\r");
rc = mxfMIL1553RtSubsystemEnableSet(rt5, MXF_MIL1553_MSGTYPE_TX, 1, MXF_MIL1553_BUS_A, rt5Buffer);
if (!rc)
rc = mxfMIL1553RtEnableSet(rt5, TRUE);
}
// Get current time and add 200 msec to it
if (!rc)
rc = mxfDeviceTimerGet(device, &startTime);
startTime += 200000000;
// Start the major frame
if (!rc)
{
memset(&minorProperties, 0, sizeof(minorProperties));
minorProperties.startTime = startTime;
rc = mxfMIL1553TxPeriodicMajorFrameStart(bc, 0, 50 * 1000 * 1000, &minorProperties); //50 msec
}
// Set high priority aperiodic command for RT5 SA1 RX
if (!rc)
{
rec1553 = (MXF_MIL1553_DATAREC*)txBuffer;
memset(rec1553, 0, sizeof(MXF_MIL1553_DATAREC));
rec1553->timeTag = startTime + 52000000; // 1 msec after beginning of first command of second run of minor frame
rec1553->repeatCount = 1;
rec1553->control = MXF_MIL1553_TXAPERIODIC_REC_CTRL_CHECKSUM_ENABLE;
rec1553->dataSize = 10; //10 bytes (command + 4 words)
mxfMIL1553CommandCompose(5, 1, MXF_MIL1553_MSGTYPE_RX, 4, &rec1553->data[0]);
rec1553->data[1] = 0x1111;
rec1553->data[2] = 0x1111;
rec1553->data[3] = 0x1111;
rec1553->data[4] = 0x1111;
rc = mxfMIL1553TxAperiodicWrite(bcHighAperBuffer, MXF_TXAPERIODIC_FLAG_USE_RECORD_ABSOLUTE_TIME, 0, 1, txBuffer);
}
// Set low priority aperiodic command for RT5 SA2 RX
if (!rc)
{
rec1553 = (MXF_MIL1553_DATAREC*)txBuffer;
memset(rec1553, 0, sizeof(MXF_MIL1553_DATAREC));
// 1 msec gap after last command of second run of minor frame
rec1553->timeTag = startTime + 54000000;
rec1553->service.txAperiodic.delay = 8000;
rec1553->repeatCount = 1;
rec1553->control = MXF_MIL1553_TXAPERIODIC_REC_CTRL_CHECKSUM_ENABLE | MXF_MIL1553_TXAPERIODIC_REC_CTRL_GAP;
rec1553->dataSize = 10; //10 bytes (command + 4 words)
mxfMIL1553CommandCompose(5, 2, MXF_MIL1553_MSGTYPE_RX, 4, &rec1553->data[0]);
rec1553->data[1] = 0x2222;
rec1553->data[2] = 0x2222;
rec1553->data[3] = 0x2222;
rec1553->data[4] = 0x2222;
rc = mxfMIL1553TxAperiodicWrite(bcLowAperBuffer, MXF_TXAPERIODIC_FLAG_USE_RECORD_ABSOLUTE_TIME, 0, 1, txBuffer);
}
// Read and display received messages
if (!rc)
{
mxfSleep(4000);
rc = mxfMIL1553RxAcqRead(bmBuffer, 0, rxBufferSize, &rxAcqStatus, &msgCount, &byteCount, rxBuffer);
rec1553 = (MXF_MIL1553_DATAREC*)rxBuffer;
for (rxRec = 0; rxRec < msgCount && !rc; rxRec++)
{
printf("\n\r%llu:\t", rec1553->timeTag);
printf("Control: 0x%08x", rec1553->control);
if (rec1553->control & MXF_MIL1553_RX_REC_CTRL_MSG_CHECKSUM_ERROR)
checksumError++;
for (data = 0; data < rec1553->dataSize / 2; data++)
{
if (data && !(data % 5))
printf("\n\r\t\t\t");
printf(" 0x%04x", rec1553->data[data]);
}
printf("\n\r");
// Get next msg
rc = mxfMIL1553NextDataRecordPtrGet(rec1553, &rec1553);
}
}
if (!rc)
{
if (rxAcqStatus & MXF_RXACQ_STATUS_BUFFER_FULL)
printf("Acquisition stopped with buffer full\n");
}
if (!rc)
printf("Number of checksum error = %u\n", checksumError);
// Stop the major frame
if (!rc)
// Stop RTs
if (!rc)
rc = mxfMIL1553RtEnableSet(rt4, FALSE);
if (!rc)
rc = mxfMIL1553RtEnableSet(rt5, FALSE);
// Stop acquisition
if (!rc)
rc = mxfRxAcqStop(bmBuffer);
// Clear the major frame
// free buffers
if (txBuffer)
free(txBuffer);
if (rxBuffer)
free(rxBuffer);
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 (bcLowAperBuffer)
{
rc = mxfTxAperiodicBufferFree(bcLowAperBuffer);
if (rc)
printf("Free buffer failed !\n\r");
}
if (bcHighAperBuffer)
{
rc = mxfTxAperiodicBufferFree(bcHighAperBuffer);
if (rc)
printf("Free buffer failed !\n\r");
}
if (bcBuffer0)
{
if (rc)
printf("Free buffer failed !\n\r");
}
if (bcBuffer1)
{
if (rc)
printf("Free buffer failed !\n\r");
}
if (bcBufferTx)
{
if (rc)
printf("Free buffer failed !\n\r");
}
if (rt4Buffer)
{
if (rc)
printf("Free buffer failed !\n\r");
}
if (rt5Buffer)
{
if (rc)
printf("Free buffer failed !\n\r");
}
if (bmBuffer)
{
rc = mxfRxAcqBufferFree(bmBuffer);
if (rc)
printf("Free buffer failed !\n\r");
}
// Unload MX Foundation library
printf("\n\rPress enter to terminate\n\r");
getchar();
return 0;
}
Updated 10/23/2023