Integrator Resources

The official home for NAI Support

Not sure where to start? Try Quick Start Guide or ask a question below!

Toggle Components with Visual Button
JavaScript Form Processing

AR429 Recv

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

Entry Point

The entry point is main().

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);
      }
   }
}

Help Bot

X