MX Foundation 4
ar429_comm_queues.c
/*****************************************************************************
//
// File:
// ar429_comm_queues.c
//
// Copyright (c) MAX Technologies Inc. 1988-2019, All Rights Reserved.
// CONFIDENTIAL AND PROPRIETARY INFORMATION WHICH IS THE
// PROPERTY OF MAX TECHNOLOGIES INC.
//
// This program demonstrates the use of MX Foundation embedded service
// for downloading and controlling the ARINC 429 embedded application.
// Two queues are used for bidirectional communication:
// Queue #0: Tx queue (command)
// Queue #1: Rx queue (response)
//
// The embedded program "ar429_embedded_comm_queues.c" is required by this program
// and compiled executable (ar429_embedded_comm_queues-flex.mxf) must be located in
// the same folder as the host application executable.
//
// Hardware Requirements:
// - MAXT Flex with loopback between first TX and RX ARINC 429 Enhanced channels.
//
*****************************************************************************/
#include "example.h"
// User commands
#define EX_USER_COMMAND_ID_INIT 0x0
#define EX_USER_COMMAND_ID_START_TX 0x1
#define EX_USER_COMMAND_ID_STOP_TX 0x2
#define EX_USER_COMMAND_ID_START_ACQ 0x3
#define EX_USER_COMMAND_ID_STOP_ACQ 0x4
#define EX_USER_COMMAND_ID_TERMINATE 0x5
#define EX_USER_COMMAND_ACK 0xA5A5A5A5
#define EX_STRING_SIZE 64
#define EX_MAX_PARAM 8
#define TX_INDEX 0
#define RX_INDEX 1
// User structures
typedef struct
{
uint32 command;
uint32 paramNum;
uint32 param[EX_MAX_PARAM];
}
EX_COMMAND;
uint32 initAttribHandler(HMXF_SERVER server, uint64 cardIndex, uint64 moduleIndex, uint64 channelIndex, uint64 attrib, uint64* value);
uint32 CommandSend(HMXF_BUFFER txBuffer, HMXF_BUFFER rxBuffer, EX_COMMAND* cmd);
/***************************************************************************************************************/
// Main
/***************************************************************************************************************/
int main(void)
{
HMXF_SERVER server = 0;
HMXF_DEVICE device = 0;
HMXF_MODULE module = 0;
HMXF_CHANNEL rxChannel = 0;
HMXF_CHANNEL txChannel = 0;
HMXF_BUFFER txBuffer = 0;
HMXF_BUFFER rxBuffer = 0;
EX_COMMAND Cmd;
uint64 devIdx = 0, modIdx = 0, rxChnIdx = 0, txChnIdx = 0;
uint64 count = 0;
uint32 rc;
// Connect to MX Foundation library
rc = mxfServerConnect("0.0.0.0", "", "", FALSE, &server);
// Attach init callback for changing "Communication queue number" attribute without a reset
if (!rc)
rc = mxfSystemInitAttributeUint64CallbackHandler(server, &initAttribHandler);
printf("Starting\n");
// Initialize the MXF library
if (!rc)
rc = mxfSystemInit(server);
// Get the device handle
if (!rc)
rc = mxfSystemDeviceAllGet(server, MXF_DEVICE_ALL, 1, &count, &device);
// Get the first A429-EH module handle
if (!rc && count)
rc = mxfDeviceModuleAllGet(device, MXF_MODULE_A429_EH, 1, &count, &module);
// Obtain the first ARINC 429 Protocol RX channel (RX logical #0)
if (!rc && count)
rc = mxfModuleChannelAllGet(module, MXF_CLASS_A429, MXF_SCLASS_RX_CHANNEL, 1, &count, &rxChannel);
// Obtain the first ARINC 429 Protocol TX channel (TX logical #0)
if (!rc && count)
rc = mxfModuleChannelAllGet(module, MXF_CLASS_A429, MXF_SCLASS_TX_CHANNEL, 1, &count, &txChannel);
// If module or channel not found, return an error
if (!rc && !count)
rc = MAXT_ERROR_NOT_FOUND;
// Obtain the location of the first ARINC 429 Protocol RX channel (RX logical #0)
if (!rc)
rc = mxfChannelLocationGet(rxChannel, &devIdx, &modIdx, &rxChnIdx);
// Obtain the location of the first ARINC 429 Protocol TX channel (TX logical #0)
if (!rc)
rc = mxfChannelLocationGet(txChannel, &devIdx, &modIdx, &txChnIdx);
// Set timebase to 64-bit nanoseconds
if (!rc)
rc = mxfSystemTimeBaseSet(server, MXF_TIMEBASE_DEVICE_NSEC);
// Allocates communication queue buffer
if (!rc)
{
rc = mxfDeviceCommBufferAlloc(device, TX_INDEX, 64 * 1024, &txBuffer, NULL);
if (!rc)
rc = mxfDeviceCommBufferAlloc(device, RX_INDEX, 64 * 1024, &rxBuffer, NULL);
}
// Upload embedded-side application
if (!rc)
rc = mxfDeviceFileUpload(device, MXF_DEVICE_FILETYPE_APPLICATION, "ar429_embedded_comm_queues-flex.mxf");
if (!rc)
{
// Initialize the embedded application
Cmd.command = EX_USER_COMMAND_ID_INIT;
Cmd.paramNum = 0;
rc = CommandSend(txBuffer, rxBuffer, &Cmd);
if (!rc)
printf("Initialisation\n");
}
if (!rc)
{
// Start acquisition (First Rx 429)
Cmd.command = EX_USER_COMMAND_ID_START_ACQ;
Cmd.paramNum = 1;
Cmd.param[0] = (uint32)rxChnIdx;
rc = CommandSend(txBuffer, rxBuffer, &Cmd);
if (!rc)
printf("Acquisition started\n");
}
if (!rc)
{
// Start acquisition (First Tx 429)
Cmd.command = EX_USER_COMMAND_ID_START_TX;
Cmd.paramNum = 1;
Cmd.param[0] = (uint32)txChnIdx;
rc = CommandSend(txBuffer, rxBuffer, &Cmd);
if (!rc)
printf("Transmission started\n");
}
if (!rc)
{
printf("Running...\n");
mxfSleep(5000); // Wait 5 seconds
}
if (!rc)
{
// Stop transmission (First Tx 429)
Cmd.command = EX_USER_COMMAND_ID_STOP_TX;
Cmd.paramNum = 0;
Cmd.param[0] = (uint32)txChnIdx;
rc = CommandSend(txBuffer, rxBuffer, &Cmd);
if (!rc)
printf("Transmission stopped\n");
}
if (!rc)
{
// Stop acquisition (First Rx 429)
Cmd.command = EX_USER_COMMAND_ID_STOP_ACQ;
Cmd.paramNum = 1;
Cmd.param[0] = (uint32)rxChnIdx;
rc = CommandSend(txBuffer, rxBuffer, &Cmd);
if (!rc)
printf("Acquisition stopped\n");
}
if (!rc)
{
// Stop embedded application
Cmd.command = EX_USER_COMMAND_ID_TERMINATE;
Cmd.paramNum = 0;
rc = CommandSend(txBuffer, rxBuffer, &Cmd);
if (!rc)
printf("Terminating\n");
}
// Catch any previous error
if (rc)
{
char buffer[256];
rc = mxfSystemErrorStringGet(server, rc, sizeof(buffer), buffer);
printf("%s\n", buffer);
}
// Free all buffers
// Free server resources
printf("\nPress enter to terminate\n");
getchar();
return 0;
}
/***************************************************************************************************************/
// initAttribHandler
/***************************************************************************************************************/
uint32 initAttribHandler(HMXF_SERVER server, uint64 cardIndex, uint64 moduleIndex, uint64 channelIndex, uint64 attrib, uint64* value)
{
(void)server;
(void)cardIndex;
(void)moduleIndex;
(void)channelIndex;
if (attrib == KMXF_DEVICE_COMM_QUEUE_NUM)
{
// Set the communication queue number attribute
*value = 2;
return TRUE;
}
return FALSE;
}
/***************************************************************************************************************/
// CommandSend
/***************************************************************************************************************/
uint32 CommandSend(HMXF_BUFFER txBuffer, HMXF_BUFFER rxBuffer, EX_COMMAND* cmd)
{
uint64 readCnt;
uint64 byteCnt;
uint32 rc = 0;
memset(&msg, 0, sizeof(msg));
msg.dataSize = (2 + cmd->paramNum) * 4;
memcpy(msg.data, cmd, msg.dataSize);
rc = mxfDeviceCommBufferWrite(txBuffer, 1, &msg);
if (rc)
printf("Write error rc=0x%08x\n", rc);
while (!rc)
{
// Wait acknowledge of embedded application
rc = mxfDeviceCommBufferRead(rxBuffer, 1, sizeof(msg), &readCnt, &byteCnt, &msg);
if (readCnt && msg.data[0] == EX_USER_COMMAND_ACK)
break;
}
return rc;
}
Updated 10/23/2023