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

SER ASync Rx

SER ASync Rx

Explanation

About this Sample Application Code

This C application is designed to interact with North Atlantic Industries' (NAI) embedded function modules, specifically to configure a serial channel for receiving RS422 data. Below is a detailed walk-through and explanation of the application’s functionality.

Included Headers

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#include "include/naiapp_boardaccess_menu.h"
#include "include/naiapp_boardaccess_query.h"
#include "include/naiapp_boardaccess_access.h"
#include "include/naiapp_boardaccess_display.h"
#include "include/naiapp_boardaccess_utils.h"
#include "nai.h"
#include "naibrd.h"
#include "functions/naibrd_ser.h"
#include "advanced/nai_ether_adv.h"

These headers include standard C libraries and specific NAI libraries for board access, querying, displaying, board functionalities, and advanced Ethernet functions.

Constants

static const int8_t *CONFIG_FILE = (const int8_t *)"default_SerASync_Rx.txt";
#define MAX_DATA_RX  20
#define MAX_TIMEOUT  10
#define CLEAR_FIFO_TIMEOUT 1000
  • CONFIG_FILE: Path to the configuration file.

  • MAX_DATA_RX: Maximum amount of data to receive.

  • MAX_TIMEOUT: Timeout duration in milliseconds.

  • CLEAR_FIFO_TIMEOUT: Timeout for clearing FIFOs in milliseconds.

Function Prototypes

void Run_SER_ASync_Rx(int32_t cardIndex, int32_t module, uint32_t moduleID);

This function is used to configure and run the serial asynchronous receive operation.

Main Function

#if defined (__VXWORKS__)
int32_t SER_ASync_Rx_Sample(void)
#else
int32_t main(void)
#endif
{
   bool_t stop = FALSE;
   int32_t cardIndex;
   int32_t moduleCnt;
   int32_t module;
   uint32_t moduleID = 0;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   if (naiapp_RunBoardMenu(CONFIG_FILE) == TRUE)
   {
      while (stop != TRUE)
      {
         stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
         if (stop != TRUE)
         {
            check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));
            stop = naiapp_query_ModuleNumber(moduleCnt, 1, &module);
            if (stop != TRUE)
            {
               moduleID = naibrd_GetModuleID(cardIndex, module);
               if ((moduleID != 0))
               {
                  Run_SER_ASync_Rx(cardIndex, module, moduleID);
               }
            }
         }
         printf("\r\nType Q to quit or Enter key to restart application:\r\n");
         stop = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
      }
   }

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

Main Function Mechanics

  1. Initial Configuration:

    • The function starts by calling naiapp_RunBoardMenu to present a menu to the user for board configuration.

  2. Card and Module Queries:

    • It queries the user to select a cardIndex and retrieves the module count using naibrd_GetModuleCount.

    • Next, it queries for the module number.

  3. Module ID Validation:

    • Retrieves the module ID and ensures it’s valid.

  4. Running the Receive Operation:

    • If the module ID is valid, it calls Run_SER_ASync_Rx to perform the asynchronous receive operation.

  5. Application Loop and Exit:

    • The application continues until the user chooses to quit by typing 'Q'.

Run_SER_ASync_Rx Function

void Run_SER_ASync_Rx(int32_t cardIndex, int32_t module, uint32_t moduleID)
{
   int32_t ch, i;
   int32_t channelCount;
   int32_t chanNum;
   int32_t nCntlValueLo;
   int32_t nNumWordsRecv = 0;
   uint32_t RecvDataStatus[MAX_DATA_RX];
   bool_t bQuit = FALSE;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   channelCount = naibrd_SER_GetChannelCount(moduleID);
   naiapp_query_ChannelNumber(channelCount, 1, &chanNum);

   naibrd_SER_ChannelReset(cardIndex, module, chanNum);
   naibrd_SER_ClearRxFifo(cardIndex, module, chanNum);
   naibrd_SER_ClearTxFifo(cardIndex, module, chanNum);
   nCntlValueLo = NAI_SER_CTRLLO_CLEAR_RX_FIFO | NAI_SER_CTRLLO_CLEAR_TX_FIFO;
   for (i = 0; i < CLEAR_FIFO_TIMEOUT && (nCntlValueLo & (NAI_SER_CTRLLO_CLEAR_RX_FIFO | NAI_SER_CTRLLO_CLEAR_TX_FIFO)); i++)
   {
      nai_ser_chanctrl chanCtrlRaw;
      naibrd_SER_GetChannelControlRaw(cardIndex, module, chanNum, &chanCtrlRaw);
      nCntlValueLo = chanCtrlRaw & 0x0000FFFF;
      nai_msDelay(1);
   }
   if (i == CLEAR_FIFO_TIMEOUT)
   {
      printf("Unable to clear FIFOs %d\n", chanNum);
      printf("Please press Enter to exit...");
      while ((ch = getchar()) != 0x0A);
      return;
   }

   printf("\nSerial Channel # %d\n", chanNum);

   check_status(naibrd_SER_SetProtocol(cardIndex, module, chanNum, NAI_SER_PROTOCOL_ASYNC));
   check_status(naibrd_SER_SetInterfaceLevel(cardIndex, module, chanNum, NAI_SER_INTF_LOOPBACK));
   check_status(naibrd_SER_SetParity(cardIndex, module, chanNum, NAI_SER_PARITY_NONE));
   check_status(naibrd_SER_SetDataBits(cardIndex, module, chanNum, 8));
   check_status(naibrd_SER_SetStopBits(cardIndex, module, chanNum, 1));
   check_status(naibrd_SER_SetBaudrate(cardIndex, module, chanNum, 9600));
   if (NAI_MODULE_ID_P8 == moduleID || NAI_MODULE_ID_PC == moduleID || NAI_MODULE_ID_PD == moduleID ||
      NAI_MODULE_ID_Px == moduleID || NAI_MODULE_ID_KB == moduleID)
   {
      nai_msDelay(20);
   }
   check_status(naibrd_SER_SetReceiverEnable(cardIndex, module, chanNum, 1));

   nai_msDelay(100);

   printf("Please press Enter to read back data...");
   while ((ch = getchar()) != 0x0A);

   do
   {
      naibrd_SER_GetRxBufferCnt(cardIndex, module, chanNum, (uint32_t*)&nNumWordsRecv);
      printf("\nReading back %d words ...", nNumWordsRecv);
      naibrd_SER_ReceiveBuffer32(cardIndex, module, chanNum, RecvDataStatus, MAX_DATA_RX, (uint32_t*)&nNumWordsRecv);
      printf(" %d words read\n", nNumWordsRecv);

      for (i = 0; i < nNumWordsRecv; i++)
         printf("Recd 0x%02X, Status= %02X\n",
         (RecvDataStatus[i] & 0x00FF), (RecvDataStatus[i] >> 8) & 0x00FF);

      printf("Press ENTER to receive again, or '%c' to exit program : ", NAI_QUIT_CHAR);
      bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);

   } while (TRUE != bQuit);

   return;
}

Function Mechanics

  1. Channel Setup:

    • Retrieves the channel count and queries the user to select a channel.

    • Resets the channel and clears the RX and TX FIFOs.

  2. Channel Configuration:

    • Configures the protocol, interface level, parity, data bits, stop bits, and baud rate.

    • Enables the receiver.

  3. Data Reception Loop:

    • Enters a do-while loop to continuously read data until the user opts to quit.

    • Retrieves the count of received data and reads the data.

    • Displays the received data and status.

This sample code provides a user-friendly interface to configure and operate a serial channel for asynchronous data reception using NAI hardware and libraries. It also handles user queries, channel setup, and continuously reads incoming data until the user decides to exit the program.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>

/* Common Sample Program include files */
#include "include/naiapp_boardaccess_menu.h"
#include "include/naiapp_boardaccess_query.h"
#include "include/naiapp_boardaccess_access.h"
#include "include/naiapp_boardaccess_display.h"
#include "include/naiapp_boardaccess_utils.h"

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

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

/* Function prototypes */
void Run_SER_ASync_Rx(int32_t cardIndex, int32_t module, uint32_t moduleID);

#define MAX_DATA_RX  20
#define MAX_TIMEOUT  10          /* 10ms timeout */
#define CLEAR_FIFO_TIMEOUT 1000  /* 1 second */

/**************************************************************************************************************/
/** \defgroup SERAsyncRx Serial Asynchronous Receive
The purpose of the Serial Asynchronous Receive sample application is to illustrate the methods to call in the
naibrd library to configure a given serial channel for receiving RS422. The SER_Async_Tx application can be run
in unison to this application to transmit data.
*/
/**************************************************************************************************************/
#if defined (__VXWORKS__)
int32_t SER_ASync_Rx_Sample(void)
#else
int32_t main(void)
#endif
{
   bool_t stop = FALSE;
   int32_t cardIndex;
   int32_t moduleCnt;
   int32_t module;
   uint32_t moduleID = 0;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   if (naiapp_RunBoardMenu(CONFIG_FILE) == TRUE)
   {
      while (stop != TRUE)
      {
         /* Query user for the card index */
         stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
         if (stop != TRUE)
         {
            check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));

            /* Query user for the module number */
            stop = naiapp_query_ModuleNumber(moduleCnt, 1, &module);
            if (stop != TRUE)
            {
               moduleID = naibrd_GetModuleID(cardIndex, module);
               if ((moduleID != 0))
               {
                  Run_SER_ASync_Rx(cardIndex, module, moduleID);
               }
            }
         }

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

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

/**************************************************************************************************************/
/** \ingroup SERAsyncRx
Configures a serial module for asynchronous receiving. The user is queried for the serial channel to receive on.
\param cardIndex (Input) Logical Card Index assigned to connection with the NAI_BOARD (0 - NAI_MAX_CARDS-1).
\param module    (Input) Module Number of the module to access (1 - [max modules for board]).
\param moduleID  (Input) The ID of the module.
*/
/**************************************************************************************************************/
void Run_SER_ASync_Rx(int32_t cardIndex, int32_t module, uint32_t moduleID)
{
   int32_t ch, i;
   int32_t channelCount;
   int32_t chanNum;
   int32_t nCntlValueLo;
   int32_t nNumWordsRecv = 0;
   uint32_t RecvDataStatus[MAX_DATA_RX];
   bool_t bQuit = FALSE;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   channelCount = naibrd_SER_GetChannelCount(moduleID);
   naiapp_query_ChannelNumber(channelCount, 1, &chanNum);

   naibrd_SER_ChannelReset(cardIndex, module, chanNum);
   naibrd_SER_ClearRxFifo(cardIndex, module, chanNum);
   naibrd_SER_ClearTxFifo(cardIndex, module, chanNum);
   nCntlValueLo = NAI_SER_CTRLLO_CLEAR_RX_FIFO | NAI_SER_CTRLLO_CLEAR_TX_FIFO;
   for (i = 0; i < CLEAR_FIFO_TIMEOUT && (nCntlValueLo & (NAI_SER_CTRLLO_CLEAR_RX_FIFO | NAI_SER_CTRLLO_CLEAR_TX_FIFO)); i++)
   {
      nai_ser_chanctrl chanCtrlRaw;
      naibrd_SER_GetChannelControlRaw(cardIndex, module, chanNum, &chanCtrlRaw);
      nCntlValueLo = chanCtrlRaw & 0x0000FFFF;
      nai_msDelay(1);
   }
   if (i == CLEAR_FIFO_TIMEOUT)
   {
      printf("Unable to clear FIFOs %d\n", chanNum);
      printf("Please press Enter to exit...");
      while ((ch = getchar()) != 0x0A);
      return;
   }

   printf("\nSerial Channel # %d\n", chanNum);

   /* Configure for ASync on the channel selected. */
   check_status(naibrd_SER_SetProtocol(cardIndex, module, chanNum, NAI_SER_PROTOCOL_ASYNC));       /* Async mode */
   check_status(naibrd_SER_SetInterfaceLevel(cardIndex, module, chanNum, NAI_SER_INTF_LOOPBACK));  /* LoopBack */
   check_status(naibrd_SER_SetParity(cardIndex, module, chanNum, NAI_SER_PARITY_NONE));            /* No Parity */
   check_status(naibrd_SER_SetDataBits(cardIndex, module, chanNum, 8));                            /* 8 Data Bits */
   check_status(naibrd_SER_SetStopBits(cardIndex, module, chanNum, 1));                            /* 1 Stop Bits */
   check_status(naibrd_SER_SetBaudrate(cardIndex, module, chanNum, 9600));                         /* 9600 baud */
   if (NAI_MODULE_ID_P8 == moduleID || NAI_MODULE_ID_PC == moduleID || NAI_MODULE_ID_PD == moduleID ||
      NAI_MODULE_ID_Px == moduleID || NAI_MODULE_ID_KB == moduleID)
   {
      nai_msDelay(20);     /* Allow 20ms for the HW to acknowledge the configuration (GEN 2/3 only)*/
   }
   check_status(naibrd_SER_SetReceiverEnable(cardIndex, module, chanNum, 1));                      /* Enable the Receiver */

   /* 100 millisecond wait to ensure the receiver is on. */
   nai_msDelay(100);

   printf("Please press Enter to read back data...");
   while ((ch = getchar()) != 0x0A);

   do
   {
      naibrd_SER_GetRxBufferCnt(cardIndex, module, chanNum, (uint32_t*)&nNumWordsRecv);
      printf("\nReading back %d words ...", nNumWordsRecv);
      naibrd_SER_ReceiveBuffer32(cardIndex, module, chanNum, RecvDataStatus, MAX_DATA_RX, (uint32_t*)&nNumWordsRecv); /* read back data */
      printf(" %d words read\n", nNumWordsRecv);

      for (i = 0; i < nNumWordsRecv; i++)
         printf("Recd 0x%02X, Status= %02X\n",
         (RecvDataStatus[i] & 0x00FF), (RecvDataStatus[i] >> 8) & 0x00FF);

      printf("Press ENTER to receive again, or '%c' to exit program : ", NAI_QUIT_CHAR);
      bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);

   } while (TRUE != bQuit);

   return;
}

Help Bot

X