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

Reg Editor BasicOps

Reg Editor BasicOps

Explanation

North Atlantic Industries Sample Application Code Explanation

Overview

This C program is an example of interacting with embedded function modules from North Atlantic Industries (NAI). It provides a user interface to read from and write to register addresses on NAI boards and modules. The program is designed to be cross-platform, with specific provisions for Linux, Windows (Win32 and Win64), and VxWorks environments.

Code Structure

  1. Header Files The code includes standard C headers for input/output, memory management, string manipulation, and others. Platform-specific headers for threading are included based on the defined platform macros.

  2. NAI Specific Includes The program includes several NAI-specific headers that provide functions for accessing and interacting with NAI boards and modules:

    • 'naiapp_boardaccess_menu.h'

    • 'naiapp_boardaccess_query.h'

    • 'naiapp_boardaccess_access.h'

    • 'naiapp_boardaccess_display.h'

    • 'naiapp_boardaccess_utils.h'

    • 'nai.h'

    • 'naibrd.h'

  3. Constants and Global Variables Several constants and global variables are defined for configuration files, file pointers, addresses, and data storage.

  4. Function Prototypes Function prototypes are declared for various operations such as running the basic menu, changing module functions, reading and writing registers, and saving register data to a file.

  5. Enumerations and Command Table An enumeration 'basicOpsMenu_commands' defines indices for various commands. A command table 'BasicOpMenuCmds' associates command strings, descriptions, command indices, and function pointers.

  6. Main Function The 'main()' function initializes the application and enters a loop where it queries the user for input, processes commands, and interacts with the NAI boards and modules.

  7. Menu Functions

    • 'BasicMenu_Run': Displays a menu and processes commands.

    • 'BasicMenu_Chng_Mod_Func': Changes the module being accessed.

    • 'BasicMenu_ReadReg_Func': Reads data from a register.

    • 'BasicMenu_WriteReg_Func': Writes data to a register.

    • 'BasicMenu_SaveRegFile_Func': Saves read data to a file.

  8. Helper Function

    • 'save_Last_Read': Saves the last read data to a file in a formatted manner.

Detailed Explanation

Header Inclusions

  • Standard C Library Headers: Common headers for input/output operations, memory management, and string manipulation.

  • Platform Detection: Conditional inclusion of threading libraries based on the operating system.

  • NAI Specific Headers: Include files for board and module access, user interface, and utility functions.

Constants and Global Variables

  • 'REG_FILE': Default file name for saved register data.

  • 'CONFIG_FILE': Configuration file for the application.

  • 'fp': File pointer for file operations.

  • 'savedAddress', 'savedCount', 'savedDataArray': Variables for storing read data details.

Function Prototypes

Function prototypes for key operations facilitate forward references in the code and improve readability.

Enumerations and Command Table

  • Enumeration 'basicOpsMenu_commands' defines command indices.

  • Command table 'BasicOpMenuCmds' associates commands with their respective functions.

Main Function

The main entry point ('main()') initializes the application and facilitates the user interface loop. It queries the user for input, processes commands, and interacts with NAI boards and modules.

Menu and Command Functions

  • 'BasicMenu_Run': Executes the main menu loop, displaying commands and processing user input.

  • 'BasicMenu_Chng_Mod_Func': Changes the module or motherboard to be accessed.

  • 'BasicMenu_ReadReg_Func': Reads data from a specified register and displays it.

  • 'BasicMenu_WriteReg_Func': Writes specified data to a register.

  • 'BasicMenu_SaveRegFile_Func': Saves the last read register data to a file.

Helper Function: 'save_Last_Read'

This function formats and writes the last read data to a specified file, providing a clear view of the data in both hexadecimal and ASCII formats.

Usage

To use this application, compile it with the appropriate platform settings and run the executable. The program will prompt the user to enter commands to read from, write to, and save register data from NAI boards and modules. The primary operations include:

  • Changing the module being accessed.

  • Reading from specified addresses.

  • Writing data to specified addresses.

  • Saving read data to a file.

Overall, this sample code showcases how to interact with NAI�s hardware using their API and libraries to perform common tasks such as reading and writing registers and saving configurations.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <math.h>
#include <ctype.h>
#if defined (LINUX)
#include <pthread.h>
#elif defined(_WIN32)
   #define PLATFORM "Win32"
#elif defined(_WIN64)
   #define PLATFORM "x64"
#else
   #define PLATFORM "not linux or windows"
#endif

/* 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"

#define REG_FILE "default_RegData.txt"

static const int8_t *CONFIG_FILE = (const int8_t *)"default_RegEditorConfig.txt";
FILE* fp = NULL;
static uint32_t savedAddress;
static uint32_t savedCount;
static uint32_t savedDataArray[4096];
/* Function prototypes */
static bool_t BasicMenu_Run(int32_t cardIndex, int32_t module);

static nai_status_t BasicMenu_Chng_Mod_Func(int32_t paramCount, int32_t* p_params);
int32_t save_Last_Read(FILE *deffile,uint32_t addr, int32_t len, int32_t dataWidth, void* p_data);
static nai_status_t BasicMenu_ReadReg_Func(int32_t paramCount, int32_t* p_params);
static nai_status_t BasicMenu_WriteReg_Func(int32_t paramCount, int32_t* p_params);
static nai_status_t BasicMenu_SaveRegFile_Func(int32_t paramCount, int32_t* p_params);


enum basicOpsMenu_commands
{
   BASICMENU_CHNG_MOD,
   BASICMENU_READ_REG,
   BASICMENU_WRITE_REG,
   BASICMENU_SAVE_REG_FILE,
   BASICMENU_CMD_COUNT
};

naiapp_cmdtbl_params_t BasicOpMenuCmds[] =
{
   { "C",        "Change Module Access",          BASICMENU_CHNG_MOD,                BasicMenu_Chng_Mod_Func       },
   { "R",        "Read Reg",                       BASICMENU_READ_REG,                BasicMenu_ReadReg_Func        },
   { "W",        "Write Reg",                      BASICMENU_WRITE_REG,               BasicMenu_WriteReg_Func       },
   { "S",        "Save Last Read",                  BASICMENU_SAVE_REG_FILE,           BasicMenu_SaveRegFile_Func    }
};

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

   if (naiapp_RunBoardMenu(CONFIG_FILE) == 1)
   {
      while (stop != 1)
      {
         /* Query the user for the card index */
         stop = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
         if (stop != 1)
         {
            check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));
            printf("\r\nEnter Module to access, or '0' for motherboard [defualt=0]:");
            stop = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
            if (!stop)
            {
               if (inputResponseCnt == 0)
               {
                  BasicMenu_Run(cardIndex, 0);
               }
               else
               {
                  module = atoi((const char*)inputBuffer);
                  BasicMenu_Run(cardIndex, module);
               }
            }
         }

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

static bool_t BasicMenu_Run(int32_t cardIndex, int32_t module)
{
   bool_t bQuit = 0, bCmdFound;
   int32_t cmd;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   naiapp_AppParameters_t  basicops_params;
   p_naiapp_AppParameters_t basicOps_params = &basicops_params;
   basicOps_params->cardIndex = cardIndex;
   basicOps_params->module = module;

   naiapp_utils_LoadParamMenuCommands(BASICMENU_CMD_COUNT,BasicOpMenuCmds);
   do
   {
      naiapp_display_ParamMenuCommands((int8_t*)"MENU_TITLE");
      printf("\r\nType command or %c to quit : ", NAI_QUIT_CHAR);
      bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
      if (!bQuit && inputResponseCnt > 0)
      {
         bCmdFound = naiapp_utils_GetParamMenuCmdNum(inputResponseCnt, inputBuffer, &cmd);
         if (bCmdFound)
         {
            switch (cmd)
            {
               case BASICMENU_CHNG_MOD:
               case BASICMENU_READ_REG:
               case BASICMENU_WRITE_REG:
               case BASICMENU_SAVE_REG_FILE:
                  BasicOpMenuCmds[cmd].func(APP_PARAM_COUNT, (int32_t*)basicOps_params);
                  break;
               default:
                  continue;
                  break;
            }
         }
         else printf("Invalid command entered\r\n");

      }
   } while (!bQuit);

   return 1;
}
static nai_status_t BasicMenu_Chng_Mod_Func(int32_t paramCount, int32_t* p_params)
{
   p_naiapp_AppParameters_t p_ad_params = (p_naiapp_AppParameters_t)p_params;
   bool_t bQuit = 0;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;
   int32_t cardIndex;
   int32_t module;
   int32_t moduleCnt;

   /* Query the user for the card index */
   bQuit = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
   if (bQuit != 1)
   {
      check_status(naibrd_GetModuleCount(cardIndex, &moduleCnt));
      printf("\r\nEnter Module to access, or '0' for motherboard [defualt=0]:");
      bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
      if (!bQuit)
      {
         if (inputResponseCnt == 0)
         {
            module = 0;
         }
         else
         {
            module = atoi((const char*)inputBuffer);
         }

         p_ad_params->cardIndex = cardIndex;
         p_ad_params->module = module;
      }
   }
   return NAI_SUCCESS;
}

static nai_status_t BasicMenu_ReadReg_Func(int32_t paramCount, int32_t* p_params)
{
   bool_t bQuit = 0;
   int8_t inputBuffer[80];

   int32_t inputResponseCnt;
   uint32_t count;
   uint32_t data[4096];
   p_naiapp_AppParameters_t p_ad_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_ad_params->cardIndex;
   int32_t module = p_ad_params->module;
   int32_t offset;
   uint32_t modBaseAddr=0;
   uint32_t address;

#if defined (WIN32)
   UNREFERENCED_PARAMETER(paramCount);
#endif

   printf("Enter valid offset: 0x");
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if (!bQuit)
   {
      while(inputResponseCnt==0 && !bQuit)
      {
         printf("Enter valid offset: 0x");
         bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);

      }
      if(!bQuit)
      {
         offset = strtol(((const char *)inputBuffer),NULL,16);
         naibrd_GetModuleOffset(cardIndex,module,&modBaseAddr);
         address = offset+modBaseAddr;

         /* reset buffer*/
         memset(inputBuffer,0,sizeof(inputBuffer));

         printf("Enter number of elements you would like to read:");
         bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
         if(!bQuit)
         {
            count=atoi((const char *)inputBuffer);
            count += ((count%4) != 0) ? (4-(count%4)) : 0;
            check_status(naibrd_Read32(cardIndex, module, offset,4,count,4,data));
            naiapp_display_DataInAscii(address,count,4,data);
         }

         memcpy(savedDataArray,data,sizeof(data));
         savedCount = count;
         savedAddress=address;
      }
   }
   return NAI_SUCCESS;
}

static nai_status_t BasicMenu_WriteReg_Func(int32_t paramCount, int32_t* p_params)
{
   bool_t bQuit = 0;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;
   uint32_t write=0;
   uint32_t offset;
   uint32_t count;
   uint32_t data[4096];
   p_naiapp_AppParameters_t p_ad_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_ad_params->cardIndex;
   int32_t module = p_ad_params->module;
   uint32_t modBaseAddr=0;
   uint32_t address;

   printf("Please enter a valid offset: 0x");
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if (!bQuit)
   {
      while(inputResponseCnt==0 && !bQuit)
      {
         printf("Please Enter valid offset: 0x");
         bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);

      }
      offset =  strtol(((const char *)inputBuffer),NULL,16);
      naibrd_GetModuleOffset(cardIndex,module,&modBaseAddr);
      address = offset+modBaseAddr;

      /*reset buffer*/
      memset(inputBuffer,0,sizeof(inputBuffer));

      printf("Enter number of elements you would like to write:");
      bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
      while(inputResponseCnt ==0 && !bQuit)
      {
         bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
      }
      if(!bQuit)
      {
         int i;
         count = atoi((const char *)inputBuffer);
         memset(inputBuffer,0,sizeof(inputBuffer));
         printf("Enter a decimal value for each address, or prefix with 0x for hex:\r\n");
         for (i=0;i<(int)count;i++)
         {
            printf("\r0x%08X: ", address + (i * 4));
            bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
            while(inputResponseCnt ==0 && !bQuit)
            {
               printf("\r0x%08X: ", address + (i * 4));
               bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
            }

            if(strstr((const char*)inputBuffer,"0x")==NULL)
            {
               write =atoi((const char *)inputBuffer);
               *data=write;
            }
            else
            {
               write=strtoul((const char *)inputBuffer,NULL,0);
               *data=write;
            }
            memset(inputBuffer,0,sizeof(inputBuffer));
            check_status(naibrd_Write32(cardIndex, module, offset,4,1,4, data));
            offset+=4;
         }
      }
   }
   return NAI_SUCCESS;
}

static nai_status_t BasicMenu_SaveRegFile_Func(int32_t paramCount, int32_t* p_params)
{
   bool_t bQuit = 0;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;
   p_naiapp_AppParameters_t p_ad_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = p_ad_params->cardIndex;
   int32_t module = p_ad_params->module;
   int32_t modid= naibrd_GetModuleID(cardIndex,module);
   char *modIdName = (char*)&modid;
   char filepathandname[162];

   printf("Enter a file name [default = %s]:", REG_FILE);
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if(!bQuit)
   {
      memset(filepathandname, 0, sizeof(filepathandname));
      if(inputResponseCnt==0)
      {
#if defined (WIN32)
         strcpy_s(filepathandname, sizeof(REG_FILE), (const char*)REG_FILE);
#else
         strcpy(filepathandname, (const char*)REG_FILE);
#endif
      }
      else
      {
#if defined(WIN32)
         strcpy_s(filepathandname, sizeof(inputBuffer), (const char*)inputBuffer);
#else
         strcpy(filepathandname, (const char*)inputBuffer);
#endif
      }
   }

   /* open the file for writing*/
#if defined (WIN32)
   fopen_s(&fp, (const char*)filepathandname, "w");
#else
   fp = fopen((const char*)filepathandname, "w");
#endif
   fprintf(fp,"Board Index: %d, %d", cardIndex, module);
   if (module > 0)
   {
      fprintf(fp,"Module No. %d, Module ID: %c%c%c%c\r\n", module, modIdName[3], modIdName[2], modIdName[1] ,modIdName[0]);
   }
   else
   {
      fprintf(fp,"Motherboard Register Space\r\n");
   }

   if(((savedAddress!=0) && (savedCount!=0)) || (savedDataArray!=NULL))
   {

      if(save_Last_Read(fp,savedAddress,savedCount,4,savedDataArray)==0)
      {
         printf("Saved %s!",filepathandname);
      }
      else
      {
         printf("Failed to save %s!",filepathandname);
      }
   }
   fclose(fp);

   return NAI_SUCCESS;
}
int32_t save_Last_Read(FILE *deffile,uint32_t addr, int32_t len, int32_t dataWidth, void* p_data)
{
   uint32_t colData[16];
   int32_t index;
   int32_t row;
   int32_t col;
   int32_t retValue = 0;
   int32_t missCnt;
   int32_t cnt;
   int32_t i;
   uint8_t ucChar;
   uint8_t* p_dataArray8 = (uint8_t*)p_data;
   uint16_t* p_dataArray16 = (uint16_t*)p_data;
   uint32_t* p_dataArray32 = (uint32_t*)p_data;

   /* Check data width */
   if (dataWidth == 1 || dataWidth == 2 || dataWidth == 4)
   {
      /* Print the Header */
      /*            00    02    04    06    08    0A    0C    0E    */
      /*            ----- ----- ----- ----- ----- ----- ----- ----- */
      /* Print the Data Header */
      fprintf(deffile,"\r            ");
      switch (dataWidth)
      {
      case 1:
         for (index = 0; index < (16 / dataWidth); index++)
         {
            fprintf(deffile,"%02X ", ((addr + (index * dataWidth)) & 0x0F));
         }
         fprintf(deffile,"\r\n            ");
         for (index = 0; index < (16 / dataWidth); index++)
         {
            fprintf(deffile,"-- ");
         }
         break;
      case 2:
         for (index = 0; index < (16 / dataWidth); index++)
         {
            fprintf(deffile,"%02X   ", ((addr + (index * dataWidth)) & 0x0F));
         }
         fprintf(deffile,"\r\n            ");
         for (index = 0; index < (16 / dataWidth); index++)
         {
            fprintf(deffile,"---- ");
         }
         break;
      case 4:
         for (index = 0; index < (16 / dataWidth); index++)
         {
            fprintf(deffile,"%02X       ", ((addr + (index * dataWidth)) & 0x0F));
         }
         fprintf(deffile,"\r            ");
         for (index = 0; index < (16 / dataWidth); index++)
         {
            fprintf(deffile,"-------- ");
         }
         break;
      default:
         fprintf(deffile,"   ");
         break;
      }

      /* Print the formatted data */
      index = 0;
      missCnt = 0;
      for (row = 0; row <= (len - 1) / (16 / dataWidth); row++)
      {
         /* Print the Hex values */
         fprintf(deffile,"\r0x%08X: ", addr + (index * dataWidth));
         for (col = 0; col < (16 / dataWidth); col++)
         {
            /* Print the Hex Value of the data */
            switch (dataWidth)
            {
            case 1:
               if (index == len)
               { /* No more data */
                  ++missCnt;
                  colData[col] = 0; /* Save data for ASCII Print */
                  fprintf(deffile,"   ");
               }
               else
               {
                  colData[col] = p_dataArray8[index]; /* Save data for ASCII Print */
                  fprintf(deffile,"%02X ", p_dataArray8[index++]);
               }
               break;
            case 2:
               if (index == len)
               { /* No more data */
                  ++missCnt;
                  colData[col] = 0; /* Save data for ASCII Print */
                  fprintf(deffile,"     ");
               }
               else
               {
                  colData[col] = p_dataArray16[index]; /* Save data for ASCII Print */
                  fprintf(deffile,"%04X ", p_dataArray16[index++]);
               }
               break;
            case 4:
               if (index == len)
               { /* No more data */
                  ++missCnt;
                  colData[col] = 0; /* Save data for ASCII Print */
                  fprintf(deffile,"         ");
               }
               else
               {
                  colData[col] = p_dataArray32[index]; /* Save data for ASCII Print */
                  fprintf(deffile,"%08X ", p_dataArray32[index++]);
               }
               break;
            default:
               fprintf(deffile,"   ");
               break;
            }
         }
         /* Print the data in ASCII */
         fprintf(deffile,"  ");
         for (col = 0; col < (16 / dataWidth); col++)
         {
            if (col > ((16 / dataWidth) - missCnt) - 1)
            { /* No more data, print blanks */
               switch (dataWidth)
               {
               case 1:
                  fprintf(deffile,"  ");
                  break;
               case 2:
                  fprintf(deffile,"   ");
                  break;
               case 4:
                  fprintf(deffile,"     ");
                  break;
               default:
                  fprintf(deffile,"  ");
                  break;
               }
            }
            else
            { /* Print the ASCII Value of the data */
               switch (dataWidth)
               {
               case 1:
                  cnt = 1;
                  break;
               case 2:
                  cnt = 2;
                  break;
               case 4:
                  cnt = 4;
                  break;
               default:
                  cnt = 0;
                  break;
               }
               for (i = 1; i <= cnt; i++)
               {
                  ucChar = (colData[col] >> (8 * (cnt - i))) & 0xFF;
                  if (isprint(ucChar))
                  {
                     fprintf(deffile,"%c", ucChar);
                  }
                  else
                  {
                     fprintf(deffile,".");
                  }
               }
               fprintf(deffile," ");
            }
         }
      }
      fprintf(deffile,"\r\n");
   }
   else
   {
      retValue = -1; /* Invalid data width */
   }
   return retValue;
}

Help Bot

X