AR429 Recv
Edit this on GitLab
AR429 Recv Sample Application (SSK 2.x)
Overview
The AR429 Recv sample application demonstrates how to configure an ARINC 429 channel for message reception using the NAI Software Support Kit (SSK 2.x). The application provides three receive modes: FIFO reception without validation (all messages accepted), FIFO reception with SDI/Label validation (only matching messages stored), and mailbox mode (messages sorted into mailboxes by SDI/Label). The user selects the card, module, channel, data rate, and timestamp setting, then chooses a receive mode from the command menu.
This sample supports AR module types including AR1 and AR2. It is designed to work with the AR429 Xmit sample application, which transmits ARINC 429 messages on a separate channel.
For the SSK 1.x version, see AR Receive (SSK 1.x).
Prerequisites
Before running this sample, make sure you have:
-
An NAI board with an AR module installed (AR1 or AR2).
-
SSK 2.x installed on your development host.
-
The sample applications built. Refer to the SSK 2.x Software Development Guide for platform-specific build instructions.
-
An ARINC 429 transmitter (use the AR429 Xmit sample or external equipment) connected to the receive channel.
How to Run
Launch the ar429_recv executable from your build output directory. On startup the application looks for a configuration file (default_ARRecv.txt). Once connected, the application queries for configuration parameters, sets up the ARINC 429 receiver, and presents a menu for choosing the receive mode.
Board Connection and Module Selection
|
Note
|
This startup sequence is common to all NAI sample applications. |
The main() function calls naiapp_RunBoardMenu() to load a saved configuration or present the interactive board menu. It then calls AR_Receive_run() in a loop until the user quits.
Program Structure
Command Menu
The application uses a command table with three receive modes:
-
NORMAL — receive without validation (all messages accepted into the FIFO).
-
VALID — receive with SDI/Label validation (only messages matching enabled labels are stored).
-
MAILBOX — mailbox mode (messages are sorted into mailboxes by SDI/Label).
Channel Configuration
The AR_Receive_run() function queries for the card, module, channel, and data rate, then configures the receiver:
check_status(naibrd_AR_ChannelReset(cardIndex, module, archan));
check_status(naibrd_AR_SetTxEnable(cardIndex, module, archan, NAI_FALSE));
check_status(naibrd_AR_SetRxEnable(cardIndex, module, archan, NAI_FALSE));
check_status(naibrd_AR_SetBaudRate(cardIndex, module, archan, datarate));
check_status(naibrd_AR_SetRxFifoThreshold(cardIndex, module, archan, 128));
check_status(naibrd_AR_SetParityBitUsage(cardIndex, module, archan, NAIBRD_AR_PAR_ODD));
check_status(naibrd_AR_SetRxStoreOnErrorEnable(cardIndex, module, archan, NAI_TRUE));
check_status(naibrd_AR_SetRxTimeStampEn(cardIndex, module, archan, bTimestampEnabled));
Key configuration parameters:
-
Data rate — high speed (100 KHz) or low speed (12.5 KHz).
-
Rx FIFO threshold — set to 128; the Rx FIFO Almost Full status is set when the count exceeds this value.
-
Parity — odd parity checking on ARINC bit 32.
-
Store on error — enabled, so all messages are stored regardless of error flags.
-
Timestamp — optionally enabled for each received message.
Receive Modes
FIFO Without Validation
In this mode, all received ARINC 429 messages are stored in the Rx FIFO regardless of their SDI/Label:
check_status(naibrd_AR_SetReceiveMode(cardIndex, module, channel, NAIBRD_AR_RX_FIFO_MODE));
naibrd_AR_SetRxValidationEnable(cardIndex, module, channel, NAI_FALSE);
The application polls for received messages over a user-specified duration:
check_status(naibrd_AR_GetRxFifoCnt(cardIndex, module, channel, &nNumWordsRecv));
if (nNumWordsRecv > 0)
{
check_status(naibrd_AR_ReadRxFifo(cardIndex, module, channel, bTimestampEnabled, nNumWordsRecv, RecvStatusWd, RecvData, RecvTimeStamp, &nNumWordsRecv));
}
FIFO With Validation
In this mode, only messages matching enabled SDI/Label combinations are stored:
naibrd_AR_SetRxValidationEnable(cardIndex, module, channel, NAI_TRUE);
naibrd_AR_SetLabelEnableAll(cardIndex, module, channel, NAI_FALSE);
for (i = 0; i < 0x400; i++)
{
if ((i + 1) % 8 == 0)
{
naibrd_AR_SetLabelEnable(cardIndex, module, channel, i, NAI_TRUE);
}
}
The sample enables every 8th SDI/Label combination from 0x000 to 0x3FF. Only messages with matching labels are stored in the FIFO.
Mailbox Mode
In mailbox mode, messages are sorted into mailboxes by their SDI/Label. The application reads the FIFO to discover which labels have new data, then reads the corresponding mailboxes:
check_status(naibrd_AR_SetReceiveMode(cardIndex, module, channel, NAIBRD_AR_RX_MBOX_MODE));
check_status(naibrd_AR_ReadMBoxRxFifo(cardIndex, module, channel, &Label[i]));
check_status(naibrd_AR_ReadMBox(cardIndex, module, channel, bTimestampEnabled, Label[i], &MailRecvStatusWd, &MailRecvData, &MailRecvTimeStamp));
Troubleshooting Reference
| Error / Symptom | Possible Causes | Suggested Resolution |
|---|---|---|
No messages received |
Transmitter not running, cable not connected, data rate mismatch |
Ensure the AR429 Xmit sample is running. Verify cabling and data rate settings match. |
No board found or connection timeout |
Board not powered, incorrect configuration file |
Verify hardware is powered and connected. |
Parity errors in status word |
Transmitter using different parity, noisy bus |
Verify both endpoints use the same parity setting. |
Validation mode receives no data |
Enabled labels do not match transmitted labels |
Check which SDI/Label combinations are enabled and ensure the transmitter sends matching values. |
Mailbox mode shows no labels |
Validation not enabled, no matching messages |
Mailbox mode requires validation. Ensure labels are enabled. |
Rx FIFO overflow |
Messages arriving faster than they are read |
Increase the read frequency or adjust the FIFO threshold. |
Full Source
The complete source for this sample is provided below for reference.
Full Source — ar429_recv.c (SSK 2.x)
/* nailib include files */
#include "nai_libs/nailib/include/naitypes.h"
#include "nai_libs/nailib/include/nailib.h"
#include "nai_libs/nailib/include/nailib_utils.h"
/* naibrd include files */
#include "nai_libs/naibrd/include/naibrd.h"
/* naiif include files */
#include "nai_libs/naiif/include/naiif_stdio.h"
/* Common Sample Program include files */
#include "nai_sample_apps/naiapp_common/include/naiapp_boardaccess_menu.h"
#include "nai_sample_apps/naiapp_common/include/naiapp_boardaccess_query.h"
#include "nai_sample_apps/naiapp_common/include/naiapp_boardaccess_access.h"
#include "nai_sample_apps/naiapp_common/include/naiapp_boardaccess_display.h"
#include "nai_sample_apps/naiapp_common/include/naiapp_boardaccess_utils.h"
/* AR Sample App include files */
#include "nai_sample_apps/naiapp_src/board_modules/ar429/ar429_common_utils/ar429_common_utils.h"
static const int8_t *CONFIG_FILE = (const int8_t *)"default_ARRecv.txt";
/* Function prototypes */
static bool_t AR_Receive_run();
static nai_status_t AR_RxWithoutValidation(int32_t paramCount, int32_t* p_params);
static nai_status_t AR_RxWithValidation(int32_t paramCount, int32_t* p_params);
static nai_status_t AR_RxWithMailbox(int32_t paramCount, int32_t* p_params);
static bool_t RxAndDisplayFIFOMsgs(int32_t cardIndex, int32_t module, int32_t channel);
static bool_t RxandDisplayFIFOandMailBox(int32_t cardIndex, int32_t module, int32_t channel);
static 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}
};
/* Default channel selection */
#define DEF_AR_CARD_INDEX 0
#define DEF_AR_MODULE 1
#define DEF_AR_RECV_CHANNEL 2
/* Default channel configuration settings */
#define DEF_AR_DATA_RATE NAIBRD_AR_SPEED_LOW
#define DEF_AR_TIMESTAMP_ENABLED NAI_TRUE
/* Global Variables */
static bool_t bTimestampEnabled = NAI_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.
* </summary>
*/
/*****************************************************************************/
int32_t main(void)
{
bool_t bQuit = NAI_FALSE;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
if (naiapp_RunBoardMenu(CONFIG_FILE) == (bool_t)NAI_TRUE)
{
while (!bQuit)
{
bQuit = AR_Receive_run();
}
naiif_printf("Type the Enter key to exit the program: ");
naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
}
naiapp_access_CloseAllOpenCards();
return 0;
}
static bool_t AR_Receive_run()
{
bool_t bQuit = NAI_FALSE;
int32_t archan;
naibrd_ar_datarate_t datarate;
int32_t cardIndex, module;
bool_t bContinue, bCmdFound;
int32_t cmd;
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, NAI_FALSE));
check_status(naibrd_AR_SetRxEnable(cardIndex, module, archan, NAI_FALSE));
/* Set the transmission speed */
check_status(naibrd_AR_SetBaudRate(cardIndex, module, archan, datarate));
/* Set the Rx Fifo Threshold to 128 */
check_status(naibrd_AR_SetRxFifoThreshold(cardIndex, module, archan, 128));
/* Set the Parity Bit Usage to odd parity */
check_status(naibrd_AR_SetParityBitUsage(cardIndex, module, archan, NAIBRD_AR_PAR_ODD));
/* Store all received messages regardless of errors */
check_status(naibrd_AR_SetRxStoreOnErrorEnable(cardIndex, module, archan, NAI_TRUE));
/* Query for Timestamp Mode Enable */
bQuit = GetARReceiverTimestampEnabled(DEF_AR_TIMESTAMP_ENABLED, &bTimestampEnabled);
if (!bQuit)
{
/* Set Timestamp Enable */
check_status(naibrd_AR_SetRxTimeStampEn(cardIndex, module, archan, bTimestampEnabled));
bContinue = NAI_TRUE;
naiapp_utils_LoadParamMenuCommands(AR_FUNCGEN_CMD_COUNT, AR_FuncGenMenuCmds);
while (bContinue)
{
naiapp_display_ParamMenuCommands((int8_t *)"AR Receive Mode Menu");
naiif_printf("\r\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:
naiif_printf("Invalid command entered\r\n");
break;
}
}
else
naiif_printf("Invalid command entered\r\n");
}
}
else
bContinue = NAI_FALSE;
}
}
}
}
return bQuit;
}
static bool_t RxAndDisplayFIFOMsgs(int32_t cardIndex, int32_t module, int32_t channel)
{
bool_t bQuit = NAI_FALSE;
bool_t bContinue = NAI_TRUE;
int32_t i;
int32_t nNumWordsRecv;
uint32_t RecvStatusWd[NAIBRD_AR_MAX_FIFO_COUNT];
uint32_t RecvData[NAIBRD_AR_MAX_FIFO_COUNT];
uint32_t RecvTimeStamp[NAIBRD_AR_MAX_FIFO_COUNT];
int32_t duration;
int32_t timeout;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
check_status(naibrd_AR_ClearRxFifo(cardIndex, module, channel));
check_status(naibrd_AR_SetRxEnable(cardIndex, module, channel, NAI_TRUE));
bContinue = NAI_TRUE;
while (bContinue)
{
naiif_printf("\r\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 = 0;
timeout = 5;
if (inputResponseCnt > 0)
timeout = (int32_t)atol((const char*)inputBuffer);
do
{
check_status(naibrd_AR_GetRxFifoCnt(cardIndex, module, channel, &nNumWordsRecv));
if (nNumWordsRecv > 0)
{
naiif_printf("\r\nReading back %d words ...\r\n", nNumWordsRecv);
check_status(naibrd_AR_ReadRxFifo(cardIndex, module, channel, bTimestampEnabled, nNumWordsRecv, RecvStatusWd, RecvData, RecvTimeStamp, &nNumWordsRecv));
for (i = 0; i < nNumWordsRecv; i++)
{
naiif_printf("Status: 0x%08X ", RecvStatusWd[i]);
naiif_printf("Data: 0x%08X ", RecvData[i]);
if (bTimestampEnabled)
{
naiif_printf("TimeStamp: 0x%08X\r\n", RecvTimeStamp[i]);
}
}
}
naiif_msDelay(1000);
} while (++duration < timeout);
}
else
bContinue = NAI_FALSE;
}
return bQuit;
}
static bool_t RxandDisplayFIFOandMailBox(int32_t cardIndex, int32_t module, int32_t channel)
{
bool_t bQuit = NAI_FALSE;
bool_t bContinue = NAI_TRUE;
uint32_t Label[NAIBRD_AR_MAX_FIFO_COUNT];
int32_t nNumWordsRecv = 16;
uint16_t MailRecvStatusWd;
uint32_t MailRecvData;
uint32_t MailRecvTimeStamp;
int32_t duration;
int32_t timeout;
int32_t i;
int8_t inputBuffer[80];
int32_t inputResponseCnt;
check_status(naibrd_AR_SetRxEnable(cardIndex, module, channel, NAI_TRUE));
while (bContinue)
{
naiif_printf("\r\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 = 0;
timeout = 5;
if (inputResponseCnt > 0)
timeout = (int32_t)atol((const char*)inputBuffer);
do
{
check_status(naibrd_AR_GetRxFifoCnt(cardIndex, module, channel, &nNumWordsRecv));
if (nNumWordsRecv > 0)
{
naiif_printf(" %d words received\r\n", nNumWordsRecv);
naiif_printf("\r\nSDI/Labels in FIFO\r\n");
for (i = 0; i < nNumWordsRecv; i++)
{
check_status(naibrd_AR_ReadMBoxRxFifo(cardIndex, module, channel, &Label[i]));
naiif_printf("Label %d = %03X\r\n", i, Label[i]);
}
naiif_printf("\r\nMailboxes with SDI/Labels read from FIFO\r\n");
for (i = 0; i < nNumWordsRecv; i++)
{
check_status(naibrd_AR_ReadMBox(cardIndex, module, channel, bTimestampEnabled, Label[i], &MailRecvStatusWd, &MailRecvData, &MailRecvTimeStamp));
if (bTimestampEnabled)
{
naiif_printf("SDI/Label %03X status = %04X, data = %08X, timestamp = %08X\r\n",
Label[i], MailRecvStatusWd, MailRecvData, MailRecvTimeStamp);
}
else
{
naiif_printf("SDI/Label %03X status = %04X, data = %08X\r\n",
Label[i], MailRecvStatusWd, MailRecvData);
}
}
}
naiif_msDelay(1000);
} while (++duration < timeout);
}
else
bContinue = NAI_FALSE;
}
return bQuit;
}
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;
NAIBSP_UNREFERENCED_PARAMETER(paramCount);
check_status(naibrd_AR_SetReceiveMode(cardIndex, module, channel, NAIBRD_AR_RX_FIFO_MODE));
naibrd_AR_SetRxValidationEnable(cardIndex, module, channel, NAI_FALSE);
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;
NAIBSP_UNREFERENCED_PARAMETER(paramCount);
check_status(naibrd_AR_SetReceiveMode(cardIndex, module, channel, NAIBRD_AR_RX_FIFO_MODE));
EnableValidation(cardIndex, module, channel);
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;
NAIBSP_UNREFERENCED_PARAMETER(paramCount);
check_status(naibrd_AR_SetReceiveMode(cardIndex, module, channel, NAIBRD_AR_RX_MBOX_MODE));
EnableValidation(cardIndex, module, channel);
bQuit = RxandDisplayFIFOandMailBox(cardIndex, module, channel);
return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}
void EnableValidation(int32_t cardIndex, int32_t module, int32_t channel)
{
uint32_t i;
naibrd_AR_SetRxValidationEnable(cardIndex, module, channel, NAI_TRUE);
naibrd_AR_SetLabelEnableAll(cardIndex, module, channel, NAI_FALSE);
for (i = 0; i < 0x400; i++)
{
if ((i + 1) % 8 == 0)
{
naibrd_AR_SetLabelEnable(cardIndex, module, channel, i, NAI_TRUE);
}
}
}