MX Foundation 4
mil1553_aperiodic_frame.cs
/*****************************************************************************
//
## File:
## mil1553_aperiodic_frame.cs
//
// 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)
//
*****************************************************************************/
#define LOCAL
#define LOOPBACK
using System;
using System.Text;
using System.Runtime.InteropServices;
using static MAXT.MXFoundation.mxf;
namespace mil1553_example
{
public class mil1553_aperiodic_frame
{
static void Main(string[] args)
{
UInt32 rc;
UInt64 deviceCount = 0;
UInt64 moduleCount = 0;
UInt64 server;
var device = new UInt64[1];
var module = new UInt64[2];
UInt64 bc = 0;
UInt64 bm = 0;
UInt64 rt4 = 0;
UInt64 rt5 = 0;
UInt64 bcLowAperBuffer = 0;
UInt64 bcHighAperBuffer = 0;
UInt64 bcBuffer0 = 0;
UInt64 bcBuffer1 = 0;
UInt64 bcBufferTx = 0;
UInt64 rt4Buffer = 0;
UInt64 rt5Buffer = 0;
UInt64 bmBuffer = 0;
var minorFrame = new MXF_MIL1553_TXPERIODIC_MJRFRAME_MSG[5];
UInt64 startTime = 0;
UInt64 txBufferSize = 0, rxBufferSize = 0;
IntPtr txBuffer = IntPtr.Zero;
IntPtr recPtr = IntPtr.Zero;
IntPtr rxBuffer = IntPtr.Zero;
rec1553.data = new UInt16[36];
UInt64 rxAcqStatus = 0;
UInt64 status, msgCount;
UInt64 byteCount;
UInt64 rxRec;
UInt32 data;
UInt32 checksumError = 0;
var errorString = new StringBuilder(200);
// Connect to services and initialize environment
#if (LOCAL)
rc = mxfServerConnect("0.0.0.0", "", "", Convert.ToUInt64(false), out server);
#else
rc = mxfServerConnect("192.168.0.1", "admin", "admin", Convert.ToUInt64(false), out server);
#endif
// Initialize MX Foundation library
if (rc == MAXT_SUCCESS)
{
Console.Write("Starting ...\n\r");
rc = mxfSystemInit(server);
}
//Get a FM1553-4 or FX1553-4 device handle
if (rc == MAXT_SUCCESS)
rc = mxfSystemDeviceAllGet(server, MXF_DEVICE_FLEXMULTI_1553, 1, out deviceCount, device);
if (rc == MAXT_SUCCESS && deviceCount == 0)
rc = mxfSystemDeviceAllGet(server, MXF_DEVICE_FLEX1553_PCIE, 1, out deviceCount, device);
// Get a MIL1553 module handle
if (rc == MAXT_SUCCESS && deviceCount != 0)
{
rc = mxfDeviceModuleAllGet(device[0], MXF_MODULE_MIL1553MRT_EH, 2, out moduleCount, module);
//If not a FM1553-4 or FX1553-4 , return an error
if (moduleCount != 2)
{
Console.Write("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 == MAXT_SUCCESS && deviceCount == 0)
rc = MAXT_ERROR_MODEL;
// Get bus controller channel
if (rc == MAXT_SUCCESS)
rc = mxfModuleChannelGet(module[0], 1, out bc);
// Get bus monitor channel
if (rc == MAXT_SUCCESS)
rc = mxfModuleChannelGet(module[0], 0, out bm);
// Get remote terminal 4 channel
if (rc == MAXT_SUCCESS)
rc = mxfModuleChannelGet(module[0], 2 + 4, out rt4);
// Get remote terminal 5 channel
if (rc == MAXT_SUCCESS)
rc = mxfModuleChannelGet(module[0], 2 + 5, out rt5);
#if LOOPBACK
if (rc == MAXT_SUCCESS)
rc = mxfAttributeUint64Set(bm, KMXF_MIL1553_TX_RX_TEST_LB, VMXF_ENABLE);
#endif
// Allocate 4KB buffer for tx data
if (rc == MAXT_SUCCESS)
{
txBufferSize = 4096;
// Device allocation
rc = mxfTxAperiodicBufferAlloc(bc, MXF_TXAPERIODIC_PRIORITY_LOW, txBufferSize, out bcLowAperBuffer, IntPtr.Zero); // Low priority aperiodic
if (rc == MAXT_SUCCESS)
rc = mxfTxAperiodicBufferAlloc(bc, MXF_TXAPERIODIC_PRIORITY_HIGH, txBufferSize, out bcHighAperBuffer, IntPtr.Zero); // High priority aperiodic
if (rc == MAXT_SUCCESS)
rc = mxfTxPeriodicUpdateMsgBufferAlloc(bc, 0, txBufferSize, out bcBuffer0, IntPtr.Zero); // BC buffer for RT4 SA1 RX
if (rc == MAXT_SUCCESS)
rc = mxfTxPeriodicUpdateMsgBufferAlloc(bc, 1, txBufferSize, out bcBuffer1, IntPtr.Zero); // BC buffer for RT4 SA2 RX
if (rc == MAXT_SUCCESS)
rc = mxfTxPeriodicUpdateMsgBufferAlloc(bc, 2, txBufferSize, out bcBufferTx, IntPtr.Zero); // BC buffer for TX command
if (rc == MAXT_SUCCESS)
rc = mxfTxPeriodicUpdateMsgBufferAlloc(rt4, 0, txBufferSize, out rt4Buffer, IntPtr.Zero); // RT buffer for RT4 SA1 TX
if (rc == MAXT_SUCCESS)
rc = mxfTxPeriodicUpdateMsgBufferAlloc(rt5, 1, txBufferSize, out rt5Buffer, IntPtr.Zero); // RT buffer for RT5 SA1 TX
// Host allocation
if (rc == MAXT_SUCCESS)
{
try
{
txBuffer = Marshal.AllocHGlobal((int)txBufferSize);
}
catch (OutOfMemoryException)
{
rc = MAXT_ERROR_MEM;
}
}
}
// Allocate 10KB buffer for rx data
if (rc == MAXT_SUCCESS)
{
rxBufferSize = 10 * 1024;
// Device allocation
rc = mxfRxAcqBufferAlloc(bm, rxBufferSize, out bmBuffer, IntPtr.Zero);
if (rc == MAXT_SUCCESS)
rc = mxfRxAcqBufferStatusGet(bmBuffer, out status, out msgCount, out byteCount, out rxBufferSize);
// Host allocation
if (rc == MAXT_SUCCESS)
{
try
{
rxBuffer = Marshal.AllocHGlobal((int)rxBufferSize);
}
catch (OutOfMemoryException)
{
rc = MAXT_ERROR_MEM;
}
}
}
// Set timebase to RTC nsec
if (rc == MAXT_SUCCESS)
rc = mxfSystemTimeBaseSet(server, MXF_TIMEBASE_DEVICE_NSEC);
// Set BM acquisition mode
if (rc == MAXT_SUCCESS)
rc = mxfRxAcqModeSet(bmBuffer, MXF_RXACQ_MODE_LINEAR);
// Enable checksum verification RT4 SA1 RX
if (rc == MAXT_SUCCESS)
rc = mxfMIL1553MsgChecksumEnableSet(bm, MXF_MIL1553_MSGTYPE_RX, 4, 1, VMXF_ENABLE);
// Enable checksum verification RT4 SA1 TX
if (rc == MAXT_SUCCESS)
rc = mxfMIL1553MsgChecksumEnableSet(bm, MXF_MIL1553_MSGTYPE_TX, 4, 1, VMXF_ENABLE);
// Enable checksum verification RT4 SA2 RX
if (rc == MAXT_SUCCESS)
rc = mxfMIL1553MsgChecksumEnableSet(bm, MXF_MIL1553_MSGTYPE_RX, 4, 2, VMXF_ENABLE);
// Enable checksum generation RT4 SA1 TX
if (rc == MAXT_SUCCESS)
rc = mxfMIL1553MsgChecksumEnableSet(rt4, MXF_MIL1553_MSGTYPE_TX, 0, 1, VMXF_ENABLE);
// Deselect acquisition of RT4 SA2 TX
if (rc == MAXT_SUCCESS)
{
var msgid = new MXF_MSGID_MIL1553[1];
msgid[0].type = MXF_MIL1553_MSGTYPE_TX;
msgid[0].address = 4;
msgid[0].subAddress = 2;
msgid[0].reserved = 0;
rc = mxfMIL1553RxAcqMsgSelectSet(bmBuffer, MXF_MSG_DESELECT, 1, msgid);
}
// Start BM acquisition
if (rc == MAXT_SUCCESS)
rc = mxfRxAcqStart(bmBuffer, MXF_RXACQ_FLAG_DEFAULT, 0, 0);
// Set the minor frame #0 using 4 Commands
if (rc == MAXT_SUCCESS)
{
// Command #0 : Address 4, Subaddress 1, RX, 4 words
rc = mxfMIL1553CommandCompose(4, 1, MXF_MIL1553_COMMAND_DIR_RX, 4, out 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 == MAXT_SUCCESS)
{
rc = mxfMIL1553CommandCompose(4, 2, MXF_MIL1553_COMMAND_DIR_RX, 4, out 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 == MAXT_SUCCESS)
{
rc = mxfMIL1553CommandCompose(4, 1, MXF_MIL1553_COMMAND_DIR_TX, 4, out 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 == MAXT_SUCCESS)
{
rc = mxfMIL1553CommandCompose(4, 2, MXF_MIL1553_COMMAND_DIR_TX, 4, out 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 == MAXT_SUCCESS)
{
rc = mxfMIL1553CommandCompose(5, 1, MXF_MIL1553_COMMAND_DIR_TX, 4, out 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 == MAXT_SUCCESS)
rc = mxfMIL1553TxPeriodicMajorFrameSet(bc, 0, 0, 5, minorFrame, IntPtr.Zero);
}
// Set default data for BC RT4 SA1 RX
if (rc == MAXT_SUCCESS)
{
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;
Marshal.StructureToPtr(rec1553, txBuffer, true);
rc = mxfMIL1553TxPeriodicUpdateMsgWrite(bcBuffer0, 1, txBuffer);
}
// Set default data for BC RT4 SA2 RX
if (rc == MAXT_SUCCESS)
{
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;
Marshal.StructureToPtr(rec1553, txBuffer, true);
rc = mxfMIL1553TxPeriodicUpdateMsgWrite(bcBuffer1, 1, txBuffer);
}
// Set default data for RT4 SA1 TX
if (rc == MAXT_SUCCESS)
{
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;
Marshal.StructureToPtr(rec1553, txBuffer, true);
rc = mxfMIL1553TxPeriodicUpdateMsgWrite(rt4Buffer, 1, txBuffer);
}
if (rc == MAXT_SUCCESS)
{
Console.Write("Starting RT 4\n\r");
rc = mxfMIL1553RtSubsystemEnableSet(rt4, MXF_MIL1553_MSGTYPE_TX, 1, MXF_MIL1553_BUS_A, rt4Buffer);
if (rc == MAXT_SUCCESS)
rc = mxfMIL1553RtEnableSet(rt4, VMXF_ENABLE);
}
if (rc == MAXT_SUCCESS)
{
Console.Write("Starting RT 5\n\r");
rc = mxfMIL1553RtSubsystemEnableSet(rt5, MXF_MIL1553_MSGTYPE_TX, 1, MXF_MIL1553_BUS_A, rt5Buffer);
if (rc == MAXT_SUCCESS)
rc = mxfMIL1553RtEnableSet(rt5, VMXF_ENABLE);
}
// Get current time and add 200 msec to it
if (rc == MAXT_SUCCESS)
rc = mxfDeviceTimerGet(device[0], out startTime);
startTime += 200000000;
// Start the major frame
if (rc == MAXT_SUCCESS)
{
minorProperties.startTime = startTime;
rc = mxfMIL1553TxPeriodicMajorFrameStart(bc, 0, 50 * 1000 * 1000, ref minorProperties); //50 msec
}
// Set high priority aperiodic command for RT5 SA1 RX
if (rc == MAXT_SUCCESS)
{
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, out rec1553.data[0]);
rec1553.data[1] = 0x1111;
rec1553.data[2] = 0x1111;
rec1553.data[3] = 0x1111;
rec1553.data[4] = 0x1111;
Marshal.StructureToPtr(rec1553, txBuffer, true);
rc = mxfMIL1553TxAperiodicWrite(bcHighAperBuffer, MXF_TXAPERIODIC_FLAG_USE_RECORD_ABSOLUTE_TIME, 0, 1, txBuffer);
}
// Set low priority aperiodic command for RT5 SA2 RX
if (rc == MAXT_SUCCESS)
{
// 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, out rec1553.data[0]);
rec1553.data[1] = 0x2222;
rec1553.data[2] = 0x2222;
rec1553.data[3] = 0x2222;
rec1553.data[4] = 0x2222;
Marshal.StructureToPtr(rec1553, txBuffer, true);
rc = mxfMIL1553TxAperiodicWrite(bcLowAperBuffer, MXF_TXAPERIODIC_FLAG_USE_RECORD_ABSOLUTE_TIME, 0, 1, txBuffer);
}
mxfSleep(4000);
// Read and display received messages
if (rc == MAXT_SUCCESS)
{
rc = mxfMIL1553RxAcqRead(bmBuffer, 0, rxBufferSize, out rxAcqStatus, out msgCount, out byteCount, rxBuffer);
recPtr = rxBuffer;
for (rxRec = 0; rxRec < msgCount && rc == MAXT_SUCCESS; rxRec++)
{
rec1553 = (MXF_MIL1553_DATAREC)Marshal.PtrToStructure(recPtr, typeof(MXF_MIL1553_DATAREC));
Console.Write("\n\r{0}:\t", rec1553.timeTag);
Console.Write("Control: 0x{0:x8}", rec1553.control);
if ((rec1553.control & MXF_MIL1553_RX_REC_CTRL_MSG_CHECKSUM_ERROR) > 0)
checksumError++;
for (data = 0; data < rec1553.dataSize / 2; data++)
{
if (data > 0 && (data % 5) == 0)
Console.Write("\n\r\t\t\t");
Console.Write(" 0x{0:x4}", rec1553.data[data]);
}
Console.Write("\n\r");
// Get next msg
rc = mxfMIL1553NextDataRecordPtrGet(recPtr, out recPtr);
}
}
if (rc == MAXT_SUCCESS)
{
if ((rxAcqStatus & MXF_RXACQ_STATUS_BUFFER_FULL) > 0)
Console.Write("Acquisition stopped with buffer full\n");
}
if (rc == MAXT_SUCCESS)
Console.Write("Number of checksum error = {0}\n", checksumError);
// Stop the major frame
if (rc == MAXT_SUCCESS)
// Stop RTs
if (rc == MAXT_SUCCESS)
rc = mxfMIL1553RtEnableSet(rt4, VMXF_DISABLE);
if (rc == MAXT_SUCCESS)
rc = mxfMIL1553RtEnableSet(rt5, VMXF_DISABLE);
// Stop acquisition
if (rc == MAXT_SUCCESS)
rc = mxfRxAcqStop(bmBuffer);
// Clear the major frame
// free buffers
if (txBuffer != IntPtr.Zero)
Marshal.FreeHGlobal(txBuffer);
if (rxBuffer != IntPtr.Zero)
Marshal.FreeHGlobal(rxBuffer);
if (rc != MAXT_SUCCESS)
{
if (mxfSystemErrorStringGet(server, rc, (UInt32)errorString.Capacity, errorString) != MAXT_SUCCESS)
{
errorString.Clear();
errorString.Append(string.Format("ERROR # 0x{0:x8}", rc));
}
Console.Write(errorString + "\n\r");
}
// Free all buffers and terminate
if (bcLowAperBuffer > 0)
{
rc = mxfTxAperiodicBufferFree(bcLowAperBuffer);
if (rc != MAXT_SUCCESS)
Console.Write("Free buffer failed !\n\r");
}
if (bcHighAperBuffer > 0)
{
rc = mxfTxAperiodicBufferFree(bcHighAperBuffer);
if (rc != MAXT_SUCCESS)
Console.Write("Free buffer failed !\n\r");
}
if (bcBuffer0 > 0)
{
if (rc != MAXT_SUCCESS)
Console.Write("Free buffer failed !\n\r");
}
if (bcBuffer1 > 0)
{
if (rc != MAXT_SUCCESS)
Console.Write("Free buffer failed !\n\r");
}
if (bcBufferTx > 0)
{
if (rc != MAXT_SUCCESS)
Console.Write("Free buffer failed !\n\r");
}
if (rt4Buffer > 0)
{
if (rc != MAXT_SUCCESS)
Console.Write("Free buffer failed !\n\r");
}
if (rt5Buffer > 0)
{
if (rc != MAXT_SUCCESS)
Console.Write("Free buffer failed !\n\r");
}
if (bmBuffer > 0)
{
rc = mxfRxAcqBufferFree(bmBuffer);
if (rc != MAXT_SUCCESS)
Console.Write("Free buffer failed !\n\r");
}
// Unload MX Foundation library
Console.Write("\n\rPress enter to terminate\n\r");
Console.ReadKey();
return;
}
}
}
Updated 10/23/2023