MX Foundation 4
hdlc_flexsmp.cs
/*****************************************************************************
//
// File:
// hdlc_flexsmp.cs
//
// Copyright (c) MAX Technologies Inc. 1988-2023, All Rights Reserved.
// CONFIDENTIAL AND PROPRIETARY INFORMATION WHICH IS THE
// PROPERTY OF MAX TECHNOLOGIES INC.
//
// This example demonstrates the basic usage of HDLC channel class
// for transmission and reception on FlexSMP Module.
//
// Hardware requirements:
// - MAXT FlexMax Device with FlexSMP Module with HDLC channels
//
*****************************************************************************/
//#define LOCAL
//#define LOOPBACK
using System;
using static MAXT.MXFoundation.mxf;
using System.Runtime.InteropServices;
using System.Text;
using System.Xml.Linq;
namespace hdlc_flexsmp_example {
class hdlc_flexsmp {
static void Main(string[] args) {
UInt32 rc = MAXT_SUCCESS;
UInt64 server = 0;
UInt64 rxChannel = 0;
UInt64 txChannel = 0;
UInt64 bufferSize = 0;
UInt64 mxfRxBuffer = 0;
UInt64 mxfTxBuffer = 0;
UInt64 rxAcqStatus = 0;
UInt64 msgCount = 0, byteCount = 0;
IntPtr recPtr = IntPtr.Zero;
//Get Server Handle
#if (LOCAL)
rc = mxfConnectPCIE(out server);
#else
rc = mxfConnectEthernet("192.168.0.1", "admin", "admin", Convert.ToUInt64(false), out server);
#endif
// Initialize MX Foundation library
if (rc == MAXT_SUCCESS) {
Console.WriteLine("Initializing ...");
rc = mxfSystemInit(server);
}
//Get Receiver (Rx) Channel Handle
if (rc == MAXT_SUCCESS) {
rc = mxfChannelGet(server, MXF_CLASS_HDLC, MXF_SCLASS_RX_CHANNEL, MXF_MODULE_FLEXSMP, 0, out rxChannel);
}
//Get Transmiter(Tx) Channel Handle
if (rc == MAXT_SUCCESS) {
rc = mxfChannelGet(server, MXF_CLASS_HDLC, MXF_SCLASS_TX_CHANNEL, MXF_MODULE_FLEXSMP, 0, out txChannel);
}
//Set Data Encoding
if (rc == MAXT_SUCCESS) {
rc = mxfAttributeUint64Set(rxChannel, KMXF_HDLC_DATA_ENCODING, VMXF_HDLC_ENCODING_NRZ);
}
if (rc == MAXT_SUCCESS) {
rc = mxfAttributeUint64Set(txChannel, KMXF_HDLC_DATA_ENCODING, VMXF_HDLC_ENCODING_NRZ);
}
//Set Clock Frequency to 1 Mbps
if (rc == MAXT_SUCCESS) {
rc = mxfAttributeUint64Set(rxChannel, KMXF_HDLC_INTERNAL_CLOCK_FREQ, 1000000);
}
if (rc == MAXT_SUCCESS) {
rc = mxfAttributeUint64Set(txChannel, KMXF_HDLC_INTERNAL_CLOCK_FREQ, 1000000);
}
//Enable InterFrame Flags
if (rc == MAXT_SUCCESS) {
rc = mxfAttributeUint64Set(txChannel, KMXF_HDLC_TX_INTERFRAME_TIME_FILL, VMXF_HDLC_TX_INTERFRAME_TIME_FILL_FLAGS);
}
//Disable Frame Size
if (rc == MAXT_SUCCESS) {
rc = mxfAttributeUint64Set(rxChannel, KMXF_HDLC_FRAME_SIZE_ENABLE, VMXF_DISABLE);
}
if (rc == MAXT_SUCCESS) {
rc = mxfAttributeUint64Set(txChannel, KMXF_HDLC_FRAME_SIZE_ENABLE, VMXF_DISABLE);
}
//Set FCS Type
if (rc == MAXT_SUCCESS) {
rc = mxfAttributeUint64Set(rxChannel, KMXF_HDLC_FCS_TYPE, VMXF_HDLC_TX_RX_FCS_CCITT);
}
if (rc == MAXT_SUCCESS) {
rc = mxfAttributeUint64Set(txChannel, KMXF_HDLC_FCS_TYPE, VMXF_HDLC_TX_RX_FCS_CCITT);
}
//Set Electrical interface
if (rc == MAXT_SUCCESS) {
rc = mxfAttributeUint64Set(txChannel, KMXF_HDLC_ELECTRICAL_INTERFACE, VMXF_HDLC_ELECTRICAL_INTERFACE_RS485);
}
// Set Electrical Termination to 120 Ohm
if (rc == MAXT_SUCCESS) {
rc = mxfAttributeUint64Set(rxChannel, KMXF_HDLC_TERMINATION, VMXF_HDLC_TERMINATION_120OHM);
}
if (rc == MAXT_SUCCESS) {
rc = mxfAttributeUint64Set(txChannel, KMXF_HDLC_TERMINATION, VMXF_HDLC_TERMINATION_120OHM);
}
#if LOOPBACK
//Set Channel loopback
if (rc == MAXT_SUCCESS) {
rc = mxfAttributeUint64Set(rxChannel, KMXF_HDLC_TX_RX_TEST_LB, VMXF_ENABLE);
}
#endif
//Enable HDLC Channels and corresponding clock source
if (rc == MAXT_SUCCESS) {
rc = mxfHDLCChannelEnable(rxChannel, VMXF_HDLC_CLOCK_SOURCE_EXTERNAL);
}
if (rc == MAXT_SUCCESS) {
rc = mxfHDLCChannelEnable(txChannel, VMXF_HDLC_CLOCK_SOURCE_INTERNAL);
}
bufferSize = (UInt64)Marshal.SizeOf(typeof(MXF_HDLC_DATAREC));
// Allocate acquisition static buffer
if (rc == MAXT_SUCCESS) {
rc = mxfRxAcqBufferAlloc(rxChannel, bufferSize, out mxfRxBuffer, IntPtr.Zero);
}
//Start acquisition service
if (rc == MAXT_SUCCESS) {
rc = mxfRxAcqStart(mxfRxBuffer, MXF_RXACQ_FLAG_DEFAULT, 0, 0);
}
// Allocate TX Aperiodic static buffer
if (rc == MAXT_SUCCESS) {
rc = mxfTxAperiodicBufferAlloc(txChannel, MXF_TXAPERIODIC_PRIORITY_HIGH, bufferSize, out mxfTxBuffer, IntPtr.Zero);
}
// Transmit One Record
if (rc == MAXT_SUCCESS) {
string dataString = "Hello, World!\0";
byte[] dataByte = Encoding.UTF8.GetBytes(dataString);
var txRec = new MXF_HDLC_DATAREC() {
reserved = 0,
timeTag = 0,
control = 0,
repeatCount = 1,
dataSize = (UInt32)dataByte.Length + 2, // Data + FCS
data = new UInt16[2048],
};
Buffer.BlockCopy(dataByte, 0, txRec.data, 0, dataByte.Length);
try {
recPtr = Marshal.AllocHGlobal((int)bufferSize);
}
catch (OutOfMemoryException) {
rc = MAXT_ERROR_MEM;
}
if (rc == MAXT_SUCCESS) {
Marshal.StructureToPtr(txRec, recPtr, false);
Console.WriteLine("Transmitting ...");
rc = mxfHDLCTxAperiodicWrite(mxfTxBuffer, MXF_TXAPERIODIC_FLAG_DEFAULT, 0, 1, recPtr);
}
if (recPtr != IntPtr.Zero) {
Marshal.FreeHGlobal(recPtr);
}
}
//Wait
if (rc == MAXT_SUCCESS) {
mxfSleep(1000);
}
if (rc == MAXT_SUCCESS) {
MXF_HDLC_DATAREC rxRec = new MXF_HDLC_DATAREC() { data = new UInt16[2048] };
try {
recPtr = Marshal.AllocHGlobal((int)bufferSize);
}
catch (OutOfMemoryException) {
rc = MAXT_ERROR_MEM;
}
// Read received record
if (rc == MAXT_SUCCESS) {
Console.WriteLine("Receiving ...");
rc = mxfHDLCRxAcqRead(mxfRxBuffer, 1, bufferSize, out rxAcqStatus, out msgCount, out byteCount, recPtr);
if (rc == MAXT_SUCCESS && msgCount == 1) {
rxRec = Marshal.PtrToStructure<MXF_HDLC_DATAREC>(recPtr);
byte[] dataByte = new byte[rxRec.dataSize-2];
Buffer.BlockCopy(rxRec.data, 0, dataByte, 0, dataByte.Length);
Console.WriteLine(" Timetag: {0} Size: {1}", rxRec.timeTag, rxRec.dataSize);
Console.WriteLine(" String: {0}", Encoding.UTF8.GetString(dataByte, 0, dataByte.Length));
}
}
if (recPtr != IntPtr.Zero) {
Marshal.FreeHGlobal(recPtr);
}
}
// Stop acquisition
if (rc == MAXT_SUCCESS) {
rc = mxfRxAcqStop(mxfRxBuffer);
}
//Disable HDLC Channels and associated clock
if (rc == MAXT_SUCCESS) {
rc = mxfHDLCChannelDisable(rxChannel);
}
if (rc == MAXT_SUCCESS) {
rc = mxfHDLCChannelDisable(txChannel);
}
// Display Return Error Codes
if (rc != MAXT_SUCCESS) {
var sb = new StringBuilder(256);
if (mxfSystemErrorStringGet(server, rc, 256, sb) != MAXT_SUCCESS) {
sb.Append(string.Format("ERROR # 0x{0:X8}", rc));
}
Console.WriteLine(sb);
}
Console.WriteLine("Terminating...");
// Free mxf buffers
if (mxfRxBuffer != 0) {
mxfRxAcqBufferFree(mxfRxBuffer);
}
if (mxfTxBuffer != 0) {
}
// Unload MX Foundation library
// Disconnect from MX Foundation library
Console.WriteLine("Press enter to exit");
Console.Read();
return;
}
}
}
Updated 10/23/2023