MX Foundation 4
discrete_fifo.cs
/******************************************************************************
//
// File:
// discrete_fifo.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 read discrete input and to write to
// discrete output. It also demonstrates how to set user led.
//
// Hardware requirements:
// - MAXT Flex or MAXT 500 series carrier with IPM with discrete channel.
//
*******************************************************************************/
#define LOCAL
using System;
using static MAXT.MXFoundation.mxf;
using System.Runtime.InteropServices;
using System.Text;
namespace discrete_example
{
public struct EVENT_INFO
{
public IntPtr rxHostBuffer;
public IntPtr txHostBuffer;
public UInt64 bufferTx;
public UInt64 moduleType;
}
class discrete_fifo
{
static void Main(string[] args)
{
UInt32 rc;
UInt64 channelCount = 0;
UInt64 server, device;
UInt64 module = 0;
var rx = new UInt64[1];
var tx = new UInt64[1];
UInt64 bufferTx = 0;
UInt64 bufferRx = 0;
UInt64 asyncEvent = 0;
MXF_ASYNCEVENT_HANDLER eventHandler = EventHandler;
var condition = new MXF_ASYNCEVENT_CONDITION[1];
UInt32 txBufferSize;
IntPtr txBuffer = IntPtr.Zero;
UInt32 rxBufferSize = 0;
IntPtr rxBuffer = IntPtr.Zero;
EVENT_INFO eventInfo = new EVENT_INFO();
StringBuilder errorString = new StringBuilder();
UInt64 moduleType = 0;
// Connect to services and initialize environment
#if LOCAL
rc = mxfServerConnect("0.0.0.0", "", "", 0, out server);
#else
rc = mxfServerConnect("192.168.0.1", "admin", "admin", 0, out server);
#endif
// Initialize MX Foundation library
if (rc == MAXT_SUCCESS)
{
Console.Write("Starting ...\n");
rc = mxfSystemInit(server);
}
// Get handle of discrete input channel
if (rc == MAXT_SUCCESS)
rc = mxfChannelAllGet(server, MXF_CLASS_DISCRETE, MXF_SCLASS_RX_CHANNEL, MXF_MODULE_ALL, 1, out channelCount, rx);
// Get handle of discrete output channel
if (rc == MAXT_SUCCESS && channelCount > 0)
rc = mxfChannelAllGet(server, MXF_CLASS_DISCRETE, MXF_SCLASS_TX_CHANNEL, MXF_MODULE_ALL, 1, out channelCount, tx);
if (rc == MAXT_SUCCESS && channelCount == 0)
rc = MAXT_ERROR_NOT_FOUND;
if (rc == MAXT_SUCCESS)
rc = mxfChannelInfoGet(rx[0], out device, out module);
// configure discrete input
if (rc == MAXT_SUCCESS)
rc = mxfAttributeUint64Set(module, KMXF_DISCRETE_MODULE_RX_FIFO_AF, 1);
if (rc == MAXT_SUCCESS)
rc = mxfAttributeUint64Set(rx[0], KMXF_DISCRETE_RX_EDGE_FALLING, 0xff);
if (rc == MAXT_SUCCESS)
rc = mxfAttributeUint64Set(rx[0], KMXF_DISCRETE_RX_EDGE_RISING, 0xff);
if (rc == MAXT_SUCCESS)
rc = mxfAttributeUint64Get(module, KMXF_MODULE_TYPE, out moduleType);
if (rc == MAXT_SUCCESS)
{
if (moduleType != MXF_MODULE_DIOFIFO_EH)
{
rc = mxfAttributeUint64Set(rx[0], KMXF_DISCRETE_DIRECTION, 0x00ff);
}
}
// Allocate buffer for tx data
if (rc == MAXT_SUCCESS)
{
txBufferSize = (UInt32)Marshal.SizeOf(typeof(MXF_DISCRETE_DATAREC));
// Device allocation
rc = mxfTxAperiodicBufferAlloc(tx[0], MXF_TXAPERIODIC_PRIORITY_LOW, txBufferSize, out bufferTx, IntPtr.Zero);
// Host allocation
if (rc == MAXT_SUCCESS)
{
try
{
txBuffer = Marshal.AllocHGlobal((int)txBufferSize);
}
catch (OutOfMemoryException)
{
rc = MAXT_ERROR_MEM;
}
}
}
// Allocate 10KB buffer for rx data
if (rc == MAXT_SUCCESS)
{
rxBufferSize = 10 * 1024;
// Device allocation
rc = mxfRxAcqBufferAlloc(rx[0], rxBufferSize, out bufferRx, IntPtr.Zero);
// Host allocation
if (rc == MAXT_SUCCESS)
{
try
{
rxBuffer = Marshal.AllocHGlobal((int)rxBufferSize);
}
catch (OutOfMemoryException)
{
rc = MAXT_ERROR_MEM;
}
}
}
// Set timebase to RTC nsec
if (rc == MAXT_SUCCESS)
rc = mxfSystemTimeBaseSet(server, MXF_TIMEBASE_DEVICE_NSEC);
// Configure acquisition asynchronous event condition
if (rc == MAXT_SUCCESS)
{
IntPtr eventInfoPtr = IntPtr.Zero;
try
{
eventInfoPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(EVENT_INFO)));
}
catch (OutOfMemoryException)
{
rc = MAXT_ERROR_MEM;
}
eventInfo.rxHostBuffer = rxBuffer;
eventInfo.txHostBuffer = txBuffer;
eventInfo.bufferTx = bufferTx;
eventInfo.moduleType = moduleType;
Marshal.StructureToPtr(eventInfo, eventInfoPtr, false);
rc = mxfAsyncEventHandlerInit(server, eventHandler, eventInfoPtr, out asyncEvent);
}
if (rc == MAXT_SUCCESS)
{
condition[0].reserved = 0;
condition[0].condID = MXF_ASYNCEVENT_COND_RXACQ_BUFFER_THRESHOLD;
condition[0].condition.txAperiodicBufferThreshold.almostEmpty = 0;
condition[0].condition.txAperiodicBufferThreshold.almostFull = 1;
condition[0].condition.txAperiodicBufferThreshold.buffer = bufferRx;
rc = mxfAsyncEventConditionsSet(asyncEvent, VMXF_ENABLE, 1, condition);
}
// Start acquisition
if (rc == MAXT_SUCCESS)
rc = mxfRxAcqStart(bufferRx, MXF_RXACQ_FLAG_DEFAULT, 0, 0);
// wait 3 seconds
if (rc == MAXT_SUCCESS)
mxfSleep(3000);
// disable asynchronous event condition
if (rc == MAXT_SUCCESS)
rc = mxfAsyncEventConditionsSet(asyncEvent, VMXF_DISABLE, 1, condition);
if (rc == MAXT_SUCCESS)
// Clear aperiodic buffer
if (rc == MAXT_SUCCESS)
rc = mxfTxAperiodicClear(bufferTx, 0);
// Stop acquisition
if (rc == MAXT_SUCCESS)
rc = mxfRxAcqStop(bufferRx);
// Clear acquisition
if (rc == MAXT_SUCCESS)
rc = mxfRxAcqClear(bufferRx);
// free buffers
if (txBuffer != IntPtr.Zero)
Marshal.FreeHGlobal(txBuffer);
if (rxBuffer != IntPtr.Zero)
Marshal.FreeHGlobal(rxBuffer);
if (rc != MAXT_SUCCESS)
{
if (mxfSystemErrorStringGet(server, rc, (UInt32)errorString.Length, errorString) > 0)
Console.Write(" {0} ERROR # 0x{1:X8}", errorString, rc);
Console.Write("{0}\n\r", errorString);
}
//Frees all buffers
if (bufferRx > 0)
mxfRxAcqBufferFree(bufferRx);
if (bufferTx > 0)
// Unload MX Foundation library
Console.Write("\nPress a key to terminate\n");
Console.ReadKey();
return;
}
private static UInt32 EventHandler(UInt64 hAsyncEvent, IntPtr pParam)
{
var eventInfo = new EVENT_INFO();
UInt32 rc;
UInt64 count = 0;
var pendingInfo = new MXF_ASYNCEVENT_PENDING_INFO[1];
IntPtr txRecPtr = IntPtr.Zero;
var txRec = new MXF_DISCRETE_DATAREC();
IntPtr rxRecPtr = IntPtr.Zero;
var rxRec = new MXF_DISCRETE_DATAREC();
UInt64 status, msgCount, byteCount;
UInt64 channel;
UInt64 device = 0;
// get asynchronous event information
rc = mxfAsyncEventPendingGet(hAsyncEvent, 1, out count, pendingInfo);
if (rc == MAXT_SUCCESS && count > 0)
{
if (pendingInfo[0].condID == MXF_ASYNCEVENT_COND_RXACQ_BUFFER_THRESHOLD)
{
eventInfo = (EVENT_INFO)Marshal.PtrToStructure(pParam, typeof(EVENT_INFO));
rxRecPtr = eventInfo.rxHostBuffer;
txRecPtr = eventInfo.txHostBuffer;
// Read discrete input
rc = mxfDiscreteRxAcqRead(pendingInfo[0].condition.rxAcqBufferThreshold.buffer, 1, (UInt64)Marshal.SizeOf(typeof(MXF_DISCRETE_DATAREC)), out status, out msgCount, out byteCount, eventInfo.rxHostBuffer);
if (rc == MAXT_SUCCESS && msgCount > 0)
{
rxRec = (MXF_DISCRETE_DATAREC)Marshal.PtrToStructure(rxRecPtr, typeof(MXF_DISCRETE_DATAREC));
txRec.repeatCount = 1;
txRec.data = rxRec.data;
if (eventInfo.moduleType == MXF_MODULE_DIOFIFO_EH)
{
txRec.edge = rxRec.edge > 0 ? rxRec.edge : 0xffff;
}
else
{
txRec.edge = 0;
}
Marshal.StructureToPtr(txRec, txRecPtr, true);
// Update discrete output with value of discrete input
rc = mxfDiscreteTxAperiodicWrite(eventInfo.bufferTx, MXF_TXAPERIODIC_FLAG_DEFAULT, 0, 1, txRecPtr);
if (rc == MAXT_SUCCESS)
{
if (eventInfo.moduleType == MXF_MODULE_DIOFIFO_EH)
{
// ligth first user led when first discrete input pin is low
rc = mxfTxAperiodicBufferInfoGet(eventInfo.bufferTx, out channel, IntPtr.Zero);
if (rc == MAXT_SUCCESS)
rc = mxfChannelInfoGet(channel, out device, IntPtr.Zero);
if (rc == MAXT_SUCCESS)
{
Console.Write("Set led #0 state to {0}\n", (rxRec.data & 0x01) > 0 ? "OFF" : "ON");
rc = mxfDeviceLedSet(device, 0x01, (UInt64)((rxRec.data & 0x01) > 0 ? 0 : 1));
}
}
}
}
}
}
if (rc != MAXT_SUCCESS)
Console.Write("event handler rc=0x%08x\n", rc);
return rc;
}
}
}
Updated 10/23/2023