MX Foundation 4
mil1553_embedded_update_host.cs
/*****************************************************************************
//
// File:
// mil1553_embedded_update_host.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 transmit information from host to
// embedded application. The communication queues are used to communicate
// between host and embedded application part. Data from communication
// queue is used to update BC message. Asynchronous event is used for
// data communication queue threshold.
//
// This file is used to generate the host part of the application.
// mil1553_embedded_update_embedded.c file is used for the embedded part
// of the application.
//
// 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_update_host
{
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 module1553;
public UInt64 bcChannel;
public UInt64 bmChannel;
public UInt64 commTxBuffer;
public UInt64 commRxBuffer;
public UInt64 commTxUpdateDataBuffer;
}
public struct EX_COMMAND
{
public UInt32 command;
public UInt32 paramNum;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)]
public UInt32[] param;
}
static void Main(string[] args)
{
TEST_INFO info = new TEST_INFO();
UInt32 rc;
UInt64 moduleCount = 0;
UInt64 channelCount = 0;
var temp = new UInt64[10];
// 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 1553-EH module
if (rc == MAXT_SUCCESS)
rc = mxfDeviceModuleAllGet(info.device, MXF_MODULE_MIL1553MRT_EH, 1, out moduleCount, temp);
info.module1553 = temp[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, temp);
info.bcChannel = temp[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, temp);
info.bmChannel = temp[0];
if (rc == MAXT_SUCCESS && channelCount == 0)
rc = MAXT_ERROR_NOT_FOUND;
if (rc == MAXT_SUCCESS)
rc = hostPart(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");
// Unload MX Foundation library
mxfSystemResourcesRelease(info.server, 0);
// 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 = 3;
return Convert.ToUInt32(true);
}
return Convert.ToUInt32(false);
}
public static UInt32 commandSend(UInt64 txBuffer, UInt64 rxBuffer, EX_COMMAND cmd)
{
msg.data = new UInt32[256];
IntPtr msgPtr = IntPtr.Zero;
UInt64 readCnt = 0;
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)
{
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.dataSize >= 8) && (msg.data[0] == EX_USER_COMMAND_ACK))
if (msg.dataSize >= 12)
rc = msg.data[2];
break;
}
}
}
Marshal.FreeHGlobal(msgPtr);
return rc;
}
public static UInt32 commandRead(UInt64 rxBuffer, UInt64 readCnt, EX_COMMAND cmd)
{
msg.data = new UInt32[256];
IntPtr msgPtr = IntPtr.Zero;
UInt64 byteCnt;
UInt32 rc;
try
{
msgPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(MXF_EMBEDDED_DATAREC)));
}
catch (OutOfMemoryException)
{
rc = MAXT_ERROR_MEM;
}
cmd = new EX_COMMAND();
cmd.param = new UInt32[32];
// Read command from the communication queue
rc = mxfDeviceCommBufferRead(rxBuffer, 1, (UInt64)Marshal.SizeOf(typeof(EX_COMMAND)), out readCnt, out byteCnt, msgPtr);
if (rc == MAXT_SUCCESS && readCnt > 0)
{
cmd.command = msg.data[0];
cmd.paramNum = msg.data[1];
for (UInt64 iData = 0; iData < cmd.paramNum * 4; iData++)
cmd.param[iData] = msg.data[iData + 2];
}
Marshal.FreeHGlobal(msgPtr);
return rc;
}
public static UInt32 hostPart(TEST_INFO info)
{
EX_COMMAND cmd = new EX_COMMAND();
cmd.param = new UInt32[32];
commRec.data = new UInt32[256];
IntPtr recPtr = IntPtr.Zero;
UInt32 rc = 0;
IntPtr txHostBuffer = IntPtr.Zero;
UInt64 txBufferSize = 0;
UInt64 data;
IntPtr rxHostBuffer = IntPtr.Zero;
UInt64 rxBufferSize = 0;
#if LOOPBACK
// Set internal loopback Mil1553 channel
rc = mxfAttributeUint64Set(info.bmChannel, KMXF_MIL1553_TX_RX_TEST_LB, VMXF_ENABLE);
#endif
if (rc == MAXT_SUCCESS)
{
// Allocate 10 KB buffer for TX communication queue
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;
}
}
}
// Allocate 1 KB buffer for TX communication update data queue
if (rc == MAXT_SUCCESS)
{
txBufferSize = 10 * 1024;
// Allocate buffer for comm queue #2
rc = mxfDeviceCommBufferAlloc(info.device, 2, txBufferSize, out info.commTxUpdateDataBuffer, IntPtr.Zero);
// Host buffer allocation
if (rc == MAXT_SUCCESS)
{
try
{
txHostBuffer = Marshal.AllocHGlobal((int)txBufferSize);
}
catch
{
rc = MAXT_ERROR_MEM;
}
}
}
// Upload and start embedded part
if (rc == MAXT_SUCCESS)
{
string filename = "mil1553_embedded_update_embedded-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);
}
// Send update data to embedded part
if (rc == MAXT_SUCCESS)
{
UInt32 dataSize = 18;
UInt32 numData = (dataSize - 2) / 2;
UInt16[] data16 = new UInt16[numData + 1];
// TX data simulation
recPtr = txHostBuffer;
for (data = 0; data < MAX_TX_RECORDS_TO_TRANSMIT; data++)
{
commRec.timeTag = 0;
commRec.control = 0;
commRec.repeatCount = 1;
commRec.dataSize = dataSize;
for (int i = 1; i <= numData; i++)
data16[i] = (UInt16)data;
Buffer.BlockCopy(data16, 0, commRec.data, 0, (int)(numData + 1) * 2);
for (int i = 0; i <= numData / 2; i++)
commRec.data[i] = dwordSwap(commRec.data[i]);
Marshal.StructureToPtr(commRec, recPtr, true);
mxfNextRecordPtrGet(MXF_CLASS_EMBEDDED, MXF_RECTYPE_DATAREC, recPtr, out recPtr);
}
Console.Write("Transmitting simulation data...\n\r");
rc = mxfDeviceCommBufferWrite(info.commTxUpdateDataBuffer, MAX_TX_RECORDS_TO_TRANSMIT, txHostBuffer);
}
// Wait 2 seconds
if (rc == MAXT_SUCCESS)
mxfSleep(2000);
// 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);
// Give time to read before terminating
if (rc == MAXT_SUCCESS)
mxfSleep(100);
}
// Send TERMINATE command to embedded part
if (rc == MAXT_SUCCESS)
{
cmd.command = 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);
return rc;
}
public static UInt32 dwordSwap(UInt32 dword)
{
return ((dword & 0x0000ffff) << 16 | (dword & 0xffff0000) >> 16);
}
}
}
Updated 10/23/2023