MX Foundation 4
ar429_comm_queues.cs
/*****************************************************************************
//
// File:
// ar429_comm_queues.cs
//
// Copyright (c) MAX Technologies Inc. 1988-2019, All Rights Reserved.
// CONFIDENTIAL AND PROPRIETARY INFORMATION WHICH IS THE
// PROPERTY OF MAX TECHNOLOGIES INC.
//
// This program demonstrates the use of MX Foundation embedded service
// for downloading and controlling an ARINC 429 embedded application.
// Two queues are used for bidirectional communication:
// Queue #0: Tx queue (command)
// Queue #1: Rx queue (response)
//
// The embedded program "ar429_embedded_comm_queues.c" is required by this program
// and compiled executable (ar429_embedded_comm_queues-flex.mxf) must be located in
// the same folder as the host application executable.
//
// Hardware Requirements:
// - MAXT Flex with loopback between first and second TX and RX ARINC 429 Enhanced channels.
//
*****************************************************************************/
using System;
using static MAXT.MXFoundation.mxf;
using System.Runtime.InteropServices;
using System.Text;
namespace ar429_example
{
class ar429_comm_queues
{
const int BUFFER_SIZE = 4096; // 4KB
const int EX_MAX_PARAM = 8;
const int TX_INDEX = 0;
const int RX_INDEX = 1;
// User commands
const UInt32 EX_USER_COMMAND_ID_INIT = 0x0;
const UInt32 EX_USER_COMMAND_ID_START_TX = 0x1;
const UInt32 EX_USER_COMMAND_ID_STOP_TX = 0x2;
const UInt32 EX_USER_COMMAND_ID_START_ACQ = 0x3;
const UInt32 EX_USER_COMMAND_ID_STOP_ACQ = 0x4;
const UInt32 EX_USER_COMMAND_ID_TERMINATE = 0x5;
const UInt32 EX_USER_COMMAND_ACK = 0xA5A5A5A5;
// User structure
public class EX_COMMAND
{
public UInt32 command;
public UInt32 paramNum;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = EX_MAX_PARAM)]
public UInt32[] param;
}
/***************************************************************************************************************/
// Main
/***************************************************************************************************************/
static void Main(string[] args)
{
UInt64 server;
var device = new UInt64[1];
var module = new UInt64[1];
var rxChannel = new UInt64[1];
var txChannel = new UInt64[1];
UInt64 rxBuffer = 0;
UInt64 txBuffer = 0;
var Cmd = new EX_COMMAND();
Cmd.param = new UInt32[EX_MAX_PARAM];
UInt64 devIdx = 0, modIdx = 0, rxChnIdx = 0, txChnIdx = 0;
UInt64 count = 0;
UInt32 rc;
// Connect to server
rc = mxfServerConnect("0.0.0.0", "", "", 0, out server);
// Attach init callback for changing "Communication queue number" attribute without a reset
if (rc == MAXT_SUCCESS)
rc = mxfSystemInitAttributeUint64CallbackHandler(server, InitAttribHandler);
Console.WriteLine("Starting");
// Initialize the MXF library
if (rc == MAXT_SUCCESS)
rc = mxfSystemInit(server);
// Get the device handle
if (rc == MAXT_SUCCESS)
rc = mxfSystemDeviceAllGet(server, MXF_DEVICE_ALL, 1, out count, device);
// Get the first A429-EH module handle
if (rc == MAXT_SUCCESS)
rc = mxfDeviceModuleAllGet(device[0], MXF_MODULE_A429_EH, 1, out count, module);
// Obtain the first ARINC 429 Protocol RX channel (RX logical #0)
if (rc == MAXT_SUCCESS)
rc = mxfModuleChannelAllGet(module[0], MXF_CLASS_A429, MXF_SCLASS_RX_CHANNEL, 1, out count, rxChannel);
// Obtain the first ARINC 429 Protocol TX channel (TX logical #0)
if ((rc == MAXT_SUCCESS) && (count != 0))
rc = mxfModuleChannelAllGet(module[0], MXF_CLASS_A429, MXF_SCLASS_TX_CHANNEL, 1, out count, txChannel);
// If module or channel not found, return an error
if ((rc == MAXT_SUCCESS) && (count == 0))
rc = MAXT_ERROR_NOT_FOUND;
// Obtain the location of the first ARINC 429 Protocol RX channel (RX logical #0)
if (rc == MAXT_SUCCESS)
rc = mxfChannelLocationGet(rxChannel[0], out devIdx, out modIdx, out rxChnIdx);
// Obtain the location of the first ARINC 429 Protocol TX channel (TX logical #0)
if (rc == MAXT_SUCCESS)
rc = mxfChannelLocationGet(txChannel[0], out devIdx, out modIdx, out txChnIdx);
// Set timebase to 64-bit nanoseconds
if (rc == MAXT_SUCCESS)
rc = mxfSystemTimeBaseSet(server, MXF_TIMEBASE_DEVICE_NSEC);
// Allocates communication queue buffer
if (rc == MAXT_SUCCESS)
{
rc = mxfDeviceCommBufferAlloc(device[0], TX_INDEX, 64 * 1024, out txBuffer, IntPtr.Zero);
if (rc == MAXT_SUCCESS)
rc = mxfDeviceCommBufferAlloc(device[0], RX_INDEX, 64 * 1024, out rxBuffer, IntPtr.Zero);
}
// Upload embedded-side application
if (rc == MAXT_SUCCESS)
rc = mxfDeviceFileUpload(device[0], MXF_DEVICE_FILETYPE_APPLICATION, "ar429_embedded_comm_queues-flex.mxf");
if (rc == MAXT_SUCCESS)
{
// Initialize the embedded application
Cmd.command = EX_USER_COMMAND_ID_INIT;
Cmd.paramNum = 0;
Cmd.param[0] = 0;
rc = CommandSend(txBuffer, rxBuffer, Cmd);
if (rc == MAXT_SUCCESS)
Console.Write("Initialisation\n");
}
if (rc == MAXT_SUCCESS)
{
// Start acquisition (First Rx 429)
Cmd.command = EX_USER_COMMAND_ID_START_ACQ;
Cmd.paramNum = 1;
Cmd.param[0] = (UInt32)rxChnIdx;
rc = CommandSend(txBuffer, rxBuffer, Cmd);
if (rc == MAXT_SUCCESS)
Console.Write("Acquisition started\n");
}
if (rc == MAXT_SUCCESS)
{
// Start acquisition (First Tx 429)
Cmd.command = EX_USER_COMMAND_ID_START_TX;
Cmd.paramNum = 1;
Cmd.param[0] = (UInt32)txChnIdx;
rc = CommandSend(txBuffer, rxBuffer, Cmd);
if (rc == MAXT_SUCCESS)
Console.Write("Transmission started\n");
}
if (rc == MAXT_SUCCESS)
{
Console.Write("Running...\n");
mxfSleep(5000); // Wait 5 seconds
}
if (rc == MAXT_SUCCESS)
{
// Stop transmission (First Tx 429)
Cmd.command = EX_USER_COMMAND_ID_STOP_TX;
Cmd.paramNum = 1;
Cmd.param[0] = (UInt32)txChnIdx;
rc = CommandSend(txBuffer, rxBuffer, Cmd);
if (rc == MAXT_SUCCESS)
Console.Write("Transmission stopped\n");
}
if (rc == MAXT_SUCCESS)
{
// Stop acquisition (First Rx 429)
Cmd.command = EX_USER_COMMAND_ID_STOP_ACQ;
Cmd.paramNum = 1;
Cmd.param[0] = (UInt32)rxChnIdx;
rc = CommandSend(txBuffer, rxBuffer, Cmd);
if (rc == MAXT_SUCCESS)
Console.Write("Acquisition stopped\n");
}
if (rc == MAXT_SUCCESS)
{
// Stop embedded application
Cmd.command = EX_USER_COMMAND_ID_TERMINATE;
Cmd.paramNum = 0;
rc = CommandSend(txBuffer, rxBuffer, Cmd);
if (rc == MAXT_SUCCESS)
Console.Write("Terminating\n");
}
// Catch any previous error
if (rc != MAXT_SUCCESS)
{
StringBuilder buffer = new StringBuilder(256);
if (mxfSystemErrorStringGet(server, rc, (UInt32)buffer.Capacity, buffer) != MAXT_SUCCESS)
{
buffer.Clear();
buffer.Append(string.Format("ERROR # 0x{0:x8}", rc));
}
Console.Write(buffer + "\n\r");
}
// Free all buffers
// Free server resources
Console.Write("\nPress enter to terminate\n");
Console.ReadKey();
return;
}
/***************************************************************************************************************/
// InitAttribHandler
/***************************************************************************************************************/
private static UInt32 InitAttribHandler(UInt64 server, UInt64 cardIndex, 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 Convert.ToUInt32(true);
}
return Convert.ToUInt32(false);
}
/***************************************************************************************************************/
// CommandSend
/***************************************************************************************************************/
private static UInt32 CommandSend(UInt64 txBuffer, UInt64 rxBuffer, EX_COMMAND cmd)
{
var msg = new MXF_EMBEDDED_DATAREC[1];
msg[0].data = new UInt32[256];
IntPtr msgPtr = IntPtr.Zero;
UInt64 readCnt;
UInt64 byteCnt;
UInt32 rc = 0;
//Allocate memory
if (rc == MAXT_SUCCESS)
{
try
{
msgPtr = Marshal.AllocHGlobal(BUFFER_SIZE);
}
catch (OutOfMemoryException)
{
rc = MAXT_ERROR_MEM;
}
}
//Transmit command
msg[0].dataSize = (2 + cmd.paramNum) * 4;
msg[0].data[0] = cmd.command;
msg[0].data[1] = cmd.paramNum;
for (int i = 0; i < cmd.paramNum; i++)
msg[0].data[i + 2] = cmd.param[i];
Marshal.StructureToPtr(msg[0], msgPtr, true);
rc = mxfDeviceCommBufferWrite(txBuffer, 1, msgPtr);
if (rc != MAXT_SUCCESS)
Console.Write("Write error rc=0x{0:x8}\n", rc);
// Wait acknowledge of the command from the embedded application.
while (rc == MAXT_SUCCESS)
{
rc = mxfDeviceCommBufferRead(rxBuffer, 1, BUFFER_SIZE, out readCnt, out byteCnt, msgPtr);
if (readCnt > 0)
{
msg[0].data[0] = 0;
msg[0] = (MXF_EMBEDDED_DATAREC)Marshal.PtrToStructure(msgPtr, typeof(MXF_EMBEDDED_DATAREC));
if (msg[0].data[0] == EX_USER_COMMAND_ACK)
break;
}
}
//Free buffer
if (msgPtr != IntPtr.Zero)
Marshal.FreeHGlobal(msgPtr);
return rc;
}
}
}
Updated 10/23/2023