MX Foundation 4
flexdio_fifo.c
/******************************************************************************
//
// File:
// flexdio_fifo.c
//
// Copyright (c) MAX Technologies Inc. 1988-2022, 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 read alarm status and
// to set user LEDs.
//
// Hardware requirements:
// - MAXT FlexMAX with FlexMAX DIO module.
//
*******************************************************************************/
#include "example.h"
//#define LOCAL
typedef struct
{
MXF_FLEXDIO_DATAREC* rxHostBuffer;
MXF_FLEXDIO_DATAREC* txHostBuffer;
HMXF_BUFFER bufferTx;
}
EVENT_INFO;
uint32 eventHandler(HMXF_HANDLE hAsyncEvent, void* pParam);
int main(void)
{
uint32 rc;
uint64 channelCount=0;
HMXF_SERVER server;
HMXF_MODULE module=0;
HMXF_CHANNEL io=0;
HMXF_BUFFER bufferTx=0;
HMXF_BUFFER bufferRx=0;
HMXF_ASYNCEVENT asyncEvent=0;
uint32 txBufferSize;
MXF_FLEXDIO_DATAREC* txBuffer=NULL;
uint32 rxBufferSize=0;
MXF_FLEXDIO_DATAREC* rxBuffer=NULL;
EVENT_INFO eventInfo;
char errorString[200];
uint64 pin;
int loop;
uint64 alarmGlobal, alarmChn;
// Connect to services and initialize environment
#ifdef LOCAL
rc = mxfServerConnect("0.0.0.0", "", "", FALSE, &server);
#else
rc = mxfServerConnect("192.168.0.1", "admin", "admin", FALSE, &server);
#endif
// Initialize MX Foundation library
if(!rc)
{
printf("Starting ...\n");
rc = mxfSystemInit(server);
}
// Get handle of discrete channel
if(!rc)
rc = mxfChannelAllGet(server, MXF_CLASS_FLEXDIO, MXF_SCLASS_ALL, MXF_MODULE_ALL, 1, &channelCount, &io);
if(!rc && !channelCount)
rc = MAXT_ERROR_NOT_FOUND;
if(!rc)
rc = mxfChannelInfoGet(io, NULL, &module);
// configure discrete
if(!rc)
rc = mxfAttributeUint64Set(module, KMXF_DISCRETE_MODULE_RX_FIFO_AF, 1);
// Configure first 32 pins as input with pull-up and next 32 pins as output low-side
for (pin = 0; pin<64 && !rc; pin++)
{
if(pin<32)
rc = mxfFlexDIOModeSet(io, pin, MXF_FLEXDIO_MODE_IN_PULLUP);
else
rc = mxfFlexDIOModeSet(io, pin, MXF_FLEXDIO_MODE_OUT_LS);
}
// Set current limit of pin 32 to 200mA
if (!rc)
rc = mxfFlexDIOCurrentLimitSet(io, 32, MXF_FLEXDIO_CURRENT_LIMIT_LOW);
// Allocate buffer for tx data
if(!rc)
{
txBufferSize = sizeof(MXF_FLEXDIO_DATAREC);
// Device allocation
rc = mxfTxAperiodicBufferAlloc(io, MXF_TXAPERIODIC_PRIORITY_LOW, txBufferSize, &bufferTx, NULL);
// Host allocation
if(!rc)
{
txBuffer = (MXF_FLEXDIO_DATAREC*)malloc(txBufferSize);
if(!txBuffer)
rc = MAXT_ERROR_MEM;
}
}
// Allocate 10KB buffer for rx data
if(!rc)
{
rxBufferSize = 10*1024;
// Device allocation
rc = mxfRxAcqBufferAlloc(io, rxBufferSize, &bufferRx, NULL);
// Host allocation
if(!rc)
{
rxBuffer = (MXF_FLEXDIO_DATAREC*)malloc(rxBufferSize);
if(!rxBuffer)
rc = MAXT_ERROR_MEM;
}
}
// Set timebase to RTC nsec
if(!rc)
rc = mxfSystemTimeBaseSet(server, MXF_TIMEBASE_DEVICE_NSEC);
// Configure acquisition asynchronous event condition
if(!rc)
{
eventInfo.rxHostBuffer = rxBuffer;
eventInfo.txHostBuffer = txBuffer;
eventInfo.bufferTx = bufferTx;
rc = mxfAsyncEventHandlerInit(server, &eventHandler, &eventInfo, &asyncEvent);
}
if(!rc)
{
condition.reserved = 0;
condition.condID = MXF_ASYNCEVENT_COND_RXACQ_BUFFER_THRESHOLD;
condition.condition.rxAcqBufferThreshold.buffer = bufferRx;
rc = mxfAsyncEventConditionsSet(asyncEvent, TRUE, 1, &condition);
}
// Start acquisition
if(!rc)
rc = mxfRxAcqStart(bufferRx, MXF_RXACQ_FLAG_DEFAULT, 0, 0);
// wait 3 seconds
for(loop=0; loop<3 && !rc; loop++)
{
mxfSleep(1000);
rc = mxfFlexDIOAlarmGet(io, &alarmGlobal, &alarmChn);
if(!rc)
{
if(alarmGlobal)
{
if (alarmGlobal & MXF_FLEXDIO_ALARM_STS_OOR_VOLTAGE_IN)
printf("OV: Voltage out of range\n");
if (alarmGlobal & MXF_FLEXDIO_ALARM_STS_OOR_CURRENT)
printf("OC: Over Current\n");
}
if(alarmChn)
{
for (pin = 0; pin<64; pin++)
{
if (alarmChn & (1ULL << pin))
printf("OC: pin #%"PRIu64"\n", pin);
}
}
}
}
// disable asynchronous event condition
if(!rc)
rc = mxfAsyncEventConditionsSet(asyncEvent, FALSE, 1, &condition);
if(!rc)
// Clear aperiodic buffer
if(!rc)
rc = mxfTxAperiodicClear(bufferTx, 0);
// Stop acquisition
if(!rc)
rc = mxfRxAcqStop(bufferRx);
// Clear acquisition
if(!rc)
rc = mxfRxAcqClear(bufferRx);
// free buffers
if(txBuffer)
free(txBuffer);
if(rxBuffer)
free(rxBuffer);
if(rc)
{
if(mxfSystemErrorStringGet(server, rc, sizeof(errorString), errorString))
sprintf (errorString,"ERROR # 0x%08X", rc);
printf("%s\n\r", errorString);
}
//Frees all buffers
if(bufferRx)
mxfRxAcqBufferFree(bufferRx);
if(bufferTx)
// Unload MX Foundation library
printf("\nPress a key to terminate\n");
getchar();
return rc;
}
uint32 eventHandler(HMXF_HANDLE hAsyncEvent, void* pParam)
{
EVENT_INFO* eventInfo=(EVENT_INFO*)pParam;
uint32 rc;
uint64 count;
uint64 status, msgCount, byteCount;
HMXF_CHANNEL channel;
HMXF_DEVICE device=0;
// get asynchronous event information
rc = mxfAsyncEventPendingGet(hAsyncEvent, 1, &count, &pendingInfo);
if(!rc && count)
{
if(pendingInfo.condID == MXF_ASYNCEVENT_COND_RXACQ_BUFFER_THRESHOLD)
{
// Read discrete input
rc = mxfFlexDIORxAcqRead(pendingInfo.condition.rxAcqBufferThreshold.buffer, 1, sizeof(MXF_FLEXDIO_DATAREC), &status, &msgCount, &byteCount, eventInfo->rxHostBuffer);
if(!rc && msgCount)
{
rxRec = eventInfo->rxHostBuffer;
txRec = eventInfo->txHostBuffer;
memset(txRec, 0, sizeof(MXF_FLEXDIO_DATAREC));
txRec->repeatCount = 1;
txRec->data = ~rxRec->data;
txRec->edge = (rxRec->edge)?rxRec->edge:0xffffffff00000000;
// Update discrete output with value of discrete input
rc = mxfFlexDIOTxAperiodicWrite(eventInfo->bufferTx, MXF_TXAPERIODIC_FLAG_DEFAULT, 0, 1, txRec);
if(!rc)
{
// light first user led when first discrete input pin is low
rc = mxfTxAperiodicBufferInfoGet(eventInfo->bufferTx, &channel, NULL);
if(!rc)
rc = mxfChannelInfoGet(channel, &device, NULL);
if(!rc)
{
printf("Set led #0 state to %s\n", (rxRec->data & 0x01)?"OFF":"ON");
rc = mxfDeviceLedSet(device, 0x01, (rxRec->data & 0x01)?0:1);
}
}
}
}
}
if(rc)
printf("event handler rc=0x%08x\n", rc);
return rc;
}
Updated 10/23/2023