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

AR CAN BasicOps

AR CAN BasicOps

Explanation

About the Sample Application Code in C

This sample application code demonstrates how to interact with the AR_CAN module in an embedded system using the North Atlantic Industries (NAI) SDK. Below is an explanation of the various sections and functionality of the code:

Header Inclusions and Declarations

The code includes several standard libraries and NAI-specific headers: - Standard Libraries: stdio.h, stdlib.h, string.h, time.h - Platform-Specific Headers: Conditional includes for different operating systems, such as LINUX and VXWORKS. - NAI-Specific Headers: Various headers related to CAN operations and utility functions.

Constants and Macros

The code defines several constants, macros, and a structure to hold user input: - CONFIG_FILE: Default configuration file path. - CAN-related constants like SINGLE_MSG_BUFFER_LEN, STANDARD_CAN_MAX_PAYLOAD, etc.

Global Variables

  • userInput: Structure to store user inputs such as card index, module number, channel number, etc.

  • Some static global variables for tracking state and counts, such as globalQuit and g_moduleCount.

Function Prototypes

Several static helper functions are declared, which are later defined to handle specific CAN operations: - Channel, Protocol, and Baud Rate Settings: CAN_SetChan, CAN_SetProtocol, CAN_SetBaud - Transmission and Reception: CAN_Single8ByteXmit, CAN_Single64ByteXmit, CAN_ReceiveMsg, CAN_ReceiveMsgPump - Scheduling: CAN_ScheduleMsg, CAN_StartSchedule, CAN_StopSchedule - Filtering: CAN_SetFilter, CAN_GetFilter, CAN_SetFilterMask, CAN_GetFilterMask, CAN_RemoveFilter, CAN_EnableFilters, CAN_DisableFilters - FIFO Operations: CAN_ResetTxFIFO, CAN_ResetRxFIFO, CAN_EnableTx, CAN_DisableTx, CAN_ResetDropCount, CAN_DisplayCounts - Utility: checkChannelNumber, Run_CAN_DisplayCANChoices, Show_CanDemoFunc_Commands

Command Table

An enumeration canFunc_MainMenuCommands lists all possible menu commands. A structured array CAN_DemoFuncMenuCmds maps command strings to their respective command identifiers.

Main Function

The main function (or AR_CAN_BasicOps on VXWORKS) initializes the system, handles user interactions, and provides a loop for selecting options from a menu: 1. Prompts the user to select a card and module number. 2. Displays menu options and handles user input to execute corresponding functions. 3. Provides options to quit or restart the application.

Key Function Implementations

Menu and Interaction Functions

  • Run_CAN_DisplayCANChoices(): Displays available commands and handles input to execute CAN operations.

  • Show_CanDemoFunc_Commands(): Prints the list of available commands.

Configuration Functions

  • CAN_SetChan(), CAN_SetProtocol(), CAN_SetBaud(): Prompt the user to set the channel, protocol, and baud rate for CAN communication.

Transmission and Reception Functions

  • CAN_Single8ByteXmit(): Transmits an 8-byte message.

  • CAN_Single64ByteXmit(): Transmits a 64-byte message.

  • CAN_ReceiveMsg(): Receives and displays a single message.

  • CAN_ReceiveMsgPump(): Continuously receives messages and displays counts.

Scheduling Functions

  • CAN_ScheduleMsg(), CAN_StartSchedule(), CAN_StopSchedule(): Handle message scheduling for periodic transmission.

Filtering Functions

  • CAN_SetFilter(), CAN_GetFilter(): Configure and retrieve filters for CAN messages.

  • CAN_SetFilterMask(), CAN_GetFilterMask(): Configure and retrieve filter masks.

  • CAN_RemoveFilter(): Remove a configured filter.

  • CAN_EnableFilters(), CAN_DisableFilters(): Enable or disable configured filters.

FIFO Management Functions

  • CAN_ResetTxFIFO(), CAN_ResetRxFIFO(): Reset the transmit and receive FIFO queues.

  • CAN_EnableTx(), CAN_DisableTx(): Enable or disable transmission on a channel.

  • CAN_ResetDropCount(): Reset the drop count for messages.

  • CAN_DisplayCounts(): Display counts for diagnostic purposes.

Utility Function

  • checkChannelNumber(): Validates the channel number against the supported range for the specified card and module.

Summary

This sample application is designed to demonstrate basic CAN-FD (Flexible Data-rate) operations using NAI’s library. It showcases how to configure CAN channels, protocols, and baud rates, send and receive CAN messages, schedule transmissions, manage filters, and perform FIFO-related diagnostics and resets. It provides a comprehensive example of interaction with a CAN module in an embedded system context.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#if defined (LINUX)
#include <ctype.h>
#include <pthread.h>
/*for ethernet code*/
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <arpa/inet.h>
#endif
#if defined (__VXWORKS__)
#include "inetLib.h"
#include <netdb.h>
#endif

#include "AR_CAN_BasicOps.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"

/* naibrd include files */
#include "nai.h"
#include "naibrd.h"
#include "functions/naibrd_ar_can.h"
#include "naibrd_ether.h"
#include "advanced/nai_ether_adv.h"

static const int8_t *CONFIG_FILE = (int8_t *)"default_ARCAN.txt";

#define SINGLE_MSG_BUFFER_LEN             80
#define STANDARD_CAN_MAX_PAYLOAD           8
#define CAN_FD_MAX_PAYLOAD                64

/* Function prototypes */
#define DEF_CAN_CARD_INDEX                 0
#define DEF_CAN_MODULE                     1
#define DEF_CAN_TX_CHANNEL                 1

#define CAN_DEFAULT_MODULE                 1

#define CAN_DATA_LENGTH_ZERO              (0u)
#define CAN_MAX_MODE_AB_DATA_LENGTH       (8u)

static struct _userInput
{
   int32_t nCardIdx;
   int32_t nModuleNumber;
   int32_t nChannelNumber;
   int32_t nProtocolIndex;
   int32_t nBaudBaseRate;
   int32_t nBaudDataRate;
}userInput;

/****** static function *******/
static bool_t checkChannelNumber(int32_t card, int32_t mod, int32_t chan);
static void Run_CAN_DisplayCANChoices();
static void Show_CanDemoFunc_Commands();
static void CAN_SetChan();
static void CAN_SetProtocol();
static void CAN_SetBaud();
static void CAN_Single8ByteXmit();
static void CAN_Single64ByteXmit();
static void CAN_ReceiveMsg();
static void CAN_ReceiveMsgPump();
static void CAN_ScheduleMsg();
static void CAN_StartSchedule();
static void CAN_StopSchedule();
static void CAN_SetFilter();
static void CAN_GetFilter();
static void CAN_SetFilterMask();
static void CAN_GetFilterMask();
static void CAN_RemoveFilter();
static void CAN_EnableFilters();
static void CAN_DisableFilters();
static void CAN_ResetTxFIFO();
static void CAN_ResetRxFIFO();
static void CAN_EnableTx();
static void CAN_DisableTx();
static void CAN_ResetDropCount();
static void CAN_DisplayCounts();

/****** Command Table *******/
enum canFunc_MainMenuCommands
{
   CAN_FUNC_CMD_SELECT_CHANNEL_MMENU,
   CAN_FUNC_CMD_SELECT_PROTOCOL_MMENU,
   CAN_FUNC_CMD_SELECT_BAUD_MMENU,
   SEPARATOR1,
   CAN_FUNC_CMD_SINGLE_8BYTE_XMIT_MMENU,
   CAN_FUNC_CMD_SINGLE_64BYTE_XMIT_MMENU,
   CAN_FUNC_CMD_RECEIVE_MMENU,
   CAN_FUNC_CMD_RECEIVE_MSG_PUMP_MMENU,
   SEPARATOR2,
   CAN_FUNC_CMD_SCHEDULE_MSG_XMIT_MMENU,
   CAN_FUNC_CMD_START_SCHEDULE_MMENU,
   CAN_FUNC_CMD_STOP_SCHEDULE_MMENU,
   SEPARATOR3,
   CAN_FUNC_CMD_SET_FILTER_MMENU,
   CAN_FUNC_CMD_GET_FILTER_MMENU,
   CAN_FUNC_CMD_SET_FILTER_MASK_MMENU,
   CAN_FUNC_CMD_GET_FILTER_MASK_MMENU,
   CAN_FUNC_CMD_REMOVE_FILTER_MMENU,
   CAN_FUNC_CMD_ENABLE_FILTERS_MMENU,
   CAN_FUNC_CMD_DISABLE_FILTERS_MMENU,
   SEPARATOR4,
   CAN_FUNC_CMD_RESET_TX_FIFO_MMENU,
   CAN_FUNC_CMD_RESET_RX_FIFO_MMENU,
   CAN_FUNC_CMD_ENABLE_TX_MMENU,
   CAN_FUNC_CMD_DISABLE_TX_MMENU,
   CAN_FUNC_CMD_RESET_DROP_COUNT_MMENU,
   CAN_FUNC_CMD_DISPLAY_COUNTS_MMENU,
   SEPARATOR5,
   CAN_FUNC_CMD_COUNT
};


struct canDemofunc_cmdtbl {
   int8_t *cmdstr;
   int8_t *menustr;
   int32_t  cmdnum;
   /*   void(*func)();*/
};


/****** Command Tables *******/
static struct canDemofunc_cmdtbl CAN_DemoFuncMenuCmds[] = {

   { (int8_t *)"1",   (int8_t *)"Set Channel",                CAN_FUNC_CMD_SELECT_CHANNEL_MMENU, },\
{(int8_t *)"2",   (int8_t *)"Set Protocol",               CAN_FUNC_CMD_SELECT_PROTOCOL_MMENU,	 },\
{(int8_t *)"3",   (int8_t *)"Set Baud",                   CAN_FUNC_CMD_SELECT_BAUD_MMENU,	       },\
{(int8_t *)"-",   (int8_t *)"---------------------------",SEPARATOR1,                            },\
{(int8_t *)"A",   (int8_t *)"Single 8byte Xmit",          CAN_FUNC_CMD_SINGLE_8BYTE_XMIT_MMENU,	 },\
{(int8_t *)"B",   (int8_t *)"Single 64byte Xmit",         CAN_FUNC_CMD_SINGLE_64BYTE_XMIT_MMENU, },\
{(int8_t *)"C",   (int8_t *)"Receive Single Msg",         CAN_FUNC_CMD_RECEIVE_MMENU,            },\
{(int8_t *)"D",   (int8_t *)"Receive Msg Pump",           CAN_FUNC_CMD_RECEIVE_MSG_PUMP_MMENU    },\
{(int8_t *)"-",   (int8_t *)"---------------------------",SEPARATOR2,                            },\
{(int8_t *)"E",   (int8_t *)"Schedule Msg",               CAN_FUNC_CMD_SCHEDULE_MSG_XMIT_MMENU,  },\
{(int8_t *)"F",   (int8_t *)"Start Schedule",             CAN_FUNC_CMD_START_SCHEDULE_MMENU,     },\
{(int8_t *)"G",   (int8_t *)"Stop Schedule",              CAN_FUNC_CMD_STOP_SCHEDULE_MMENU,      },\
{(int8_t *)"-",   (int8_t *)"---------------------------",SEPARATOR3,	                         },\
{(int8_t *)"I",   (int8_t *)"Set Filter",                 CAN_FUNC_CMD_SET_FILTER_MMENU,         },\
{(int8_t *)"J",   (int8_t *)"Get Filter",                 CAN_FUNC_CMD_GET_FILTER_MMENU,         },\
{(int8_t *)"K",   (int8_t *)"Set Filter Mask",            CAN_FUNC_CMD_SET_FILTER_MASK_MMENU,    },\
{(int8_t *)"L",   (int8_t *)"Get Filter Mask",            CAN_FUNC_CMD_GET_FILTER_MASK_MMENU,    },\
{(int8_t *)"M",   (int8_t *)"Remove Filter",              CAN_FUNC_CMD_REMOVE_FILTER_MMENU,      },\
{(int8_t *)"N",   (int8_t *)"Enable Filters",             CAN_FUNC_CMD_ENABLE_FILTERS_MMENU,     },\
{(int8_t *)"O",   (int8_t *)"Disable Filters",            CAN_FUNC_CMD_DISABLE_FILTERS_MMENU,    },\
{(int8_t *)"-",   (int8_t *)"---------------------------",SEPARATOR4,	                         },\
{(int8_t *)"U",   (int8_t *)"Reset Tx FIFO",              CAN_FUNC_CMD_RESET_TX_FIFO_MMENU,      },\
{(int8_t *)"V",   (int8_t *)"Reset Rx FIFO",              CAN_FUNC_CMD_RESET_RX_FIFO_MMENU,      },\
{(int8_t *)"W",   (int8_t *)"Enable Tx FIFO",             CAN_FUNC_CMD_ENABLE_TX_MMENU,          },\
{(int8_t *)"X",   (int8_t *)"Disable Tx FIFO",            CAN_FUNC_CMD_DISABLE_TX_MMENU,         },\
{(int8_t *)"Y",   (int8_t *)"Reset Drop Count",           CAN_FUNC_CMD_RESET_DROP_COUNT_MMENU,   },\
{(int8_t *)"Z",   (int8_t *)"Display Counts",             CAN_FUNC_CMD_DISPLAY_COUNTS_MMENU,     },\
{(int8_t *)"-",   (int8_t *)"---------------------------",SEPARATOR5,	                         },\
{NULL,             NULL,                                  0,                                     }
};

/***** Global Variables *****/
static bool_t globalQuit = FALSE;
static int32_t g_moduleCount = 0;

/**************************************************************************************************************/
/** \defgroup AR-CAN_BasicOps Arinc CAN-FD Basic Operations
The purpose of the AR_CAN_BasicOps is to illustrate the naibrd library methods for CAN-FD
operations with the module, including configuration setup, transmitting messages, receiving messages,
scheduling messages and filtering messages.
*/
/**************************************************************************************************************/
#if defined (__VXWORKS__)
int32_t AR_CAN_BasicOps(void)
#else
int32_t main(void)
#endif
{
   bool_t stop = FALSE;
   int32_t cardIndex;
   int32_t moduleCnt;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   if (naiapp_RunBoardMenu(CONFIG_FILE) == TRUE)
   {
      while (stop != TRUE)
      {
         /* Query the user for the card index */
         stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
         /* Set global var userInput.nCardIdx */
         userInput.nCardIdx = cardIndex;
         if (stop != TRUE)
         {
            check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));
            /* Set global var g_moduleCount */
            g_moduleCount = moduleCnt;
            /* Query the user for the module number */
            stop = naiapp_query_ModuleNumber(moduleCnt, 1, &userInput.nModuleNumber);
            if (stop != TRUE)
            {
               Run_CAN_DisplayCANChoices();
            }
         }

         printf("\nType Q to quit or Enter key to restart application:\n");
         stop = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
      }
   }

   printf("\nType the Enter key to exit the program: ");
   naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   naiapp_access_CloseAllOpenCards();

   return 0;
}

/**************************************************************************************************************/
/** \ingroup AR-CAN_BasicOps
Handles displaying available menu of options to demonstrate how to interact with the AR-CAN module.
Menu prompts are exposed to the user to enter in a desired menu command from the following:
\verbatim
Set Channel
   > Specify which channel is being targeted for configuration.
Set Protocol
   > Specify which protocol to be used for the selected channel (i.e. 0 (AB), 1 (FD)).
Set Baud
   > Specify what baud rate should be used for the selected channel.
Single 8byte Xmit
   > Transmits a single 8 byte (predefined payload) message onto the bus from the selected channel.
Single 64byte Xmit
   > Transmits a single 64 byte (predefined payload) message onto the bus from the selected channel.
Receive Single Msg
   > Receives a single message from the bus on the specified channel.
Receive Msg Pump
   > Continually tries to read messages from the bus on the specified channel.
Schedule Msg
   > Schedules a single 64 bye (predefined payload) message to be transmitted at a predefined interval.
     NOTE: scheduler needs to be enabled in order for the transmit schedule to start
Start Schedule
   > Starts the scheduler so all configured schedules will be started.
Stop Schedule
   > Stops the scheduler, halting all active schedules
Set Filter
   > Specifies a predefined filter (as demonstration) for the specified channel and filter index.
Get Filter
   > Retrieves the configured filter for the specified channel and filter index.
Set Filter Mask
   > Configures a predefined filter mask (as demonstration) for the specified channel at filter index 0.
Get Filter Mask
   > Retrieves the configured Filter Mask for the specified channel at filter index 0.
Remove Filter
   > Removes the specified configured filter (filter index 0 as demonstration) from the specified channel's set of configured filters.
Enable Filters
   > Enables all configured filters for the specified channel.
Disable Filters
   > Disables all configured filters for the specified channel.
Reset Tx FIFO
   > Specifies resetting of the Tx FIFO for the selected channel.
Reset Rx FIFO
   > Specifies resetting of the Rx FIFO for the selected channel.
Enable Tx FIFO
   > Enables the Tx FIFO for the selected channel (Tx FIFO must be enabled in order to transmit).
Disable Tx FIFO
   > Disables the Tx FIFO for the selected channel (no transmits will take place while the Tx FIFO is disabled for the specified channel)
Reset Drop Count
   > Resets the counter that keeps track of how many messages (over all channels) have been dropped due to no room left on the Rx FIFO.
Display Counts
   > Displays a key set of FIFO counts and drop count.
\endverbatim
*/
/**************************************************************************************************************/
void Run_CAN_DisplayCANChoices(void)
{
   bool_t bQuit = FALSE;
   int32_t cmdIdx;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   do
   {
      if (globalQuit)
         break;

      Show_CanDemoFunc_Commands();
      printf("\nType CAN command or %c to quit : ", NAI_QUIT_CHAR);
      bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
      if (!bQuit)
      {
         for (cmdIdx = 0; cmdIdx < CAN_FUNC_CMD_COUNT; cmdIdx++)
         {
            if (0 == naiapp_strnicmp((const int8_t*)inputBuffer, (const int8_t*)CAN_DemoFuncMenuCmds[cmdIdx].cmdstr, inputResponseCnt))
               break;
         }

         switch (cmdIdx)
         {
         case CAN_FUNC_CMD_SELECT_CHANNEL_MMENU:
            CAN_SetChan();
            break;

         case CAN_FUNC_CMD_SELECT_PROTOCOL_MMENU:
            CAN_SetProtocol();
            break;

         case CAN_FUNC_CMD_SELECT_BAUD_MMENU:
            CAN_SetBaud();
            break;

         case CAN_FUNC_CMD_SINGLE_8BYTE_XMIT_MMENU:
            CAN_Single8ByteXmit();
            break;

         case CAN_FUNC_CMD_SINGLE_64BYTE_XMIT_MMENU:
            CAN_Single64ByteXmit();
            break;

         case CAN_FUNC_CMD_RECEIVE_MMENU:
            CAN_ReceiveMsg();
            break;

         case CAN_FUNC_CMD_RECEIVE_MSG_PUMP_MMENU:
            CAN_ReceiveMsgPump();
            break;

         case CAN_FUNC_CMD_SCHEDULE_MSG_XMIT_MMENU:
            CAN_ScheduleMsg();
            break;

         case CAN_FUNC_CMD_START_SCHEDULE_MMENU:
            CAN_StartSchedule();
            break;

         case CAN_FUNC_CMD_STOP_SCHEDULE_MMENU:
            CAN_StopSchedule();
            break;

         case CAN_FUNC_CMD_SET_FILTER_MMENU:
            CAN_SetFilter();
            break;

         case CAN_FUNC_CMD_GET_FILTER_MMENU:
            CAN_GetFilter();
            break;

         case CAN_FUNC_CMD_SET_FILTER_MASK_MMENU:
            CAN_SetFilterMask();
            break;

         case CAN_FUNC_CMD_GET_FILTER_MASK_MMENU:
            CAN_GetFilterMask();
            break;

         case CAN_FUNC_CMD_REMOVE_FILTER_MMENU:
            CAN_RemoveFilter();
            break;

         case CAN_FUNC_CMD_ENABLE_FILTERS_MMENU:
            CAN_EnableFilters();
            break;

         case CAN_FUNC_CMD_DISABLE_FILTERS_MMENU:
            CAN_DisableFilters();
            break;

         case CAN_FUNC_CMD_RESET_TX_FIFO_MMENU:
            CAN_ResetTxFIFO();
            break;

         case CAN_FUNC_CMD_RESET_RX_FIFO_MMENU:
            CAN_ResetRxFIFO();
            break;

         case CAN_FUNC_CMD_ENABLE_TX_MMENU:
            CAN_EnableTx();
            break;

         case CAN_FUNC_CMD_DISABLE_TX_MMENU:
            CAN_DisableTx();
            break;

         case CAN_FUNC_CMD_RESET_DROP_COUNT_MMENU:
            CAN_ResetDropCount();
            break;

         case CAN_FUNC_CMD_DISPLAY_COUNTS_MMENU:
            CAN_DisplayCounts();
            break;

         default:
            break;
         }
      }
   } while (bQuit == FALSE);

   if (bQuit)
      globalQuit = TRUE;

   return;
}

/**************************************************************************************************************/
/** \ingroup AR-CAN_BasicOps
Makes a call to the function that displays all of the menu options for this basic ops sample application.
*/
/**************************************************************************************************************/
static void Show_CanDemoFunc_Commands(void)
{
   int i;
   printf("\n\t\t CAN Demo Program with FD (flexible data).");
   printf("\n\t\t ==========================\n");
   printf("\n\nCommands");
   printf("\n--------");
   for (i = 0; i < CAN_FUNC_CMD_COUNT && CAN_DemoFuncMenuCmds[i].cmdstr != NULL; i++)
      printf("\n%s\t%s", CAN_DemoFuncMenuCmds[i].cmdstr, CAN_DemoFuncMenuCmds[i].menustr);
   printf("\n");
}

/**************************************************************************************************************/
/** \ingroup AR-CAN_BasicOps
Prompts the user for which channel they would like to work with and stores the desired value in a global
variable to be used in subsequent basic ops menu operations.
*/
/**************************************************************************************************************/
static void CAN_SetChan()
{
   bool_t bQuit = FALSE;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   printf("\nEnter <<Channel>> Number or %c to quit [[default = 1]]: ", NAI_QUIT_CHAR);
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if (!bQuit)
   {
      if (inputResponseCnt == 0)
         userInput.nChannelNumber = 1;
      else
         userInput.nChannelNumber = atoi((const char *)inputBuffer);
   }
}

/**************************************************************************************************************/
/** \ingroup AR-CAN_BasicOps
Prompts the user for which protocol they would like to use.
/verbatim
protocol options:
   > CAN AB value "0"
   > CAN FD value "1"
/endverbatim
*/
/**************************************************************************************************************/
static void CAN_SetProtocol()
{
   bool_t bQuit = FALSE;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   printf("---------------------\r\n");
   printf("CAN AB Protocol    ENTER: '0'\r\n");
   printf("CAN FD Protocol    ENTER: '1'\r\n");
   printf("---------------------\r\n");
   printf("\nEnter Protocol Index Number or %c to quit [[default = 1 (CAN FD)]]: ", NAI_QUIT_CHAR);
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if (!bQuit)
   {
      if (inputResponseCnt == 0)
         userInput.nProtocolIndex = 1;
      else
         userInput.nProtocolIndex = atoi((const char *)inputBuffer);

      if (userInput.nProtocolIndex > 1)
      {
         printf("Invalid protocol index detected. Defaulting to CAN-FD - protocol index 1\r\n");
         userInput.nProtocolIndex = 1;
      }
   }
}

/**************************************************************************************************************/
/** \ingroup AR-CAN_BasicOps
Prompts the user for which baud rate they would like to use for the currently selected channel. Baud rate is
specified with 2 values, a base rate and a data rate.
\verbatim
Base Rate:
   > 1000K  -  value "0"
   >  500K  -  value "1"
   >  250K  -  value "3"

Data Rate:
   > 2000K  -  value "0" (Defatult)
   > 4000K  -  value "6"
   > 3000K  -  value "7"
   > 2000K  -  value "8"
   > 1000K  -  value "9"
\endverbatim
*/
/**************************************************************************************************************/
static void CAN_SetBaud()
{
   nai_status_t status;
   bool_t bQuit = FALSE;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;
   naibrd_ar_can_low_rate_type_t origBaseRate;
   naibrd_ar_can_high_rate_type_t origDataRate;

   printf("\r\n----------------------------\r\n");
   printf("Base Rate 1000K    ENTER: '0'\r\n");
   printf("Base Rate  500K    ENTER: '1'\r\n");
   printf("Base Rate  250K    ENTER: '3'\r\n");
   printf("----------------------------\r\n");
   printf("\nEnter Base Rate Index Number or %c to quit [[default = 1 (500K)]]: ", NAI_QUIT_CHAR);
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if (!bQuit)
   {
      if (inputResponseCnt == 0)
         userInput.nBaudBaseRate = 1;
      else
         userInput.nBaudBaseRate = atoi((const char *)inputBuffer);

      if (userInput.nBaudBaseRate > 3)
      {
         printf("Invalid Base Rate index detected. Defaulting to 500K - Base Rate index 1\r\n");
         userInput.nBaudBaseRate = 1;
      }
   }

   printf("\r\n---------------------------------\r\n");
   printf("Data Rate 2000K (default)  ENTER: '0'\r\n");
   printf("Data Rate  4000K    ENTER: '6'\r\n");
   printf("Data Rate  3000K    ENTER: '7'\r\n");
   printf("Data Rate  2000K    ENTER: '8'\r\n");
   printf("Data Rate  1000K    ENTER: '9'\r\n");
   printf("---------------------------------\r\n");
   printf("\nEnter Data Rate Index Number or %c to quit [[default = 8 (2000K)]]: ", NAI_QUIT_CHAR);
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if (!bQuit)
   {
      if (inputResponseCnt == 0)
         userInput.nBaudDataRate = 1;
      else
         userInput.nBaudDataRate = atoi((const char *)inputBuffer);

      if (userInput.nBaudDataRate == 0)
         userInput.nBaudDataRate = 8;

      if (userInput.nBaudDataRate > 9)
      {
         printf("Invalid Data Rate index detected. Defaulting to 2000K - Data Rate index 8\r\n");
         userInput.nBaudDataRate = 1;
      }
   }

   status = naibrd_AR_CAN_GetBaudRate(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, &origBaseRate, &origDataRate);
   if (NAI_SUCCESS == status)
      printf("Orig Base Rate: %d    Orig Data Rate: %d\r\n", (int32_t)origBaseRate, (int32_t)origDataRate);
   else
      printf("ERROR: naibrd_AR_CAN_GetBaudRate returned status: %d\r\n", status);

   status = naibrd_AR_CAN_SetBaudRate(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber,
      (naibrd_ar_can_low_rate_type_t)userInput.nBaudBaseRate, (naibrd_ar_can_high_rate_type_t)userInput.nBaudDataRate);

   if (NAI_SUCCESS == status)
      printf("Successfully set base and data baud rates for channel %d\r\n", userInput.nChannelNumber);
   else
      printf("ERROR: naibrd_AR_CAN_SetBaudRate returned status: %d\r\n", status);
}

/**************************************************************************************************************/
/** \ingroup AR-CAN_BasicOps
Forces a single 8 byte CAN FD message to be transmitted on the bus. The msg ID, CAN Mode and payload are all not
user configurable in this sample function. The values used in the sample are:
\verbatim
Message ID:
   > 0x111444
Is Mode A (CAN A)
   > FALSE
Payload Buffer
   > [0] = 0x00
   > [1] = 0x11
   > [2] = 0x22
   > [3] = 0x33
   > [4] = 0x44
   > [5] = 0x55
   > [6] = 0x66
   > [7] = 0x77
\endverbatim
*/
/**************************************************************************************************************/
static void CAN_Single8ByteXmit()
{
   nai_status_t status;
   uint8_t u8Buffer[STANDARD_CAN_MAX_PAYLOAD];
   uint32_t msgId = 0x111444;
   bool_t isModeA = FALSE;
   uint32_t i;

   if (!checkChannelNumber(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber))
      return;

   u8Buffer[0] = 0x00;
   u8Buffer[1] = 0x11;
   u8Buffer[2] = 0x22;
   u8Buffer[3] = 0x33;
   u8Buffer[4] = 0x44;
   u8Buffer[5] = 0x55;
   u8Buffer[6] = 0x66;
   u8Buffer[7] = 0x77;

   /* Load one-shot 8 byte message into FIFO */
   status = naibrd_AR_CAN_QueueTransmit(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber,
      (naibrd_ar_can_protocol_type_t)userInput.nProtocolIndex, isModeA, msgId, &u8Buffer[0], STANDARD_CAN_MAX_PAYLOAD);

   if (NAI_SUCCESS == status)
   {
      /* Now set the TX Enable so the message gets transmitted */
      status = naibrd_AR_CAN_SetTxEnable(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, TRUE);

      if (NAI_SUCCESS == status)
      {
         printf("CAN Message sent for chan: %d\r\n", userInput.nChannelNumber);
         if (userInput.nProtocolIndex == 0)
            printf("Protocol: CAN AB\r\n");
         else
            printf("Protocol: CAN FD\r\n");

         printf("Extended: %d\r\n", (isModeA) ? 0 : 1);
         printf("MsgId = 0x%x\r\n", msgId);
         for (i = 0; i < STANDARD_CAN_MAX_PAYLOAD; i++)
         {
            printf("   Payload[%d] = 0x%x\r\n", i, u8Buffer[i]);
         }
      }
      else
      {
         printf("ERROR: naibrd_AR_CAN_SetTxEnable returned status: %d\r\n", status);
      }
   }
   else /* naibrd_AR_CAN_QueueTransmit error detected */
   {
      printf("ERROR: naibrd_AR_CAN_QueueTransmit returned status: %d\r\n", status);
   }
}

/**************************************************************************************************************/
/** \ingroup AR-CAN_BasicOps
Forces a single 64 byte CAN FD message to be transmitted on the bus. The msg ID, CAN Mode and payload are all not
user configurable in this sample function. The values used in the sample are:
\verbatim
Message ID:
   > 0x17778888
Is Mode A (CAN A)
   > FALSE
Payload Buffer
   > [0] = 0x00
   > [1] = 0x01
   > [2] = 0x02
   > [3] = 0x03
   >     .
   >     .
   >     .
   > [63] = 0x3F
\endverbatim
*/
/**************************************************************************************************************/
static void CAN_Single64ByteXmit()
{
   nai_status_t status;
   uint8_t u8Buffer[CAN_FD_MAX_PAYLOAD];
   uint32_t msgId = 0x17778888;
   bool_t isModeA = FALSE;
   uint32_t i;

   if (!checkChannelNumber(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber))
      return;

   /* Fill up 64 byte payload buffer */
   for (i = 0; i < CAN_FD_MAX_PAYLOAD; i++)
   {
      u8Buffer[i] = (i & 0x000000FF);
   }

   /* Load one-shot 64 byte message into FIFO - we force use of protocol CAN-FD since 64 byte payload */
   status = naibrd_AR_CAN_QueueTransmit(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, NAIBRD_AR_CAN_PROTOCOL_FD,
      isModeA, msgId, &u8Buffer[0], CAN_FD_MAX_PAYLOAD);

   if (NAI_SUCCESS == status)
   {
      /* Now set the TX Enable so the message gets transmitted */
      status = naibrd_AR_CAN_SetTxEnable(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, TRUE);

      if (NAI_SUCCESS == status)
      {
         printf("CAN Message sent for chan: %d\r\n", userInput.nChannelNumber);
         printf("Protocol: CAN FD\r\n");
         printf("Extended: %d\r\n", (isModeA) ? 0 : 1);
         printf("MsgId = 0x%x\r\n", msgId);
         for (i = 0; i < CAN_FD_MAX_PAYLOAD; i++)
         {
            printf("   Payload[%d] = 0x%x\r\n", i, u8Buffer[i]);
         }
      }
      else
      {
         printf("ERROR: naibrd_AR_CAN_SetTxEnable returned status: %d\r\n", status);
      }
   }
   else /* naibrd_AR_CAN_QueueTransmit error detected */
   {
      printf("ERROR: naibrd_AR_CAN_QueueTransmit returned status: %d\r\n", status);
   }
}

/**************************************************************************************************************/
/** \ingroup AR-CAN_BasicOps
Attempts to read a single message off of the Rx FIFO for the selected channel and displays the message contents
to the screen.
*/
/**************************************************************************************************************/
static void CAN_ReceiveMsg()
{
   nai_status_t status;
   uint8_t u8Buffer[SINGLE_MSG_BUFFER_LEN];
   uint32_t msgId = 0;
   uint32_t timestamp;
   int32_t outRxCount = 0;
   int32_t i = 0;
   bool_t msgWaiting = FALSE;

   if (!checkChannelNumber(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber))
      return;

   /* 1st determine if there is a CAN message that we should be waiting for! */
   status = naibrd_AR_CAN_GetRxFIFOMessageWaiting(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, &msgWaiting);
   if (NAI_SUCCESS == status && msgWaiting)
   {
      status = naibrd_AR_CAN_Receive(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, SINGLE_MSG_BUFFER_LEN,
         &msgId, &timestamp, &u8Buffer[0], &outRxCount);

      if (NAI_SUCCESS == status)
      {
         printf("\r\nCAN Message Received For Channel: %d\r\n", userInput.nChannelNumber);
         printf("MsgId = 0x%x\r\n", msgId);
         printf("Timestamp = 0x%x\r\n", timestamp);
         printf("Payload Count = %d\r\n", outRxCount);

         for (i = 0; i < outRxCount; i++)
         {
            printf("   Payload[%d] = 0x%x\r\n", i, u8Buffer[i]);
         }
      }
      else
      {
         printf("ERROR: naibrd_AR_CAN_Receive returned status: %d\r\n", status);
      }
   }
   else /* Either an error trying to detect if message is waiting or there are no messages waiting */
   {
      if (NAI_SUCCESS == status)
      {
         printf("There are no messages waiting for retrieval!\r\n");
      }
      else
      {
         printf("ERROR: naibrd_AR_CAN_GetRxFIFOMessageWaiting returned status: %d\r\n", status);
      }
   }
}

/**************************************************************************************************************/
/** \ingroup AR-CAN_BasicOps
Continually reads messages off of the selected channel's Rx FIFO and keeps count of how many messages were in
fact received.
*/
/**************************************************************************************************************/
static void CAN_ReceiveMsgPump()
{
   nai_status_t status;
   uint8_t u8Buffer[SINGLE_MSG_BUFFER_LEN];
   uint32_t msgId = 0;
   uint32_t timestamp;
   int32_t outRxCount = 0;
   int32_t receivedMsgCount = 0;
   bool_t msgWaiting = FALSE;

   if (!checkChannelNumber(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber))
      return;

   do
   {
      /* 1st determine if there is a CAN message that we should be waiting for! */
      status = naibrd_AR_CAN_GetRxFIFOMessageWaiting(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, &msgWaiting);
      if (NAI_SUCCESS == status && msgWaiting)
      {
         status = naibrd_AR_CAN_Receive(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, SINGLE_MSG_BUFFER_LEN,
            &msgId, &timestamp, &u8Buffer[0], &outRxCount);

         if (NAI_SUCCESS == status)
         {
            receivedMsgCount++;
            printf("\r\nCAN Message Received For Channel: %d\r\n", userInput.nChannelNumber);
            printf("Msg Receive Count = %d\r\n", receivedMsgCount);
         }
         else
         {
            printf("ERROR: naibrd_AR_CAN_Receive returned status: %d\r\n", status);
         }
      }
      else /* Either an error trying to detect if message is waiting or there are no messages waiting ...
           if no message we continue to poll */
      {
         if (NAI_SUCCESS != status)
         {
            printf("ERROR: naibrd_AR_CAN_GetRxFIFOMessageWaiting returned status: %d\r\n", status);
         }
      }
   } while (NAI_SUCCESS == status);
}

/**************************************************************************************************************/
/** \ingroup AR-CAN_BasicOps
Schedules a single message to be transmitted at 5 milli-second intervals (rate) and starting 5 milli-seconds
(skew) after the scheduler is enabled. The schedule will be placed into the 1st scheduled message slot and the
schedule will not start until the actual scheduler is enabled.
NOTE: rate is the time in milli-seconds between each transmit of the scheduled message. skew is the amount of
delay in milli-seconds to wait once the scheduler for the channel is enabled to start sending messages. By defining
different skew values for each schedule configured for a given channel, users can essentially stagger msg transmits
thus reducing bus collisions.
\verbatim
Message ID:
   > 0x11112222
Is Mode A (CAN A)
   > FALSE
Payload Buffer
   > [0] = 0x00
   > [1] = 0x01
   > [2] = 0x02
   > [3] = 0x03
   >     .
   >     .
   >     .
   > [63] = 0x3F
\endverbatim
*/
/**************************************************************************************************************/
static void CAN_ScheduleMsg()
{
   nai_status_t status;
   uint8_t u8Buffer[CAN_FD_MAX_PAYLOAD];
   uint32_t msgId = 0x11112222;
   bool_t isModeA = FALSE;
   uint32_t i;
   uint8_t value = CAN_FD_MAX_PAYLOAD;
   int16_t entryIndex = 1;
   int16_t rate = 5;
   int16_t skew = 5;

   if (!checkChannelNumber(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber))
      return;

   /* Fill up 64 byte payload buffer */
   for (i = 0; i < CAN_FD_MAX_PAYLOAD; i++)
   {
      u8Buffer[i] = value;
      value--;
   }

   /* Submit 1st scheduled message */
   status = naibrd_AR_CAN_ScheduleMsg(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber,
      entryIndex, rate, skew, NAIBRD_AR_CAN_PROTOCOL_FD, isModeA, msgId, &u8Buffer[0], CAN_FD_MAX_PAYLOAD);

   if (NAI_SUCCESS == status)
   {
      printf("CAN Message with msgId: 0x%x was scheduled for chan: %d at entryIndex %d\r\n", msgId, userInput.nChannelNumber, entryIndex);
   }
   else /* naibrd_AR_CAN_QueueTransmit error detected */
   {
      printf("ERROR: naibrd_AR_CAN_ScheduleMsg returned status: %d\r\n", status);
   }
}

/**************************************************************************************************************/
/** \ingroup AR-CAN_BasicOps
Forces the selected channel's scheduler to start - Once started all schedules configured for the selected
channel will begin to transmit once their "skew" times have elapsed.
*/
/**************************************************************************************************************/
static void CAN_StartSchedule()
{
   nai_status_t status;

   if (!checkChannelNumber(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber))
      return;

   status = naibrd_AR_CAN_StartScheduler(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber);
   if (NAI_SUCCESS == status)
   {
      printf("Scheduler for channel %d has been started!\r\n", userInput.nChannelNumber);
   }
   else
   {
      printf("ERROR: naibrd_AR_CAN_StartScheduler returned status: %d\r\n", status);
   }
}

/**************************************************************************************************************/
/** \ingroup AR-CAN_BasicOps
Forces the selected channel's scheduler to stop - Once stopped all configured schedules will no longer
transmit until the scheduler is once again started.
*/
/**************************************************************************************************************/
static void CAN_StopSchedule()
{
   nai_status_t status;

   if (!checkChannelNumber(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber))
      return;

   status = naibrd_AR_CAN_StopScheduler(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber);
   if (NAI_SUCCESS == status)
   {
      printf("Scheduler for channel %d has been stopped!\r\n", userInput.nChannelNumber);
   }
   else
   {
      printf("ERROR: naibrd_AR_CAN_StartScheduler returned status: %d\r\n", status);
   }
}

/**************************************************************************************************************/
/** \ingroup AR-CAN_BasicOps
Forces a single filter to be applied for the selected channel. For the sake of simplicity, the filter values
are not user configurable in this sample function. The filter defined specifies a specific message Id that is
slightly different than the message sent in the 64 byte single message transmit menu option so once this filter
is configured and filtering is enabled, the selected channel will no longer receive those messages.
NOTE: Filter Mask also plays a part in filtering - The message Id mask dictates which bits of the message Id
should be compared between the message being compared and the msg Id of the filter that was defined. If the mask
message Id has a 1 in a specified bit, the corresponding bit of the message Id being analyzed must match the
corresponding message Id bit of the configured filter. Likewise, the payload mask dictates which bits of the
payload being analyzed need to match the payload value defined in the actual filter set by this function.
If the Mask has a zero in a specified payload bit, that bit will not be taken into account during the filtering
determination. If the Mask has a 1 in a specified payload bit, that same bit on the payload being analyzed must
match the bit found in the configured filter in order for the message to pass the filter.
Up to 4 filters can be assigned to each channel (zero based indexed).
\verbatim
Message ID:
   > 0x17778889
Is Mode A (CAN A)
   > FALSE
First two bytes of payload
   > [0] = 0x00
   > [1] = 0x00
\endverbatim
*/
/**************************************************************************************************************/
static void CAN_SetFilter()
{
   nai_status_t status;

   int32_t filterIndex = 0;
   uint32_t msgId = 0x17778889; /* This acceptance filter is 1 byte off from the 64 byte message sent when invoked from this sample app */
                                /*   uint32_t msgId = 0x17778888; This is the original ID so setting the new acceptance filter should stop the traffic if original msg is sent */
   bool_t isModeA = FALSE;
   uint8_t firstTwoBytes[2];

   /* Acceptance filtering based upon 1st two bytes of payload is also a capability offered but only if the corresponding filter mask
   dictates these bits should be used during the comparison */
   firstTwoBytes[0] = 0x00;
   firstTwoBytes[1] = 0x00;

   status = naibrd_AR_CAN_SetAcceptFilter(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, filterIndex, msgId,
      isModeA, &firstTwoBytes[0]);

   if (NAI_SUCCESS == status)
      printf("Acceptance filter: %d is now active for channel %d\r\n", filterIndex, userInput.nChannelNumber);
   else
      printf("ERROR: naibrd_AR_CAN_SetAcceptFilter returned status: %d\r\n", status);
}

/**************************************************************************************************************/
/** \ingroup AR-CAN_BasicOps
Retrieves the 1st acceptance filter that was configured and displays the information to the display.
Other filters that were configured can be retrieved in a similar fashion as what is demonstrated in this
sample.
*/
/**************************************************************************************************************/
static void CAN_GetFilter()
{
   nai_status_t status;

   int32_t filterIndex = 0;
   uint32_t msgId;
   bool_t isModeA;
   uint8_t firstTwoBytes[2];

   status = naibrd_AR_CAN_GetAcceptFilter(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, filterIndex, &msgId,
      &isModeA, &firstTwoBytes[0]);

   if (NAI_SUCCESS == status)
   {
      printf("Acceptance filter for channel: %d and filter index: %d\r\n", userInput.nChannelNumber, filterIndex);
      printf("MsgId = 0x%x\r\n", msgId);
      printf("ExtendedId = %d\r\n", (isModeA ? 0 : 1));
      printf("firstTwoBytes[0] = 0x%x\r\n", firstTwoBytes[0]);
      printf("firstTwoBytes[1] = 0x%x\r\n", firstTwoBytes[1]);
   }
   else
      printf("ERROR: naibrd_AR_CAN_GetAcceptFilter returned status: %d\r\n", status);
}

/**************************************************************************************************************/
/** \ingroup AR-CAN_BasicOps
The Filter Mask plays a part in filtering - The message Id mask dictates which bits of the message Id
should be compared between the message being compared and the msg Id of the filter that was defined. If the mask
message Id has a 1 in a specified bit, the corresponding bit of the message Id being analyzed must match the
corresponding message Id bit of the configured filter. Likewise, the payload mask dictates which bits of the
payload being analyzed need to match the payload value defined in the actual filter set by this function.
If the Mask has a zero in a specified payload bit, that bit will not be taken into account during the filtering
determination. If the Mask has a 1 in a specified payload bit, that same bit on the payload being analyzed must
match the bit found in the configured filter in order for the message to pass the filter. The following example
forces the message Id mask to 0x1FFFFFFF which dictates all of the bits of the incoming message Id must match
whatever the filter message Id is set to in order to pass the filter. The 1st two bytes of the mask payload
are set to zero which indicates none of the bits the make up the payload will be taken into account during the
filter determination.
Up to 4 filter masks can be assigned to each channel (zero based indexed) - 1 for each filter configured.
\verbatim
Message ID:
   > 0x1FFFFFFF
Is Mode A (CAN A)
   > FALSE
First two bytes of payload
   > [0] = 0x00
   > [1] = 0x00
\endverbatim
*/
/**************************************************************************************************************/
static void CAN_SetFilterMask()
{
   nai_status_t status;

   int32_t maskIndex = 0;
   uint32_t msgId = 0x1FFFFFFF; /* This means all bits of incoming msgId must match what is set in filterIndex 1 msgId in order for it to
                                pass. */
   bool_t isModeA = FALSE;
   uint8_t firstTwoBytes[2];

   /* Here setting the first two bytes to zero for the mask indicates we are not interesting on filtering based on the 1st two bytes of
   the payload */
   firstTwoBytes[0] = 0x00;
   firstTwoBytes[1] = 0x00;

   status = naibrd_AR_CAN_SetAcceptMask(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, maskIndex, msgId,
      isModeA, &firstTwoBytes[0]);

   if (NAI_SUCCESS == status)
      printf("Mask filter: %d is now active for channel %d\r\n", maskIndex, userInput.nChannelNumber);
   else
      printf("ERROR: naibrd_AR_CAN_SetAcceptMask returned status: %d\r\n", status);
}

/**************************************************************************************************************/
/** \ingroup AR-CAN_BasicOps
Retrieves the 1st acceptance filter mask that was configured and displays the information to the display.
Other filter masks that were configured can be retrieved in a similar fashion as what is demonstrated in this
sample.
*/
/**************************************************************************************************************/
static void CAN_GetFilterMask()
{
   nai_status_t status;

   int32_t maskIndex = 0;
   uint32_t msgId;
   bool_t isModeA;
   uint8_t firstTwoBytes[2];

   status = naibrd_AR_CAN_GetAcceptMask(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, maskIndex, &msgId,
      &isModeA, &firstTwoBytes[0]);

   if (NAI_SUCCESS == status)
   {
      printf("Acceptance mask for channel: %d and mask index: %d\r\n", userInput.nChannelNumber, maskIndex);
      printf("MsgId = 0x%x\r\n", msgId);
      printf("ExtendedId = %d\r\n", (isModeA ? 0 : 1));
      printf("firstTwoBytes[0] = 0x%x\r\n", firstTwoBytes[0]);
      printf("firstTwoBytes[1] = 0x%x\r\n", firstTwoBytes[1]);
   }
   else
      printf("ERROR: naibrd_AR_CAN_GetAcceptMask returned status: %d\r\n", status);
}

/**************************************************************************************************************/
/** \ingroup AR-CAN_BasicOps
This function shows how to remove a filter that was previously configured for the specified channel. Calling
this remove will remove both the filter and mask configurations for the specified filter index.
*/
/**************************************************************************************************************/
static void CAN_RemoveFilter()
{
   nai_status_t status;
   int32_t filterIndex = 0;

   status = naibrd_AR_CAN_RemoveAcceptFilter(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, filterIndex);

   if (NAI_SUCCESS == status)
      printf("Acceptance Filter at filterIndex: %d has been removed\r\n", filterIndex);
   else
      printf("ERROR: naibrd_AR_CAN_RemoveAcceptFilter returned status: %d\r\n", status);
}

/**************************************************************************************************************/
/** \ingroup AR-CAN_BasicOps
Filters are NOT enabled by default. This function demonstrates enabling the configured filters for the selected
channel. Once enabled, all incoming messages will need to pass the acceptance filtering logic in order to be
received on the channel and put on the Rx FIFO.
*/
/**************************************************************************************************************/
static void CAN_EnableFilters()
{
   nai_status_t status;

   if (!checkChannelNumber(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber))
      return;

   status = naibrd_AR_CAN_EnableAcceptFilters(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, TRUE /*Enable*/);

   if (NAI_SUCCESS == status)
      printf("Filters are now enabled for channel: %d\r\n", userInput.nChannelNumber);
   else
   {
      printf("ERROR: naibrd_AR_CAN_EnableAcceptFilters returned status: %d\r\n", status);
   }
}

/**************************************************************************************************************/
/** \ingroup AR-CAN_BasicOps
This function disables all filters for the specified channel.
NOTE: Filters that were configured are not removed, they are just disabled thus allowing all incoming messages
to be put on the Rx FIFO.
*/
/**************************************************************************************************************/
static void CAN_DisableFilters()
{
   nai_status_t status;

   if (!checkChannelNumber(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber))
      return;

   status = naibrd_AR_CAN_EnableAcceptFilters(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, FALSE /*Disable*/);

   if (NAI_SUCCESS == status)
      printf("Filters are now disabled for channel: %d\r\n", userInput.nChannelNumber);
   else
   {
      printf("ERROR: naibrd_AR_CAN_EnableAcceptFilters returned status: %d\r\n", status);
   }
}

/**************************************************************************************************************/
/** \ingroup AR-CAN_BasicOps
This function clears the Tx FIFO of any data. Clearing of the Tx FIFO is not typically needed but can be
useful in error recovery instead of forcing a channel reset if expected activity is not taking place.
*/
/**************************************************************************************************************/
static void CAN_ResetTxFIFO()
{
   nai_status_t status;
   int32_t fifoCount = 0;

   if (!checkChannelNumber(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber))
      return;

   status = naibrd_AR_CAN_GetTxFIFOCount(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, &fifoCount);
   if (NAI_SUCCESS == status)
   {
      printf("Tx FIFO Count before reset: %d\r\n", fifoCount);

      status = naibrd_AR_CAN_ResetTxFifo(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber);
      if (NAI_SUCCESS == status)
      {
         printf("Tx FIFO was reset for chan %d!\r\n", userInput.nChannelNumber);

         status = naibrd_AR_CAN_GetTxFIFOCount(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, &fifoCount);
         if (NAI_SUCCESS == status)
            printf("Tx FIFO Count after reset: %d\r\n", fifoCount);
         else
            printf("ERROR: naibrd_AR_CAN_GetTxFIFOCount reported status: %d\r\n", status);
      }
      else
      {
         printf("ERROR: naibrd_AR_CAN_ResetTxFifo reported status: %d\r\n", status);
      }
   }
   else
   {
      printf("ERROR: naibrd_AR_CAN_GetTxFIFOCount reported status: %d\r\n", status);
   }
}

/**************************************************************************************************************/
/** \ingroup AR-CAN_BasicOps
This function clears the Rx FIFO of any data. Clearing of the Rx FIFO is not typically needed but can be
useful in error recovery instead of forcing a channel reset if expected activity is not taking place.
*/
/**************************************************************************************************************/
static void CAN_ResetRxFIFO()
{
   nai_status_t status;
   int32_t fifoCount;

   if (!checkChannelNumber(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber))
      return;

   status = naibrd_AR_CAN_GetRxFIFOCount(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, &fifoCount);
   if (NAI_SUCCESS == status)
   {
      printf("Rx FIFO Count before reset: %d\r\n", fifoCount);

      status = naibrd_AR_CAN_ResetRxFifo(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber);
      if (NAI_SUCCESS == status)
      {
         printf("Rx FIFO was reset for chan %d!\r\n", userInput.nChannelNumber);

         status = naibrd_AR_CAN_GetRxFIFOCount(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, &fifoCount);
         if (NAI_SUCCESS == status)
            printf("Rx FIFO Count after reset: %d\r\n", fifoCount);
         else
            printf("ERROR: naibrd_AR_CAN_GetRxFIFOCount reported status: %d\r\n", status);
      }
      else
      {
         printf("ERROR: naibrd_AR_CAN_ResetRxFifo reported status: %d\r\n", status);
      }
   }
   else
   {
      printf("ERROR: naibrd_AR_CAN_GetRxFIFOCount reported status: %d\r\n", status);
   }
}

/**************************************************************************************************************/
/** \ingroup AR-CAN_BasicOps
By default, each channel's Tx capability is disabled. This function demonstrates how to enable Tx for the
selected channel.
*/
/**************************************************************************************************************/
static void CAN_EnableTx()
{
   nai_status_t status;

   if (!checkChannelNumber(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber))
      return;

   status = naibrd_AR_CAN_SetTxEnable(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, TRUE);
   if (NAI_SUCCESS == status)
   {
      printf("Tx was enabled for chan %d!\r\n", userInput.nChannelNumber);
   }
   else
   {
      printf("ERROR: naibrd_AR_CAN_SetTxEnable reported status: %d\r\n", status);
   }
}

/**************************************************************************************************************/
/** \ingroup AR-CAN_BasicOps
This function allows a caller to disable Tx for the specified channel. Disabling Tx may come in handy if a
user would like to queue up some messages in the Tx FIFO but not send them out right away. Disabling of Tx still
allows for messages to be placed on the Tx FIFO but there will be no attempt to send those messages on the bus
until the Tx is enabled.
*/
/**************************************************************************************************************/
static void CAN_DisableTx()
{
   nai_status_t status;

   if (!checkChannelNumber(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber))
      return;

   status = naibrd_AR_CAN_SetTxEnable(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, FALSE);
   if (NAI_SUCCESS == status)
   {
      printf("Tx was disabled for chan %d!\r\n", userInput.nChannelNumber);
   }
   else
   {
      printf("ERROR: naibrd_AR_CAN_SetTxEnable reported status: %d\r\n", status);
   }
}

/**************************************************************************************************************/
/** \ingroup AR-CAN_BasicOps
Everytime the AR-CAN module receives a message off of the bus but does not have any more room in its Rx FIFO
to put the entire message, the message will be dropped. Each time a message is dropped, a counter is incremented
in case an interested party would like to know how many dropped messages were made. This function will reset
that drop counter back to zero.
*/
/**************************************************************************************************************/
static void CAN_ResetDropCount()
{
   nai_status_t status;
   int32_t dropCount = 0;

   if (!checkChannelNumber(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber))
      return;

   status = naibrd_AR_CAN_GetDropCount(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, &dropCount);
   if (NAI_SUCCESS == status)
   {
      printf("Drop Count before reset is: %d\r\n", dropCount);
      status = naibrd_AR_CAN_ResetDropCount(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber);
      if (NAI_SUCCESS == status)
      {
         printf("Reset Drop Count was executed for chan %d!\r\n", userInput.nChannelNumber);

         status = naibrd_AR_CAN_GetDropCount(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, &dropCount);
         if (NAI_SUCCESS == status)
            printf("Drop Count after reset is now: %d\r\n", dropCount);
         else
            printf("ERROR: naibrd_AR_CAN_GetDropCount reported status: %d\r\n", status);
      }
      else
      {
         printf("ERROR: naibrd_AR_CAN_ResetDropCount reported status: %d\r\n", status);
      }
   }
   else
   {
      printf("ERROR: naibrd_AR_CAN_GetDropCount reported status: %d\r\n", status);
   }
}

/**************************************************************************************************************/
/** \ingroup AR-CAN_BasicOps
This function provides some diagnostic insight. It is responsible for retrieving and displaying information
about each of the FIFOs, the drop count as well as the error count. FIFO information include current FIFO Count
which is the number of entries found in the FIFO as well as FIFO Frame Count which is the number of full CAN
messages detected on the FIFO.
*/
/**************************************************************************************************************/
static void CAN_DisplayCounts()
{
   nai_status_t status;
   int32_t txFIFOCount = 0;
   int32_t txFIFOFrameCount = 0;
   int32_t rxFIFOCount = 0;
   int32_t rxFIFOFrameCount = 0;
   int32_t dropCount = 0;
   int32_t errorCount = 0;

   if (!checkChannelNumber(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber))
      return;

   /* Retrieve counts for Tx FIFO count, Tx FIFO Frame count, Rx FIFO count, Rx FIFO Frame count and Drop Count */
   status = naibrd_AR_CAN_GetTxFIFOCount(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, &txFIFOCount);
   if (NAI_SUCCESS != status)
   {
      errorCount++;
      printf("ERROR: naibrd_AR_CAN_GetTxFIFOCount reported status: %d for chan %d\r\n", status, userInput.nChannelNumber);
   }

   status = naibrd_AR_CAN_GetTxFIFOFrameCount(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, &txFIFOFrameCount);
   if (NAI_SUCCESS != status)
   {
      errorCount++;
      printf("ERROR: naibrd_AR_CAN_GetTxFIFOFrameCount reported status: %d for chan %d\r\n", status, userInput.nChannelNumber);
   }

   status = naibrd_AR_CAN_GetRxFIFOCount(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, &rxFIFOCount);
   if (NAI_SUCCESS != status)
   {
      errorCount++;
      printf("ERROR: naibrd_AR_CAN_GetRxFIFOCount reported status: %d for chan %d\r\n", status, userInput.nChannelNumber);
   }

   status = naibrd_AR_CAN_GetRxFIFOFrameCount(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, &rxFIFOFrameCount);
   if (NAI_SUCCESS != status)
   {
      errorCount++;
      printf("ERROR: naibrd_AR_CAN_GetRxFIFOFrameCount reported status: %d for chan %d\r\n", status, userInput.nChannelNumber);
   }

   status = naibrd_AR_CAN_GetDropCount(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, &dropCount);
   if (NAI_SUCCESS != status)
   {
      errorCount++;
      printf("ERROR: naibrd_AR_CAN_GetDropCount reported status: %d for chan %d\r\n", status, userInput.nChannelNumber);
   }

   printf("-----------------------------------------------------------------\r\n");
   printf("Counts for Channel %d\r\n", userInput.nChannelNumber);
   printf("TxFIFOCount:      %d\r\n", txFIFOCount);
   printf("TxFIFOFrameCount: %d\r\n", txFIFOFrameCount);
   printf("RxFIFOCount:      %d\r\n", rxFIFOCount);
   printf("RxFIFOFrameCount: %d\r\n", rxFIFOFrameCount);
   printf("NUMBER OF ERRORS RETRIEVING COUNTS: %d\r\n", errorCount);
   printf("-----------------------------------------------------------------\r\n");
}

/**************************************************************************************************************/
/** \ingroup AR-CAN_BasicOps
Internal function that merely checks to see if the specified channel number is within range of what is expected
for the given module.
*/
/**************************************************************************************************************/
static bool_t checkChannelNumber(int32_t card, int32_t mod, int32_t chan)
{
   bool_t validChannel = TRUE;

   if (chan < 1 || chan > naibrd_AR_CAN_GetChannelCountForModule(card, mod))
   {
      validChannel = FALSE;
      printf("ERROR: Invalid channel number detected: %d\r\n", chan);
      printf("Try setting the desired channel before calling this function by invoking the Set Channel menu item\r\n");
   }

   return validChannel;
}

Help Bot

X