MX Foundation 4
mil1553_embedded_async_to_1553.cs
/*****************************************************************************
//
// File:
// mil1553_embedded_async_to_1553.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 how to route ASYNC port data to MIL1553 BC to
// update data of a BC-RT command.
// The communication queues are used to communicate between host and embedded
// application parts. MIL1553 BM is returned through communication queue.
// Asynchronous event is used for async receiver threshold.
//
// The embedded makefile must define "EMBEDDED_PART" to build embedded
// part function. The embedded makefile must be compiled using the C version
// of this exemple
//
// Hardware requirements:
// - MAXT Flex1553-PCIe or FlexMulti
//
*****************************************************************************/
#define LOOPBACK
using System;
using System.Text;
using System.Runtime.InteropServices;
using static MAXT.MXFoundation.mxf;
namespace mil1553_example
{
public class mil1553_embedded_async_to_1553
{
private const UInt64 MAX_TX_RECORDS_TO_TRANSMIT = 8;
private const UInt32 EX_USER_COMMAND_ID_START = 0x80000001;
private const UInt32 EX_USER_COMMAND_ID_STOP = 0x80000002;
private const UInt32 EX_USER_COMMAND_ID_READ = 0x80000003;
private const UInt32 EX_USER_COMMAND_ID_TERMINATE = 0x80000005;
private const UInt32 EX_USER_COMMAND_ACK = 0xA5A5A5A5;
private const UInt64 RT_ADDRESS = 1;
private const UInt64 RT_SUBADDRESS = 2;
public struct TEST_INFO
{
public UInt64 server;
public UInt64 device;
public UInt64 moduleAsync;
public UInt64 module1553;
public UInt64 rxChannel;
public UInt64 txChannel;
public UInt64 bcChannel;
public UInt64 bmChannel;
public UInt64 commTxBuffer;
public UInt64 commRxBuffer;
}
public struct EX_COMMAND
{
public UInt32 command;
public UInt32 paramNum;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
public UInt32[] param;
}
public struct EVENT_INFO
{
public IntPtr rxHostBuffer;
public IntPtr bcHostBuffer;
public UInt64 rxBufferSize;
public UInt64 bcBuffer;
}
static void Main(string[] args)
{
TEST_INFO info = new TEST_INFO();
UInt32 rc;
UInt64 moduleCount = 0;
var tempAr = new UInt64[10];
UInt64 channelCount = 0;
// Connect to MX Foundation library
rc = mxfServerConnect("0.0.0.0", "", "", Convert.ToUInt64(false), out info.server);
// Set initialisation handler
if (rc == MAXT_SUCCESS)
rc = mxfSystemInitAttributeUint64CallbackHandler(info.server, initHandler);
// Initialize MX Foundation library
if (rc == MAXT_SUCCESS)
{
Console.Write("Starting ...\n\r");
rc = mxfSystemInit(info.server);
}
// Get the device handle
if (rc == MAXT_SUCCESS)
rc = mxfSystemDeviceGet(info.server, 0, out info.device);
// Get handle of first ASYNC-EH module
if (rc == MAXT_SUCCESS)
rc = mxfDeviceModuleAllGet(info.device, MXF_MODULE_ASYNC_EH, 1, out moduleCount, tempAr);
info.moduleAsync = tempAr[0];
// Get handle of first ASYNC-EH RX channel
if (rc == MAXT_SUCCESS && moduleCount > 0)
rc = mxfModuleChannelAllGet(info.moduleAsync, MXF_CLASS_ASYNC_ENHANCED, MXF_SCLASS_RX_CHANNEL, 1, out channelCount, tempAr);
info.rxChannel = tempAr[0];
// Get handle of first ASYNC-EH TX channel
if (rc == MAXT_SUCCESS && channelCount > 0)
rc = mxfModuleChannelAllGet(info.moduleAsync, MXF_CLASS_ASYNC_ENHANCED, MXF_SCLASS_TX_CHANNEL, 1, out channelCount, tempAr);
info.txChannel = tempAr[0];
if (rc == MAXT_SUCCESS && channelCount == 0)
rc = MAXT_ERROR_NOT_FOUND;
// Get handle of first 1553-EH module
if (rc == MAXT_SUCCESS)
rc = mxfDeviceModuleAllGet(info.device, MXF_MODULE_MIL1553MRT_EH, 1, out moduleCount, tempAr);
info.module1553 = tempAr[0];
// Get handle of first MIL1553 BC channel
if (rc == MAXT_SUCCESS && moduleCount > 0)
rc = mxfModuleChannelAllGet(info.module1553, MXF_CLASS_MIL1553, MXF_SCLASS_BC_CHANNEL, 1, out channelCount, tempAr);
info.bcChannel = tempAr[0];
// Get handle of first MIL1553 BM channel
if (rc == MAXT_SUCCESS && channelCount > 0)
rc = mxfModuleChannelAllGet(info.module1553, MXF_CLASS_MIL1553, MXF_SCLASS_BM_CHANNEL, 1, out channelCount, tempAr);
info.bmChannel = tempAr[0];
if (rc == MAXT_SUCCESS && channelCount > 0)
rc = MAXT_ERROR_NOT_FOUND;
rc = testHostPart(info);
if (rc != MAXT_SUCCESS)
{
StringBuilder errorString = new StringBuilder(200);
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");
}
Console.Write("Terminating ...\n\r");
// Free device buffers
mxfDeviceBuffersFree(info.device);
// Unload MX Foundation library
mxfSystemTerminate(info.server);
// Disconnect from MX Foundation library
mxfServerDisconnect(info.server);
Console.Write("Press enter to terminate\n\r");
Console.ReadKey();
return;
}
public static UInt32 initHandler(UInt64 server, UInt64 deviceIndex, UInt64 moduleIndex, UInt64 channelIndex, UInt64 attrib, ref UInt64 value)
{
if (attrib == KMXF_DEVICE_COMM_QUEUE_NUM)
{
// Set the communication queue number attribute
value = 2;
return 1;
}
return 0;
}
public static UInt32 commandSend(UInt64 txBuffer, UInt64 rxBuffer, EX_COMMAND cmd)
{
msg.data = new UInt32[256];
IntPtr msgPtr = IntPtr.Zero;
UInt64 readCnt;
UInt64 byteCnt;
UInt32 rc = 0;
try
{
msgPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(MXF_EMBEDDED_DATAREC)));
}
catch (OutOfMemoryException)
{
rc = MAXT_ERROR_MEM;
}
msg.dataSize = (2 + cmd.paramNum) * 4;
msg.data[0] = cmd.command;
msg.data[1] = cmd.paramNum;
for (int i = 0; i < cmd.paramNum; i++)
{
msg.data[i] = cmd.param[i];
}
Marshal.StructureToPtr(msg, msgPtr, true);
// Write command in the communication queue
rc = mxfDeviceCommBufferWrite(txBuffer, 1, msgPtr);
// Wait acknowledge of embedded application
if (rc == MAXT_SUCCESS && rxBuffer > 0)
{
msg = new MXF_EMBEDDED_DATAREC();
msg.data = new UInt32[256];
while (rc == MAXT_SUCCESS)
{
rc = mxfDeviceCommBufferRead(rxBuffer, 1, (UInt64)Marshal.SizeOf(msg), out readCnt, out byteCnt, msgPtr);
if (rc == MAXT_SUCCESS && readCnt > 0)
{
msg = (MXF_EMBEDDED_DATAREC)Marshal.PtrToStructure(msgPtr, typeof(MXF_EMBEDDED_DATAREC));
if (msg.data[0] == EX_USER_COMMAND_ACK)
break;
}
}
}
Marshal.FreeHGlobal(msgPtr);
return rc;
}
public static UInt32 testHostPart(TEST_INFO info)
{
EX_COMMAND cmd = new EX_COMMAND();
cmd.param = new UInt32[32];
recAsync.data = new byte[256];
IntPtr recPtr;
UInt64 txBuffer = 0;
UInt32 rc;
IntPtr txHostBuffer = IntPtr.Zero;
UInt64 txBufferSize = 0;
UInt64 msgCount = 0;
UInt64 byteCount = 0;
UInt64 data;
UInt64 ibyte;
int word;
IntPtr rxHostBuffer = IntPtr.Zero;
UInt64 rxBufferSize = 0;
// Set ASYNC RX & TX channels speed to 1 mbps
rc = mxfAttributeUint64Set(info.rxChannel, KMXF_ASYNCEH_SPEED, 1000000);
if (rc == MAXT_SUCCESS)
rc = mxfAttributeUint64Set(info.txChannel, KMXF_ASYNCEH_SPEED, 1000000);
// Set RX string gap to 1 bit
if (rc == MAXT_SUCCESS)
rc = mxfAttributeUint64Set(info.rxChannel, KMXF_ASYNCEH_RX_STRING_GAP, 1);
#if LOOPBACK
// Set internal loopback async channel
if (rc == MAXT_SUCCESS)
rc = mxfAttributeUint64Set(info.rxChannel, KMXF_ASYNCEH_TX_RX_TEST_LB, VMXF_ENABLE);
// Set internal loopback Mil1553 channel
if (rc == MAXT_SUCCESS)
rc = mxfAttributeUint64Set(info.bmChannel, KMXF_MIL1553_TX_RX_TEST_LB, VMXF_ENABLE);
#endif
if (rc == MAXT_SUCCESS)
{
// Allocate 10 KB buffer for tx data
txBufferSize = 10 * 1024;
// Allocate TX Aperiodic buffer for HIGH priority queue
rc = mxfTxAperiodicBufferAlloc(info.txChannel, MXF_TXAPERIODIC_PRIORITY_HIGH, txBufferSize, out txBuffer, IntPtr.Zero);
// Host buffer allocation
if (rc == MAXT_SUCCESS)
{
txBufferSize = 10 * 1024;
try
{
txHostBuffer = Marshal.AllocHGlobal((int)txBufferSize);
}
catch
{
rc = MAXT_ERROR_MEM;
}
}
}
// Allocate 10 KB buffer for TX communication queue
if (rc == MAXT_SUCCESS)
{
txBufferSize = 10 * 1024;
// Allocate buffer for comm queue #0
rc = mxfDeviceCommBufferAlloc(info.device, 0, txBufferSize, out info.commTxBuffer, IntPtr.Zero);
}
// Allocate 10 KB buffer for RX communication queue
if (rc == MAXT_SUCCESS)
{
rxBufferSize = 10 * 1024;
// Allocate buffer for comm queue #1
rc = mxfDeviceCommBufferAlloc(info.device, 1, rxBufferSize, out info.commRxBuffer, IntPtr.Zero);
// Host buffer allocation
if (rc == MAXT_SUCCESS)
{
try
{
rxHostBuffer = Marshal.AllocHGlobal((int)rxBufferSize);
}
catch
{
rc = MAXT_ERROR_MEM;
}
}
}
// TX data simulation @ 500 msec
if (rc == MAXT_SUCCESS)
{
UInt64 startTime = 500 * 1000 * 1000; //500 msec
UInt64 delay = 100 * 1000 * 1000; //100 msec
byte value = 0;
// Prepare string array (8 bytes per string with delay of 100 msec between each)
recPtr = txHostBuffer;
for (data = 0; rc == MAXT_SUCCESS && data < MAX_TX_RECORDS_TO_TRANSMIT; data++, value++)
{
recAsync.timeTag = startTime + (delay * data);
recAsync.control = 0;
recAsync.repeatCount = 1;
recAsync.dataSize = 8;
for (ibyte = 0; ibyte < recAsync.dataSize; ibyte++)
recAsync.data[ibyte] = value;
recAsync.reserved = 0;
Marshal.StructureToPtr(recAsync, recPtr, true);
rc = mxfASYNCEHNextDataRecordPtrGet(recPtr, out recPtr);
}
if (rc == MAXT_SUCCESS)
{
Console.Write("Transmitting simulation data...\n\r");
// Transmit strings on relative record time
rc = mxfASYNCEHTxAperiodicWrite(txBuffer, MXF_TXAPERIODIC_FLAG_USE_RECORD_RELATIVE_TIME, 0, MAX_TX_RECORDS_TO_TRANSMIT, txHostBuffer);
}
}
// Upload and start embedded part
if (rc == MAXT_SUCCESS)
{
string fileName = ("mil1553_embedded_async_to_1553-flex.mxf");
rc = mxfDeviceFileUpload(info.device, MXF_DEVICE_FILETYPE_APPLICATION, fileName);
}
// Send START command to embedded part
if (rc == MAXT_SUCCESS)
{
cmd.command = EX_USER_COMMAND_ID_START;
cmd.paramNum = 0;
rc = commandSend(info.commTxBuffer, info.commRxBuffer, cmd);
}
// Wait 3 seconds
if (rc == MAXT_SUCCESS)
mxfSleep(3000);
// Send STOP command to embedded part
if (rc == MAXT_SUCCESS)
{
cmd.command = EX_USER_COMMAND_ID_STOP;
cmd.paramNum = 0;
rc = commandSend(info.commTxBuffer, info.commRxBuffer, cmd);
}
// Send READ command to embedded part
if (rc == MAXT_SUCCESS)
{
cmd.command = EX_USER_COMMAND_ID_READ;
cmd.paramNum = 0;
rc = commandSend(info.commTxBuffer, info.commRxBuffer, cmd);
}
// Read RX communication buffer (BM messages)
if (rc == MAXT_SUCCESS)
{
mxfSleep(100);
rc = mxfDeviceCommBufferRead(info.commRxBuffer, 0, rxBufferSize, out msgCount, out byteCount, rxHostBuffer);
if (rc == MAXT_SUCCESS)
Console.Write("String received count = {0} \n\r", msgCount);
// Display received strings
if (rc == MAXT_SUCCESS)
{
byte[] dataByte;
recPtr = rxHostBuffer;
for (data = 0; data < msgCount; data++)
{
commRec = (MXF_EMBEDDED_DATAREC)Marshal.PtrToStructure(recPtr, typeof(MXF_EMBEDDED_DATAREC));
Console.Write(" {0:00}: Timetag={1}, Size={2}, Data=", data, commRec.timeTag, commRec.dataSize);
//display data
dataByte = new byte[(int)commRec.dataSize];
Buffer.BlockCopy(commRec.data, 0, dataByte, 0, dataByte.Length);
for (word = 0; word < dataByte.Length; word++)
Console.Write("{0:X2}", dataByte[word]);
Console.Write("\n\r");
mxfNextRecordPtrGet(MXF_CLASS_EMBEDDED, MXF_RECTYPE_DATAREC, recPtr, out recPtr);
}
}
}
// Send TERMINATE command to embedded part
if (rc == MAXT_SUCCESS)
{
cmd.command = (UInt32)EX_USER_COMMAND_ID_TERMINATE;
cmd.paramNum = 0;
rc = commandSend(info.commTxBuffer, info.commRxBuffer, cmd);
}
// Free host buffers
if (txHostBuffer != IntPtr.Zero)
Marshal.FreeHGlobal(txHostBuffer);
if (rxHostBuffer != IntPtr.Zero)
Marshal.FreeHGlobal(rxHostBuffer);
// Reload MXF
if (rc == MAXT_SUCCESS)
rc = mxfSystemResourcesRelease(info.server, 0);
if (rc == MAXT_SUCCESS)
rc = mxfSystemResourcesInit(info.server, 0);
return rc;
}
}
}
Updated 10/23/2023