AR Receive
Edit this on GitLab
AR Receive
Explanation
About the Sample Application Code
This sample application code is provided by North Atlantic Industries (NAI) for use with their Software Support Kit (SSK) to interact with their embedded function modules. Specifically, this code demonstrates how to configure and receive ARINC messages using the NAI ARINC module.
Overview
The application allows users to configure an ARINC channel to receive ARINC messages through various modes: without validation, with validation, or using mailboxes. These modes illustrate different methods for how ARINC data messages can be retrieved, providing flexibility depending on the use case requirements.
Key Components
Headers and Definitions
- Headers: The code includes standard C libraries (stdio.h
, stdlib.h
, string.h
, time.h
, ctype.h
) and several NAI-specific headers (e.g., naiapp_boardaccess_menu.h
, nai.h
, naibrd.h
) which collectively provide access to necessary functions and definitions.
- CONFIG_FILE: Points to a configuration file CONFIG_FILE.txt
.
- Function Prototypes: Declares various functions used for different modes of receiving ARINC messages.
Enumerations
- arfuncgen_commands
: Enumeration that defines different command modes:
- AR_FUNCGEN_CMD_RX_WITHOUT_VALIDATION
- AR_FUNCGEN_CMD_RX_WITH_VALIDATION
- AR_FUNCGEN_CMD_RX_WITH_MAILBOX
- AR_FUNCGEN_CMD_COUNT
Command Table
- AR_FuncGenMenuCmds[]
: Contains command strings linked to their respective functions for user interaction.
Configuration Constants Defines default values for card index, module, receiver channel, data rate, and timestamp enabling.
Functions Overview
main
- This is the entry point of the application (or AR_Receive
for VxWorks systems).
- Initializes an interaction loop allowing users to configure and run ARINC receive modes repeatedly.
- Provides a user query to stop or restart the application.
Run_AR_Receive
- Guides users through the setup for receiving ARINC messages.
- Requests user input for card, module, channel, and data rate configurations.
- Sets up the ARINC channel using the naibrd library functions and then presents menu commands for different reception modes.
AR_RxWithoutValidation
- Configures the ARINC channel to receive all transmitted data without validation.
- Uses the FIFO mode to enable the receiver and display received data.
AR_RxWithValidation
- Configures the ARINC channel to receive data validated by specific SDI/Labels.
- Enables validation and uses FIFO mode to display received data.
AR_RxWithMailbox
- Configures the ARINC channel to use mailbox mode, receiving new data for matched SDI/Labels found in the receive FIFO.
- Enables validation and reads from mailboxes to display data.
RxAndDisplayFIFOMsgs
- Reads and displays ARINC messages in FIFO mode for a user-specified duration.
- Continuously checks the buffer count and reads the data, displaying the status, data, and timestamp (if enabled).
RxandDisplayFIFOandMailBox
- Reads and displays ARINC messages using FIFO and mailbox mode for a user-specified duration.
- Retrieves labels from the FIFO and then reads corresponding mailboxes to display data.
EnableValidation
- Enables validation for a specified range of SDI/Label combinations.
- Constructs and writes a validation array to the ARINC channel.
Usage Notes
- System Configuration Routines: The following functions from the nai_sys_cfg.c
file support setup:
- ClearDeviceCfg
- QuerySystemCfg
- DisplayDeviceCfg
- GetBoardSNModCfg
- SaveDeviceCfg
-
Running in Conjunction: The
AR_Receive
application can run withAR_Transmit
applications for complete ARINC receive and transmit operations.
This code serves as a robust template for understanding and implementing ARINC data reception using NAI’s software and hardware solutions.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
/* Common Sample Program include files */
#include "include/naiapp_boardaccess_menu.h"
#include "include/naiapp_boardaccess_query.h"
#include "include/naiapp_boardaccess_access.h"
#include "include/naiapp_boardaccess_display.h"
#include "include/naiapp_boardaccess_utils.h"
#include "nai_ar_utils.h"
/* naibrd include files */
#include "nai.h"
#include "naibrd.h"
#include "functions/naibrd_ar.h"
static const int8_t *CONFIG_FILE = (int8_t *)"CONFIG_FILE.txt";
/* Function prototypes */
void Run_AR_Receive(void);
nai_status_t AR_RxWithoutValidation(int32_t paramCount, int32_t* p_params);
nai_status_t AR_RxWithValidation(int32_t paramCount, int32_t* p_params);
nai_status_t AR_RxWithMailbox(int32_t paramCount, int32_t* p_params);
bool_t RxAndDisplayFIFOMsgs(int32_t cardIndex, int32_t module, int32_t channel);
bool_t RxandDisplayFIFOandMailBox(int32_t cardIndex, int32_t module, int32_t channel);
void EnableValidation(int32_t cardIndex, int32_t module, int32_t channel);
/****** Command Table *******/
enum arfuncgen_commands
{
AR_FUNCGEN_CMD_RX_WITHOUT_VALIDATION,
AR_FUNCGEN_CMD_RX_WITH_VALIDATION,
AR_FUNCGEN_CMD_RX_WITH_MAILBOX,
AR_FUNCGEN_CMD_COUNT
};
/****** Command Tables *******/
static naiapp_cmdtbl_params_t AR_FuncGenMenuCmds[] =
{
{"NORMAL ", "AR Receive Without Validation", AR_FUNCGEN_CMD_RX_WITHOUT_VALIDATION, AR_RxWithoutValidation},
{"VALID ", "AR Receive With Validation ", AR_FUNCGEN_CMD_RX_WITH_VALIDATION, AR_RxWithValidation},
{"MAILBOX", "AR Receive Using Mailbox ", AR_FUNCGEN_CMD_RX_WITH_MAILBOX, AR_RxWithMailbox}
};
#define DEF_AR_CARD_INDEX 0
#define DEF_AR_MODULE 1
#define DEF_AR_RECV_CHANNEL 2
#define DEF_AR_DATA_RATE AR_SPEED_LOW
#define DEF_AR_TIMESTAMP_ENABLED TRUE
static bool_t bTimestampEnabled = FALSE;
/**************************************************************************************************************/
/**
<summary>
The purpose of the AR_Receive is to illustrate the methods to call in the naibrd library to configure
the ARINC channel to receive ARINC messages. ARINC data messages can be retrieved as follows:
a) Using Validation to selectively receive data that match enabled SDI/Labels, or
b) Using Mailbox mode to read mailboxes of the matched SDI/Labels found in the receive FIFO, or
c) Receiving all of the transmitted data in the receive FIFO (without validation).
The following system configuration routines from the nai_sys_cfg.c file are called to assist with the configuration
setup for this program prior to calling the naibrd ARINC routines.
- ClearDeviceCfg
- QuerySystemCfg
- DisplayDeviceCfg
- GetBoardSNModCfg
- SaveDeviceCfg
Note, the AR_Receive application can run in conjunction with the AR_Transmit applications to illustrate
ARINC receive and transmit operations together with the NAI ARINC module.
</summary>
*/
/**************************************************************************************************************/
#if defined (__VXWORKS__)
int32_t AR_Receive(void)
#else
int32_t main(void)
#endif
{
bool_t stop = FALSE;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
if (naiapp_RunBoardMenu(CONFIG_FILE) == TRUE)
{
while (stop != TRUE)
{
Run_AR_Receive();
}
printf("\nType Q to quit or Enter key to restart application:\n");
stop = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
}
naiapp_access_CloseAllOpenCards();
return 0;
}
nai_status_t AR_RxWithoutValidation(int32_t paramCount, int32_t* p_params)
{
bool_t bQuit;
p_naiapp_AppParameters_t p_ad_params = (p_naiapp_AppParameters_t)p_params;
int32_t cardIndex = p_ad_params->cardIndex;
int32_t module = p_ad_params->module;
int32_t channel = p_ad_params->channel;
#if defined (WIN32)
UNREFERENCED_PARAMETER(paramCount);
#endif
/* Enable FIFO mode */
check_status(naibrd_AR_SetRxMode(cardIndex, module, channel, AR_RX_FIFO_MODE));
/* Disable Validation */
naibrd_AR_SetRxValidationEn(cardIndex, module, channel, FALSE);
/* Enable Receiver and Display Data Received in the Rx FIFO */
bQuit = RxAndDisplayFIFOMsgs(cardIndex, module, channel);
return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}
nai_status_t AR_RxWithValidation(int32_t paramCount, int32_t* p_params)
{
bool_t bQuit;
p_naiapp_AppParameters_t p_ad_params = (p_naiapp_AppParameters_t)p_params;
int32_t cardIndex = p_ad_params->cardIndex;
int32_t module = p_ad_params->module;
int32_t channel = p_ad_params->channel;
#if defined (WIN32)
UNREFERENCED_PARAMETER(paramCount);
#endif
/* Enable FIFO mode */
check_status(naibrd_AR_SetRxMode(cardIndex, module, channel, AR_RX_FIFO_MODE));
/* Enable Validation for select SDI/Labels */
EnableValidation(cardIndex, module, channel);
/* Enable Receiver and Display Data Received in the Rx FIFO */
bQuit = RxAndDisplayFIFOMsgs(cardIndex, module, channel);
return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}
nai_status_t AR_RxWithMailbox(int32_t paramCount, int32_t* p_params)
{
bool_t bQuit;
p_naiapp_AppParameters_t p_ad_params = (p_naiapp_AppParameters_t)p_params;
int32_t cardIndex = p_ad_params->cardIndex;
int32_t module = p_ad_params->module;
int32_t channel = p_ad_params->channel;
#if defined (WIN32)
UNREFERENCED_PARAMETER(paramCount);
#endif
/* Enable MailBox mode */
check_status(naibrd_AR_SetRxMode(cardIndex, module, channel, AR_RX_MBOX_MODE));
/* Enable Validation for select SDI/Labels */
EnableValidation(cardIndex, module, channel);
/* Enable Receiver and Read FIFO for Mailbox Addresses that have new messages, then read these Mailboxes to get new data */
bQuit = RxandDisplayFIFOandMailBox(cardIndex, module, channel);
return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}
/**************************************************************************************************************/
/**
<summary>
Run_AR_Receive queries the user for the card, module and channel to configure as the ARINC receiver
as well as the data rate (high (100KHz) or low (12.5KHz)) and how to retrieve the ARINC messages.
Methods in the naibrd library are invoked to configure the ARINC channel.
</summary>
*/
/**************************************************************************************************************/
void Run_AR_Receive(void)
{
int32_t cardIndex, module, archan;
bool_t bQuit = FALSE;
bool_t bContinue, bCmdFound;
int32_t cmd;
nai_ar_datarate_t datarate;
uint32_t moduleID;
int32_t AR_FIFO_Size;
naiapp_AppParameters_t ar_params;
p_naiapp_AppParameters_t ar_receive_params = &ar_params;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
bQuit = GetARCfg(DEF_AR_CARD_INDEX, DEF_AR_MODULE, DEF_AR_RECV_CHANNEL, &cardIndex, &module, &archan);
ar_receive_params->cardIndex = cardIndex;
ar_receive_params->module = module;
ar_receive_params->channel = archan;
if (!bQuit)
{
/* Get Data Rate */
bQuit = GetARINCDataRate(DEF_AR_DATA_RATE, &datarate);
if (!bQuit)
{
/* Reset the channel */
check_status(naibrd_AR_ChannelReset(cardIndex, module, archan));
/* Disable Tx/Rx */
check_status(naibrd_AR_SetTxEnable(cardIndex, module, archan, AR_DISABLE));
check_status(naibrd_AR_SetRxEnable(cardIndex, module, archan, AR_DISABLE));
/* Set the transmission speed */
check_status(naibrd_AR_SetDataRate(cardIndex, module, archan, datarate));
/* Set the Rx Fifo Threshold to the maximum size of the FIFO */
moduleID = naibrd_GetModuleID(cardIndex, module);
AR_FIFO_Size = naibrd_AR_GetMaxFifoCount(moduleID);
check_status(naibrd_AR_SetRxFifoThreshold(cardIndex, module, archan, AR_FIFO_Size));
/* Set the Parity Disable bit to cause the ARINC bit 32 to be treated as an odd parity bit */
check_status(naibrd_AR_SetParityAsData(cardIndex, module, archan, AR_PAR_ODD));
check_status(naibrd_AR_SetRxStoreErrorDisable(cardIndex, module, archan, AR_STORE_ON_ERROR_ENABLE));
/* Query for Timestamp Mode Enable */
bQuit = GetARReceiverTimestampEnabled(DEF_AR_TIMESTAMP_ENABLED, &bTimestampEnabled);
if (!bQuit)
{
/* Set Timestamp Enable */
naibrd_AR_SetRxTimeStampEn(cardIndex, module, archan, bTimestampEnabled);
bContinue = TRUE;
naiapp_utils_LoadParamMenuCommands(AR_FUNCGEN_CMD_COUNT, AR_FuncGenMenuCmds);
while (bContinue)
{
naiapp_display_ParamMenuCommands((int8_t *)"AR Receive Mode Menu");
printf("\nType AR command or %c to quit : ", NAI_QUIT_CHAR);
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
if (inputResponseCnt > 0)
{
bCmdFound = naiapp_utils_GetParamMenuCmdNum(inputResponseCnt, inputBuffer, &cmd);
if (bCmdFound)
{
switch (cmd)
{
case AR_FUNCGEN_CMD_RX_WITHOUT_VALIDATION:
case AR_FUNCGEN_CMD_RX_WITH_VALIDATION:
case AR_FUNCGEN_CMD_RX_WITH_MAILBOX:
AR_FuncGenMenuCmds[cmd].func(APP_PARAM_COUNT, (int32_t*)ar_receive_params);
break;
default:
printf("Invalid command entered\n");
break;
}
}
else
printf("Invalid command entered\n");
}
}
else
bContinue = FALSE;
}
}
}
}
return;
}
bool_t RxAndDisplayFIFOMsgs(int32_t cardIndex, int32_t module, int32_t channel)
{
time_t end;
bool_t bQuit = FALSE;
bool_t bContinue = TRUE;
int32_t i;
int32_t nNumWordsRecv;
uint32_t RecvStatusWd[A4_MAX_FIFO_COUNT];
uint32_t RecvData[A4_MAX_FIFO_COUNT];
uint32_t RecvTimeStamp[A4_MAX_FIFO_COUNT];
int32_t duration;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
/* Clear Rx FIFO */
check_status(naibrd_AR_ClearRxFifo(cardIndex, module, channel));
/* Enable Receiver */
check_status(naibrd_AR_SetRxEnable(cardIndex, module, channel, AR_ENABLE));
bContinue = TRUE;
while (bContinue)
{
printf("\nType duration (in seconds) for ARINC receive messages test or %c to quit (default: 300) : ", NAI_QUIT_CHAR);
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
duration = 5;
if (inputResponseCnt > 0)
duration = (int32_t)atol((const char*)inputBuffer);
end = time(NULL) + duration;
/* Read data */
while (time(NULL) < end)
{
check_status(naibrd_AR_GetRxBufferCnt(cardIndex, module, channel, &nNumWordsRecv));
if (nNumWordsRecv > 0)
{
printf("\nReading back %d words ...\n", nNumWordsRecv);
check_status(naibrd_AR_ReadFifo(cardIndex, module, channel, bTimestampEnabled, nNumWordsRecv, RecvStatusWd, RecvData, RecvTimeStamp, &nNumWordsRecv)); /* read back data */
for (i = 0; i < nNumWordsRecv; i++)
{
printf("Status: 0x%08X ", RecvStatusWd[i]);
printf("Data: 0x%08X ", RecvData[i]);
if (bTimestampEnabled)
{
printf("TimeStamp: 0x%08X\n", RecvTimeStamp[i]);
}
}
}
#if defined (__VXWORKS__)
taskDelay(1);
#endif
}
}
else
bContinue = FALSE;
}
return bQuit;
}
bool_t RxandDisplayFIFOandMailBox(int32_t cardIndex, int32_t module, int32_t channel)
{
time_t end;
bool_t bQuit = FALSE;
bool_t bContinue = TRUE;
uint32_t Label[A4_MAX_FIFO_COUNT];
int32_t nNumWordsRecv = 16;
uint16_t MailRecvStatusWd;
uint32_t MailRecvData;
uint32_t MailRecvTimeStamp;
int32_t duration;
int32_t i;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
/* Enable Receiver */
check_status(naibrd_AR_SetRxEnable(cardIndex, module, channel, AR_ENABLE));
while (bContinue)
{
printf("\nType duration (in seconds) for ARINC receive messages test or %c to quit (default: 5) : ", NAI_QUIT_CHAR);
bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
if (!bQuit)
{
duration = 5;
if (inputResponseCnt > 0)
duration = (int32_t)atol((const char*)inputBuffer);
end = time(NULL) + duration;
/* Read data */
while (time(NULL) < end)
{
check_status(naibrd_AR_GetRxBufferCnt(cardIndex, module, channel, &nNumWordsRecv));
if (nNumWordsRecv > 0)
{
/* Read FIFO words for new MailBox addresses */
printf(" %d words received\n", nNumWordsRecv);
printf("\nSDI/Labels in FIFO\n");
for (i = 0; i < nNumWordsRecv; i++)
{
check_status(naibrd_AR_ReadFifoMBox(cardIndex, module, channel, &Label[i]));
printf("Label %d = %03X\n", i, Label[i]);
}
/* Using SDI / Labels from FIFO, read MailBoxes to get new data */
printf("\nMailboxes with SDI/Labels read from FIFO\n");
for (i = 0; i < nNumWordsRecv; i++)
{
check_status(naibrd_AR_ReadMBox(cardIndex, module, channel, bTimestampEnabled, Label[i], &MailRecvStatusWd, &MailRecvData, &MailRecvTimeStamp)); /* read MailBox */
if (bTimestampEnabled)
{
printf("SDI/Label %03X status = %04X, data = %08X, timestamp = %08X\n",
Label[i], MailRecvStatusWd, MailRecvData, MailRecvTimeStamp);
}
else
{
printf("SDI/Label %03X status = %04X, data = %08X\n",
Label[i], MailRecvStatusWd, MailRecvData);
}
}
}
#if defined (__VXWORKS__)
taskDelay(1);
#endif
}
}
else
bContinue = FALSE;
}
return bQuit;
}
void EnableValidation(int32_t cardIndex, int32_t module, int32_t channel)
{
int32_t i;
bool_t ValEnableArray[0x400] = { FALSE };
/* Enable Validation */
naibrd_AR_SetRxValidationEn(cardIndex, module, channel, TRUE);
/* Create array of size 0x400 where every 8th element is set TRUE and all others FALSE */
for (i = 0; i < sizeof(ValEnableArray); i++)
{
if ((i + 1) % 8 == 0)
{
ValEnableArray[i] = TRUE;
}
}
/* Enable Validation for every 8th SDI/Label combination from 0x000 to 0x3FF */
check_status(naibrd_AR_WrRxValMemRange(cardIndex, module, channel, 0x000, 0x3FF, ValEnableArray));
}