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

CAN Interactive

CAN Interactive

Explanation

About the CAN Transmit Interactive Program

This program is a sample application from North Atlantic Industries designed to interact with their embedded function modules using their Software Support Kit (SSK). Specifically, it facilitates the configuration and transmission of CAN (Controller Area Network) messages. Below is a detailed explanation of the code.

Header Files The program starts by including necessary header files:

  • Standard Libraries: <stdio.h>, <stdlib.h>, <string.h>, <time.h> for basic input/output, memory management, string manipulation, and time functions.

  • Conditional Includes: Based on platform:

  • LINUX and VXWORKS Headers: Libraries for pthreads and socket operations.

  • CAN Transmit and NAI Headers: Specific headers for interacting with the CAN modules and NAI board access.

Constants and Macros Several constants and macros are defined for default configurations and module settings: - Default Indices and Channels: Defaults for CAN card, module, and transmit channels. - CAN Modules and Control Indicators: Values for indicating all modules and default modules.

Global Variables and Structures The main structures and global variables used in the application are defined: - CONFIG_FILE: The default configuration file name. - _userInput: A structure to store user inputs for CAN configuration such as acceptance mask/code, delays, repeat flags, and data. - Function Pointers: Arrays of function pointers (canDemofunc_cmdtbl and canDemofuncChannel_cmdtbl) for command and function mapping.

Function Prototypes Prototype definitions for the various static functions this application uses to handle CAN transmission, configuration, and user interaction are listed.

Enumerations Command enumerations are provided to facilitate command-based user interaction for CAN single and multi-transmission modes as well as configuration submenus.

Main Program Logic The main function (or CAN_Transmit_Interactive in VXWORKS) is the entry point. It runs a board menu, queries the user for card and module indices, and then invokes related CAN transmission tasks.

Key Functions - Run_CAN_TransmitByChoice: Handles the main interaction loop for the user to choose between single and multi-transmit modes. - CAN_SetSingleXmit: Presents the user with single transmit mode options. - CAN_SetMultiXmit: Presents the user with multi-transmit mode options. - CAN_SingleXmitConfig: Allows the single transmit configuration. - CAN_SingleXmitRun: Executes the single transmit operation based on user configurations. - CAN_MultiXmitConfig: Allows multi-transmit configuration. - CAN_MulitXmitRun: Placeholder for multi-transmit run functionality. - Show Functions: These functions show commands and configuration options to the user (Show_CanDemoFunc_Commands, etc.). - Configuration Functions: Functions to set various CAN configurations like CAN_SetModule, CAN_SetChan, CAN_SetPreScaler, and CAN_SetDataPatternEnable. - Transmission and Helper Functions: Helper functions for transmission like fillTxBuffer, fireMessage, fireJ1939Message, and displaying results (Show_TxResult).

User Interaction The program’s primary interaction with the user is through a console interface, prompting for various configuration inputs and presenting command menus to guide the user through setting up and executing CAN transmissions.

Conclusion This sample application provides a comprehensive demonstration of configuring and interacting with CAN modules using North Atlantic Industries hardware and software support kit, illustrating the process from initialization, user interaction, configuration, and execution of CAN messaging tasks.

Important Considerations - Threading: The application uses threading for continuous monitoring of CAN Rx FIFO Buffers. - Platform Specific Operations: Different functions and methodologies applied for Windows, Linux, and VXWORKS platforms, ensuring comprehensive coverage.

This detailed commentary guides you through each section of the code, providing context and explanations for each component, aiding understanding and ease of use.

#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
/*Specified to CAN Transmit*/
#include "CAN_Interactive.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"

/* Common CAN Sample Program include files */
#include "nai_can_cfg.h"

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

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

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

#define CAN_ALL_MODULES_INDICATOR          0
#define CAN_DEFAULT_MODULE                 1

static struct _userInput
{
   uint32_t nAcceptanceMask;
   uint32_t nAcceptanceCode;
   uint32_t nDelay_Ms;
   uint8_t nRepeat;
   uint8_t nUseDataPattern;
   int32_t nCardIdx;
   int32_t nModuleNumber;
   int32_t nChannelNumber;
   int32_t nP6ChanNumber;
   int32_t nPreScaler;
   int32_t nSJW;
   int32_t nModeAB;
   int32_t nTseg1;
   int32_t nTseg2;
   int32_t nData;
   int32_t nDataLength;
   int32_t nLoopCount;
   int32_t nIncrement;
   int32_t nMsgNumber;
   int32_t nRealTimeMsgNum;
   uint16_t nCtrlWord;
   int8_t n8UserThreadEscapeKey;
   int32_t nRxMsgCounter;
   union
   {
      uint16_t n16DataArray;
      struct
      {
         uint8_t loByte;
         uint8_t hiByte;
      } nBytes;
   } nDataArray[4];
}userInput;

/****** static function *******/
static void CAN_SetSingleXmit();
static void CAN_SetMultiXmit();
static void Run_CAN_TransmitByChoice();
static void Show_CanDemoFunc_Commands();
static void Show_CanSingleXmitFunc_Commands();
static void Show_CanMultiXmitFunc_Commands();
static void CAN_SingleXmitConfig();
static void CAN_SingleXmitRun();
static void CAN_MultiXmitConfig();
static void CAN_MulitXmitRun();
static void CAN_SetModule();
static void CAN_SetChan();
static void CAN_SetPreScaler();
static void CAN_SetSJW();
static void CAN_SetModeAB();
static void CAN_SetTseg1();
static void CAN_SetTseg2();
static void CAN_SetData();
static void CAN_SetDataPattern();
static void Show_CanSingleXmitConfigSubMenuFunc_Commands();
static void Show_CanMultiXmitConfigSubMenuFunc_Commands();
static void CAN_SetDataLength();
static void CAN_SetMessageNumber();
static void CAN_SetDataLoopCount();
static void CAN_SetIncrement();
static void Show_CanConfiguration();
static void fillTxBuffer(uint8_t *u8Buffer);
static void Show_TxResult();
static void setCanBitTiming();
static void setCanControlRegister();
static void CAN_SetDataPatternEnable();
static void CAN_SetDelay();
static void CAN_SetLoopEnable();
static void fireMessage(int32_t, int32_t, bool_t, uint8_t*);
static void fireJ1939Message(int32_t, int32_t, uint8_t*);
static void CAN_SetCtrlWord();
static uint16_t constructCanCtrlWord(const char*, uint8_t);
static uint32_t calcBaudRate(uint32_t unPreScaler, uint32_t unSJW, uint32_t unSetupTime, uint32_t unHoldTime);
static void CAN_SetAccMask();
static void CAN_SetAccCode();
static void CAN_Listen();
static void showRxData();
static uint32_t tcpTx(uint8_t *MsgBuf, int32_t MsgLeg);
static void basicReadWrite();
static void testEthernetTx();
static void testTxRx();
static void testTxMultiChan();
static void applyToAllCANChan();

/****** Command Table *******/
enum canFunc_MainMenuCommands
{
   CAN_FUNC_CMD_SINGLE_XMIT_MMENU,
   CAN_FUNC_CMD_MULTI_XMIT_MMENU,
   CAN_FUNC_CMD_COUNT
};

enum canFunc_singleXmitCommands
{
   CAN_FUNC_CMD_SINGLE_XMIT_MMENU_CONFIG,
   CAN_FUNC_CMD_SINGLE_XMIT_MMENU_RUN,
   CAN_FUNC_CMD_SINGLE_XMIT_MMENU_COUNT
};

enum canFunc_MultiXmitCommands
{
   CAN_FUNC_CMD_MULTI_XMIT_MMENU_CONFIG,
   CAN_FUNC_CMD_MULTI_XMIT_MMENU_RUN,
   CAN_FUNC_CMD_MULTI_XMIT_MMENU_COUNT
};

enum canFunc_singleXmitConfigSubMenuCommands
{
   CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_MODULE,
   CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_CHAN,
   CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_PRESCALER,
   CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_SJW,
   CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_MODE_AB,
   CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_TSEG1,
   CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_TSEG2,
   CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_CTRL_WORD,
   CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_ACC_MASK,
   CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_ACC_CODE,
   CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_DATA,
   CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_DATA_PATTERN,
   CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_DATA_LENGTH,
   CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_MSG_NUMBER,
   CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_USE_DATA_PATTERN,
   CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_SET_DELAY,
   CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_SET_LOOP_ENABLE,
   CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_SET_LOOP_COUNT,
   CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_LISTEN,
   CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_RW,
   CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_TX,
   CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_ETHERNET_TX,
   CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_TX_RX,
   CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_TX_MULTI_CHAN,
   CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_COPY_ALL_CHAN,
   CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_COUNT
};

enum canFunc_multiXmitConfigSubMenuCommands
{
   CAN_FUNC_CMD_MULTI_XMIT_CONFIG_SUBMENU_MODULE,
   CAN_FUNC_CMD_MULTI_XMIT_CONFIG_SUBMENU_CHAN,
   CAN_FUNC_CMD_MULTI_XMIT_CONFIG_SUBMENU_PRESCALER,
   CAN_FUNC_CMD_MULTI_XMIT_CONFIG_SUBMENU_SJW,
   CAN_FUNC_CMD_MULTI_XMIT_CONFIG_SUBMENU_MODE_AB,
   CAN_FUNC_CMD_MULTI_XMIT_CONFIG_SUBMENU_TSEG1,
   CAN_FUNC_CMD_MULTI_XMIT_CONFIG_SUBMENU_TSEG2,
   CAN_FUNC_CMD_MULTI_XMIT_CONFIG_SUBMENU_DATA,
   CAN_FUNC_CMD_MULTI_XMIT_CONFIG_SUBMENU_DATA_LENGTH,
   CAN_FUNC_CMD_MULTI_XMIT_CONFIG_SUBMENU_LOOP_COUNT,
   CAN_FUNC_CMD_MULTI_XMIT_CONFIG_SUBMENU_INCREMENT,
   CAN_FUNC_CMD_MULTI_XMIT_CONFIG_SUBMENU_MSG_NUMBER,
   CAN_FUNC_CMD_MULTI_XMIT_CONFIG_SUBMENU_COUNT
};

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

struct canDemofuncChannel_cmdtbl {
   int8_t *cmdstr;
   int8_t *menustr;
   int32_t  cmdnum;
   void(*func)(int32_t cardIndex, int32_t module, int32_t channel);
};

/****** Command Tables *******/
static struct canDemofunc_cmdtbl CAN_DemoFuncMenuCmds[] = {
   {(int8_t *)"S",   (int8_t *)"Single Xmit",          CAN_FUNC_CMD_SINGLE_XMIT_MMENU,			 CAN_SetSingleXmit},\
   {(int8_t *)"M ",	(int8_t *)"Multi Xmit",           CAN_FUNC_CMD_MULTI_XMIT_MMENU,         CAN_SetMultiXmit},\
   {NULL,            NULL,                             0,                               NULL}
};

static struct canDemofunc_cmdtbl CAN_SingleXmitFuncMenuCmds[] = {
   {(int8_t *)"C",   (int8_t *)"CAN Configuration",    CAN_FUNC_CMD_SINGLE_XMIT_MMENU_CONFIG,	  CAN_SingleXmitConfig},\
   {(int8_t *)"R ",	(int8_t *)"Run",                  CAN_FUNC_CMD_SINGLE_XMIT_MMENU_RUN,         CAN_SingleXmitRun},\
   {NULL,            NULL,                             0,                               NULL}
};

static struct canDemofunc_cmdtbl CAN_MultiXmitFuncMenuCmds[] = {
   {(int8_t *)"C",   (int8_t *)"CAN Configuration",    CAN_FUNC_CMD_MULTI_XMIT_MMENU_CONFIG,	  CAN_MultiXmitConfig},\
   {(int8_t *)"R ",	(int8_t *)"Run",                 CAN_FUNC_CMD_MULTI_XMIT_MMENU_RUN,         CAN_MulitXmitRun},\
   {NULL,            NULL,                             0,                               NULL}
};

static struct canDemofunc_cmdtbl CAN_SingleXmitConfigSubMenuCmds[] = {
   {(int8_t *)"M",   (int8_t *)"Select Module",       CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_MODULE,	            CAN_SetModule},\
   {(int8_t *)"C ",	(int8_t *)"Select Channel",      CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_CHAN,                CAN_SetChan},\
   {(int8_t *)"P ",	(int8_t *)"Prescaler",           CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_PRESCALER,           CAN_SetPreScaler},\
   {(int8_t *)"S ",	(int8_t *)"Sync Jump Width",     CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_SJW,                 CAN_SetSJW},\
   {(int8_t *)"AB ",	(int8_t *)"Mode A/B",            CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_MODE_AB,             CAN_SetModeAB},\
   {(int8_t *)"O",	(int8_t *)"T-Seg 1",             CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_TSEG1,               CAN_SetTseg1},\
   {(int8_t *)"T",	(int8_t *)"T-Seg 2",             CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_TSEG2,               CAN_SetTseg2},\
   {(int8_t *)"CW",	(int8_t *)"Ctrl Word",           CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_CTRL_WORD,           CAN_SetCtrlWord},\
   {(int8_t *)"AM",	(int8_t *)"Acceptance Mask",     CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_ACC_MASK,            CAN_SetAccMask},\
   {(int8_t *)"AC",	(int8_t *)"Acceptance Code",     CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_ACC_CODE,            CAN_SetAccCode},\
   {(int8_t *)"D",	(int8_t *)"Data",                CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_DATA,                CAN_SetData},\
   {(int8_t *)"DP",	(int8_t *)"Data Pattern",        CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_DATA_PATTERN,        CAN_SetDataPattern},\
   {(int8_t *)"L",	(int8_t *)"Data Length",         CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_DATA_LENGTH,         CAN_SetDataLength},\
   {(int8_t *)"N",	(int8_t *)"Message Number",      CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_MSG_NUMBER,          CAN_SetMessageNumber},\
   {(int8_t *)"UDP",	(int8_t *)"Use Data Pattern",    CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_USE_DATA_PATTERN,    CAN_SetDataPatternEnable},\
   {(int8_t *)"DLY",	(int8_t *)"Delay Between Tx",    CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_SET_DELAY,           CAN_SetDelay},\
   {(int8_t *)"LOOP", (int8_t *)"Enable Loop",        CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_SET_LOOP_ENABLE,     CAN_SetLoopEnable},\
   {(int8_t *)"LC",	(int8_t *)"Loop Counts",         CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_SET_LOOP_COUNT,      CAN_SetDataLoopCount},\
   {(int8_t *)"RX",	(int8_t *)"Listen",              CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_LISTEN,              CAN_Listen},\
   {(int8_t *)"RW",	(int8_t *)"Read/Write",          CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_RW,                  basicReadWrite},\
   {(int8_t *)"X",	(int8_t *)"Transmit",            CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_TX,                  CAN_SingleXmitRun},\
   {(int8_t *)"ETH", (int8_t *)"Eth Tx",              CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_ETHERNET_TX,         testEthernetTx},\
   {(int8_t *)"XR", (int8_t *)"Transmit and Receive", CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_TX_RX,               testTxRx},\
   {(int8_t *)"XM", (int8_t *)"Tx Multiple Chan ",    CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_TX_MULTI_CHAN,       testTxMultiChan},\
   {(int8_t *)"COPY", (int8_t *)"Copy To All Chan ",  CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_COPY_ALL_CHAN,       applyToAllCANChan},\
   {NULL,            NULL,                            0,                               NULL}
};

static struct canDemofunc_cmdtbl CAN_MultiXmitConfigSubMenuCmds[] = {
   {(int8_t *)"M",   (int8_t *)"Select Module",       CAN_FUNC_CMD_MULTI_XMIT_CONFIG_SUBMENU_MODULE,	      CAN_SetModule},\
   {(int8_t *)"C ",	(int8_t *)"Select Channel",      CAN_FUNC_CMD_MULTI_XMIT_CONFIG_SUBMENU_CHAN,          CAN_SetChan},\
   {(int8_t *)"P ",	(int8_t *)"Prescaler",           CAN_FUNC_CMD_MULTI_XMIT_CONFIG_SUBMENU_PRESCALER,     CAN_SetPreScaler},\
   {(int8_t *)"S ",	(int8_t *)"Sync Jump Width",     CAN_FUNC_CMD_MULTI_XMIT_CONFIG_SUBMENU_SJW,           CAN_SetSJW},\
   {(int8_t *)"AB ",	(int8_t *)"Mode A/B",            CAN_FUNC_CMD_MULTI_XMIT_CONFIG_SUBMENU_MODE_AB,       CAN_SetModeAB},\
   {(int8_t *)"O",	(int8_t *)"T-Seg 1",             CAN_FUNC_CMD_MULTI_XMIT_CONFIG_SUBMENU_TSEG1,         CAN_SetTseg1},\
   {(int8_t *)"T",	(int8_t *)"T-Seg 2",             CAN_FUNC_CMD_MULTI_XMIT_CONFIG_SUBMENU_TSEG2,         CAN_SetTseg2},\
   {(int8_t *)"D",	(int8_t *)"Data",                CAN_FUNC_CMD_MULTI_XMIT_CONFIG_SUBMENU_DATA,          CAN_SetData},\
   {(int8_t *)"DL",	(int8_t *)"Data Length",         CAN_FUNC_CMD_MULTI_XMIT_CONFIG_SUBMENU_DATA_LENGTH,   CAN_SetDataLength},\
   {(int8_t *)"L",	(int8_t *)"Loop Counts",         CAN_FUNC_CMD_MULTI_XMIT_CONFIG_SUBMENU_LOOP_COUNT,    CAN_SetDataLoopCount},\
   {(int8_t *)"I",	(int8_t *)"Increment Step",      CAN_FUNC_CMD_MULTI_XMIT_CONFIG_SUBMENU_INCREMENT,     CAN_SetIncrement},\
   {(int8_t *)"N",	(int8_t *)"Message Number",      CAN_FUNC_CMD_MULTI_XMIT_CONFIG_SUBMENU_MSG_NUMBER,    CAN_SetMessageNumber},\
   {NULL,            NULL,                            0,                               NULL}
};

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

/**************************************************************************************************************/
/**
<summary>
CAN_Transmit_Interactive illustrates the following:

</summary>
*/
/**************************************************************************************************************/
#if defined (__VXWORKS__)
int32_t CAN_Transmit_Interactive(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_TransmitByChoice();
            }
         }

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

void Run_CAN_TransmitByChoice(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_SINGLE_XMIT_MMENU:
               CAN_SetSingleXmit();
               break;

            case CAN_FUNC_CMD_MULTI_XMIT_MMENU:
               CAN_SetMultiXmit();
               break;

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

   if (bQuit)
      globalQuit = TRUE;

   return;
}

static void Show_CanDemoFunc_Commands(void)
{
   int i;
   printf("\n\t\t Can Transmit Demo Program.");
   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");
}

static void Show_CanSingleXmitFunc_Commands(void)
{
   int i;
   printf("\n\t\t CAN Single Transmit Demo Program.");
   printf("\n\t\t =================================\n");
   printf("\n\nCommands");
   printf("\n--------");
   for (i = 0; i < CAN_FUNC_CMD_SINGLE_XMIT_MMENU_COUNT && CAN_SingleXmitFuncMenuCmds[i].cmdstr != NULL; i++)
      printf("\n%s\t%s", CAN_SingleXmitFuncMenuCmds[i].cmdstr, CAN_SingleXmitFuncMenuCmds[i].menustr);
   printf("\n");
}

static void Show_CanMultiXmitFunc_Commands(void)
{
   int i;
   printf("\n\t\t CAN Multi Transmit Demo Program.");
   printf("\n\t\t ================================\n");
   printf("\n\nCommands");
   printf("\n--------");
   for (i = 0; i < CAN_FUNC_CMD_MULTI_XMIT_MMENU_COUNT && CAN_MultiXmitFuncMenuCmds[i].cmdstr != NULL; i++)
      printf("\n%s\t%s", CAN_MultiXmitFuncMenuCmds[i].cmdstr, CAN_MultiXmitFuncMenuCmds[i].menustr);
   printf("\n");
}

static void Show_CanSingleXmitConfigSubMenuFunc_Commands(void)
{
   int i;
   printf("\n\t\t CAN Single Transmit Configuration Menu.");
   printf("\n\t\t =======================================\n");
   printf("\n\nCommands");
   printf("\n--------");
   for (i = 0; i < CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_COUNT && CAN_SingleXmitConfigSubMenuCmds[i].cmdstr != NULL; i++)
      printf("\n%s\t%s", CAN_SingleXmitConfigSubMenuCmds[i].cmdstr, CAN_SingleXmitConfigSubMenuCmds[i].menustr);
   printf("\n");
}

static void Show_CanMultiXmitConfigSubMenuFunc_Commands(void)
{
   int i;
   printf("\n\t\t CAN Multi Transmit Configuration Menu.");
   printf("\n\t\t ======================================\n");
   printf("\n\nCommands");
   printf("\n--------");
   for (i = 0; i < CAN_FUNC_CMD_MULTI_XMIT_CONFIG_SUBMENU_COUNT && CAN_MultiXmitConfigSubMenuCmds[i].cmdstr != NULL; i++)
      printf("\n%s\t%s", CAN_MultiXmitConfigSubMenuCmds[i].cmdstr, CAN_MultiXmitConfigSubMenuCmds[i].menustr);
   printf("\n");
}

static void CAN_SetSingleXmit()
{
   bool_t bQuit = FALSE;
   int32_t cmdIdx;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   do
   {
      if (globalQuit)
         break;

      Show_CanSingleXmitFunc_Commands();
      printf("\nType CAN Single Transmit 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_SINGLE_XMIT_MMENU_COUNT; cmdIdx++)
         {
            if (0 == naiapp_strnicmp((const int8_t*)inputBuffer, (const int8_t*)CAN_SingleXmitFuncMenuCmds[cmdIdx].cmdstr, inputResponseCnt))
               break;
         }
         switch (cmdIdx)
         {
            case CAN_FUNC_CMD_SINGLE_XMIT_MMENU_CONFIG:
               CAN_SingleXmitConfig();
               break;

            case CAN_FUNC_CMD_SINGLE_XMIT_MMENU_RUN:
               CAN_SingleXmitRun();
               break;

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

   if (bQuit)
      globalQuit = TRUE;

   return;

}
static void CAN_SetMultiXmit()
{
   bool_t bQuit = FALSE;
   int32_t cmdIdx;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   do
   {
      Show_CanMultiXmitFunc_Commands();
      printf("\nType CAN Multi Transmit 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_MULTI_XMIT_MMENU_COUNT; cmdIdx++)
         {
            if (0 == naiapp_strnicmp((const int8_t*)inputBuffer, (const int8_t*)CAN_MultiXmitFuncMenuCmds[cmdIdx].cmdstr, inputResponseCnt))
               break;
         }
         switch (cmdIdx)
         {
            case CAN_FUNC_CMD_MULTI_XMIT_MMENU_CONFIG:
               CAN_MultiXmitConfig();
               break;

            case CAN_FUNC_CMD_MULTI_XMIT_MMENU_RUN:
               CAN_MulitXmitRun();
               break;

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

static void CAN_SingleXmitConfig()
{
   bool_t bQuit = FALSE;
   int32_t cmdIdx;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   do
   {
      if (globalQuit)
         break;

      Show_CanSingleXmitConfigSubMenuFunc_Commands();
      printf("\nType CAN Single Transmit Configuration Selection 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_SINGLE_XMIT_SUBMENU_COUNT; cmdIdx++)
         {
            if (0 == naiapp_strnicmp((const int8_t*)inputBuffer, (const int8_t*)CAN_SingleXmitConfigSubMenuCmds[cmdIdx].cmdstr, inputResponseCnt))
               break;
         }
         switch (cmdIdx)
         {
            case CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_MODULE:
               CAN_SetModule();
               break;

            case CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_CHAN:
               CAN_SetChan();
               break;

            case CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_PRESCALER:
               CAN_SetPreScaler();
               break;

            case CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_SJW:
               CAN_SetSJW();
               break;

            case CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_MODE_AB:
               CAN_SetModeAB();
               break;

            case CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_TSEG1:
               CAN_SetTseg1();
               break;

            case CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_TSEG2:
               CAN_SetTseg2();
               break;

            case CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_DATA:
               CAN_SetData();
               break;

            case CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_DATA_PATTERN:
               CAN_SetDataPattern();
               break;

            case CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_DATA_LENGTH:
               CAN_SetDataLength();
               break;

            case CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_MSG_NUMBER:
               CAN_SetMessageNumber();
               break;

            case CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_USE_DATA_PATTERN:
               CAN_SetDataPatternEnable();
               break;

            case CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_SET_DELAY:
               CAN_SetDelay();
               break;

            case CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_SET_LOOP_ENABLE:
               CAN_SetLoopEnable();
               break;

            case CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_SET_LOOP_COUNT:
               CAN_SetDataLoopCount();
               break;

            case CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_CTRL_WORD:
               CAN_SetCtrlWord();
               break;

            case CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_ACC_MASK:
               CAN_SetAccMask();
               break;

            case CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_ACC_CODE:
               CAN_SetAccCode();
               break;

            case CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_LISTEN:
               setCanBitTiming(); /*write user input to module*/
               CAN_Listen();
               break;

            case CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_RW:
               setCanBitTiming(); /*write user input to module*/
               basicReadWrite();
               break;

            case CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_TX:
               setCanBitTiming(); /*write user input to module*/
               setCanControlRegister();
               CAN_SingleXmitRun();
               break;

            case CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_ETHERNET_TX:
               setCanBitTiming(); /*write user input to module*/
               setCanControlRegister();
               testEthernetTx();
               break;

            case CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_TX_RX:
               setCanBitTiming(); /*write user input to module*/
               setCanControlRegister();
               testTxRx();
               break;

            case CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_TX_MULTI_CHAN:
               setCanBitTiming(); /*write user input to module*/
               setCanControlRegister();
               testTxMultiChan();
               break;

            case CAN_FUNC_CMD_SINGLE_XMIT_SUBMENU_COPY_ALL_CHAN:
               applyToAllCANChan();
               break;

            default:
               break;
         }

      }
   } while (bQuit == FALSE);

   if (bQuit)
      globalQuit = TRUE;

   return;
}

static void CAN_SingleXmitRun()
{
   int32_t nTestLoopCountIdx = 0;
   bool_t is_CAN_A = FALSE;
   uint8_t u8Buffer[8];
   int32_t msgid = 0;
   int32_t activeModuleNumber = CAN_DEFAULT_MODULE;

   if (userInput.nModuleNumber != CAN_ALL_MODULES_INDICATOR)
      activeModuleNumber = userInput.nModuleNumber;

   Show_CanConfiguration();
   if (userInput.nModeAB == CAN_MODE_A)
      is_CAN_A = TRUE;

   /*   if(userInput.nMsgNumber == CAN_INCREMENT_AUTO)
         userInput.nRealTimeMsgNum++;
      msgid = userInput.nRealTimeMsgNum;
   */
   memset(u8Buffer, 0x0, sizeof(u8Buffer));
   fillTxBuffer(u8Buffer);
   if (userInput.nRepeat == NO)
   {
      if (userInput.nMsgNumber == CAN_INCREMENT_AUTO)
         userInput.nRealTimeMsgNum++;
      msgid = userInput.nRealTimeMsgNum;

      if (IsCAN_AB(userInput.nCardIdx, activeModuleNumber, 1))
         fireMessage(activeModuleNumber, msgid, is_CAN_A, u8Buffer);
      else if (IsCAN_J1939(userInput.nCardIdx, activeModuleNumber, 1))
         fireJ1939Message(activeModuleNumber, msgid, u8Buffer);
   }
   else
   {
      for (nTestLoopCountIdx = 0; nTestLoopCountIdx < userInput.nLoopCount; nTestLoopCountIdx++)
      {
         if (userInput.nMsgNumber == CAN_INCREMENT_AUTO)
         {
            msgid = userInput.nRealTimeMsgNum++;
         }

         if (IsCAN_AB(userInput.nCardIdx, activeModuleNumber, 1))
            fireMessage(activeModuleNumber, msgid, is_CAN_A, u8Buffer);
         else if (IsCAN_J1939(userInput.nCardIdx, activeModuleNumber, 1))
            fireJ1939Message(activeModuleNumber, msgid, u8Buffer);

         printf("\nLoop Count:%d", nTestLoopCountIdx + 1);

#if defined(WIN32) || defined(__VXWORKS__)
         nai_msDelay(userInput.nDelay_Ms);
#else
         usleep(userInput.nDelay_Ms * 1000);
#endif
      }
   }
   return;
}

static void CAN_MultiXmitConfig()
{
   bool_t bQuit = FALSE;
   int32_t cmdIdx;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   do
   {
      if (globalQuit)
         break;

      Show_CanMultiXmitConfigSubMenuFunc_Commands();
      printf("\nType CAN Multi Transmit Configuration Selection 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_MULTI_XMIT_CONFIG_SUBMENU_COUNT; cmdIdx++)
         {
            if (0 == naiapp_strnicmp((const int8_t*)inputBuffer, (const int8_t*)CAN_MultiXmitConfigSubMenuCmds[cmdIdx].cmdstr, inputResponseCnt))
               break;
         }
         switch (cmdIdx)
         {
            case CAN_FUNC_CMD_MULTI_XMIT_CONFIG_SUBMENU_MODULE:
               CAN_SetModule();
               break;

            case CAN_FUNC_CMD_MULTI_XMIT_CONFIG_SUBMENU_CHAN:
               CAN_SetChan();
               break;

            case CAN_FUNC_CMD_MULTI_XMIT_CONFIG_SUBMENU_PRESCALER:
               CAN_SetPreScaler();
               break;

            case CAN_FUNC_CMD_MULTI_XMIT_CONFIG_SUBMENU_SJW:
               CAN_SetSJW();
               break;

            case CAN_FUNC_CMD_MULTI_XMIT_CONFIG_SUBMENU_MODE_AB:
               CAN_SetModeAB();
               break;

            case CAN_FUNC_CMD_MULTI_XMIT_CONFIG_SUBMENU_TSEG1:
               CAN_SetTseg1();
               break;

            case CAN_FUNC_CMD_MULTI_XMIT_CONFIG_SUBMENU_TSEG2:
               CAN_SetTseg2();
               break;

            case CAN_FUNC_CMD_MULTI_XMIT_CONFIG_SUBMENU_DATA:
               CAN_SetData();
               break;

            case CAN_FUNC_CMD_MULTI_XMIT_CONFIG_SUBMENU_DATA_LENGTH:
               CAN_SetDataLength();
               break;

            case CAN_FUNC_CMD_MULTI_XMIT_CONFIG_SUBMENU_LOOP_COUNT:
               CAN_SetDataLoopCount();
               break;

            case CAN_FUNC_CMD_MULTI_XMIT_CONFIG_SUBMENU_INCREMENT:
               CAN_SetIncrement();
               break;

            case CAN_FUNC_CMD_MULTI_XMIT_CONFIG_SUBMENU_MSG_NUMBER:
               CAN_SetMessageNumber();
               break;

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

   if (bQuit)
      globalQuit = TRUE;

   return;
}

static void CAN_MulitXmitRun()
{
   return;
}

static void CAN_SetModule()
{
   bool_t bQuit = FALSE;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   printf("\nEnter <<Module>> Number or %c to quit [[default = 1]] Use '0' to denote ALL CHANNELS : ", NAI_QUIT_CHAR);
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if (!bQuit)
   {
      if (inputResponseCnt == 0)
         userInput.nModuleNumber = CAN_DEFAULT_MODULE;
      else
         userInput.nModuleNumber = atoi((const char *)inputBuffer);
   }
   return;
}
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);
   }
   userInput.nP6ChanNumber = userInput.nChannelNumber;
   return;
}
static void CAN_SetPreScaler()
{
   bool_t bQuit = FALSE;
   int32_t defaultPreScaler = PRESCALER_1MBit;
   int32_t activeModuleNumber = CAN_DEFAULT_MODULE;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;


   if (userInput.nModuleNumber != CAN_ALL_MODULES_INDICATOR)
      activeModuleNumber = userInput.nModuleNumber;

   if (IsCAN_J1939(userInput.nCardIdx, activeModuleNumber, 1))
      defaultPreScaler = PRESCALER_500K;

   printf("\nEnter CAN <<Pre-scaler>> or %c to quit [[default = 0x%02X]]: ", NAI_QUIT_CHAR, defaultPreScaler);
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if (!bQuit)
   {
      if (inputResponseCnt == 0)
         userInput.nPreScaler = defaultPreScaler;
      else
         userInput.nPreScaler = atoi((const char *)inputBuffer);
   }
   return;
}
static void CAN_SetSJW()
{
   bool_t bQuit = FALSE;
   int32_t defaultSJW = SJW_1MBit;
   int32_t activeModuleNumber = CAN_DEFAULT_MODULE;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;


   if (userInput.nModuleNumber != CAN_ALL_MODULES_INDICATOR)
      activeModuleNumber = userInput.nModuleNumber;

   if (IsCAN_J1939(userInput.nCardIdx, activeModuleNumber, 1))
      defaultSJW = SJW_500K;

   printf("\nEnter CAN <<SYNC Jump Width>> or %c to quit [[default = 0x%02X]]: ", NAI_QUIT_CHAR, defaultSJW);
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if (!bQuit)
   {
      if (inputResponseCnt == 0)
         userInput.nSJW = defaultSJW;
      else
         userInput.nSJW = atoi((const char *)inputBuffer);
   }
   return;
}
static void CAN_SetModeAB()
{
   bool_t bQuit = FALSE;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   printf("\nEnter CAN <<Mode A/B>> [A=0, B=1] or %c to quit [[default = A]]: ", NAI_QUIT_CHAR);
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if (!bQuit)
   {
      if (inputResponseCnt == 0)
         userInput.nModeAB = 0;
      else
         userInput.nModeAB = atoi((const char *)inputBuffer);
   }
   return;
}
static void CAN_SetTseg1()
{
   bool_t bQuit = FALSE;
   int32_t defaultTSEG1 = TSEG1_1MBit;
   int32_t activeModuleNumber = CAN_DEFAULT_MODULE;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   if (userInput.nModuleNumber != CAN_ALL_MODULES_INDICATOR)
      activeModuleNumber = userInput.nModuleNumber;

   if (IsCAN_J1939(userInput.nCardIdx, activeModuleNumber, 1))
      defaultTSEG1 = TSEG1_500K;

   printf("\nEnter CAN Setup Time <<T-Seg1>> or %c to quit [[default = 0x%02X]]: ", NAI_QUIT_CHAR, defaultTSEG1);
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if (!bQuit)
   {
      if (inputResponseCnt == 0)
         userInput.nTseg1 = defaultTSEG1;
      else
         userInput.nTseg1 = atoi((const char *)inputBuffer);
   }
   return;
}
static void CAN_SetTseg2()
{
   bool_t bQuit = FALSE;
   int32_t defaultTSEG2 = TSEG2_1MBit;
   int32_t activeModuleNumber = CAN_DEFAULT_MODULE;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   if (userInput.nModuleNumber != CAN_ALL_MODULES_INDICATOR)
      activeModuleNumber = userInput.nModuleNumber;

   if (IsCAN_J1939(userInput.nCardIdx, activeModuleNumber, 1))
      defaultTSEG2 = TSEG2_500K;

   printf("\nEnter CAN Hold Time <<T-Seg2>> or %c to quit [[default =  0x%02X]]: ", NAI_QUIT_CHAR, defaultTSEG2);
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if (!bQuit)
   {
      if (inputResponseCnt == 0)
         userInput.nTseg2 = defaultTSEG2;
      else
         userInput.nTseg2 = atoi((const char *)inputBuffer);
   }
   return;
}

static void CAN_SetData()
{
   bool_t bQuit = FALSE;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   printf("\nEnter CAN Transmit <<Data>> in Hex (one byte only) or %c to quit [[default = 0x0]]: ", NAI_QUIT_CHAR);
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if (!bQuit)
   {
      if (inputResponseCnt == 0)
         userInput.nData = 0;
      else
      {
         userInput.nData = naiapp_utils_HexStrToDecInt32((int8_t *)inputBuffer);
      }
   }
   return;
}

static void CAN_SetDataPattern()
{
   uint8_t uArrayCount = 0;
   uint8_t uCharDestCount = 0;
   uint8_t uCharSrcCount = 0;
   uint8_t uCharRemaining = 0;
   uint8_t u8SingleData[3];
   uint8_t u8Idx = 0;
   bool_t bQuit = FALSE;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   printf("\nEnter CAN Transmit <<Data Pattern>> in Hex (8 Bytes Max.) or %c to quit.  Enter data as 0102 => 01 02: ", NAI_QUIT_CHAR);
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);

   if (inputResponseCnt <= CAN_MAX_MODE_AB_DATA_LENGTH * 2)
   {
      uint16_t nActualData = 0;

      if (!bQuit)
      {
         if (inputResponseCnt == 0)
            userInput.nData = 0;
         else
         {
            uCharSrcCount = 0;
            for (u8Idx = 0; u8Idx < inputResponseCnt;)
            {
               uCharDestCount = 0;
               memset(u8SingleData, 0x0, sizeof(u8SingleData));
               uCharRemaining = (uint8_t)inputResponseCnt - u8Idx;
               uCharDestCount = 0;
               if (uCharRemaining >= 2)
               {
                  u8SingleData[uCharDestCount++] = inputBuffer[uCharSrcCount++];
                  u8SingleData[uCharDestCount++] = inputBuffer[uCharSrcCount++];
                  u8Idx += 2;
               }
               else
               {
                  u8SingleData[uCharDestCount++] = inputBuffer[uCharSrcCount++];
                  u8Idx++;
               }
               nActualData = (uint16_t)naiapp_utils_HexStrToDecInt32((int8_t *)u8SingleData);
               if (uArrayCount % 2 == 0)
                  userInput.nDataArray[uArrayCount / 2].nBytes.loByte = (uint8_t)nActualData;
               else
                  userInput.nDataArray[uArrayCount / 2].nBytes.hiByte = (uint8_t)nActualData;
               uArrayCount++;
            }
            userInput.nDataLength = uArrayCount;
         }
      }
   }
   else
      printf("\nCAN Transmit <<Data Pattern>> must be less than 8 Bytes");

   return;
}

static void CAN_SetDataLength()
{
   bool_t bQuit = FALSE;
   uint32_t nLength = 0;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   printf("\nEnter CAN Transmit <<Data Length>> (Data Length must be 8 bytes or less!) or %c to quit [[default = 0x1]]: ", NAI_QUIT_CHAR);
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if (!bQuit)
   {
      if (inputResponseCnt == 0)
         userInput.nDataLength = 1;
      else
      {
         nLength = atoi((const char *)inputBuffer);
         if ((nLength <= CAN_MAX_MODE_AB_DATA_LENGTH) && (nLength > CAN_DATA_LENGTH_ZERO))
         {
            userInput.nDataLength = nLength;
         }
         else
            printf("\nCAN Transmit <<Data Length>> Error.  Data Length Limit[1-8]");
      }
   }
   return;
}

static void CAN_SetDataLoopCount()
{
   bool_t bQuit = FALSE;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   printf("\nEnter CAN Transmit <<Loop Count>> or %c to quit [[default = 0x1]]: ", NAI_QUIT_CHAR);
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if (!bQuit)
   {
      if (inputResponseCnt == 0)
         userInput.nLoopCount = 1;
      else
         userInput.nLoopCount = atoi((const char *)inputBuffer);
   }
   return;
}
static void CAN_SetIncrement()
{
   bool_t bQuit = FALSE;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

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

static void Show_CanConfiguration()
{
   nai_can_ctrl_t can_ctrl = 0;
   int32_t        nValue = 0;
   int32_t        nValue2 = 0;
   int32_t        nValue3 = 0;
   int32_t        nValue4 = 0;
   int32_t        activeModuleNumber = CAN_DEFAULT_MODULE;

   if (userInput.nModuleNumber != CAN_ALL_MODULES_INDICATOR)
      activeModuleNumber = userInput.nModuleNumber;

   printf("\nModule      Channel     Mode A/B    Ctrl Word   Acceptance  Acceptance  Prescaler   SJW         TSeg1       TSeg2       Baud Rate   Tx FIFO     Rx FIFO     ");
   printf("\n                                                  Mask        Code                                                                   Count       Count      ");
   printf("\n----------  ----------  ----------  ----------  ----------  ----------  ----------  ----------  ----------  ----------  ----------  ----------  ----------\n");
   /*Module*/
   printf("%-12d", activeModuleNumber);
   /*Channel*/
   printf("%-12d", userInput.nChannelNumber);
   /*Mode A/B*/
   if (userInput.nModeAB == 0)
      printf("%-12s", "A");
   else
      printf("%-12s", "B");
   /*Ctrl Word */
   check_status(naibrd_CAN_GetControlRaw(userInput.nCardIdx, activeModuleNumber, userInput.nChannelNumber, &can_ctrl));
   printf("0x%-10x", can_ctrl);
   /*Acceptance Mask */
   check_status(naibrd_CAN_GetAcceptMask(userInput.nCardIdx, activeModuleNumber, userInput.nChannelNumber, DEF_ACCEPTANCE_FILTER, &nValue));
   printf("0x%-10x", nValue);
   /*Acceptance Code */
   check_status(naibrd_CAN_GetAcceptCode(userInput.nCardIdx, activeModuleNumber, userInput.nChannelNumber, DEF_ACCEPTANCE_FILTER, &nValue));
   printf("0x%-10x", nValue);
   /*Prescaler */
   /* NAIBRDFUNC nai_status_t NAIAPI naibrd_CAN_GetBitTiming( int32_t cardIndex, int32_t module, int32_t channel, int32_t* outprescaler, int32_t* outSJW, int32_t* outtseg1, int32_t* outtseg2 ); */
   check_status(naibrd_CAN_GetBitTiming(userInput.nCardIdx, activeModuleNumber, userInput.nChannelNumber, &nValue, &nValue2, &nValue3, &nValue4));
   printf("0x%-10x", nValue);
   /*SJW */
   printf("0x%-10x", nValue2);
   /*Setup Time TSeg1 */
   printf("0x%-10x", nValue3);
   /*Hold Time TSeg2 */
   printf("0x%-10x", nValue4);
   /*Baud Rate */
   nValue = calcBaudRate(nValue, nValue2, nValue3, nValue4);
   printf("%-12d", nValue);
   /*Tx FIFO Count */
   check_status(naibrd_CAN_GetTxBufferCount(userInput.nCardIdx, activeModuleNumber, userInput.nChannelNumber, &nValue));
   printf("0x%-10d", nValue);
   /*Rx FIFO Count */
   check_status(naibrd_CAN_GetRxBufferCount(userInput.nCardIdx, activeModuleNumber, userInput.nChannelNumber, &nValue));
   printf("0x%-10d", nValue);
   printf("\n");
}

static void Show_TxResult()
{
   int32_t   moduleIdx = 0;
   uint8_t   u8ChanIdx = 0;
   uint8_t   u8Channel = 0;
   int32_t   nValue = 0;
   int32_t   nValue2 = 0;
   uint8_t   u8Value = 0;
   int32_t   startModuleIdx = 0;
   int32_t   endModuleIdx = g_moduleCount;
   int32_t   activeModuleNumber = 0;
   int32_t   maxChannels = 0;

   printf("\n\n\nSingle Data Transmission Result.\n");
   printf("=========================================================================================================================");
   printf("\nModule      Channel     Tx FIFO     Tx Frame    Rx FIFO     Rx Frame    Error       Error      Error       Error         ");
   printf("\n                        Count       Count       Count       Count       Code        Pass./Act. Cnt Tx      Cnt Rx        ");
   printf("\n----------  ----------  ----------  ----------  ----------  ----------  ----------  ---------- ----------  ----------  \n");

   if (userInput.nModuleNumber != CAN_ALL_MODULES_INDICATOR)
   {
      startModuleIdx = (userInput.nModuleNumber - 1);
      endModuleIdx = userInput.nModuleNumber;
   }

   for (moduleIdx = startModuleIdx; moduleIdx < endModuleIdx; moduleIdx++)
   {
      activeModuleNumber = (moduleIdx + 1);
      if (!IsCAN_AB(userInput.nCardIdx, activeModuleNumber, 1) &&
         !IsCAN_J1939(userInput.nCardIdx, activeModuleNumber, 1))
         continue;

      maxChannels = naibrd_CAN_GetChannelCount(naibrd_GetModuleID(userInput.nCardIdx, activeModuleNumber));

      for (u8ChanIdx = 0; u8ChanIdx < maxChannels; u8ChanIdx++)
      {
         u8Channel = u8ChanIdx + 1;
         /*Module*/
         printf("%-12d", activeModuleNumber);
         /*Channel*/
         printf("%-12d", u8Channel);
         /*Tx FIFO Count*/
         check_status(naibrd_CAN_GetTxBufferCount(userInput.nCardIdx, activeModuleNumber, u8Channel, &nValue));
         printf("%-12d", nValue);
         /*Tx Frame Count*/
         check_status(naibrd_CAN_GetTxFrameCount(userInput.nCardIdx, activeModuleNumber, u8Channel, &nValue));
         printf("%-12d", nValue);
         /*Rx FIFO Count*/
         check_status(naibrd_CAN_GetRxBufferCount(userInput.nCardIdx, activeModuleNumber, u8Channel, &nValue));
         printf("%-12d", nValue);
         /*Rx Frame Count*/
         check_status(naibrd_CAN_GetRxFrameCount(userInput.nCardIdx, activeModuleNumber, u8Channel, &nValue));
         printf("%-12d", nValue);
         /*Last Error Code*/
         check_status(naibrd_CAN_GetLastError(userInput.nCardIdx, activeModuleNumber, u8Channel, &nValue));
         printf("0x%-10x", nValue);
         /*Error Count*/
         check_status(naibrd_CAN_GetErrorCount(userInput.nCardIdx, activeModuleNumber, u8Channel, &u8Value, &nValue, &nValue2));
         /*passive/active*/
         if (u8Value == CAN_ERROR_PASSIVE)
            printf("%-12s", u8PASSIVE);
         else
            printf("%-12s", u8ACTIVE);
         /*Tx Error Count*/
         printf("0x%-10x", nValue2);
         /*Rx Error Count*/
         printf("0x%-10x", nValue);
         printf("\n");
      }
   }
}

static uint32_t calcBaudRate(uint32_t unPreScaler, uint32_t unSJW, uint32_t unSetupTime, uint32_t unHoldTime)
{
   uint32_t  nBaudRate = 0;
   nBaudRate = (uint32_t)(CAN_MODULE_CLK / ((unPreScaler + 1) * (3 + unSJW + unSetupTime + unHoldTime)));
   return(nBaudRate);
}

static void CAN_SetMessageNumber()
{
   bool_t bQuit = FALSE;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   printf("\nEnter CAN Transmit Message Number <<Message Number>> in Hex or %c to quit [[default = 0x1(auto)]]: ", NAI_QUIT_CHAR);
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if (!bQuit)
   {
      if (inputResponseCnt == 0)
      {
         userInput.nMsgNumber = CAN_INCREMENT_AUTO;
         userInput.nRealTimeMsgNum = 0;
      }
      else
      {
         userInput.nRealTimeMsgNum = userInput.nMsgNumber = naiapp_utils_HexStrToDecInt32((int8_t *)inputBuffer);
      }
   }
   return;

}

static void applyToAllCANChan()
{
   int32_t chanIdx;
   int32_t moduleIdx;
   int32_t startModuleIdx = 0;
   int32_t endModuleIdx = g_moduleCount;
   int32_t activeModuleNumber = 0;
   int32_t maxChannels = 0;

   if (userInput.nModuleNumber != CAN_ALL_MODULES_INDICATOR)
   {
      startModuleIdx = (userInput.nModuleNumber - 1);
      endModuleIdx = userInput.nModuleNumber;
   }

   for (moduleIdx = startModuleIdx; moduleIdx < endModuleIdx; moduleIdx++)
   {
      activeModuleNumber = (moduleIdx + 1);
      if (!IsCAN_AB(userInput.nCardIdx, activeModuleNumber, 1) &&
         !IsCAN_J1939(userInput.nCardIdx, activeModuleNumber, 1))
         continue;

      maxChannels = naibrd_CAN_GetChannelCount(naibrd_GetModuleID(userInput.nCardIdx, activeModuleNumber));

      for (chanIdx = 0; chanIdx < maxChannels; chanIdx++)
         check_status(naibrd_CAN_SetBitTiming(userInput.nCardIdx, activeModuleNumber, chanIdx + 1, userInput.nPreScaler, userInput.nSJW, userInput.nTseg1, userInput.nTseg2));
   }

   //Bit Timing must be set on all channels in use prior to enabling TX and RX (via the control register)
   for (moduleIdx = startModuleIdx; moduleIdx < endModuleIdx; moduleIdx++)
   {
      activeModuleNumber = (moduleIdx + 1);
      if (!IsCAN_AB(userInput.nCardIdx, activeModuleNumber, 1) &&
         !IsCAN_J1939(userInput.nCardIdx, activeModuleNumber, 1))
         continue;

      maxChannels = naibrd_CAN_GetChannelCount(naibrd_GetModuleID(userInput.nCardIdx, activeModuleNumber));

      for (chanIdx = 0; chanIdx < maxChannels; chanIdx++)
         check_status(naibrd_CAN_SetControlRaw(userInput.nCardIdx, activeModuleNumber, chanIdx + 1, userInput.nCtrlWord));
   }
}

static void fillTxBuffer(uint8_t *u8Buffer)
{
   uint8_t uByteCount = 0;
   uint8_t u8Idx = 0;
   uint8_t *u8Ptr = u8Buffer;

   for (u8Idx = 0; u8Idx < userInput.nDataLength; u8Idx++)
   {
      if (userInput.nUseDataPattern == USE_DATA_PATTERN)
      {
         if (uByteCount % 2 == 0)
            *u8Ptr++ = userInput.nDataArray[uByteCount / 2].nBytes.loByte;
         else
            *u8Ptr++ = userInput.nDataArray[uByteCount / 2].nBytes.hiByte;
         uByteCount++;
      }
      else
         *u8Ptr++ = userInput.nData & 0xFF;
   }
}

static void setCanBitTiming()
{
   /*DANT - WE SHOULD NOT ENABLE TX AND RX UNTIL WE ARE DONE WITH CONFIGURATION!
      check_status(naibrd_CAN_SetControlRaw(userInput.nCardIdx, userInput.nModuleNumber, userInput.nChannelNumber, userInput.nCtrlWord));
   */
   int32_t activeModuleNumber = CAN_DEFAULT_MODULE;

   if (userInput.nModuleNumber != CAN_ALL_MODULES_INDICATOR)
      activeModuleNumber = userInput.nModuleNumber;

   check_status(naibrd_CAN_SetBitTiming(userInput.nCardIdx, activeModuleNumber, userInput.nChannelNumber, userInput.nPreScaler, userInput.nSJW, userInput.nTseg1, userInput.nTseg2));
   return;
}

static void setCanControlRegister()
{
   int32_t activeModuleNumber = CAN_DEFAULT_MODULE;

   if (userInput.nModuleNumber != CAN_ALL_MODULES_INDICATOR)
      activeModuleNumber = userInput.nModuleNumber;

   check_status(naibrd_CAN_SetControlRaw(userInput.nCardIdx, activeModuleNumber, userInput.nChannelNumber, userInput.nCtrlWord));
   return;
}

static void CAN_SetDataPatternEnable()
{
   bool_t bQuit = FALSE;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   printf("\nEnter use Data Pattern <<DATA PATTERNS>> [0=No, 1=Yes] or %c to quit [[default = 0x1]]: ", NAI_QUIT_CHAR);
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if (!bQuit)
   {
      if (inputResponseCnt == 0)
         userInput.nUseDataPattern = USE_DATA_PATTERN;
      else
         userInput.nUseDataPattern = (uint8_t)atoi((const char *)inputBuffer);
   }
   return;

}

static void CAN_SetDelay()
{
   bool_t bQuit = FALSE;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   printf("\nEnter Delay between Tx in mS. <<DELAY>> or %c to quit [[default = 1000ms]]: ", NAI_QUIT_CHAR);
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if (!bQuit)
   {
      if (inputResponseCnt == 0)
         userInput.nDelay_Ms = DEFAULT_1000MS;
      else
         userInput.nDelay_Ms = atoi((const char *)inputBuffer);
   }
   return;

}

static void CAN_SetLoopEnable()
{
   bool_t bQuit = FALSE;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   printf("\nEnable or Disable continue Tx. <<CONTINUE LOOP>> [0=No, 1=Yes] or %c to quit [[default = No(0)]]: ", NAI_QUIT_CHAR);
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if (!bQuit)
   {
      if (inputResponseCnt == 0)
         userInput.nRepeat = NO;
      else
         userInput.nRepeat = (uint8_t)atoi((const char *)inputBuffer);
   }
   return;

}

static void fireMessage(int32_t moduleNumber, int32_t msgid, bool_t isCanA, uint8_t* u8Buffer)
{
   bool_t is_CAN_A = isCanA;

   userInput.nChannelNumber = userInput.nP6ChanNumber;
   check_status(naibrd_CAN_QueueTransmit(userInput.nCardIdx, moduleNumber, userInput.nChannelNumber, is_CAN_A, msgid, u8Buffer, userInput.nDataLength));
   check_status(naibrd_CAN_SetTxEnable(userInput.nCardIdx, moduleNumber, userInput.nChannelNumber, CAN_TX_ENABLE));
   Show_TxResult();
   return;
}

static void fireJ1939Message(int32_t moduleNumber, int32_t msgid, uint8_t* u8Buffer)
{
#if defined (WIN32)
   UNREFERENCED_PARAMETER(msgid);
#endif  /* WIN32 */

   userInput.nChannelNumber = userInput.nP6ChanNumber;
   check_status(naibrd_CAN_QueueTransmit_J1939(userInput.nCardIdx, moduleNumber, userInput.nChannelNumber, 0xFEBF, 0x7 /*Priority*/, 0xFF /*Destination*/, u8Buffer, userInput.nDataLength));
   check_status(naibrd_CAN_SetTxEnable(userInput.nCardIdx, moduleNumber, userInput.nChannelNumber, CAN_TX_ENABLE));
   Show_TxResult();
   return;
}

static void CAN_SetCtrlWord()
{
   bool_t bQuit = FALSE;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   printf("\nSet CAN control word <<CONTROL WORD>> [Reset chan | Ebl std/ext | CAN A/B filter | Use Acceptance Code/Mask | Rx | Tx ] or %c to quit [[default = 000011]]: ", NAI_QUIT_CHAR);
   printf("\nReset chan(D15): Reset Channel [1=Clear Rx and Tx FIFO buffer]");
   printf("\nEbl std/ext(D5): Filter Std/Ext[0(and D4 is 1)=Only accept Ext Mode Msg, 1(and D4 is 1)=Only accept Std Mode Msg] ");
   printf("\nCAN A/B filter(D4): Use CAN-A/B filtering [0=Can't inhibit the acc filtering, 1=the filter Std/Ext bit D5 is used to filter receive msg]");
   printf("\nUse Acceptance Code/Mask(D3): Use Acceptance Mask/Code for Rx filtering [0=Don't use Acc Mask/Code, 1=Use Acc Mask/Code]");
   printf("\nRx(D2): Enable Rx[0=Disable, 1=Enable]");
   printf("\nTx(D0): Enable Tx[0=Disable, 1=Enable]\n");
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if (!bQuit)
   {
      if (inputResponseCnt == 0)
         userInput.nCtrlWord = 0x5;
      else
      {
         userInput.nCtrlWord = constructCanCtrlWord((const char *)inputBuffer, (uint8_t)inputResponseCnt);
      }
   }
   return;
}

static uint16_t constructCanCtrlWord(const char* userStr, uint8_t inputLength)
{
   uint8_t un8Idx = 0;
   uint16_t un16CtrlWord = 0;
   uint16_t un16Mask = 0x1;

   for (un8Idx = 0; un8Idx < inputLength; un8Idx++)
   {
      un16Mask = 0x1;
      if (*userStr > ASCII_1_HEX || *userStr < ASCII_0_HEX || inputLength != 6)
      {
         printf("Error Input String:%s", userStr);
      }
      else
      {
         switch (un8Idx)
         {
            case 0:
               un16Mask <<= ctrlWord_ResetChan_D15;
               if (*userStr == ASCII_1_HEX)
                  un16CtrlWord |= un16Mask;
               else
                  un16CtrlWord &= ~un16Mask;
               break;

            case 1:
               un16Mask <<= ctrlWord_Filter_STD_EXT_D5;
               if (*userStr == ASCII_1_HEX)
                  un16CtrlWord |= un16Mask;
               else
                  un16CtrlWord &= ~un16Mask;
               break;

            case 2:
               un16Mask <<= ctrlWord_UseCanA_B_Filter_D4;
               if (*userStr == ASCII_1_HEX)
                  un16CtrlWord |= un16Mask;
               else
                  un16CtrlWord &= ~un16Mask;
               break;

            case 3:
               un16Mask <<= ctrlWord_UseAcceptanceCode_D3;
               if (*userStr == ASCII_1_HEX)
                  un16CtrlWord |= un16Mask;
               else
                  un16CtrlWord &= ~un16Mask;
               break;

            case 4:
               un16Mask <<= ctrlWord_Rx_D2;
               if (*userStr == ASCII_1_HEX)
                  un16CtrlWord |= un16Mask;
               else
                  un16CtrlWord &= ~un16Mask;
               break;

            case 5:
               un16Mask <<= ctrlWord_Tx_D0;
               if (*userStr == ASCII_1_HEX)
                  un16CtrlWord |= un16Mask;
               else
                  un16CtrlWord &= ~un16Mask;
               break;
         }
         userStr++;
      }
   }
   return(un16CtrlWord);
}

static void CAN_SetAccMask()
{
   bool_t bQuit = FALSE;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   printf("\nSet CAN acceptance mask <<ACC. MASK>> (32bit value) or %c to quit [default = 0x00000000]: ", NAI_QUIT_CHAR);
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if (!bQuit)
   {
      if (inputResponseCnt == 0)
         userInput.nAcceptanceMask = 0x0;
      else
      {
         userInput.nAcceptanceMask = atoi((const char *)inputBuffer);
      }
   }
   return;
}

static void CAN_SetAccCode()
{
   bool_t bQuit = FALSE;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   printf("\nSet CAN acceptance code <<ACC. CODE>> (32bit value) or %c to quit [default = 0x00000000]: ", NAI_QUIT_CHAR);
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if (!bQuit)
   {
      if (inputResponseCnt == 0)
         userInput.nAcceptanceCode = 0x0;
      else
      {
         userInput.nAcceptanceCode = atoi((const char *)inputBuffer);
      }
   }
   return;
}

#if defined (WIN32)
DWORD WINAPI proc_MonitorRxBuffer(LPVOID param)
{
   bool_t bQuit = FALSE;
   (void)param;
   printf("\nBegin Monitoring Rx FIFO Buffer\n");

   do
   {
      if ((userInput.n8UserThreadEscapeKey == PROC_RX_BUFFER_ESCAPE_KEY_q) || (userInput.n8UserThreadEscapeKey == PROC_RX_BUFFER_ESCAPE_KEY_Q))
      {
         bQuit = TRUE;
         break;
      }
      else
      {

         //    	  Sleep(userInput.nDelay_Ms);
         //#else
         //    	  usleep(userInput.nDelay_Ms*1000);
         //#endif
         showRxData();
      }
   } while (bQuit == FALSE);
   return(0);
}

#endif

#if defined (LINUX)
void proc_MonitorRxBuffer(void *ptr)
{
   bool_t bQuit = FALSE;
   printf("\nBegin Monitoring Rx FIFO Buffer\n");

   do
   {
      if ((userInput.n8UserThreadEscapeKey == PROC_RX_BUFFER_ESCAPE_KEY_q) || (userInput.n8UserThreadEscapeKey == PROC_RX_BUFFER_ESCAPE_KEY_Q))
      {
         bQuit = TRUE;
         break;
      }
      else
      {
         /*usleep(userInput.nDelay_Ms*1000);*/
         showRxData();
      }
   } while (bQuit == FALSE);
   pthread_exit(0); /* exit */
}
#endif

#if defined (__VXWORKS__)
void proc_MonitorRxBuffer(void)
{
   bool_t bQuit = FALSE;
   printf("\nBegin Monitoring Rx FIFO Buffer\n");

   do
   {
      if ((userInput.n8UserThreadEscapeKey == PROC_RX_BUFFER_ESCAPE_KEY_q) || (userInput.n8UserThreadEscapeKey == PROC_RX_BUFFER_ESCAPE_KEY_Q))
      {
         bQuit = TRUE;
         break;
      }
      else
      {
         nai_msDelay(userInput.nDelay_Ms);
         showRxData();
      }
   } while (bQuit == FALSE);
}

#endif
static void CAN_Listen()
{
#if defined (LINUX)
   pthread_t thread1;
#endif

   bool_t bQuit = FALSE;
   int32_t maxChannels = 0;
   int32_t activeModuleNumber = CAN_DEFAULT_MODULE;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   if (userInput.nModuleNumber != CAN_ALL_MODULES_INDICATOR)
      activeModuleNumber = userInput.nModuleNumber;

   maxChannels = naibrd_CAN_GetChannelCount(naibrd_GetModuleID(userInput.nCardIdx, activeModuleNumber));

   printf("\nCAN Rx <<RX>>.  Prints out what is in the RX FIFO buffer or %c to quit [[default = 0x00000000]]: ", NAI_QUIT_CHAR);
   printf("\nThis function will launch a thread to keep polling the FIFO RX buffer from channel 1-%d", maxChannels);
   userInput.n8UserThreadEscapeKey = 0;
   userInput.nRxMsgCounter = 0;
   /*do two things: a. Monitor for the 'q' key.
                    b. Thread to keep tracking the Rx buffer for Chan 1 - CAN_MAX_CHANNEL
   */
#if defined (WIN32)
   printf("\nCreated new thread!");
   CreateThread(NULL, 0, proc_MonitorRxBuffer, NULL, 0, NULL);
#elif defined (LINUX)
   pthread_create(&thread1, NULL, (void *)&proc_MonitorRxBuffer, NULL);
#elif defined (__VXWORKS__)
   taskSpawn("MonitorRxBuffer", 99, 0, 0x4000, (FUNCPTR)proc_MonitorRxBuffer, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
#endif

   do
   {
      bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
      if (inputResponseCnt != 0)
      {
         userInput.n8UserThreadEscapeKey = inputBuffer[0];
#if defined (LINUX)
         pthread_join(thread1, NULL);
#endif
   }
} while (!bQuit);
return;
}

static void showRxData()
{

   int32_t nStatus = 0;
   int32_t nValue = 0;
   int32_t nValue2 = 0;
   bool_t bValue = 0;
   int32_t nChanIdx = 0;
   int32_t nChan = 0;
   bool_t  bIsModeA = TRUE;
   int32_t nMsgId = 0;
   int32_t nLength = 0;
   uint8_t unMsg[CAN_MAX_MSG_SIZE];
   int32_t nBufLength = CAN_MAX_MSG_SIZE;
   int32_t nRxFrameCnt = 0;
   int32_t moduleIdx = 0;
   int32_t nPGN = 0;
   int32_t nSource = 0;
   int32_t nDest = 0;
   uint8_t i = 0;
   int32_t   startModuleIdx = 0;
   int32_t   endModuleIdx = g_moduleCount;
   int32_t   activeModuleNumber = 0;
   int32_t   maxChannels = 0;

   if (userInput.nModuleNumber != CAN_ALL_MODULES_INDICATOR)
   {
      startModuleIdx = (userInput.nModuleNumber - 1);
      endModuleIdx = userInput.nModuleNumber;
   }

   for (moduleIdx = startModuleIdx; moduleIdx < endModuleIdx; moduleIdx++)
   {
      activeModuleNumber = (moduleIdx + 1);
      if (!IsCAN_AB(userInput.nCardIdx, activeModuleNumber, 1) &&
         !IsCAN_J1939(userInput.nCardIdx, activeModuleNumber, 1))
         continue;

      maxChannels = naibrd_CAN_GetChannelCount(naibrd_GetModuleID(userInput.nCardIdx, activeModuleNumber));
      for (nChanIdx = 0; nChanIdx < maxChannels; nChanIdx++)
      {
         nChan = nChanIdx + 1;

         nStatus = check_status(naibrd_CAN_GetRxFrameCount(userInput.nCardIdx, activeModuleNumber, nChan, &nRxFrameCnt));
         if (nStatus != 0)
            printf("\nerror!");

         if (nRxFrameCnt > 0)
         {
            memset(unMsg, 0x0, sizeof(unMsg));
            printf("\nCAN RX DATA\n");
            printf("=========================================================================================================================");
            printf("\nMsg Count   Module      Channel     Rx FIFO     Rx Frame    Error       Error      Error        Data                                 ");
            printf("\n                                    Count       Count       Code        Pass./Act. Cnt Rx                                            ");
            printf("\n----------  ----------  ----------  ----------  ----------  ----------  ---------- ----------   -------------------------------------  \n");
            /*Rx Msg Count*/
            printf("%-12d", ++userInput.nRxMsgCounter);
            /*Module*/
            printf("%-12d", activeModuleNumber);
            /*Channel*/
            printf("%-12d", nChan);
            /*Rx FIFO Count*/
            check_status(naibrd_CAN_GetRxBufferCount(userInput.nCardIdx, activeModuleNumber, nChan, &nValue));
            printf("%-12d", nValue);
            /*Rx Frame Count*/
            check_status(naibrd_CAN_GetRxFrameCount(userInput.nCardIdx, activeModuleNumber, nChan, &nValue));
            printf("%-12d", nValue);
            /*Last Error Code*/
            check_status(naibrd_CAN_GetLastError(userInput.nCardIdx, activeModuleNumber, nChan, &nValue));
            printf("0x%-10x", nValue);
            /*Error Count*/
            check_status(naibrd_CAN_GetErrorCount(userInput.nCardIdx, activeModuleNumber, nChan, &bValue, &nValue, &nValue2));
            /*passive/active*/
            if (bValue == CAN_ERROR_PASSIVE)
               printf("%-12s", u8PASSIVE);
            else
               printf("%-12s", u8ACTIVE);
            /*Rx Error Count*/
            printf("0x%-10x", nValue);

            /*Data*/
            if (IsCAN_AB(userInput.nCardIdx, activeModuleNumber, 1))
               check_status(naibrd_CAN_Receive(userInput.nCardIdx, activeModuleNumber, nChan, nBufLength, &bIsModeA, &nMsgId, unMsg, &nLength));
            else if (IsCAN_J1939(userInput.nCardIdx, activeModuleNumber, 1))
               check_status(naibrd_CAN_Receive_J1939(userInput.nCardIdx, activeModuleNumber, nChan, nBufLength, &nPGN, &nSource, &nDest, unMsg, &nLength));

            for (i = 0; i < nLength; i++)
               printf("0x%-2x ", unMsg[i]);

            printf("\n");
         }
      }
   }
}

static void basicReadWrite()
{
   int dataRegLength = 10;
   /*uint32_t address[] = {0x1054, 0x1058, 0x105c, 0x1060, 0x1064, 0x1068, 0x106c, 0x1070, 0x1074, 0x1078};*/
   uint32_t address[] = { 0x1054, 0x1058, 0x105c, 0x1060, 0x1064, 0x1068, 0x106c, 0x1070, 0x1074, 0x1078 };
   /*uint32_t address[] = {0x0, 0x4, 0x8, 0xc, 0x10, 0x14, 0x18, 0x1c, 0x20, 0x24 };*/
   uint32_t data = 0xa5a5a5a5;
   int32_t idx = 0;
   uint32_t result[10];
   uint32_t maxLoopCnt = 100000;
   uint32_t loopCntIdx = 0;
   uint32_t expectedValue = 0;
   int32_t  activeModuleNumber = CAN_DEFAULT_MODULE;

   if (userInput.nModuleNumber != CAN_ALL_MODULES_INDICATOR)
      activeModuleNumber = userInput.nModuleNumber;

   for (loopCntIdx = 0; loopCntIdx < maxLoopCnt; loopCntIdx++)
   {
      for (idx = 0; idx < dataRegLength; idx++)
      {
         expectedValue = data + idx;
         naibrd_Write32(userInput.nCardIdx, activeModuleNumber, address[idx], 0, 1, 4, &expectedValue);
         /*usleep(.001*1000);*/
         naibrd_Read32(userInput.nCardIdx, activeModuleNumber, address[idx], 0, 1, 4, &result[idx]);
         if (expectedValue != result[idx])
         {
            printf("\nError: idx:%d, expected:%d, actual:%d", idx, expectedValue, result[idx]);
            break;
         }
         /*usleep(100*1000);*/
      }
      /*printf("\nLoop Count:%d", loopCntIdx);*/

   }
   printf("\n***End***");
   /*
   naibrd_ReadReg32(userInput.nCardIdx, activeModuleNumber, offset, &rdArray[0]);
   naibrd_ReadReg32(userInput.nCardIdx, activeModuleNumber, offset, &rdArray[0]);
   */

   /*
   for(idx=0; idx<100; idx++)
   {

      naibrd_WriteReg32(userInput.nCardIdx, activeModuleNumber, offset, 0xa1011001);
      naibrd_ReadReg32(userInput.nCardIdx, activeModuleNumber, offset, &rdArray[idx]);

   }
   */
}

static void testEthernetTx()
{
   uint8_t testMsg[] = { "Hello" };
   int32_t testMsgLength = sizeof(testMsg);

   tcpTx(testMsg, testMsgLength);

}

static uint32_t tcpTx(uint8_t *MsgBuf, int32_t MsgLeg)
{
   (void)MsgBuf;
   (void)MsgLeg;

#if defined(LINUX) || defined(__VXWORKS__)
   int sd, rc, length = sizeof(int);
   struct sockaddr_in serveraddr;
   char buffer[CanBufferLength];
   char server[255];
   char temp;
   int totalcnt = 0;
   struct hostent *hostp;
   char data[100] = "This is a test string from client ";

   memset(data, 0x0, sizeof(data));
   strcpy(data, (char*)MsgBuf);
   /* The socket() function returns a socket */
   /* descriptor representing an endpoint. */
   /* The statement also identifies that the */
   /* INET (Internet Protocol) address family */
   /* with the TCP transport (SOCK_STREAM) */
   /* will be used for this socket. */
   /******************************************/

   /* get a socket descriptor */
   if ((sd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
   {
      perror("Client-socket() error");
      exit(-1);
   }
   else
      printf("Client-socket() OK\n");
   /*Use the default server name or IP*/
   strcpy(server, SERVER);
   memset(&serveraddr, 0x00, sizeof(struct sockaddr_in));
   serveraddr.sin_family = AF_INET;
   serveraddr.sin_port = htons(SERVPORT);
   if ((serveraddr.sin_addr.s_addr = inet_addr(server)) == (unsigned long)INADDR_NONE)
   {
      /* When passing the host name of the server as a */
      /* parameter to this program, use the gethostbyname() */
      /* function to retrieve the address of the host server. */
      /***************************************************/
      /* get host address */
      hostp = gethostbyname(server);
      if (hostp == (struct hostent *)NULL)
      {
         printf("HOST NOT FOUND --> ");
         /* h_errno is usually defined */
         /* in netdb.h */
#if !defined (__VXWORKS__)
         printf("h_errno = %d\n", h_errno);
#else
         printf("h_errno = %d \n", errnoGet());
#endif
         printf("---This is a client program---\n");
         close(sd);
         exit(-1);
      }
      memcpy(&serveraddr.sin_addr, hostp->h_addr, sizeof(serveraddr.sin_addr));
   }
   /* After the socket descriptor is received, the */
   /* connect() function is used to establish a */
   /* connection to the server. */
   /***********************************************/
   /* connect() to server. */
   if ((rc = connect(sd, (struct sockaddr *)&serveraddr, sizeof(serveraddr))) < 0)
   {
      perror("Client-connect() error");
      close(sd);
      exit(-1);
   }
   else
      printf("Connection established...\n");
   /* Send string to the server using */
   /* the write() function. */
   /*********************************************/
   /* Write() some string to the server. */
   printf("Sending some string to the server %s...\n", server);
   rc = write(sd, data, sizeof(data));
   if (rc < 0)
   {
      perror("Client-write() error");
      rc = getsockopt(sd, SOL_SOCKET, SO_ERROR, &temp, (socklen_t*)(&length));
      if (rc == 0)
      {
         /* Print out the asynchronously received error. */
         errno = temp;
         perror("SO_ERROR was");
      }
      close(sd);
      exit(-1);
   }
   else
   {
      printf("Client-write() is OK\n");
      printf("String successfully sent \n");
      printf("Waiting the %s to echo back...\n", server);
   }
   totalcnt = 0;
   while (totalcnt < CanBufferLength)
   {
      /* Wait for the server to echo the */
      /* string by using the read() function. */
      /***************************************/
      /* Read data from the server. */
      rc = read(sd, &buffer[totalcnt], CanBufferLength - totalcnt);
      if (rc < 0)
      {
         perror("Client-read() error");
         close(sd);
         exit(-1);
      }
      else if (rc == 0)
      {
         printf("Server program has issued a close()\n");
         close(sd);
         exit(-1);
      }
      else
         totalcnt += rc;
   }
   printf("Client-read() is OK\n");
   printf("Echoed data from the server: %s\n", buffer);
   /* When the data has been read, close() */
   /* the socket descriptor. */
   /****************************************/
   /* Close socket descriptor from client side. */
   close(sd);
   exit(0);
#endif
   return 0;
}

static void testTxRx()
{
#if defined(LINUX) || defined(__VXWORKS__)
#if defined (LINUX)
   pthread_t thread_Tx;
#endif
   bool_t bQuit = FALSE;
   printf("\nCAN Transmit and Receive Threads <<TX RX>> or tyep %c to quit. ", NAI_QUIT_CHAR);
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   userInput.n8UserThreadEscapeKey = 0;
   userInput.nRxMsgCounter = 0;
   /*do the followings: a. Launch Tx thread.
    * 					b. Launch Rx thread.
    * 					c. Setup Tx thread for CAN transmission
    * 					d. Setup Rx thread for CAN receive
    * 					e. setup loop for Tx and end Tx thread when finish
    * 					f. setup do-while for Rx thread and end by user input Q key.
    */
#if defined (WIN32)
   printf("\nCreated new thread!");
   CreateThread(NULL, 0, proc_MonitorRxBuffer, NULL, 0, NULL);
#elif defined (LINUX)
   pthread_create(&thread_Tx, NULL, (void *)&proc_MonitorRxBuffer, NULL);
#elif defined (__VXWORKS__)
   taskSpawn("MonitorRxBuffer", 99, 0, 0x4000, (FUNCPTR)proc_MonitorRxBuffer, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
#endif

   do
   {
      bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
      if (inputResponseCnt != 0)
      {
         userInput.n8UserThreadEscapeKey = inputBuffer[0];
#if defined (LINUX)
         pthread_join(thread_Tx, NULL);
#endif
      }
   } while (!bQuit);
#endif

   return;
}

static void testTxMultiChan()
{
   int32_t nTestLoopCountIdx = 0;
   bool_t is_CAN_A = FALSE;
   uint8_t u8Buffer[8];
   int32_t msgid = 0;
   uint8_t chanData[] = { '1','2','3','4','5','6','7','8' };
   int32_t chanIdx;
   int32_t moduleIdx;
   int32_t startModuleIdx = 0;
   int32_t endModuleIdx = g_moduleCount;
   int32_t activeModuleNumber = 0;
   int32_t maxChannels = 0;

   Show_CanConfiguration();
   if (userInput.nModeAB == CAN_MODE_A)
      is_CAN_A = TRUE;

   if (userInput.nMsgNumber == CAN_INCREMENT_AUTO)
      userInput.nRealTimeMsgNum++;
   msgid = userInput.nRealTimeMsgNum;

   if (userInput.nModuleNumber != CAN_ALL_MODULES_INDICATOR)
   {
      startModuleIdx = (userInput.nModuleNumber - 1);
      endModuleIdx = userInput.nModuleNumber;
   }

   //userInput.nDataArray[0].nBytes.loByte = chanData[0];
   //userInput.nDataArray[0].nBytes.loByte = chanData[1];
   for (nTestLoopCountIdx = 0; nTestLoopCountIdx < userInput.nLoopCount; nTestLoopCountIdx++)
   {
      for (moduleIdx = startModuleIdx; moduleIdx < endModuleIdx; moduleIdx++)
      {
         activeModuleNumber = (moduleIdx + 1);
         if (!IsCAN_AB(userInput.nCardIdx, activeModuleNumber, 1) &&
            !IsCAN_J1939(userInput.nCardIdx, activeModuleNumber, 1))
            continue;

         maxChannels = naibrd_CAN_GetChannelCount(naibrd_GetModuleID(userInput.nCardIdx, activeModuleNumber));
         for (chanIdx = 0; chanIdx < maxChannels; chanIdx++)
         {
            //userInput.nDataArray[0].nBytes.loByte = chanData[chanIdx + 4*moduleIdx ];
            userInput.nDataArray[0].nBytes.loByte = chanData[0];
            userInput.nDataArray[0].nBytes.hiByte = chanData[1];
            userInput.nDataArray[1].nBytes.loByte = chanData[2];
            userInput.nDataArray[1].nBytes.hiByte = chanData[3];
            userInput.nDataArray[2].nBytes.loByte = chanData[4];
            userInput.nDataArray[2].nBytes.hiByte = chanData[5];
            userInput.nDataArray[3].nBytes.loByte = chanData[6];
            userInput.nDataArray[3].nBytes.hiByte = chanData[7];
            userInput.nDataLength = 8;

            userInput.nChannelNumber = chanIdx + 1;
            userInput.nP6ChanNumber = chanIdx % 4 + 1;

            memset(u8Buffer, 0x0, sizeof(u8Buffer));
            fillTxBuffer(u8Buffer);
            if (userInput.nRepeat == NO)
            {
               if (userInput.nMsgNumber == CAN_INCREMENT_AUTO)
                  userInput.nRealTimeMsgNum++;
               msgid = userInput.nRealTimeMsgNum;

               if (IsCAN_AB(userInput.nCardIdx, activeModuleNumber, 1))
                  fireMessage(activeModuleNumber, msgid, is_CAN_A, u8Buffer);
               else if (IsCAN_J1939(userInput.nCardIdx, activeModuleNumber, 1))
                  fireJ1939Message(activeModuleNumber, msgid, u8Buffer);
            }
            else
            {
               if (userInput.nMsgNumber == CAN_INCREMENT_AUTO)
                  msgid = userInput.nRealTimeMsgNum++;

               if (IsCAN_AB(userInput.nCardIdx, activeModuleNumber, 1))
                  fireMessage(activeModuleNumber, msgid, is_CAN_A, u8Buffer);
               else if (IsCAN_J1939(userInput.nCardIdx, activeModuleNumber, 1))
                  fireJ1939Message(activeModuleNumber, msgid, u8Buffer);

               printf("\nLoop Count:%d", nTestLoopCountIdx + 1);

#if defined(WIN32) || defined(__VXWORKS__)
               nai_msDelay(userInput.nDelay_Ms);
#else
               usleep(userInput.nDelay_Ms * 1000);
#endif
            }
         }
      }
   }

   return;
}

Help Bot

X