MX Foundation 4
ar664_end_system.cs
/*******************************************************************************
//
// File:
// ar664_end_system.cs
//
// Copyright (c) MAX Technologies Inc. 1988-2019, All Rights Reserved.
// CONFIDENTIAL AND PROPRIETARY INFORMATION WHICH IS THE
// PROPERTY OF MAX TECHNOLOGIES INC.
//
// This demo shows how to configure a client for a Boeing End System (ES).
// In this case the ES 23.1 ACP-CAP T) ES_ACP_FO is configured for 3 VL.
//
// Hardware Requirements:
// - FlexMulti A664
//
*******************************************************************************/
#define LOOPBACK
//#define LOCAL
using System;
using System.Runtime.InteropServices;
using static MAXT.MXFoundation.mxf;
namespace ar664_example
{
public class ar664_end_system
{
private const UInt32 TRUE = 1;
private const UInt32 FALSE = 0;
private const UInt32 TEST_DATASIZE = 64;
private const UInt64 TEST_MAX_CHANNELS = 64;
private const UInt64 DATARECS_BUFFER_SIZE_MAX = 64 * 1024;
/* -------------------- VL - COM Ports Configuration Tables -----------------*/
private const string ES_ACP_FO = "ES_ACP-FO";
private const UInt64 gFrameType = MXF_A664_FRAME_TYPE_BOEING;
private const UInt16 VL_33569 = 33569;
private const UInt32 UDP_PORT_60256 = 60256;
private const UInt32 UDP_PORT_60257 = 60257;
private const UInt16 VL_33570 = 33570;
private const UInt32 UDP_PORT_60262 = 60262;
private const UInt16 VL_33571 = 33571;
private const UInt32 UDP_PORT_60265 = 60265;
private const UInt32 EQUIPMENT_CLASS = 23;
private const UInt32 EQUIPMENT_POSITION = 1;
private const UInt32 PARTITION_ID = 0;
public static UInt32 recvCount = 0;
public static UInt32 TxCount = 0;
/*******************************************************************************
// Methods: COM Ports configurtion tables
/*******************************************************************************/
private const UInt64 MAX_PORTS = 4;
private const UInt32 STATE_DISABLE = 0;
private const UInt32 STATE_ENABLE = 1;
public struct A664_ES_PORT
{
public UInt64 index;
public UInt16 direction;
public UInt16 vlId;
public UInt32 destPort;
public UInt64 port;
public UInt64 vl;
public struct Buff
{
public UInt64 bufferHandle;
public IntPtr bufferPtr;
public IntPtr reserved;
}
public Buff buffer;
public UInt32 initChannel(IntPtr ptr) { return 0; } //UInt32(*initChannel)(void*);
public RxProcessRequest rxProcessRequest;
public TxUpdateDatarecPDU txUpdateDatarecPDU;
//UInt32* reserved;
public UInt32 status;
public UInt32 reserved1;
}
private static A664_ES_PORT[] portRxTable = new A664_ES_PORT[MAX_PORTS];
private static int A664_ES_PORT_RX_TABLE_SIZE = portRxTable.Length;
public static A664_ES_PORT[] portTxTable = new A664_ES_PORT[MAX_PORTS];
public static int A664_ES_PORT_TX_TABLE_SIZE = portTxTable.Length;
/* -------------------------- VL Attributes Tables -----------------------*/
public struct A664_ES_VL_TX_LIST_ATTRIBUTE
{
public UInt32 equipmentClass;
public UInt32 equipmentPosition;
public UInt32 vlId;
public UInt32 subVL;
public UInt32 destPort;
public UInt32 bag;
public UInt32 maxBuffers;
public UInt32 buffSize;
public UInt32 edeEnable;
public UInt32 edeSID;
public UInt32 icEnable;
public UInt32 frameSizeMax;
public UInt32 jitter;
}
private static readonly A664_ES_VL_TX_LIST_ATTRIBUTE[] esVLTxAttrib = {
new A664_ES_VL_TX_LIST_ATTRIBUTE{equipmentClass = EQUIPMENT_CLASS, equipmentPosition = EQUIPMENT_POSITION, vlId = VL_33569, subVL = 1, destPort = UDP_PORT_60257, bag = 1 * 1000 * 1000, maxBuffers = 16, buffSize = 1024, edeEnable = 1, edeSID = 0x04, icEnable = 1, frameSizeMax = 1024, jitter = 0 },
new A664_ES_VL_TX_LIST_ATTRIBUTE{equipmentClass = EQUIPMENT_CLASS, equipmentPosition = EQUIPMENT_POSITION, vlId = VL_33569, subVL = 1, destPort = UDP_PORT_60256, bag = 1 * 1000 * 1000, maxBuffers = 32, buffSize = 1024, edeEnable = 1, edeSID = 0x05, icEnable = 1, frameSizeMax = 1024, jitter = 0 },
new A664_ES_VL_TX_LIST_ATTRIBUTE{equipmentClass = EQUIPMENT_CLASS, equipmentPosition = EQUIPMENT_POSITION, vlId = VL_33570, subVL = 1, destPort = UDP_PORT_60262, bag = 1 * 1000 * 1000, maxBuffers = 16, buffSize = 1024, edeEnable = 1, edeSID = 0x06, icEnable = 1, frameSizeMax = 1024, jitter = 0 },
new A664_ES_VL_TX_LIST_ATTRIBUTE{equipmentClass = EQUIPMENT_CLASS, equipmentPosition = EQUIPMENT_POSITION, vlId = VL_33571, subVL = 1, destPort = UDP_PORT_60265, bag = 1 * 1000 * 1000, maxBuffers = 16, buffSize = 1024, edeEnable = 1, edeSID = 0x06, icEnable = 1, frameSizeMax = 1024, jitter = 0 }
};
private static readonly int A664_ES_VL_TX_ATTRIBUTE_LIST_SIZE = esVLTxAttrib.Length;
struct A664_ES_VL_RX_LIST_ATTRIBUTE
{
public UInt32 equipmentClass;
public UInt32 equipmentPosition;
public UInt32 vlId;
public UInt32 destPort;
public UInt32 maxBuffers;
public UInt32 buffSize;
public UInt32 edeEnable;
public UInt32 edeSID;
public UInt32 icEnable;
public UInt32 skewMax;
public UInt32 frameSizeMax;
}
private static readonly A664_ES_VL_RX_LIST_ATTRIBUTE[] esVLRxAttrib = {
new A664_ES_VL_RX_LIST_ATTRIBUTE{equipmentClass = EQUIPMENT_CLASS, equipmentPosition = EQUIPMENT_POSITION, vlId = VL_33569, destPort = UDP_PORT_60256, maxBuffers = 10, buffSize = 1024, edeEnable = 1, edeSID = 0x04, icEnable = 1, skewMax = 1024, frameSizeMax = 1024 },
new A664_ES_VL_RX_LIST_ATTRIBUTE{equipmentClass = EQUIPMENT_CLASS, equipmentPosition = EQUIPMENT_POSITION, vlId = VL_33569, destPort = UDP_PORT_60257, maxBuffers = 10, buffSize = 1024, edeEnable = 1, edeSID = 0x05, icEnable = 1, skewMax = 1024, frameSizeMax = 1024 },
new A664_ES_VL_RX_LIST_ATTRIBUTE{equipmentClass = EQUIPMENT_CLASS, equipmentPosition = EQUIPMENT_POSITION, vlId = VL_33570, destPort = UDP_PORT_60262, maxBuffers = 20, buffSize = 1024, edeEnable = 1, edeSID = 0x06, icEnable = 1, skewMax = 1024, frameSizeMax = 900 },
new A664_ES_VL_RX_LIST_ATTRIBUTE{equipmentClass = EQUIPMENT_CLASS, equipmentPosition = EQUIPMENT_POSITION, vlId = VL_33571, destPort = UDP_PORT_60265, maxBuffers = 12, buffSize = 1024, edeEnable = 1, edeSID = 0x06, icEnable = 1, skewMax = 1024, frameSizeMax = 600 }
};
private static readonly int A664_ES_VL_RX_ATTRIBUTE_LIST_SIZE = esVLRxAttrib.Length;
struct A664_ES_PORT_ATTRIBUTES
{
public UInt32 equipmentClass;
public UInt32 equipmentPosition;
public UInt32 partitionId;
public UInt32 vlId;
public UInt32 multicast;
public UInt32 dstIpAdrs;
public UInt32 srcPort;
public UInt32 destPort;
public UInt32 maxBuffers;
public UInt32 buffSize;
public UInt32 edeEnable;
public UInt32 ageValidationEnable;
public UInt32 edeOrdinalEnable;
public UInt32 edeSID;
public UInt32 frameSizeMax;
public string esName;
}
private static readonly A664_ES_PORT_ATTRIBUTES[] esCOMAttrib = {
new A664_ES_PORT_ATTRIBUTES{equipmentClass = EQUIPMENT_CLASS, equipmentPosition = EQUIPMENT_POSITION, partitionId = PARTITION_ID, vlId = VL_33569, multicast = 1, dstIpAdrs = 0, srcPort = 60257 , destPort = UDP_PORT_60256, maxBuffers = 10, buffSize = 1024, edeEnable = 1, ageValidationEnable = 0, edeOrdinalEnable = 1, edeSID = 0x04, frameSizeMax = 1200 , esName = ES_ACP_FO},
new A664_ES_PORT_ATTRIBUTES{equipmentClass = EQUIPMENT_CLASS, equipmentPosition = EQUIPMENT_POSITION, partitionId = PARTITION_ID, vlId = VL_33569, multicast = 1, dstIpAdrs = 0, srcPort = 60256 , destPort = UDP_PORT_60257, maxBuffers = 10, buffSize = 1024, edeEnable = 1, ageValidationEnable = 0, edeOrdinalEnable = 1, edeSID = 0x04, frameSizeMax = 1200 , esName = ES_ACP_FO},
new A664_ES_PORT_ATTRIBUTES{equipmentClass = EQUIPMENT_CLASS, equipmentPosition = EQUIPMENT_POSITION, partitionId = PARTITION_ID, vlId = VL_33570, multicast = 1, dstIpAdrs = 0, srcPort = 60262 , destPort = UDP_PORT_60262, maxBuffers = 10, buffSize = 1024, edeEnable = 1, ageValidationEnable = 0, edeOrdinalEnable = 1, edeSID = 0x04, frameSizeMax = 1200 , esName = ES_ACP_FO},
new A664_ES_PORT_ATTRIBUTES{equipmentClass = EQUIPMENT_CLASS, equipmentPosition = EQUIPMENT_POSITION, partitionId = PARTITION_ID, vlId = VL_33571, multicast = 1, dstIpAdrs = 0, srcPort = 60265 , destPort = UDP_PORT_60265, maxBuffers = 10, buffSize = 1024, edeEnable = 1, ageValidationEnable = 0, edeOrdinalEnable = 1, edeSID = 0x04, frameSizeMax = 1200 , esName = ES_ACP_FO}
};
private static readonly int A664_ES_PORT_COM_ATTRIBUTES_SIZE = esCOMAttrib.Length;
// Declare delegate -- defines required signature:
public delegate UInt32 TxUpdateDatarecPDU(A664_ES_PORT port, ref byte[] DatarecData);
public delegate void RxProcessRequest(UInt16 vlId, UInt16 port, byte[] bufferPtr);
/*******************************************************************************
// Methods: VL33569Port60257
/*******************************************************************************/
public struct A664_PORT60257_PDU
{
public struct Header
{
public UInt32 Reserved_Word;
public UInt32 FSS; // Functional_Status_set
}
public Header header;
public UInt32 bit64;
/* Include:
PA_PTT_ECHO bit64 num 1
SPEAKER_STATUS bit65 num 1
HANDMIC_PTT_ECHO bit66 num 1
GLARESHIELD_PTT_ECHO bit67 num 1
CONTROL_WHEEL_PTT_ECHO bit68 num 1
ACT_MIC_PTT_ECHO bit69 num 1
*/
public UInt16 WARN_AUD_ENUM_RTN_1_A; // bit 96 num 16
public UInt16 WARN_AUD_ENUM_RTN_1_B; // bit 112 num 16
public UInt16 WARN_AUD_ENUM_RTN_2_A; // bit 128 num 16
public UInt16 WARN_AUD_ENUM_RTN_2_B; // bit 144 num 16
public UInt16 WARN_AUD_ENUM_RTN_3_A; // bit 160 num 16
public UInt16 WARN_AUD_ENUM_RTN_3_B; // bit 176 num 16
public UInt16 WARN_AUD_ENUM_RTN_4_A; // bit 192 num 16
public UInt16 WARN_AUD_ENUM_RTN_4_B; // bit 208 num 16
public UInt32 CDN_REVERSION_STATUS; // bit 224 num 1
public UInt32 bit256;
/* Include:
HF_L_PTT bit 256 num 1
HF_R_PTT bit 257 num 1
SAT_L1_PTT bit 258 num 1
SAT_L2_PTT bit 259 num 1
VHF_C_PTT bit 260 num 1
VHF_L_PTT bit 261 num 1
VHF_R_PTT bit 262 num 1
FLT_PTT bit 263 num 1
SAT_R1_PTT bit 264 num 1
SAT_R2_PTT bit 265 num 1
*/
public UInt32 bit288;
/* Include:
CAB_PTT bit 288 num 2
PA_PTT bit 290 num 2
*/
public UInt32 bit320;
/* Include:
HF_L_SELCAL_RESET bit 320 num 1
HF_R_SELCAL_RESET bit 321 num 1
VHF_C_SELCAL_RESET bit 322 num 1
VHF_L_SELCAL_RESET bit 323 num 1
VHF_R_SELCAL_RESET bit 324 num 1
MIC_ON_VHF_L bit 325 num 1
MIC_ON_VHF_C bit 326 num 1
MIC_ON_VHF_R bit 327 num 1
SAT_L1_MIC_ON bit 333 num 1
SAT_L2_MIC_ON bit 334 num 1
SAT_R1_MIC_ON bit 335 num 1
SAT_R2_MIC_ON bit 336 num 1
*/
public UInt32 bit352;
/* Include:
MIC_ON_CAB bit 352 num 2
CAB_PRIORITY_CALL bit 354 num 2
FLT_RESET bit 356 num 2
*/
public UInt32 TUNING_DISPLAY_CODE; //bit 384 num 8
public UInt32 bit416;
/* Include:
CAPT_USING_OBS_ACP bit 416 num 1
OXY_MIC_ON bit 417 num 1
FO_USING_OBS_ACP bit 418 num 1
*/
}
//initialising port60257
private static A664_PORT60257_PDU port60257 = new A664_PORT60257_PDU();
private static void showPort60257Status(UInt16 vlId, UInt16 port, byte[] data)
{
A664_PORT60257_PDU dataParam = new A664_PORT60257_PDU();
dataParam = (A664_PORT60257_PDU)ByteToObj(data, dataParam);
Console.Write("\n<= {0:d3}: Receiving Status from VL {1} Port {2}\n\n", ++recvCount, vlId, port);
Console.Write(" PA-PTT_ECHO: {0}\n", (dataParam.bit64 & 0x1) > 0 ? "is active" : "is not active");
Console.Write(" SPEAKER_STATUS: {0}\n", ((dataParam.bit64 >> 1) & 0x01) > 0 ? "Appropriate speaker_current exist" : "is not Active");
Console.Write(" HANDMIC_PTT_ECHO: {0}\n", ((dataParam.bit64 >> 2) & 0x01) > 0 ? "is active" : "is not active");
Console.Write(" GLARESHIELD_PTT_ECHO: {0}\n", ((dataParam.bit64 >> 3) & 0x01) > 0 ? "is active" : "is not active");
Console.Write(" CONTROL_WHEEL_PTT_ECHO: {0}\n", ((dataParam.bit64 >> 4) & 0x01) > 0 ? "is active" : "is not active");
Console.Write(" ACT_MIC_PTT_ECHO: {0}\n", ((dataParam.bit64 >> 5) & 0x01) > 0 ? "is active" : "is not active");
Console.Write(" WARN_AUD_ENUM_RTN_1_A: 0x{0:x4}\n", dataParam.WARN_AUD_ENUM_RTN_1_A);
Console.Write(" WARN_AUD_ENUM_RTN_1_B: 0x{0:x4}\n", dataParam.WARN_AUD_ENUM_RTN_1_B);
Console.Write(" CDN_REVERSION_STATUS: {0}\n", dataParam.CDN_REVERSION_STATUS > 0 ? "asserted" : "not asserted");
Console.Write(" HF-L_PTT: PTT Keyline {0}\n", (dataParam.bit256 & 0x01) > 0 ? "is active" : "is not actived");
Console.Write(" HF-R_PTT: PTT Keyline {0}\n", ((dataParam.bit256 >> 1) & 0x01) > 0 ? "is active" : "is not actived");
Console.Write(" HF-MIC_ON_VHF_L: Mic Switch {0}\n", ((dataParam.bit320 >> 5) & 0x01) > 0 ? "selected" : "not selected");
Console.Write(" HF-MIC_ON_CAB: {0}\n", (dataParam.bit352 & 0x03) > 0 ? "valid" : "invalid");
Console.Write(" TUNING_DISPLAY_CODE: {0}\n", dataParam.TUNING_DISPLAY_CODE> 0 ? "valid" : "invalid");
Console.Write(" CAPT_USING_OBS_ACP: {0}\n", (dataParam.bit416 & 0x01) > 0 ? "valid" : "invalid");
Console.Write(" OXY_MIC_ON: oxigen mask {0}\n", ((dataParam.bit416 >> 1) & 0x01) > 0 ? "deployed" : " not deployed");
Console.Write(" FO_USING_OBS_ACP: First Officer using Observer audio : {0}\n",((dataParam.bit416 >> 2) & 0x01) > 0 ? "yes" : "no");
Console.Write("\n\n");
}
private static UInt32 txUpdateParmsVL33569Port60257(A664_ES_PORT port, ref byte[] pdu)
{
UInt32 length = 0;
//Start at bit 64
UInt32 PA_PTT_ECHO = 0;
UInt32 SPEAKER_STATUS = 1;
UInt32 HANDMIC_PTT_ECHO = 0;
UInt32 GLARESHIELD_PTT_ECHO = 0;
UInt32 CONTROL_WHEEL_PTT_ECHO = 0;
UInt32 ACT_MIC_PTT_ECHO = 0;
//Start at bit 320
UInt32 MIC_ON_VHF_L = 1;
UInt32 MIC_ON_VHF_C = 1;
UInt32 MIC_ON_VHF_R = 1;
//Start at bit352
UInt32 MIC_ON_CAB = 0;
//Start at bit 416
UInt32 OXY_MIC_ON = 0;
UInt32 FO_USING_OBS_ACP = 1;
// Build the updated status vector
if (port.buffer.bufferPtr != IntPtr.Zero)
{
port60257 = (A664_PORT60257_PDU)Marshal.PtrToStructure(port.buffer.bufferPtr, typeof(A664_PORT60257_PDU));
port60257.header.Reserved_Word = 0;
port60257.header.FSS = 0;
port60257.bit64 =(PA_PTT_ECHO | SPEAKER_STATUS << 1 | HANDMIC_PTT_ECHO << 2 | GLARESHIELD_PTT_ECHO << 3 | CONTROL_WHEEL_PTT_ECHO << 4 | ACT_MIC_PTT_ECHO << 5);
port60257.WARN_AUD_ENUM_RTN_1_A += 0x0010;
port60257.WARN_AUD_ENUM_RTN_1_B += 0x0020;
port60257.CDN_REVERSION_STATUS = FALSE;
port60257.bit320 = MIC_ON_VHF_L << 5 | MIC_ON_VHF_C << 6 | MIC_ON_VHF_R << 7;
port60257.bit352 = MIC_ON_CAB;
port60257.bit416 = (OXY_MIC_ON << 1 | FO_USING_OBS_ACP << 2);
Marshal.StructureToPtr(port60257, port.buffer.bufferPtr, true);
pdu = ObjectToByteArray(port60257, Marshal.SizeOf(typeof(A664_PORT60257_PDU)));
length = (UInt32)Marshal.SizeOf(typeof(A664_PORT60257_PDU));
}
else
Console.Write("COM Port buffer not assigned ");
return length;
}
/*******************************************************************************
// Methods: VL33569Port60256
/*******************************************************************************/
public enum NAV_SELECT_CODE { VOR_L, VOR_R, ADF_L, ADF_R };
public enum APP_SELECT_CODE { APP_L, APP_R, MK_R, Invalid };
public enum VBR_CODE { VOICE, BOTH, RANGE };
public struct A664_PORT60256_PDU
{
public struct Header
{
public UInt32 Reserved_Word;
public UInt32 FSS; // Functional_Status_set
}
public Header header;
// bit start 64
public UInt32 wordBit64;
// bit start 96
public UInt16 VHF_L_VOLUME ;
public UInt16 VHF_C_VOLUME ;
public UInt16 VHF_R_VOLUME ;
public UInt16 FLT_VOLUME ;
public UInt16 CAB_VOLUME ;
public UInt16 PA_VOLUME ;
public UInt16 HF_L_VOLUME ;
public UInt16 HF_R_VOLUME ;
public UInt16 SAT1_VOLUME ;
public UInt16 SAT2_VOLUME ;
public UInt16 NAV_VOLUME ;
public UInt16 APPROACH_VOLUME ;
public UInt16 SPEAKER_VOLUME ;
public UInt16 reserved ;
}
private static A664_PORT60256_PDU port60256 = new A664_PORT60256_PDU();
private static void showPort60256Status(UInt16 vlId, UInt16 port, byte[] data) // data array from a RxAcqRead
{
A664_PORT60256_PDU dataParam = new A664_PORT60256_PDU();
dataParam = (A664_PORT60256_PDU)ByteToObj(data, dataParam);
Console.Write("\n<= %{0:000}: Receiving Status from VL {1} Port {2}\n\n", ++recvCount, vlId, port);
Console.Write(" NAV_SELECT_CODE: {0}\n", dataParam.wordBit64 & 0x03);
Console.Write(" APP_SELECT_CODE: {0}\n", dataParam.wordBit64 >> 2 & 0x03);
Console.Write(" VBR_CODE: {0}\n", dataParam.wordBit64 >> 4 & 0x03);
Console.Write(" VHF_L_VOLUME: {0}\n", dataParam.VHF_L_VOLUME);
Console.Write(" VHF_C_VOLUME: {0}\n", dataParam.VHF_C_VOLUME);
Console.Write(" VHF_R_VOLUME: {0}\n", dataParam.VHF_R_VOLUME);
Console.Write(" FLT_VOLUME: {0}\n", dataParam.FLT_VOLUME);
Console.Write(" CAB_VOLUME: {0}\n", dataParam.CAB_VOLUME);
Console.Write(" PA_VOLUME: {0}\n", dataParam.PA_VOLUME);
Console.Write(" HF_L_VOLUME: {0}\n", dataParam.HF_L_VOLUME);
Console.Write(" HF_R_VOLUME: {0}\n", dataParam.HF_R_VOLUME);
Console.Write(" SAT1_VOLUME: {0}\n", dataParam.SAT1_VOLUME);
Console.Write(" SAT2_VOLUME: {0}\n", dataParam.SAT2_VOLUME);
Console.Write(" NAV_VOLUME: {0}\n", dataParam.NAV_VOLUME);
Console.Write(" APPROACH_VOLUME: {0}\n", dataParam.APPROACH_VOLUME);
Console.Write(" SPEAKER_VOLUME: {0}\n", dataParam.SPEAKER_VOLUME);
}
private static UInt32 txUpdateParmsVL33569Port60256(A664_ES_PORT port, ref byte[] pdu)
{
UInt32 length = 0;
// Build the updated status vector
if (port.buffer.bufferPtr != IntPtr.Zero)
{
port60256 = new A664_PORT60256_PDU();
port60256.header.Reserved_Word = 0;
port60256.header.FSS = 0;
port60256.wordBit64 = (UInt32)NAV_SELECT_CODE.ADF_L | (UInt32)APP_SELECT_CODE.APP_L << 2 | (UInt32)VBR_CODE.BOTH << 4;
port60256.VHF_L_VOLUME = 5000;
port60256.VHF_C_VOLUME = 6000;
port60256.VHF_R_VOLUME = 5000;
port60256.FLT_VOLUME = 7000;
port60256.CAB_VOLUME = 7000;
port60256.HF_L_VOLUME = 5000;
port60256.HF_R_VOLUME = 5000;
port60256.SAT1_VOLUME = 6000;
port60256.SAT2_VOLUME = 6000;
port60256.NAV_VOLUME = 10000;
port60256.APPROACH_VOLUME = 10000;
port60256.SPEAKER_VOLUME = 10000;
Marshal.Copy(new byte[Marshal.SizeOf(typeof(A664_PORT60256_PDU))], 0, port.buffer.bufferPtr, Marshal.SizeOf(typeof(A664_PORT60256_PDU)));
Marshal.StructureToPtr(port60256, port.buffer.bufferPtr, true);
pdu = ObjectToByteArray(port60256, Marshal.SizeOf(typeof(A664_PORT60256_PDU)));
length = (UInt32)Marshal.SizeOf(typeof(A664_PORT60256_PDU));
}
else
Console.Write("COM Port buffer not assigned for VL={0}, port={1}\n", port.vlId, port.destPort);
return length;
}
/*******************************************************************************
// Methods: Inbound - Outbound Messages
/*******************************************************************************/
private static UInt32 processPartitionOutboundTraffic()
{
UInt32 portIdx, dataIdx;
IntPtr bufferPtr = IntPtr.Zero;
UInt32 rc = 0;
UInt64 count;
IntPtr recPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(MXF_A664_DATAREC)));
for (portIdx = 0; portIdx < A664_ES_PORT_TX_TABLE_SIZE; portIdx++)
{
bufferPtr = portTxTable[portIdx].buffer.bufferPtr;
if (bufferPtr == IntPtr.Zero)
{
Console.Write("parm vector not assigned for vlId={0}, port={1}", portTxTable[portIdx].vlId, portTxTable[portIdx].destPort);
continue;
}
if (portTxTable[portIdx].status == STATE_ENABLE)
{
// Something to send
datarec = new MXF_A664_DATAREC();
datarec.data = new byte[8192];
// Build the Transmit Record
datarec.timeTag = 0;
datarec.control = 0;
datarec.repeatCount = 1;
datarec.dataSize = portTxTable[portIdx].txUpdateDatarecPDU(portTxTable[portIdx], ref datarec.data);
Console.Write("==> {0:000}: Sending for vlId={1}, port={2}\n", TxCount++, portTxTable[portIdx].vlId, portTxTable[portIdx].destPort);
Console.Write(" timeTag={0:x12}, control={1}, dataSize={2}", datarec.timeTag, datarec.control, datarec.dataSize);
Console.Write("\n data=");
for (dataIdx = 0; dataIdx < datarec.dataSize; dataIdx++)
{
Console.Write("{0:X2} ", datarec.data[dataIdx]);
if (((dataIdx + 1) % 8) == 0 && (dataIdx + 1 < datarec.dataSize))
Console.Write("\n ");
}
Console.Write("\n\n");
Marshal.StructureToPtr(datarec, recPtr, false);
// Ethernet RJ45 TX and Systen unit light 1 indicate the transmission
rc = mxfA664TxAperiodicWrite(portTxTable[portIdx].port, MXF_TXAPERIODIC_FLAG_DEFAULT, 0, 1, recPtr, out count);
if (rc == MAXT_SUCCESS)
Console.Write("Transmission Error rc=0x{0:x8}\r", rc);
}
}
Marshal.FreeHGlobal(recPtr);
mxfSleep(2000);
return rc;
}
private static UInt32 processPartitionInboundTraffic()
{
var rxRec664 = new MXF_A664_DATAREC();
IntPtr recPtr = IntPtr.Zero; //MXF_A664_DATAREC ptr
A664_ES_PORT portRx;
UInt64 bufferHandle;
UInt64 status, msgsCount, bytesCount, pendingBytes, freeByteso;
UInt32 portIdx;
UInt32 maxPorts, rc = 0;
maxPorts = (UInt32)A664_ES_PORT_RX_TABLE_SIZE;
// Free the Resources Allocated
for (portIdx = 0; portIdx < maxPorts; portIdx++)
{
portRx = portRxTable[portIdx];
if (portRx.status == STATE_ENABLE)
{
bufferHandle = portRx.buffer.bufferHandle;
recPtr = portRx.buffer.bufferPtr;
rc = mxfRxAcqBufferStatusGet(bufferHandle, out status, out msgsCount, out pendingBytes, out freeByteso);
if (rc != MAXT_SUCCESS || (status & MXF_RXACQ_STATUS_RUNNING) == 0)
{
Console.Write("Acquisition stopped; status={0:X}, rc=0x{1:x8}\n\n", status, rc);
continue;
}
if (msgsCount > 0)
{
// Read the data
rc = mxfA664RxAcqRead(bufferHandle, 0, DATARECS_BUFFER_SIZE_MAX, out status, out msgsCount, out bytesCount, recPtr);
if (rc == MAXT_SUCCESS)
{
rxRec664 = (MXF_A664_DATAREC)Marshal.PtrToStructure(recPtr, typeof(MXF_A664_DATAREC));
portRx.rxProcessRequest(portRx.vlId, (UInt16)portRx.destPort, rxRec664.data);
}
}
}
}
return rc;
}
/*******************************************************************************
// Methods: Resources Allocation
/*******************************************************************************/
private static UInt32 CreateVlTx(UInt64 phy, ref A664_ES_VL_TX_LIST_ATTRIBUTE attrib, UInt32 vlid, UInt64 frameType, out UInt64 vlHandle)
{
UInt32 rc = 0;
MXF_A664_VL_PARAM_TX param = new MXF_A664_VL_PARAM_TX();
param.dir.Tx.subVl = new MXF_A664_VL_PARAM_TX.Dir.TX.SubVl[4];
param.direction = MXF_A664_VL_DIR_TX;
param.VLId = vlid;
param.frameType = frameType;
param.dir.Tx.netSelection = MXF_A664_NETSELECT_ALL;
param.frameSizeMax = attrib.frameSizeMax;
param.dir.Tx.subVlNumber = attrib.subVL;
param.dir.Tx.bag = attrib.bag;
param.dir.Tx.netSelection = MXF_A664_NETSELECT_ALL;
param.dir.Tx.Ede.enable = attrib.edeEnable;
param.dir.Tx.subVl[0].maxBuffers = attrib.maxBuffers;
param.dir.Tx.subVl[0].bufferSize = attrib.buffSize;
rc = mxfA664VlCreate(phy, ref param, out vlHandle);
// The VL was created previously; return the VL handle
if (rc == MAXT_ERROR_VL_IN_USE)
rc = mxfA664VlGet(phy, ref param, out vlHandle);
return rc;
}
private static UInt32 CreateVlRx(UInt64 phy, ref A664_ES_VL_RX_LIST_ATTRIBUTE attrib, UInt32 vlid, UInt64 frameType, out UInt64 vlHandle)
{
UInt32 rc = 0;
MXF_A664_VL_PARAM_RX param = new MXF_A664_VL_PARAM_RX();
param.direction = MXF_A664_VL_DIR_RX;
param.VLId = vlid;
param.frameType = frameType;
param.frameSizeMax = attrib.frameSizeMax;
if (attrib.edeEnable > 0)
{
// Boeing EDE
param.dir.Rx.Ede.enable = attrib.edeEnable;
param.dir.Rx.Ede.skewMax = attrib.skewMax;
}
else
{
// ARINC MAC
param.dir.Rx.Mac.skewMax = 4000;
param.dir.Rx.Mac.rmPSNRange = 2;
}
// Create the VL
rc = mxfA664VlCreate(phy, ref param, out vlHandle);
if (rc == MAXT_ERROR_VL_IN_USE)
{
// The VL was created previously; return the VL handle
rc = mxfA664VlGet(phy, ref param, out vlHandle);
}
return rc;
}
private static UInt32 CreateCOMPort(UInt64 vl, UInt64 direction, UInt64 mode, A664_ES_PORT_ATTRIBUTES attribCOM, out UInt64 portHandle, out UInt64 bufferHandle)
{
UInt32 srcIpAdrs, dstIpAdrs;
UInt64 size;
UInt32 rc;
portHandle = 0;
bufferHandle = 0;
srcIpAdrs = 0x0A000000 | ((attribCOM.equipmentClass & 0xff) << 16) | ((attribCOM.equipmentPosition & 0xff) << 8) | (attribCOM.equipmentClass & 0xff);
portParam.portType = MXF_A664_PORT_TYPE_COM;
portParam.family = MXF_A664_PORT_FAMILY_IPV4;
portParam.mode = mode;
if (direction == MXF_A664_VL_DIR_RX)
{
portParam.dir.Rx.bufferSize = attribCOM.buffSize;
portParam.dir.Rx.maxBuffers = attribCOM.maxBuffers;
portParam.dir.Rx.network = MXF_A664_NETSELECT_ALL;
}
else
portParam.dir.Tx.subVl = 0;
if (attribCOM.edeEnable > 0)
portParam.Ede.sid = attribCOM.edeSID;
portParam.type.COM.srcAddress.version.IPv4.address = srcIpAdrs;
portParam.type.COM.srcAddress.port = attribCOM.srcPort;
if (attribCOM.multicast > 0)
dstIpAdrs = 0xE0E00000 | attribCOM.vlId;
else
dstIpAdrs = attribCOM.dstIpAdrs;
portParam.type.COM.destAddress.version.IPv4.address = dstIpAdrs;
portParam.type.COM.destAddress.port = attribCOM.destPort;
Console.Write("\nCreating {0} COM Port (vlId={1})\n", direction == MXF_A664_VL_DIR_TX ? "Tx" : "Rx", attribCOM.vlId);
Console.Write(" srcAddress=0x{0:x8}\n", srcIpAdrs);
Console.Write(" srcPort=0x{0:x8} ({1})\n", attribCOM.srcPort, attribCOM.srcPort);
Console.Write(" destAddress=0x{0:x8}\n", dstIpAdrs);
Console.Write(" dstPort=0x{0:x8} ({1})\n", attribCOM.destPort, attribCOM.destPort);
// Allocate the TX buffer for the port - just create the handle...)
rc = mxfA664PortCreate(vl, ref portParam, out portHandle);
if (rc == MAXT_SUCCESS)
{
size = attribCOM.maxBuffers * attribCOM.buffSize;
switch (direction)
{
case MXF_A664_VL_DIR_TX:
rc = mxfTxAperiodicBufferGet(vl, portParam.dir.Tx.subVl, out bufferHandle);
break;
case MXF_A664_VL_DIR_RX:
rc = mxfRxAcqBufferGet(portHandle, out bufferHandle);
break;
}
}
return rc;
}
private static UInt32 allocateTxCOMChannelsResources(UInt64 phy)
{
UInt32 rc = 0;
UInt64 vl = 0;
UInt64 port;
UInt64 bufferHandle;
IntPtr bufferPtr = IntPtr.Zero;
int vlIdx, portIdx, comIdx;
for (comIdx = 0; comIdx < A664_ES_PORT_TX_TABLE_SIZE && rc == MAXT_SUCCESS; comIdx++)
{
for (portIdx = 0; portIdx < A664_ES_PORT_TX_TABLE_SIZE && rc == MAXT_SUCCESS; portIdx++)
{
if (esCOMAttrib[comIdx].vlId == portTxTable[portIdx].vlId &&
esCOMAttrib[comIdx].destPort == portTxTable[portIdx].destPort)
{
for (vlIdx = 0; vlIdx < A664_ES_VL_TX_ATTRIBUTE_LIST_SIZE; vlIdx++)
{
// Locate attribute for the VL Creation
if (esCOMAttrib[comIdx].vlId == esVLTxAttrib[vlIdx].vlId)
{
// Allocate a Tx Port
rc = CreateVlTx(phy, ref esVLTxAttrib[vlIdx], esVLTxAttrib[vlIdx].vlId, MXF_A664_FRAME_TYPE_BOEING, out vl);
if (rc == MAXT_SUCCESS)
{
// Add TX COM Port(s) to the VL
rc = CreateCOMPort(vl, MXF_A664_VL_DIR_TX, MXF_A664_PORT_MODE_QUEUING, esCOMAttrib[comIdx], out port, out bufferHandle);
if (rc == MAXT_SUCCESS)
{
bufferPtr = Marshal.AllocHGlobal((int)DATARECS_BUFFER_SIZE_MAX);
// Add a new session to list
if (bufferPtr != IntPtr.Zero)
{
//memset(bufferPtr, 0, DATARECS_BUFFER_SIZE_MAX);
Marshal.Copy(new byte[DATARECS_BUFFER_SIZE_MAX], 0, bufferPtr, (int)DATARECS_BUFFER_SIZE_MAX);
portTxTable[portIdx].index = (UInt32)portIdx;
portTxTable[portIdx].direction = (UInt16)MXF_A664_VL_DIR_TX;
portTxTable[portIdx].vl = vl;
portTxTable[portIdx].port = port;
portTxTable[portIdx].buffer.bufferHandle = bufferHandle;
portTxTable[portIdx].buffer.bufferPtr = bufferPtr;
Console.Write("Port TX {0} allocated for vlId={1} destPort={2}\n", portRxTable[portIdx].index, portTxTable[portIdx].vlId, portTxTable[portIdx].destPort);
break;
}
}
break;
}
}
}
}
}
}
Console.Write("\n");
return rc;
}
private static UInt32 allocateRxCOMChannelResources(UInt64 phy)
{
UInt32 rc = 0;
UInt64 vl;
UInt64 port;
UInt64 rxBuffer;
UInt32 vlIdx, comIdx, portIdx;
IntPtr bufferPtr = IntPtr.Zero;
// Define the Rx COM Port
for (comIdx = 0; comIdx < A664_ES_PORT_COM_ATTRIBUTES_SIZE && rc == MAXT_SUCCESS; comIdx++)
{
for (portIdx = 0; portIdx < A664_ES_PORT_RX_TABLE_SIZE && rc == MAXT_SUCCESS; portIdx++)
{
if (esCOMAttrib[comIdx].vlId == portRxTable[portIdx].vlId &&
esCOMAttrib[comIdx].destPort == portRxTable[portIdx].destPort)
{
for (vlIdx = 0; vlIdx < A664_ES_VL_RX_ATTRIBUTE_LIST_SIZE; vlIdx++)
{
// Locate attribute for the VL Creation
if (esCOMAttrib[comIdx].vlId == esVLRxAttrib[vlIdx].vlId)
{
// Allocate the receive VL
rc = CreateVlRx(phy, ref esVLRxAttrib[vlIdx], esVLRxAttrib[vlIdx].vlId, MXF_A664_FRAME_TYPE_BOEING, out vl);
if (rc == MAXT_SUCCESS)
{
rc = CreateCOMPort(vl, MXF_A664_VL_DIR_RX, MXF_A664_PORT_MODE_QUEUING, esCOMAttrib[comIdx], out port, out rxBuffer);
if (rc == MAXT_SUCCESS)
{
bufferPtr = Marshal.AllocHGlobal((int)DATARECS_BUFFER_SIZE_MAX);
if (bufferPtr != IntPtr.Zero)
{
Marshal.Copy(new byte[DATARECS_BUFFER_SIZE_MAX], 0, bufferPtr, (int)DATARECS_BUFFER_SIZE_MAX);
// Set and start acquisition channel
rc = mxfRxAcqModeSet(rxBuffer, MXF_RXACQ_MODE_LINEAR);
if (rc == MAXT_SUCCESS)
rc = mxfRxAcqStart(rxBuffer, MXF_RXACQ_FLAG_DEFAULT, 0, 0);
if (rc == MAXT_SUCCESS)
{
portRxTable[portIdx].index = portIdx;
portRxTable[portIdx].vl = vl;
portRxTable[portIdx].port = port;
portRxTable[portIdx].buffer.bufferHandle = rxBuffer;
portRxTable[portIdx].buffer.bufferPtr = bufferPtr;
portRxTable[portIdx].direction = (UInt16)MXF_A664_VL_DIR_RX;
Console.Write("Port RX {0} allocated for vlId={1}, destPort={2}\n", portRxTable[portIdx].index, portRxTable[portIdx].vlId, portRxTable[portIdx].destPort);
}
}
break;
}
}
}
}
}
}
}
Console.Write("\n");
return rc;
}
/*******************************************************************************
// Partition Base Initialisation - Termination
/*******************************************************************************/
private static void configureApplicationPartition()
{
portTxTable = new A664_ES_PORT[A664_ES_PORT_TX_TABLE_SIZE];
portTxTable = new A664_ES_PORT[A664_ES_PORT_RX_TABLE_SIZE];
// Set static info in Tx port table
portTxTable[0].index = 0;
portTxTable[0].status = STATE_ENABLE;
portTxTable[0].vlId = VL_33569;
portTxTable[0].destPort = UDP_PORT_60256;
portTxTable[0].buffer.bufferPtr = IntPtr.Zero;
portTxTable[0].txUpdateDatarecPDU = txUpdateParmsVL33569Port60256;
portTxTable[1].index = 1;
portTxTable[1].status = STATE_ENABLE;
portTxTable[1].vlId = VL_33569;
portTxTable[1].destPort = UDP_PORT_60257;
portTxTable[1].buffer.bufferPtr = IntPtr.Zero;
portTxTable[1].txUpdateDatarecPDU = txUpdateParmsVL33569Port60257;
portTxTable[2].index = 2;
portTxTable[2].status = STATE_DISABLE;
portTxTable[2].vlId = VL_33570;
portTxTable[2].destPort = UDP_PORT_60262;
portTxTable[2].buffer.bufferPtr = IntPtr.Zero;
portTxTable[2].txUpdateDatarecPDU = null;
portTxTable[3].index = 3;
portTxTable[3].status = STATE_DISABLE;
portTxTable[3].vlId = VL_33571;
portTxTable[3].destPort = UDP_PORT_60265;
portTxTable[3].buffer.bufferPtr = IntPtr.Zero;
portTxTable[3].txUpdateDatarecPDU = null;
// Set static info in Rx port table
portRxTable[0].index = 0;
portRxTable[0].status = STATE_ENABLE;
portRxTable[0].vlId = VL_33569;
portRxTable[0].destPort = UDP_PORT_60256;
portRxTable[0].buffer.bufferPtr = IntPtr.Zero;
portRxTable[0].rxProcessRequest = showPort60256Status;
portRxTable[1].index = 1;
portRxTable[1].status = STATE_ENABLE;
portRxTable[1].vlId = VL_33569;
portRxTable[1].destPort = UDP_PORT_60257;
portRxTable[1].buffer.bufferPtr = IntPtr.Zero;
portRxTable[1].rxProcessRequest = showPort60257Status;
portRxTable[2].index = 2;
portRxTable[2].status = STATE_DISABLE;
portRxTable[2].vlId = VL_33570;
portRxTable[2].destPort = UDP_PORT_60262;
portRxTable[2].buffer.bufferPtr = IntPtr.Zero;
portRxTable[2].rxProcessRequest = null;
portRxTable[3].index = 3;
portRxTable[3].status = STATE_DISABLE;
portRxTable[3].vlId = VL_33571;
portRxTable[3].destPort = UDP_PORT_60265;
portRxTable[3].buffer.bufferPtr = IntPtr.Zero;
portRxTable[3].rxProcessRequest = null;
}
private static void FreeAllAllocatedResources()
{
UInt32 rc = 0;
UInt64 bufferHandle;
IntPtr bufferPtr;
UInt64 status, msgCount, pendingBytes, freeBytes;
UInt32 index;
// Free the Resources Allocated
for (index = 0; index < A664_ES_PORT_RX_TABLE_SIZE; index++)
{
bufferHandle = portRxTable[index].buffer.bufferHandle;
bufferPtr = portRxTable[index].buffer.bufferPtr;
if (bufferPtr != IntPtr.Zero)
Marshal.FreeHGlobal(bufferPtr);
rc = mxfRxAcqStop(bufferHandle);
// Make sure the acquisition if stopped
while (rc == MAXT_SUCCESS)
{
rc = mxfRxAcqBufferStatusGet(bufferHandle, out status, out msgCount, out pendingBytes, out freeBytes);
if ((status & MXF_RXACQ_STATUS_STOPPED) > 0)
break;
}
mxfRxAcqBufferFree(bufferHandle);
mxfA664PortRelease(portRxTable[index].port);
mxfA664VlRelease(portRxTable[index].vl);
}
for (index = 0; index < A664_ES_PORT_RX_TABLE_SIZE; index++)
{
bufferHandle = portTxTable[index].buffer.bufferHandle;
bufferPtr = portTxTable[index].buffer.bufferPtr;
if (bufferPtr != IntPtr.Zero)
Marshal.FreeHGlobal(bufferPtr);
mxfA664PortRelease(portTxTable[index].port);
mxfA664VlRelease(portTxTable[index].vl);
}
}
/*******************************************************************************
// Main
/*******************************************************************************/
static void Main(string[] args)
{
UInt64 server = 0;
UInt64 device = 0;
var module = new UInt64[1];
var phyChn = new UInt64[1];
UInt32 rc;
UInt64 count = 0;
int loop = 0;
#if !LOCAL
string szAddress;
#endif
Console.Write("\nARINC664 End System (ES) Simulation Demo\n\n");
// Connect to server
# if LOCAL
rc = mxfServerConnect("0.0.0.0", "", "", FALSE, &server);
#else
rc = mxfServerConnect("192.168.0.1", "admin", "admin", 0, out server);
#endif
if (rc != MAXT_SUCCESS)
{
Console.Write("Failed to connect; rc=0x{0:x8}\n", rc);
Console.Write("\nPress a key to terminate\n");
Console.ReadKey();
return;
}
// Initialize server, allocate base resources
rc = mxfSystemInit(server);
// Set Timebase
if (rc == MAXT_SUCCESS)
rc = mxfSystemTimeBaseSet(server, MXF_TIMEBASE_DEVICE_NSEC);
// Get the first device handle
if (rc == MAXT_SUCCESS)
rc = mxfSystemDeviceGet(server, 0, out device);
// Get the first A664 module
if (rc == MAXT_SUCCESS)
rc = mxfDeviceModuleAllGet(device, MXF_MODULE_A664, 1, out count, module);
// Obtain the first ARINC 664 Phy channel (Phy logical #0)
if (rc == MAXT_SUCCESS && count != 0)
rc = mxfModuleChannelAllGet(module[0], MXF_CLASS_A664, MXF_SCLASS_RX_CHANNEL, 1, out count, phyChn);
// If module or channel not found, return an error
if (rc == MAXT_SUCCESS && count == 0)
rc = MAXT_ERROR_NOT_FOUND;
# if LOOPBACK
if (rc == MAXT_SUCCESS)
rc = mxfAttributeUint64Set(phyChn[0], KMXF_A664_PHY_LOOPBACK, VMXF_A664_PHY_LOOPBACK_EXTERNAL);
if (rc == MAXT_SUCCESS)
mxfSleep(500);
#endif
// Define the number of endpoints
configureApplicationPartition();
// Create the VL and COM ports (TX/RX) from the tables
if (rc == MAXT_SUCCESS)
{
// Create the transmission (TX) virtual link
rc = allocateTxCOMChannelsResources(phyChn[0]);
// Create the transmission (RX) virtual link
if (rc == MAXT_SUCCESS)
rc = allocateRxCOMChannelResources(phyChn[0]);
}
// Mainloop Check for requests for the Sessions
if (rc == MAXT_SUCCESS)
{
while (rc == MAXT_SUCCESS && loop++ < 1)
{
rc = processPartitionOutboundTraffic();
rc = processPartitionInboundTraffic();
}
// Free allocated Vl, PORT(s), buffers
FreeAllAllocatedResources();
}
// Close the server
if (server > 0)
{
}
Console.Write("\n\nPress a key to terminate rc=0x{0:x8}\n", rc);
Console.ReadKey();
return;
}
//copy structure to byte array
private static byte[] ObjectToByteArray(object obj, int size)
{
if (obj == null)
return null;
byte[] arr = new byte[size];
IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(obj));
Marshal.StructureToPtr(obj, ptr, true);
Marshal.Copy(ptr, arr, 0, size);
Marshal.FreeHGlobal(ptr);
return arr;
}
//copy byte array to structure
private static object ByteToObj(byte[] Array, object structure)
{
if (structure == null)
return 0;
IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(structure.GetType()));
Marshal.Copy(Array, 0, ptr, Marshal.SizeOf(structure.GetType()));
structure = (object)Marshal.PtrToStructure(ptr, structure.GetType());
Marshal.FreeHGlobal(ptr);
return structure;
}
}
}
Updated 10/23/2023