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 HDLC Rx

SER HDLC Rx

Explanation

About the Sample Application Code

This C application interacts with North Atlantic Industries (NAI) embedded function modules using NAI’s Software Support Kit (SSK). The sample code configures a module for Serial High-Level Data Link Control (HDLC) reception. Below is an overview and a step-by-step explanation of the application.

Overview

Definitions and Enumerations: - 'CONFIG_FILE': Path to the configuration file. - 'MAX_DATA_RX', 'MAX_TIMEOUT', and 'CLEAR_FIFO_TIMEOUT': Constants for buffer size and timeout durations. - 'NAI_QUIT_CHAR': Character to terminate the application loop.

Include Files: - Standard libraries: 'stdio.h', 'stdlib.h', 'string.h', 'time.h', and 'ctype.h'. - NAI-specific headers for board access, querying, displaying, and utility functions.

Function Prototypes: - 'void Run_SER_HDLC_Rx(int32_t cardIndex, int32_t module, uint32_t modid)': Configures and runs HDLC reception.

Application Walkthrough

Main Entry Point

int32_t main(void)
{
   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_HDLC_Rx(cardIndex, module, moduleID);
               }
            }
         }

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

Explanation: 1. Initializes multiple variables for managing user input and module details. 2. Runs a configurable board access menu ('naiapp_RunBoardMenu'). 3. Enters a loop to interact with the user for card and module selection. 4. Uses 'naiapp_query_CardIndex' to determine which card is being used. 5. Obtains the module count with 'naibrd_GetModuleCount'. 6. Queries the user for module number using 'naiapp_query_ModuleNumber'. 7. Gets the module ID using 'naibrd_GetModuleID'. 8. Calls 'Run_SER_HDLC_Rx' to configure and run the HDLC reception if a valid module ID is retrieved. 9. Prompts the user to either quit or restart the application. 10. Closes all open cards and exits when prompted.

HDLC Reception Function

void Run_SER_HDLC_Rx(int32_t cardIndex, int32_t modNum, uint32_t modid)
{
   int32_t ch, i;
   int32_t channelCount;
   int32_t chanNum;
   int32_t nCntlValueLo, nConfigWordLo;
   int32_t nNumWordsRecv = 0;
   uint32_t RecvDataStatus[255];
   bool_t bQuit = FALSE;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

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

   naibrd_SER_ChannelReset(cardIndex, modNum, chanNum);
   naibrd_SER_ClearRxFifo(cardIndex, modNum, chanNum);
   naibrd_SER_ClearTxFifo(cardIndex, modNum, 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, modNum, 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, modNum, chanNum, NAI_SER_PROTOCOL_HDLC));
   check_status(naibrd_SER_SetInterfaceLevel(cardIndex, modNum, chanNum, NAI_SER_INTF_RS422));
   check_status(naibrd_SER_SetClockMode(cardIndex, modNum, chanNum, TXINT_RXINT));
   check_status(naibrd_SER_SetBaudrate(cardIndex, modNum, chanNum, 115200));
   check_status(naibrd_SER_SetRxHdlcAddrsSyncChar(cardIndex, modNum, chanNum, 0x247A));
   nConfigWordLo = (NAI_SER_CFGLO_ADDR_LEN_16 | NAI_SER_CFGLO_ADDR_REC);
   check_status(naibrd_SER_SetChannelConfigRaw(cardIndex, modNum, chanNum, nConfigWordLo));

   if (NAI_MODULE_ID_P8 == modid || NAI_MODULE_ID_PC == modid || NAI_MODULE_ID_PD == modid ||
      NAI_MODULE_ID_Px == modid || NAI_MODULE_ID_KB == modid)
   {
      nai_msDelay(20);
   }
   check_status(naibrd_SER_SetReceiverEnable(cardIndex, modNum, chanNum, 1));

   nai_msDelay(100);

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

   do
   {
      check_status(naibrd_SER_GetHDLCPacket32(cardIndex, modNum, chanNum, RecvDataStatus, MAX_DATA_RX,
         (uint32_t*)&nNumWordsRecv, MAX_TIMEOUT));
      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;
}

Explanation: 1. Queries the number of channels for the given module using 'naibrd_SER_GetChannelCount'. 2. Asks the user for the channel number using 'naiapp_query_ChannelNumber'. 3. Resets, clears the RX/TX FIFO buffers, and waits for them to clear. 4. Configures the serial channel for HDLC reception with specific baud rate and protocol settings. 5. Enables the receiver and waits for the user to press Enter to start reading data. 6. Enters a loop to read HDLC packets and displays received data until the user opts to quit.

Summary

This application uses NAI’s SSK to set up a module for Serial HDLC reception, illustrating steps from configuration to data reception. It uses utility, querying, and board access functions provided by NAI’s libraries to interact with the hardware.

#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_SerHDLC_Rx.txt";

/* Function prototypes */
void Run_SER_HDLC_Rx(int32_t cardIndex, int32_t module, uint32_t modid);

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

/**************************************************************************************************************/
/** \defgroup SERHDLCRx Serial Synchronous Receive
The purpose of the Serial Synchronous Receive sample application is to illustrate the methods to call in the
naibrd library to configure a given serial channel for receiving. The SER_HDLC_Tx application can be run in
unison to this application to receive serial data.
*/
/**************************************************************************************************************/
#if defined (__VXWORKS__)
int32_t SER_HDLC_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 the user for the card index */
         stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
         if (stop != TRUE)
         {
            check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));

            /* Query the 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_HDLC_Rx(cardIndex, module, moduleID);
               }
            }
         }

         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 SERHDLCRx
Configures a serial module for synchronous 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 modNum    (Input) Module Number of the module to access (1 - [max modules for board]).
\param modid  (Input) The ID of the module.
*/
/**************************************************************************************************************/
void Run_SER_HDLC_Rx(int32_t cardIndex, int32_t modNum, uint32_t modid)
{
   int32_t ch, i;
   int32_t channelCount;
   int32_t chanNum;
   int32_t nCntlValueLo, nConfigWordLo;
   int32_t nNumWordsRecv = 0;
   uint32_t RecvDataStatus[255];
   bool_t bQuit = FALSE;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

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

   naibrd_SER_ChannelReset(cardIndex, modNum, chanNum);
   naibrd_SER_ClearRxFifo(cardIndex, modNum, chanNum);
   naibrd_SER_ClearTxFifo(cardIndex, modNum, 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, modNum, 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 HDLC on the channel selected. */
   check_status(naibrd_SER_SetProtocol(cardIndex, modNum, chanNum, NAI_SER_PROTOCOL_HDLC));        /* HDLC mode */
   check_status(naibrd_SER_SetInterfaceLevel(cardIndex, modNum, chanNum, NAI_SER_INTF_RS422));     /* RS422 */
   check_status(naibrd_SER_SetClockMode(cardIndex, modNum, chanNum, TXINT_RXINT));                 /* Tx and Rx internal */
   check_status(naibrd_SER_SetBaudrate(cardIndex, modNum, chanNum, 115200));                       /* 115,200 baud */
   check_status(naibrd_SER_SetRxHdlcAddrsSyncChar(cardIndex, modNum, chanNum, 0x247A));            /* recv sync char - must be same as xmit for loopback */
   nConfigWordLo = (NAI_SER_CFGLO_ADDR_LEN_16 | NAI_SER_CFGLO_ADDR_REC);                           /* 16-bit HDLC addr recognition */
   check_status(naibrd_SER_SetChannelConfigRaw(cardIndex, modNum, chanNum, nConfigWordLo));

   if (NAI_MODULE_ID_P8 == modid || NAI_MODULE_ID_PC == modid || NAI_MODULE_ID_PD == modid ||
      NAI_MODULE_ID_Px == modid || NAI_MODULE_ID_KB == modid)
   {
      nai_msDelay(20);     /* Allow 20ms for the HW to acknowledge the configuration (GEN 2/3 only)*/
   }
   check_status(naibrd_SER_SetReceiverEnable(cardIndex, modNum, 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
   {
      check_status(naibrd_SER_GetHDLCPacket32(cardIndex, modNum, chanNum, RecvDataStatus, MAX_DATA_RX,
         (uint32_t*)&nNumWordsRecv, MAX_TIMEOUT));
      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