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

DA PatternGenerator

DA PatternGenerator

Explanation

About the Application Code for North Atlantic Industries' Embedded Function Modules

This C sample application code illustrates the usage of North Atlantic Industries' Standard Software Kit (SSK) to interact with their embedded function modules. It focuses on configuring and operating a Digital-to-Analog (D/A) Pattern Generator.

Overview and Dependencies

Required Libraries and Headers - Standard Libraries: stdio.h, ctype.h, stdlib.h, string.h, time.h, math.h. - Platform-specific Headers: On Windows (WIN32), io.h is included. On other platforms, dirent.h is used. - NAI Specific Include Files: - naiapp_boardaccess_menu.h, naiapp_boardaccess_query.h, naiapp_boardaccess_access.h, naiapp_boardaccess_display.h, naiapp_boardaccess_utils.h - nai.h, naibrd.h, naibrd_da.h, nai_ether_adv.h, naibrd_gen5.h

Constants and Data Structures - Constants: - CONFIG_FILE: The path to the default configuration file. - MAX_NUM_PATTERN_FILES, MAX_FILE_NAME_SIZE, MAX_LINE_SIZE: Various limits for handling files and data.

  • Structures: PatternInfo contains details about the pattern to be generated, including:

  • patternFileName: Name of the pattern file.

  • sampleRate: Sample rate for the pattern.

  • range: Voltage range.

  • polarity: Voltage polarity.

  • dataLength: Length of the data.

  • data: Pointer to the data array.

Function Prototypes - Main application function and helper functions: - Run_DA_PatternGenerator(), GeneratePattern(), GetPatternFileList(), LoadPatternFile(), GetParamFromLine(), GetDataFromPatternFile(), SupportsDAFuncGeneration()

Detailed Code Walkthrough

Main Function The main() function initializes the D/A Pattern Generator application. Under both VxWorks and other environments: 1. Run Board Menu: Calls naiapp_RunBoardMenu(). 2. User Queries: Utilizes naiapp_query_* functions to get user inputs for card index, module number, etc. 3. Module Identification: Fetches and verifies module information using naibrd_GetModuleID(). 4. Pattern Generation: If the module ID is valid, it executes Run_DA_PatternGenerator() for pattern generation.

Run_DA_PatternGenerator Function This function sets up and runs the D/A Pattern Generator: 1. User Inputs: Queries the user for card and module details. 2. Validation: Checks if the selected module supports floating point mode and queries the user for enabling it. 3. Pattern Files: Lists available pattern files (GetPatternFileList()) and prompts the user to select one. 4. Load and Generate Pattern: Loads the selected pattern file (LoadPatternFile()) and generates the pattern (GeneratePattern()).

GeneratePattern Function Handles the actual loading of the pattern into the D/A module and setting various parameters: 1. Sample Rate: Sets using naibrd_DA_SetFIFORate(). 2. Operation Mode: Configures using naibrd_DA_SetOpMode(). 3. Polarity and Range: Sets using naibrd_DA_SetRange(). 4. Addresses: Configures start and end addresses using naibrd_DA_SetPatternGenStartAddr() and naibrd_DA_SetPatternGenEndAddr(). 5. Writing Data: Loads the data using naibrd_DA_SetPatternGenData(). 6. Toggle Output: Enables or disables the pattern output based on user input.

Helper Functions for Pattern File Handling Functions like GetPatternFileList(), LoadPatternFile(), GetParamFromLine(), and GetDataFromPatternFile() handle pattern file processing: - Pattern File Listing: Searches for files with .ptrn extension. - Loading and Parsing: Reads parameters and data from the pattern file, checks formats, and allocates memory for the data.

Support Check for DA Functionality - SupportsDAFuncGeneration(): Checks if the module supports the DA functionality based on its module ID.

Explanation of Enumerations and Key Variables - Enumerations: Used for indicating enabling/disabling states and operation modes. - Key Variables: - cardIndex, module, channel: Indices selected by the user. - patternInfo: Structure holding pattern information.

This application provides a comprehensive example of setting up and using the D/A Pattern Generator provided by North Atlantic Industries, incorporating user interactions, configuration, pattern file handling, and actual pattern generation on supported modules.

#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <math.h>
#if WIN32
#include <io.h>
#else
#include <dirent.h>
#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"
#include "functions/naibrd_da.h"
#include "advanced/nai_ether_adv.h"
#include "boards/naibrd_gen5.h"

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

#define MAX_NUM_PATTERN_FILES 20
#define MAX_FILE_NAME_SIZE 100
#define MAX_LINE_SIZE 256

typedef struct _PatternInfo
{
   char patternFileName[MAX_FILE_NAME_SIZE];
   uint32_t sampleRate;
   uint32_t range;
   uint32_t polarity;
   uint32_t dataLength;
   float64_t *data;
} PatternInfo;

/* Function prototypes */
static int32_t Run_DA_PatternGenerator(void);
static int32_t GeneratePattern( int32_t cardIndex, int32_t module, int32_t channel, PatternInfo *patternInfo );
static int32_t GetPatternFileList( char patternFileNames[][MAX_FILE_NAME_SIZE], int32_t *numPatternFiles );
static int32_t LoadPatternFile( char patternFileName[], PatternInfo *patternInfo );
static int32_t GetParamFromLine( char line[], char paramName[], char paramValue[] );
static int32_t GetDataFromPatternFile( FILE *file, uint32_t *dataLength, float64_t **patternData );
static bool_t SupportsDAFuncGeneration(uint32_t moduleID);

/************************************************************************
GEN 5
-----
The DA Fifo Size is 26,213
 The DA Fifo Output Data Rate is 2.50 usec.
 Thus the DA Fifo Output Frequency is (1/2.50 usec) or 400 kHz.

The Maximum Output Frequency is:
      Max Request Frequency = DA Fifo Output Frequency/Fifo Size
                            = 400 kHz/26213
                            = 15.260
************************************************************************/

/**************************************************************************************************************/
/**
<summary>
DA_PatternGenerator illustrates setting up the D/A Pattern Generator to generate various types of outputs. Output
 data is read in from a file, loaded into the DA Pattern RAM, and then set to loop the pattern.
</summary>
*/
/**************************************************************************************************************/
#if defined (__VXWORKS__)
int32_t DA_PatternGenerator(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_DA_PatternGenerator();
               }
            }
         }

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

/**************************************************************************************************************/
/**
<summary>

</summary>
*/
/**************************************************************************************************************/
static int32_t Run_DA_PatternGenerator(void)
{
   bool_t bQuit = FALSE;
   bool_t bContinue = TRUE;
   int32_t cardIndex = -1, module = 1, channel = 1;
   nai_status_t status;
   int32_t MaxModule, MaxChannel;
   uint32_t moduleID;
   char patternFileNames[MAX_NUM_PATTERN_FILES][MAX_FILE_NAME_SIZE];
   int32_t numPatternFiles;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   /* Query user on the Card and Module to use for this example */
   bQuit = naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
   if (!bQuit)
   {
      status = check_status(naibrd_GetModuleCount(cardIndex, &MaxModule));
      if (status == NAI_SUCCESS)
      {
         bContinue = TRUE;
         while (bContinue)
         {
            bQuit = naiapp_query_ModuleNumber(MaxModule, 1, &module);
            if (!bQuit)
            {
               /* Get the number of D/A channels on the module */
               moduleID = naibrd_GetModuleID(cardIndex, module);
               if (SupportsDAFuncGeneration(moduleID))
               {
                  bool_t floatingPointMode = FALSE;
                  bool_t floatingPointCapable = FALSE;

                  /* If this module supports H/W floatingPoint, then query the user to enable it. */
                  naibrd_GetFloatingPointModeCapability(cardIndex, module, &floatingPointCapable);
                  if (FALSE != floatingPointCapable)
                  {
                     printf("This module supports H/W floating point conversion. Do you want to enable it? If not, software converting will\n");
                     printf(" be used (slower and processor intensive) (default: Y)");
                     inputResponseCnt = 0;
                     bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
                     if ((toupper(inputBuffer[0]) == 'Y') || (inputResponseCnt == 0))
                     {
                        naibrd_SetFloatingPointModeEnable(cardIndex, module, TRUE);
                     }
                     else
                     {
                        naibrd_SetFloatingPointModeEnable(cardIndex, module, FALSE);
                     }

                     /* Make sure FloatingPoint was enabled/disabled */
                     naibrd_GetRunningInFloatingPointMode(cardIndex, module, &floatingPointMode);
                     if (FALSE == floatingPointMode)
                     {
                        printf("**Floating point mode is disabled!**\n");
                     }
                     else
                     {
                        printf("**Floating point mode is enabled.**\n");
                     }
                  }

                  MaxChannel = naibrd_DA_GetChannelCount(moduleID);

                  /* Get the DA channel */
                  printf("\nD/A Setup\n");
                  printf("---------------------\n");
                  printf("D/A Channel Selection:");
                  bQuit = naiapp_query_ChannelNumber(MaxChannel, 1, &channel);
                  bContinue = FALSE;
               }
               else
                  printf("ERROR: Module selected does not support DA Functionality\n");
            }
            else
               bContinue = FALSE;
         }
      }

      /* Get a list of available pattern files */
      GetPatternFileList( patternFileNames, &numPatternFiles );

      /* Prompt user for the Pattern File */
      if ( 0 < numPatternFiles )
      {
         PatternInfo patternInfo;
         int32_t patternFileIndex = 0;

         if ( 1 == numPatternFiles )
         {
            printf("1 Pattern File found. ");
         }
         else
         {
            printf( "List of Pattern Files:\n\n");

            for( patternFileIndex = 0; patternFileIndex < numPatternFiles; patternFileIndex++ )
            {
               printf( "%d) %s\n", patternFileIndex + 1, patternFileNames[patternFileIndex] );
            }

            do
            {
               printf( "\n\nPlease select a Pattern File (1 - %d):\n", numPatternFiles );
               bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
               patternFileIndex = inputBuffer[0] - 0x31;
            } while ( (patternFileIndex < 0) || (patternFileIndex >= numPatternFiles));
         }

         /* Load the pattern file */
         printf( "Loading Pattern file %s...", patternFileNames[patternFileIndex] );
         if ( 0 == LoadPatternFile(patternFileNames[patternFileIndex], &patternInfo) )
         {
            printf("Done.\n");

            /* Load the pattern into the D/A and output the signal. */
            GeneratePattern(cardIndex, module, channel, &patternInfo);
         }
         else
         {
            printf("\nError loading pattern file! Can not generate output. Press ENTER to quit.\n");
            getchar();
         }
      }
      else
      {
         printf("No pattern files found!\n");
         bContinue = FALSE;
      }

      if (bQuit)
         bContinue = FALSE;
      else
         bContinue = TRUE;
   }

   return cardIndex;
}

static int32_t GeneratePattern( int32_t cardIndex, int32_t module, int32_t channel, PatternInfo *patternInfo )
{
   nai_da_enable_t patternEnable = NAI_DA_ENABLE;
   int key;
   const char szPolarity[][10] = { "UniPolar", "BiPolar" };
   uint32_t startAddress = 0, endAddress = 0;

   /* Set Sample Rate */
   printf("Setting Sample Rate to %u\n", patternInfo->sampleRate);
   check_status(naibrd_DA_SetFIFORate(cardIndex, module, channel, patternInfo->sampleRate));

   /* Set Operation Mode */
   printf("Setting Operation Mode to VOLTAGE_PATTERN_GEN.\n");
   check_status(naibrd_DA_SetOpMode(cardIndex, module, channel, NAI_DA_DATA_VOLTAGE_PATTERN_GEN));

   /* Set Polarity and Range */
   printf("Setting Range to %uv, Polarity to %s.\n", patternInfo->range, szPolarity[patternInfo->polarity]);
   check_status(naibrd_DA_SetRange(cardIndex, module, channel, NAI_DA_DATA_VOLTAGE_PATTERN_GEN,
      patternInfo->polarity, patternInfo->range));

   /* Set the Start and End Addresses. */
   startAddress = 0x20000 * channel;
   printf("Setting START Address to 0x%4X.\n", startAddress );
   check_status(naibrd_DA_SetPatternGenStartAddr(cardIndex, module, channel, startAddress));

   endAddress = startAddress + ((patternInfo->dataLength - 1) * sizeof(uint32_t));
   printf("Setting END Address to 0x%4X.\n", endAddress);
   check_status(naibrd_DA_SetPatternGenEndAddr(cardIndex, module, channel, endAddress));

   printf("Amount of data to write: (%u items x 4 bytes/item) = %u (0x%04X) total bytes.\n", patternInfo->dataLength,
      patternInfo->dataLength * 4, patternInfo->dataLength * 4);

   /* Write the pattern to the D/A and free allocated memory*/
   printf("Writing pattern data to RAM..");
   check_status(naibrd_DA_SetPatternGenData(cardIndex, module, channel, patternInfo->dataLength, patternInfo->data));
   free(patternInfo->data);
   printf("Done.\n");

   /* Toggle the Pattern output Enable and Disable based on user input. */
   do
   {
      check_status(naibrd_DA_SetPatternGenCtrl(cardIndex, module, channel, NAI_DA_CTRL_PATTERN_ENABLE, patternEnable));

      if ( NAI_DA_ENABLE == patternEnable )
      {
         printf( "Pattern is ENABLED.\n" );
         patternEnable = NAI_DA_DISABLE;
      }
      else
      {
         patternEnable = NAI_DA_ENABLE;
         printf( "Pattern is DISABLED.\n" );
      }

      printf("Hit ENTER to toggle output, Type 'q' to quit\n" );
      for (key = getchar(); ('q' != key) && ('Q' != key) && ('\n' != key); key = getchar());

   } while ( ('q' != key) && ('Q' != key) );

   /* Disable the output before exiting. */
   check_status(naibrd_DA_SetPatternGenCtrl(cardIndex, module, channel,NAI_DA_CTRL_PATTERN_ENABLE, NAI_DA_DISABLE));

   return 0;
}

#if WIN32
static int32_t GetPatternFileList( char patternFileNames[][MAX_FILE_NAME_SIZE], int32_t *numPatternFiles )
{
   intptr_t hFile;
   struct _finddata_t finddata;
   int32_t done;

   /* Search the directory for files with the .ptrn extension */
   *numPatternFiles = 0;
   hFile = _findfirst( "*.ptrn", &finddata );

   done = ( 0 >= hFile );

   while(!done)
   {
      strcpy( patternFileNames[*numPatternFiles], finddata.name );
      (*numPatternFiles)++;

      done = _findnext(hFile, &finddata);
   }

   _findclose(hFile);

   return 0;
}
#else
static int32_t GetPatternFileList( char patternFileNames[][MAX_FILE_NAME_SIZE], int32_t *numPatternFiles )
{
   DIR *dir;
   struct dirent *entry;
   int32_t done;

   /* Search the directory for files with the .ptrn extension */
   *numPatternFiles = 0;
   dir = opendir( "./" );

   done = ( NULL == dir );

   while(!done)
   {
      entry = readdir(dir);
      if (NULL != entry)
      {
         if (NULL != strstr(entry->d_name, ".ptrn"))
         {
            strcpy( patternFileNames[*numPatternFiles], entry->d_name );
            (*numPatternFiles)++;
         }
      }
      else
         done = TRUE;
   }

   closedir(dir);

   return 0;
}
#endif

static int32_t LoadPatternFile( char patternFileName[], PatternInfo *patternInfo )
{
   char paramValue[20];
   FILE *file;
   int32_t retVal = 0;

   strcpy( patternInfo->patternFileName, patternFileName );

   /* Open Pattern File for reading */
   file = fopen( patternInfo->patternFileName, "r" );

   if ( NULL != file )
   {
      char line[MAX_LINE_SIZE];

      /*** Load Parameters ***/
      while ( (0 == retVal) && (fgets(line, MAX_LINE_SIZE, file)) )
      {
         if ( '/' != line[0] && '*' != line[1] )
         {
            if ( 0 == GetParamFromLine(line, "SAMPLE_RATE", paramValue) )
               sscanf( paramValue, "%u", &(patternInfo->sampleRate) );
            else if ( 0 == GetParamFromLine(line, "POLARITY", paramValue) )
            {
               if ( 0 == strcmp(paramValue, "BIPOLAR") )
                  patternInfo->polarity = 1;
               else if ( 0 == strcmp(paramValue, "UNIPOLAR") )
                  patternInfo->polarity = 0;
               else
               {
                  printf( "\nIllegal value specified for the POLARITY parameter (%s?). Please check the pattern file!\n",
                     paramValue );
                  retVal = -1;
               }
            }
            else if ( 0 == GetParamFromLine(line, "RANGE", paramValue) )
               sscanf( paramValue, "%u", &(patternInfo->range) );
            else if ( NULL != strstr(line, "DATA") )
               retVal = GetDataFromPatternFile(file, &(patternInfo->dataLength), &(patternInfo->data));
         }
      }

      /*** END Load Parameters ***/
      fclose(file);
   }

   return retVal;
}

static int32_t GetParamFromLine( char line[], char paramName[], char paramValue[] )
{
   int32_t retVal = -1;

   if ( NULL != strstr(line, paramName) )
   {
      char *lineData = strstr(line, "=");
      char *newLine;

      (lineData)++;
      if ( NULL != lineData )
      {
         while ( ' ' == *lineData )
            lineData++;

         newLine = strrchr(lineData, '\r');
         if (NULL != newLine)
            *newLine = '\0';
         else
         {
            newLine = strrchr(lineData, '\n');
            if (NULL != newLine)
               *newLine = '\0';
         }

         strcpy(paramValue, lineData);

         retVal = 0;
      }
   }

   return retVal;
}

static int32_t GetDataFromPatternFile( FILE *file, uint32_t *dataLength, float64_t **patternData )
{
   int32_t retVal = 0;
   char lineData;
   long fpos;
   uint32_t patternDataIndex = 0;
   bool_t doneReadingFile = FALSE;

   *dataLength = 0;

   do
   {
      lineData = (char)fgetc(file);
   } while ( '=' == lineData || ' ' == lineData || '\n' == lineData );

   /* Store this location, we'll need to come back after counting the ',' */
   fpos = ftell(file);
   fpos--;

   /* Count the ',' to determine how much data is in the file. */
   do
   {
      lineData = (char)fgetc(file);

      if ( (char)EOF == lineData || ',' == lineData )
         (*dataLength)++;
   } while ( (char)EOF != lineData );

   /* Allocate memory based on the count */
   *patternData = (float64_t*)malloc(*dataLength * sizeof(float64_t));

   /* Read the data */
   fseek(file, fpos, SEEK_SET);

   while (!doneReadingFile)
   {
      char data[20];
      int32_t dataIndex = 0;
      bool_t dataItemDone = FALSE;

      /* Parse a datum */
      do
      {
         data[dataIndex] = (char)fgetc(file);

         if ((char)EOF == data[dataIndex])
         {
            /* Finished parsing last datum.. finished with file. */
            data[dataIndex] = '\0';
            dataItemDone = TRUE;
            doneReadingFile = TRUE;
         }
         else if (',' == data[dataIndex])
         {
            /* Finished parsing a datum.. still more data to parse. */
            data[dataIndex] = '\0';
            dataItemDone = TRUE;
         }
         else
            dataIndex++;

      } while (!dataItemDone);

      /* Store this datum as pattern data. */
      sscanf( data, "%lf", &(*patternData)[patternDataIndex] );

      patternDataIndex++;
   }

   return retVal;
}

static bool_t SupportsDAFuncGeneration(uint32_t moduleID)
{
   bool_t bSupportDAFunc = FALSE;

   switch (moduleID)
   {
   case NAI_MODULE_ID_DA3:
      bSupportDAFunc = TRUE;
      break;
   default:
      bSupportDAFunc = FALSE;
      break;
   }

   return bSupportDAFunc;
}

Help Bot

X