MX Foundation 4
SAP Acquisition and Sampling

The way to set a basic SAP receive application is as follows:

The MXF_A664_DATAREC structure must be used for reading an ARINC 664 message with queuing type.

Example

ar664_aperiodicSap.c
The snippet below demonstrates the basic steps needed to setup a SAP Receive application.

#define DATARECS_BUFFER_SIZE_MAX 64*1024
#define DST_IP_ADRS "10.0.0.222"
#define DST_UDP_PORT 5678
HMXF_SERVER server = 0;
HMXF_PORT portRx = 0;
HMXF_VL vlRx = 0;
HMXF_BUFFER rxBuffer = 0;
HMXF_MODULE module = 0;
HMXF_DEVICE device = 0;
HMXF_CHANNEL phyChn = 0;
MXF_A664_DATAREC* rxRec = NULL;
uint32 dstIpAdrs = 0;
uint64 usedBytes, freeBytes;
uint64 msgCount = 0;
uint32 recordIdx, dataIdx;
uint32 vlid = 100;
uint32 rc;
uint64 count = 0;
uint64 recordIdx, dataIdx;
uint64 status, msgsCount, bytesCount;
uint32 dataSize;
char srcAddress[32];
uint32 address;
// Initialize server, allocate base resources
rc = mxfSystemInit(server);
// Get the first device handle
if (!rc)
rc = mxfSystemDeviceGet(server, 0, &device);
// Get the first A664 module
if (!rc)
rc = mxfDeviceModuleAllGet(device, MXF_MODULE_A664, 1, &count, &module);
// Obtain the first ARINC 664 Phy channel (Phy logical #0)
if (!rc && count)
rc = mxfModuleChannelAllGet(module, MXF_CLASS_A664, MXF_SCLASS_RX_CHANNEL, 1, &count, &phyChn);
// If module or channel not found, return an error
if (!rc && !count)
rc = MAXT_ERROR_NOT_FOUND;
// Set Timebase
if (!rc)
rc = mxfSystemTimeBaseSet(server, MXF_TIMEBASE_DEVICE_NSEC);
...
// Create the reception (RX) virtual link
if (!rc)
{
memset(&vlParam, 0, sizeof(MXF_A664_VL_PARAM));
vlParam.VLId = vlid;
vlParam.frameType = MXF_A664_FRAME_TYPE_ARINC664;
vlParam.direction = MXF_A664_VL_DIR_RX;
vlParam.frameSizeMax = 512;
vlParam.dir.Rx.Mac.skewMax = 4 * 1000 * 1000;
vlParam.dir.Rx.Mac.rmPSNRange = 2;
rc = mxfA664VlCreate(phyChn, &vlParam, &vlRx);
}
// Create SAP RX port
if (!rc)
{
inet_pton(AF_INET, SRC_IP_ADRS, &dstIpAdrs);
memset(&portParam, 0, sizeof(MXF_A664_PORT_PARAM));
portParam.portType = MXF_A664_PORT_TYPE_SAP;
portParam.family = MXF_A664_PORT_FAMILY_IPV4;
portParam.mode = MXF_A664_PORT_MODE_QUEUING;
portParam.dir.Rx.network = MXF_A664_NETSELECT_ALL;
portParam.dir.Rx.maxBuffers = 16;
portParam.dir.Rx.bufferSize = 1518;
portParam.type.SAP.destAddress.port = DST_UDP_PORT;
portParam.type.SAP.destAddress.version.IPv4.address = nothl(dstIpAdrs);
rc = mxfA664PortCreate(vlRx, &portParam, &portRx);
}
// Get buffer handle automatically allocated for the port
if (!rc)
rc = mxfRxAcqBufferGet(portRx, &rxBuffer);
if (!rc)
{
rxRec = malloc(DATARECS_BUFFER_SIZE_MAX);
memset(rxRec, 0, DATARECS_BUFFER_SIZE_MAX);
if (!rxRec)
rc = MAXT_ERROR_MEM;
}
// Set acquisition mode
if (!rc)
rc = mxfRxAcqModeSet(rxBuffer, MXF_RXACQ_MODE_LINEAR);
// Start acquisition, check status
if (!rc)
rc = mxfRxAcqStart(rxBuffer, MXF_RXACQ_FLAG_DEFAULT, 0, 0);
if (!rc)
{
rc = mxfRxAcqBufferStatusGet(rxBuffer, &status, &msgCount, &usedBytes, &freeBytes);
if (!rc && (status & MXF_RXACQ_STATUS_RUNNING))
printf("Acquisition Running\n\n");
}
...
// Read records
rc = mxfA664RxAcqRead(rxBuffer, 0, DATARECS_BUFFER_SIZE_MAX, &status, &msgsCount, &bytesCount, rxRec);
if (!rc)
printf("%llu records received\n\n", msgsCount);
recPtr = rxRec;
for (recordIdx = 0; recordIdx < msgsCount && !rc; recordIdx++)
{
printf(" %03llu: timeTag=%012llu, Size=%u", recordIdx, recPtr->timeTag, recPtr->dataSize);
address = htonl(recPtr->type.Sap.ipAddress);
inet_ntop(AF_INET, &address, srcAddress, sizeof(srcAddress));
printf(" SAP Source Address: %s:%u\n", srcAddress, recPtr->type.Sap.udpPort);
printf("\n data=");
dataSize = recPtr->dataSize;
for (dataIdx = 0; dataIdx < dataSize; dataIdx++)
{
printf("%02X ", recPtr->data[dataIdx]);
if (!((dataIdx + 1) % 8) && (dataIdx + 1 < recPtr->dataSize))
printf("\n ");
}
printf("\n\n");
mxfA664NextDataRecordPtrGet(recPtr, &recPtr);
}
...
// Terminate Acquisition
if (!rc)
rc = mxfRxAcqStop(rxBuffer);
if (!rc)
rc = mxfRxAcqClear(rxBuffer);
if (!rc)
rc = mxfRxAcqBufferFree(rxBuffer);
// Free COM ports
if (!rc)
rc = mxfA664PortRelease(portRx);
// Free VL(s)
if (!rc)
rc = mxfA664VlRelease(vlRx);
// Free datarec buffers
if (rxRec)
free(rxRec);
...
Updated 10/23/2023