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 FunctionGenerator

DA FunctionGenerator

Explanation

About This Application Code

Overview

This C application is designed to illustrate the usage of North Atlantic Industries (NAI) Software Support Kit (SSK) for interacting with embedded function modules, particularly focusing on the Digital to Analog (DA) function generator module. This program demonstrates setting up the DA FIFO to generate different types of outputs such as: 1. Constant Voltage 2. Square Wave 3. Triangle Wave 4. Sawtooth Wave 5. Sine Wave

The application prompts the user to select a card index and module number, and further assists in generating the specified waveforms based on user input.

Key Components and Definitions

Include Directives - Standard Libraries: - stdio.h: Standard Input/Output definitions - stdlib.h: Standard library definitions including dynamic memory management, random numbers, etc. - string.h: String manipulation functions - time.h: Time and date functions - math.h: Mathematical functions - ctype.h: Character type functions

  • Common Sample Program Files: Files specific to NAI applications to manage board access, queries, display, and utilities.

  • "include/naiapp_boardaccess_menu.h"

  • "include/naiapp_boardaccess_query.h"

  • "include/naiapp_boardaccess_access.h"

  • "include/naiapp_boardaccess_display.h"

  • "include/naiapp_boardaccess_utils.h"

  • NAI Board Include Files: Including specific board access functions and data acquisition functions.

  • "nai.h"

  • "naibrd.h"

  • "functions/naibrd_da.h"

  • "advanced/nai_ether_adv.h"

Constant Definitions - CONFIG_FILE: Path to the default configuration file.

Function Prototypes - The application defines multiple static functions for generating different waveforms and initializing the DA FIFOs. - Run_DA_FunctionGenerator(): Manages the process of setting up the DA Function Generator. - Several specialized functions for generating different waveforms: - DA_GenerateConstantVoltage() - DA_GenerateSquareWave() - DA_GenerateTriangleWave() - DA_GenerateSawToothWave() - DA_GenerateSineWave() - Utility functions for parameter queries and FIFO initialization: - QueryForDAFuncGeneratorParameters() - Initialize_DAFifo() - GetNumberOfDAFifoDataPoints() - SupportsDAFuncGeneration()

Command Table Enumeration Defines commands for the function generator menu: - DA_FUNCGEN_CMD_CONSTANT_VOLT - DA_FUNCGEN_CMD_SQUARE_WAVE - DA_FUNCGEN_CMD_TRIANGLE_WAVE - DA_FUNCGEN_CMD_SAWTOOTH_WAVE - DA_FUNCGEN_CMD_SINE_WAVE - DA_FUNCGEN_CMD_COUNT

Command Tables An array DA_FuncGenMenuCmds associates command strings with respective function pointers.

GEN2 / GEN3 / GEN5 Definitions Defines the differences in handling FIFO for GEN3 and GEN5 DA modules such as FIFO size, data rate, and maximum frequencies.

Main Application - The main() function initializes the DA Function Generator demonstration. - It utilizes naiapp_RunBoardMenu() to run the initial board query and setup. - Depending on user input, it queries the card index and module number and calls Run_DA_FunctionGenerator() to handle DA operations.

DA Functions - Each waveform generation function follows a similar sequence: - Query parameters from the user. - Initialize the DA FIFO. - Populate the FIFO with appropriate waveform data. - Trigger the FIFO to start outputting the waveform.

Utility Functions - QueryForDAFuncGeneratorParameters(): Prompts the user for waveform parameters. - Initialize_DAFifo(): Initializes the FIFO with appropriate settings based on the module type. - GetNumberOfDAFifoDataPoints(): Calculates the number of data points required for the given frequency. - SupportsDAFuncGeneration(): Determines if the given module ID supports DA functionality.

Error Handling Different functions use the check_status macro to handle and report errors encountered during execution.

Conclusions This code example provides a comprehensive guide on how to set up and generate DA signals using NAI’s embedded function modules. Users can generate various waveforms by following the menu-driven interface, ensuring a straightforward process for interacting with the DA hardware.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <math.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_da.h"
#include "advanced/nai_ether_adv.h"

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

/* Function prototypes */
static int32_t Run_DA_FunctionGenerator(int32_t cardIndex, int32_t module, int32_t ModuleID);
static nai_status_t DA_GenerateConstantVoltage(int32_t paramCount, int32_t* p_params);
static nai_status_t DA_GenerateSquareWave(int32_t paramCount, int32_t* p_params);
static nai_status_t DA_GenerateTriangleWave(int32_t paramCount, int32_t* p_params);
static nai_status_t DA_GenerateSawToothWave(int32_t paramCount, int32_t* p_params);
static nai_status_t DA_GenerateSineWave(int32_t paramCount, int32_t* p_params);

static bool_t QueryForDAFuncGeneratorParameters(bool_t bQueryFreq, bool_t bQueryAmplitude, bool_t bQueryOffset, bool_t bQueryInitState,
   float64_t *pdDAFrequency, float64_t *pdDAAmplitude, float64_t *pdDAOffset, bool_t *pbOutputInitialHigh, uint32_t modid);
static void Initialize_DAFifo(int32_t cardIndex, int32_t module, int32_t channel, uint32_t modid);
static void GetNumberOfDAFifoDataPoints(double dReqFreq, unsigned int *punNumFifoDataPoints, double *pdActualFrequency, uint32_t modid);
static bool_t SupportsDAFuncGeneration(uint32_t moduleID);

/****** Command Table *******/
enum dafuncgen_commands
{
   DA_FUNCGEN_CMD_CONSTANT_VOLT,
   DA_FUNCGEN_CMD_SQUARE_WAVE,
   DA_FUNCGEN_CMD_TRIANGLE_WAVE,
   DA_FUNCGEN_CMD_SAWTOOTH_WAVE,
   DA_FUNCGEN_CMD_SINE_WAVE,
   DA_FUNCGEN_CMD_COUNT
};

/****** Command Tables *******/
naiapp_cmdtbl_params_t DA_FuncGenMenuCmds[] = {
   {"CONST VOLT", "DA Generate Constant Voltage", DA_FUNCGEN_CMD_CONSTANT_VOLT,  DA_GenerateConstantVoltage},
   {"SQUARE    ", "DA Generate Square Wave",      DA_FUNCGEN_CMD_SQUARE_WAVE,    DA_GenerateSquareWave},
   {"TRIANGLE  ", "DA Generate Triangle Wave",    DA_FUNCGEN_CMD_TRIANGLE_WAVE,  DA_GenerateTriangleWave},
   {"SAWTOOTH  ", "DA Generate Saw Tooth Wave",   DA_FUNCGEN_CMD_SAWTOOTH_WAVE,  DA_GenerateSawToothWave},
   {"SINE WAVE ", "DA Generate Sine Wave",        DA_FUNCGEN_CMD_SINE_WAVE,      DA_GenerateSineWave},
};

#define DAFUNCGEN_FIFO_CLEAR                   0x0000
#define DAFUNCGEN_FIFO_BUF_CTRL_GEN3_DA        (NAI_DA_GEN3_FIFO_CTRL_ENABLE | NAI_DA_GEN3_FIFO_CTRL_MODE)  /* 0x0003 */
#define DAFUNCGEN_FIFO_BUF_CTRL_GEN5_DA        (NAI_DA_GEN5_FIFO_CTRL_ENABLE | NAI_DA_GEN5_FIFO_CTRL_REPEAT_MODE)
#define DAFUNCGEN_FIFO_TRIG_CTRL_GEN3_DA       (NAI_DA_GEN3_FIFO_TRIG_SOFT | NAI_DA_GEN3_FIFO_TRIG_ENABLE)  /* 0x0022 */
#define DAFUNCGEN_FIFO_TRIG_CTRL_GEN5_DA       (NAI_DA_GEN5_FIFO_TRIG_SOFT)  /* 0x0130 */
#define DAFUNCGEN_FIFO_RATE_GEN3_DA            0x0001
#define DAFUNCGEN_FIFO_RATE_GEN5_DA            0x61A80  /*400,000 */
#define DAFUNCGEN_FIFO_DELAY                   0x0000
#define DAFUNCGEN_FIFO_SOFT_TRIG               0x00FF

/************************************************************************
 GEN 2 / GEN 3
 -------------
 The DA Fifo Size is 26,213
 The DA Fifo Output Data Rate is 2.56 usec.
 Thus the DA Fifo Output Frequency is (1/2.56 usec) or 390.625 kHz.

 The Maximum Output Frequency is:
      Max Request Frequency = DA Fifo Output Frequency/Fifo Size
                            = 390.625 kHz/26213
                            = 14.902 kHz
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
************************************************************************/
#define DA_MAX_FIFO_SAMPLES                         26213

static const float64_t DA_FIFO_GEN3_OUTPUT_DATARATE = 2.56E-6;
static const float64_t DA_FIFO_GEN3_OUTPUT_FREQUENCY = 390.625E+3;

static const float64_t DA_FIFO_GEN5_OUTPUT_DATARATE = 2.50E-6;
static const float64_t DA_FIFO_GEN5_OUTPUT_FREQUENCY = 400.000E+3;

static const float64_t PI = 3.1415926536;

/**************************************************************************************************************/
/**
<summary>
DA_FunctionGenerator illustrates setting up the D/A FIFO to generate the following types of outputs:
1) Constant Voltage
2) Square Wave
3) Triangle Wave
4) Sawtooth Wave
5) Sine Wave

The following system configuration routines from the nai_sys_cfg.c file are called to assist with the configuration
setup for this program prior to calling the naibrd DA routines.
 - ClearDeviceCfg
 - QuerySystemCfg
 - DisplayDeviceCfg
 - GetBoardSNModCfg
 - SaveDeviceCfg
</summary>
*/
/**************************************************************************************************************/
#if defined (__VXWORKS__)
int32_t DA_FunctionGenerator(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_FunctionGenerator(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;
}

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

</summary>
*/
/**************************************************************************************************************/
static int32_t Run_DA_FunctionGenerator(int32_t cardIndex, int32_t module, int32_t ModuleID)
{
   bool_t bQuit = FALSE;
   bool_t bContinue = TRUE;
   bool_t bCmdFound = FALSE;
   int32_t MaxChannel;
   uint32_t moduleID;
   int32_t cmd;
   int32_t channel;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;
   naiapp_AppParameters_t  da_params;
   p_naiapp_AppParameters_t da_funcgen_params = &da_params;
   da_funcgen_params->cardIndex = cardIndex;
   da_funcgen_params->module = module;
   da_funcgen_params->modId = ModuleID;

   if (!bQuit)
   {
      /* Get the number of D/A channels on the module */
      moduleID = naibrd_GetModuleID(cardIndex, module);
      if (SupportsDAFuncGeneration(moduleID))
      {
         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);
         da_funcgen_params->channel = channel;
         bContinue = FALSE;
      }
      else
         printf("ERROR: Module selected does not support DA Functionality\n");
   }
   else
      bContinue = FALSE;

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

   naiapp_utils_LoadParamMenuCommands(DA_FUNCGEN_CMD_COUNT, DA_FuncGenMenuCmds);
   while (bContinue)
   {
      naiapp_display_ParamMenuCommands((int8_t *)"DA Function Generator Menu");
      printf("\nType DA command or %c to quit : ", NAI_QUIT_CHAR);
      bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
      if (!bQuit)
      {
         if (inputResponseCnt > 0)
         {
            bCmdFound = naiapp_utils_GetParamMenuCmdNum(inputResponseCnt, inputBuffer, &cmd);
            if (bCmdFound)
            {
               switch (cmd)
               {
               case DA_FUNCGEN_CMD_CONSTANT_VOLT:
               case DA_FUNCGEN_CMD_SQUARE_WAVE:
               case DA_FUNCGEN_CMD_TRIANGLE_WAVE:
               case DA_FUNCGEN_CMD_SAWTOOTH_WAVE:
               case DA_FUNCGEN_CMD_SINE_WAVE:
                  DA_FuncGenMenuCmds[cmd].func(APP_PARAM_COUNT, (int32_t*)da_funcgen_params);
                  break;
               default:
                  printf("Invalid command entered");
                  break;
               }
            }
            else
               printf("Invalid command entered\n");
         }
      }
      else
         bContinue = FALSE;
   }
   return cardIndex;
}

static nai_status_t DA_GenerateConstantVoltage(int32_t paramCount, int32_t* p_params)
{
   bool_t bQuit = FALSE;
   uint32_t modid;
   float64_t dDAFrequency = 0.0;
   float64_t dDAAmplitude = 0.0;
   float64_t dDAOffset = 0.0;
   bool_t    bOutputInitHigh = FALSE;
   p_naiapp_AppParameters_t da_funcgen_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = da_funcgen_params->cardIndex;
   int32_t module = da_funcgen_params->module;
   int32_t channel= da_funcgen_params->channel;

   uint32_t unNumFifoDataPoints;  /* Number of Data Points to fill in the fifo */
   uint32_t unDataCnt;
   nai_da_range_mode_t damode;
   float64_t darange;
   uint16_t rawdata;
   uint16_t hexVoltages16[1024];
   uint32_t hexVoltages32[1024];

   int32_t j;

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

   modid = naibrd_GetModuleID(cardIndex, module);

   bQuit = QueryForDAFuncGeneratorParameters(FALSE, TRUE, FALSE, FALSE,
      &dDAFrequency, &dDAAmplitude, &dDAOffset, &bOutputInitHigh, modid);
   if (!bQuit)
   {

      Initialize_DAFifo(cardIndex, module, channel, modid);

      /* Fill the DA Fifo with the Constant Voltage Waveform Data */
      unNumFifoDataPoints = 3;

      check_status(naibrd_DA_SetFIFOSize(cardIndex, module, channel, unNumFifoDataPoints));

      check_status(naibrd_DA_GetRange(cardIndex, module, channel, NAI_DA_DATA_VOLTAGE, &damode, &darange));
      for (j = 0; j < (int32_t)unNumFifoDataPoints; j++)
      {
         naibrd_DA_ConvertToDataRaw16(modid, NAI_DA_DATA_VOLTAGE, damode, (nai_da_range_t)darange, dDAAmplitude, &rawdata);
         if (damode == NAI_DA_GEN3_RANGE_MODE_UNIPOLAR)  /* Unipolar voltage */
         {
            hexVoltages16[j] = rawdata;
            hexVoltages32[j] = rawdata;
         }
         else   /* Bipolar Voltage*/
         {
            hexVoltages16[j] = rawdata;
            hexVoltages32[j] = (uint32_t)((int16_t)rawdata);
         }
      }
      if (modid == NAI_MODULE_ID_DA1)
         check_status(naibrd_DA_SetFIFORaw32(cardIndex, module, channel, unNumFifoDataPoints, hexVoltages32, &unDataCnt));
      else
         check_status(naibrd_DA_SetFIFORaw16(cardIndex, module, channel, unNumFifoDataPoints, hexVoltages16, &unDataCnt));

      if (unDataCnt != unNumFifoDataPoints)
         printf("Problem with writing to FIFO - Elements in Fifo: Expected %d, Actual %d\n", unNumFifoDataPoints, unDataCnt);
      else
         printf("FIFO Data Population is complete.\n");

      printf("\nDA channel %d for Module %d has been programmed to output %f volts.\n\n",
         channel, module, dDAAmplitude);

      /* Trigger the FIFO to start outputting the voltage */
      if (modid == NAI_MODULE_ID_DA1)
         check_status(naibrd_DA_SetFIFOTrigCtrl(cardIndex, module, channel, NAI_DA_GEN5_FIFO_TRIG_ENABLE | DAFUNCGEN_FIFO_TRIG_CTRL_GEN5_DA));

      check_status(naibrd_DA_SoftwareTrigger(cardIndex, module));
   }
   return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}

static nai_status_t DA_GenerateSquareWave(int32_t paramCount, int32_t* p_params)
{
   bool_t bQuit = FALSE;
   uint32_t modid;
   float64_t dDAFrequency = 0.0;
   float64_t dDAAmplitude = 0.0;
   float64_t dDAOffset = 0.0;
   bool_t    bOutputInitHigh = FALSE;
   p_naiapp_AppParameters_t da_funcgen_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = da_funcgen_params->cardIndex;
   int32_t module = da_funcgen_params->module;
   int32_t channel= da_funcgen_params->channel;

   float64_t dDAActualFrequency = 0.0, dDAVoltage;
   uint32_t unNumFifoDataPoints;  /* Number of Data Points to fill in the fifo */
   uint32_t unDataCnt;
   nai_da_range_mode_t damode;
   float64_t darange;
   uint16_t rawdata;
   uint16_t hexVoltages16[DA_MAX_FIFO_SAMPLES];
   uint32_t hexVoltages32[DA_MAX_FIFO_SAMPLES];
   int32_t j;

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

   modid = naibrd_GetModuleID(cardIndex, module);

   bQuit = QueryForDAFuncGeneratorParameters(TRUE, TRUE, TRUE, TRUE,
      &dDAFrequency, &dDAAmplitude, &dDAOffset, &bOutputInitHigh, modid);
   if (!bQuit)
   {
      Initialize_DAFifo(cardIndex, module, channel, modid);

      /* Fill the DA Fifo with one iteration of the Square Waveform Data */
      GetNumberOfDAFifoDataPoints(dDAFrequency, &unNumFifoDataPoints, &dDAActualFrequency, modid);
      check_status(naibrd_DA_SetFIFOSize(cardIndex, module, channel, unNumFifoDataPoints));
      check_status(naibrd_DA_GetRange(cardIndex, module, channel, NAI_DA_DATA_VOLTAGE, &damode, &darange));

      printf("\nPlease wait while FIFO data is being populated for channel %d...\n", channel);
      for (j = 0; j < (int32_t)unNumFifoDataPoints; j++)
      {
         if (j == (int32_t)(unNumFifoDataPoints / 2))
            /* Change the voltage level to output a square wave */
            bOutputInitHigh = !bOutputInitHigh;

         if (bOutputInitHigh)
            dDAVoltage = dDAAmplitude - dDAOffset;
         else
            dDAVoltage = 0 - dDAOffset;

         naibrd_DA_ConvertToDataRaw16(modid, NAI_DA_DATA_VOLTAGE, damode, (nai_da_range_t)darange, dDAVoltage, &rawdata);
         if (damode == NAI_DA_GEN3_RANGE_MODE_UNIPOLAR)  /* Unipolar voltage */
         {
            hexVoltages16[j] = rawdata;
            hexVoltages32[j] = rawdata;
         }
         else   /* Bipolar Voltage*/
         {
            hexVoltages16[j] = rawdata;
            hexVoltages32[j] = (uint32_t)((int16_t)rawdata);
         }
      }
      if (modid == NAI_MODULE_ID_DA1)
         check_status(naibrd_DA_SetFIFORaw32(cardIndex, module, channel, unNumFifoDataPoints, hexVoltages32, &unDataCnt));
      else
         check_status(naibrd_DA_SetFIFORaw16(cardIndex, module, channel, unNumFifoDataPoints, hexVoltages16, &unDataCnt));

      if (unDataCnt != unNumFifoDataPoints)
         printf("Problem with writing to FIFO - Elements in Fifo: Expected %d, Actual %d\n", unNumFifoDataPoints, unDataCnt);
      else
         printf("FIFO Data Population is complete.\n");

      printf("\nDA channel %d for Module %d have been programmed to output a %f Hz square wave\n with an amplitude of %f volts offset by %f volts.\n\n",
         channel, module, dDAActualFrequency, dDAAmplitude, dDAOffset);
      /* Trigger the FIFO to start outputting the voltage */
      if (modid == NAI_MODULE_ID_DA1)
         check_status(naibrd_DA_SetFIFOTrigCtrl(cardIndex, module, channel, NAI_DA_GEN5_FIFO_TRIG_ENABLE | DAFUNCGEN_FIFO_TRIG_CTRL_GEN5_DA));

      check_status(naibrd_DA_SoftwareTrigger(cardIndex, module));
   }
   return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}

static nai_status_t DA_GenerateTriangleWave(int32_t paramCount, int32_t* p_params)
{
   bool_t bQuit = FALSE;
   uint32_t modid;
   float64_t dDAFrequency = 0.0;
   float64_t dDAAmplitude = 0.0;
   float64_t dDAOffset = 0.0;
   bool_t    bOutputInitHigh = FALSE;
   p_naiapp_AppParameters_t da_funcgen_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = da_funcgen_params->cardIndex;
   int32_t module = da_funcgen_params->module;
   int32_t channel= da_funcgen_params->channel;

   float64_t dDAActualFrequency = 0.0, dDAVoltage;
   uint32_t unNumFifoDataPoints;  /* Number of Data Points to fill in the fifo */
   uint32_t unDataCnt;
   nai_da_range_mode_t damode;
   float64_t darange;
   uint16_t rawdata;
   uint16_t hexVoltages16[DA_MAX_FIFO_SAMPLES];
   uint32_t hexVoltages32[DA_MAX_FIFO_SAMPLES];
   int32_t j;

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

   modid = naibrd_GetModuleID(cardIndex, module);

   bQuit = QueryForDAFuncGeneratorParameters(TRUE, TRUE, TRUE, FALSE,
      &dDAFrequency, &dDAAmplitude, &dDAOffset, &bOutputInitHigh, modid);
   if (!bQuit)
   {
      Initialize_DAFifo(cardIndex, module, channel, modid);

      /* Fill the DA Fifo with one iteration of the Square Waveform Data */
      GetNumberOfDAFifoDataPoints(dDAFrequency, &unNumFifoDataPoints, &dDAActualFrequency, modid);
      check_status(naibrd_DA_SetFIFOSize(cardIndex, module, channel, unNumFifoDataPoints));
      check_status(naibrd_DA_GetRange(cardIndex, module, channel, NAI_DA_DATA_VOLTAGE, &damode, &darange));

      printf("\nPlease wait while FIFO data is being populated for channel %d...\n", channel);
      for (j = 0; j < (int32_t)unNumFifoDataPoints; j++)
      {
         if (j < (int32_t)(unNumFifoDataPoints / 2))
            dDAVoltage = (dDAAmplitude - 4.0*dDAAmplitude*((double)j / (double)unNumFifoDataPoints)) - dDAOffset;
         else
            dDAVoltage = (4.0*dDAAmplitude*((double)j / (double)unNumFifoDataPoints) - 3.0*dDAAmplitude) - dDAOffset;

         naibrd_DA_ConvertToDataRaw16(modid, NAI_DA_DATA_VOLTAGE, damode, (nai_da_range_t)darange, dDAVoltage, &rawdata);
         if (damode == NAI_DA_GEN3_RANGE_MODE_UNIPOLAR)  /* Unipolar voltage */
         {
            hexVoltages16[j] = rawdata;
            hexVoltages32[j] = rawdata;
         }
         else   /* Bipolar Voltage*/
         {
            hexVoltages16[j] = rawdata;
            hexVoltages32[j] = (uint32_t)((int16_t)rawdata);
         }
      }
      if (modid == NAI_MODULE_ID_DA1)
         check_status(naibrd_DA_SetFIFORaw32(cardIndex, module, channel, unNumFifoDataPoints, hexVoltages32, &unDataCnt));
      else
         check_status(naibrd_DA_SetFIFORaw16(cardIndex, module, channel, unNumFifoDataPoints, hexVoltages16, &unDataCnt));

      if (unDataCnt != unNumFifoDataPoints)
         printf("Problem with writing to FIFO - Elements in Fifo: Expected %d, Actual %d\n", unNumFifoDataPoints, unDataCnt);
      else
         printf("FIFO Data Population is complete.\n");

      printf("\nDA channel %d for Module %d have been programmed to output a %f Hz triangle wave\n with an amplitude of %f volts offset by %f volts.\n\n",
         channel, module, dDAActualFrequency, dDAAmplitude, dDAOffset);

      /* Trigger the FIFO to start outputting the voltage */
      if (modid == NAI_MODULE_ID_DA1) /*if its a DA1 you need to enable the trigger to allow outputting*/
         check_status(naibrd_DA_SetFIFOTrigCtrl(cardIndex, module, channel, NAI_DA_GEN5_FIFO_TRIG_ENABLE | DAFUNCGEN_FIFO_TRIG_CTRL_GEN5_DA));

      check_status(naibrd_DA_SoftwareTrigger(cardIndex, module));
   }
   return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}

static nai_status_t DA_GenerateSawToothWave(int32_t paramCount, int32_t* p_params)
{
   bool_t bQuit = FALSE;
   uint32_t modid;
   float64_t dDAFrequency = 0.0;
   float64_t dDAAmplitude = 0.0;
   float64_t dDAOffset = 0.0;
   bool_t    bOutputInitHigh = FALSE;
   p_naiapp_AppParameters_t da_funcgen_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = da_funcgen_params->cardIndex;
   int32_t module = da_funcgen_params->module;
   int32_t channel= da_funcgen_params->channel;

   float64_t dDAActualFrequency = 0.0, dDAVoltage;
   uint32_t unNumFifoDataPoints;  /* Number of Data Points to fill in the fifo */
   uint32_t unDataCnt;
   nai_da_range_mode_t damode;
   float64_t darange;
   uint16_t rawdata;
   uint16_t hexVoltages16[DA_MAX_FIFO_SAMPLES];
   uint32_t hexVoltages32[DA_MAX_FIFO_SAMPLES];
   int32_t j;

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

   modid = naibrd_GetModuleID(cardIndex, module);

   bQuit = QueryForDAFuncGeneratorParameters(TRUE, TRUE, TRUE, FALSE,
      &dDAFrequency, &dDAAmplitude, &dDAOffset, &bOutputInitHigh, modid);
   if (!bQuit)
   {
      Initialize_DAFifo(cardIndex, module, channel, modid);

      /* Fill the DA Fifo with one iteration of the Square Waveform Data */
      GetNumberOfDAFifoDataPoints(dDAFrequency, &unNumFifoDataPoints, &dDAActualFrequency, modid);
      check_status(naibrd_DA_SetFIFOSize(cardIndex, module, channel, unNumFifoDataPoints));
      check_status(naibrd_DA_GetRange(cardIndex, module, channel, NAI_DA_DATA_VOLTAGE, &damode, &darange));

      printf("\nPlease wait while FIFO data is being populated for channel %d...\n", channel);
      for (j = 0; j < (int32_t)unNumFifoDataPoints; j++)
      {
         /* Amp*(x/WaveCountMax) will adjust for frequency */
         dDAVoltage = ((2.0*dDAAmplitude*((double)j / (double)unNumFifoDataPoints)) - dDAAmplitude) - dDAOffset;

         naibrd_DA_ConvertToDataRaw16(modid, NAI_DA_DATA_VOLTAGE, damode, (nai_da_range_t)darange, dDAVoltage, &rawdata);
         if (damode == NAI_DA_GEN3_RANGE_MODE_UNIPOLAR)  /* Unipolar voltage */
         {
            hexVoltages16[j] = rawdata;
            hexVoltages32[j] = rawdata;
         }
         else   /* Bipolar Voltage*/
         {
            hexVoltages16[j] = rawdata;
            hexVoltages32[j] = (uint32_t)((int16_t)rawdata);
         }
      }
      if (modid == NAI_MODULE_ID_DA1)
         check_status(naibrd_DA_SetFIFORaw32(cardIndex, module, channel, unNumFifoDataPoints, hexVoltages32, &unDataCnt));
      else
         check_status(naibrd_DA_SetFIFORaw16(cardIndex, module, channel, unNumFifoDataPoints, hexVoltages16, &unDataCnt));

      if (unDataCnt != unNumFifoDataPoints)
         printf("Problem with writing to FIFO - Elements in Fifo: Expected %d, Actual %d\n", unNumFifoDataPoints, unDataCnt);
      else
         printf("FIFO Data Population is complete.\n");

      printf("\nDA channel %d for Module %d have been programmed to output a %f Hz saw-tooth wave\n with an amplitude of %f volts offset by %f volts.\n\n",
         channel, module, dDAActualFrequency, dDAAmplitude, dDAOffset);

      /* Trigger the FIFO to start outputting the voltage */
      if (modid == NAI_MODULE_ID_DA1)
         check_status(naibrd_DA_SetFIFOTrigCtrl(cardIndex, module, channel, NAI_DA_GEN5_FIFO_TRIG_ENABLE | DAFUNCGEN_FIFO_TRIG_CTRL_GEN5_DA));
      check_status(naibrd_DA_SoftwareTrigger(cardIndex, module));
   }
   return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}

static nai_status_t DA_GenerateSineWave(int32_t paramCount, int32_t* p_params)
{
   bool_t bQuit = FALSE;
   uint32_t modid;
   float64_t dDAFrequency = 0.0;
   float64_t dDAAmplitude = 0.0;
   float64_t dDAOffset = 0.0;
   bool_t    bOutputInitHigh = FALSE;
   p_naiapp_AppParameters_t da_funcgen_params = (p_naiapp_AppParameters_t)p_params;
   int32_t cardIndex = da_funcgen_params->cardIndex;
   int32_t module = da_funcgen_params->module;
   int32_t channel= da_funcgen_params->channel;

   float64_t dDAActualFrequency = 0.0, dDAVoltage, dDARadians;
   uint32_t unNumFifoDataPoints;  /* Number of Data Points to fill in the fifo */
   uint32_t unDataCnt;
   nai_da_range_mode_t damode;
   float64_t darange;
   uint16_t rawdata;
   uint16_t hexVoltages16[DA_MAX_FIFO_SAMPLES];
   uint32_t hexVoltages32[DA_MAX_FIFO_SAMPLES];
   int32_t j;

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

   modid = naibrd_GetModuleID(cardIndex, module);

   bQuit = QueryForDAFuncGeneratorParameters(TRUE, TRUE, TRUE, FALSE,
      &dDAFrequency, &dDAAmplitude, &dDAOffset, &bOutputInitHigh, modid);
   if (!bQuit)
   {
      Initialize_DAFifo(cardIndex, module, channel, modid);

      /* Fill the DA Fifo with one iteration of the Square Waveform Data */
      GetNumberOfDAFifoDataPoints(dDAFrequency, &unNumFifoDataPoints, &dDAActualFrequency, modid);
      check_status(naibrd_DA_SetFIFOSize(cardIndex, module, channel, unNumFifoDataPoints));
      check_status(naibrd_DA_GetRange(cardIndex, module, channel, NAI_DA_DATA_VOLTAGE, &damode, &darange));

      printf("\nPlease wait while FIFO data is being populated for channel %d...\n", channel);
      for (j = 0; j < (int32_t)unNumFifoDataPoints; j++)
      {
         /* 360*(x/nNumFifoDataPoints) will spread out Sine wave to adjust for Frequency */
         dDARadians = (360.0 * j * PI / 180.0) / (double)unNumFifoDataPoints;
         dDAVoltage = (dDAAmplitude*sin(dDARadians)) - dDAOffset;

         naibrd_DA_ConvertToDataRaw16(modid, NAI_DA_DATA_VOLTAGE, damode, (nai_da_range_t)darange, dDAVoltage, &rawdata);
         if (damode == NAI_DA_GEN3_RANGE_MODE_UNIPOLAR)  /* Unipolar voltage */
         {
            hexVoltages16[j] = rawdata;
            hexVoltages32[j] = rawdata;
         }
         else   /* Bipolar Voltage*/
         {
            hexVoltages16[j] = rawdata;
            hexVoltages32[j] = (uint32_t)((int16_t)rawdata);

         }
      }
      if (modid == NAI_MODULE_ID_DA1)
         check_status(naibrd_DA_SetFIFORaw32(cardIndex, module, channel, unNumFifoDataPoints, hexVoltages32, &unDataCnt));
      else
         check_status(naibrd_DA_SetFIFORaw16(cardIndex, module, channel, unNumFifoDataPoints, hexVoltages16, &unDataCnt));

      if (unDataCnt != unNumFifoDataPoints)
         printf("Problem with writing to FIFO - Elements in Fifo: Expected %d, Actual %d\n", unNumFifoDataPoints, unDataCnt);
      else
         printf("FIFO Data Population is complete.\n");

      printf("\nDA channel %d for Module %d have been programmed to output a %f Hz sine wave\n with an amplitude of %f volts offset by %f volts.\n\n",
         channel, module, dDAActualFrequency, dDAAmplitude, dDAOffset);

      /* Trigger the FIFO to start outputting the voltage */
      if (modid == NAI_MODULE_ID_DA1)
         check_status(naibrd_DA_SetFIFOTrigCtrl(cardIndex, module, channel, NAI_DA_GEN5_FIFO_TRIG_ENABLE | DAFUNCGEN_FIFO_TRIG_CTRL_GEN5_DA));
      else
         check_status(naibrd_DA_SetUseFifo(cardIndex, module, channel, TRUE));

      check_status(naibrd_DA_SoftwareTriggerByChannel(cardIndex, module, channel));

   }
   return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}

static void Initialize_DAFifo(int32_t cardIndex, int32_t module, int32_t channel, uint32_t modid)
{
   check_status(naibrd_DA_ClearFIFO(cardIndex, module, channel));
   if (modid == NAI_MODULE_ID_DA1)
   {
      check_status(naibrd_DA_SetRange(cardIndex, module, channel, NAI_DA_DATA_VOLTAGE, NAI_DA_GEN5_RANGE_MODE_BIPOLAR, 10.0));
      check_status(naibrd_DA_SetFIFOTrigCtrl(cardIndex, module, channel, DAFUNCGEN_FIFO_TRIG_CTRL_GEN5_DA));
      check_status(naibrd_DA_SetFIFORate(cardIndex, module, channel, DAFUNCGEN_FIFO_RATE_GEN5_DA));
      check_status(naibrd_DA_SetFIFOCtrl(cardIndex, module, channel, DAFUNCGEN_FIFO_BUF_CTRL_GEN5_DA));
   }
   else
   {
      check_status(naibrd_DA_SetFIFOTrigCtrl(cardIndex, module, channel, DAFUNCGEN_FIFO_TRIG_CTRL_GEN3_DA));
      check_status(naibrd_DA_SetFIFORate(cardIndex, module, channel, DAFUNCGEN_FIFO_RATE_GEN3_DA));
      check_status(naibrd_DA_SetFIFOCtrl(cardIndex, module, channel, DAFUNCGEN_FIFO_BUF_CTRL_GEN3_DA));
   }
   check_status(naibrd_DA_SetOutputTrigger(cardIndex, module, channel, NAI_DA_OUT_TRG_CONST_UPDATE));
   check_status(naibrd_DA_SetFIFOSize(cardIndex, module, channel, 0x0000));
   check_status(naibrd_DA_SetFIFODelay(cardIndex, module, channel, DAFUNCGEN_FIFO_DELAY));
   /* Initialize Data Registers to Zero */
   check_status(naibrd_DA_SetData(cardIndex, module, channel, NAI_DA_DATA_VOLTAGE, 0.0));
}

static bool_t QueryForDAFuncGeneratorParameters(bool_t bQueryFreq, bool_t bQueryAmplitude, bool_t bQueryOffset, bool_t bQueryInitState,
   float64_t *pdDAFrequency, float64_t *pdDAAmplitude, float64_t *pdDAOffset, bool_t *pbOutputInitialHigh, uint32_t modid)
{
   bool_t    bQuit = FALSE;
   bool_t    bContinue = TRUE;
   bool_t    bInvalidEntry = FALSE;
   float64_t DA_MIN_REQUEST_FREQ;
   float64_t dValue = 0.0;
   int32_t   nValue;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   if (modid == NAI_MODULE_ID_DA1)
      DA_MIN_REQUEST_FREQ = (float64_t)(DA_FIFO_GEN5_OUTPUT_FREQUENCY / DA_MAX_FIFO_SAMPLES);
   else
      DA_MIN_REQUEST_FREQ = (float64_t)(DA_FIFO_GEN3_OUTPUT_FREQUENCY / DA_MAX_FIFO_SAMPLES);

   /* Initialize the output values */
   *pdDAFrequency = 0.0;
   *pdDAAmplitude = 0.0;
   *pdDAOffset = 0.0;

   if (bQueryFreq)
   {
      bContinue = TRUE;
      while (bContinue)
      {
         bInvalidEntry = FALSE;
         printf("\nPlease enter Waveform Frequency (Valid Value: %4.0f Hz to 15000 Hz) : ", DA_MIN_REQUEST_FREQ);
         bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
         if (!bQuit)
         {
            if (inputResponseCnt > 0)
            {
               dValue = atof((const char *)inputBuffer);
               if ((dValue >= DA_MIN_REQUEST_FREQ) && (dValue <= 15000.0))
               {
                  *pdDAFrequency = dValue;
                  bContinue = FALSE;
               }
               else
                  bInvalidEntry = TRUE;
            }
            else
               bInvalidEntry = TRUE;

            if (bInvalidEntry)
               printf("ERROR: Invalid entry\n");
         }
         else
            bContinue = FALSE;
      }
   }

   if (!bQuit && bQueryAmplitude)
   {
      bContinue = TRUE;
      while (bContinue)
      {
         bInvalidEntry = FALSE;
         printf("\nPlease enter Waveform Amplitude Voltage (Valid Value: -10V to 10V) : ");
         bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
         if (!bQuit)
         {
            if (inputResponseCnt > 0)
            {
               dValue = atof((const char *)inputBuffer);
               if ((dValue >= -10) && (dValue <= 10.0))
               {
                  *pdDAAmplitude = dValue;
                  bContinue = FALSE;
               }
               else
                  bInvalidEntry = TRUE;
            }
            else
               bInvalidEntry = TRUE;

            if (bInvalidEntry)
               printf("ERROR: Invalid entry\n");
         }
         else
            bContinue = FALSE;
      }
   }

   if (!bQuit && bQueryOffset)
   {
      bContinue = TRUE;
      while (bContinue)
      {
         bInvalidEntry = FALSE;
         printf("\nPlease enter Waveform Offset Voltage (Valid Value: -10V to 10V) : ");
         bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
         if (!bQuit)
         {
            if (inputResponseCnt > 0)
            {
               dValue = atof((const char *)inputBuffer);
               if ((dValue >= -10.0) && (dValue <= 10.0))
               {
                  *pdDAOffset = dValue;
                  bContinue = FALSE;
               }
               else
                  bInvalidEntry = TRUE;
            }
            else
               bInvalidEntry = TRUE;

            if (bInvalidEntry)
               printf("ERROR: Invalid entry\n");
         }
         else
            bContinue = FALSE;
      }
   }

   if (!bQuit && bQueryInitState)
   {
      bContinue = TRUE;
      while (bContinue)
      {
         bInvalidEntry = FALSE;
         printf("\nPlease enter Waveform Initial Output State (Valid Value: 1 (High) or 0 (Low)) : ");
         bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
         if (!bQuit)
         {
            if (inputResponseCnt > 0)
            {
               nValue = atol((const char *)inputBuffer);
               if ((nValue == 0) || (nValue == 1))
               {
                  if (nValue == 0)
                     *pbOutputInitialHigh = FALSE;
                  else
                     *pbOutputInitialHigh = TRUE;
                  bContinue = FALSE;
               }
               else
                  bInvalidEntry = TRUE;
            }
            else
               bInvalidEntry = TRUE;

            if (bInvalidEntry)
               printf("ERROR: Invalid entry\n");
         }
         else
            bContinue = FALSE;
      }
   }
   return bQuit;
}

static void GetNumberOfDAFifoDataPoints(double dReqFreq, unsigned int *punNumFifoDataPoints, double *pdActualFrequency, uint32_t modid)
{
   /*
      FOR ALL GEN 3 D/A modules
      -------------------------
      Compute the number of data points to fill in the fifo based on
      the requested frequency.
      The DA Fifo Output Data Rate is 2.56 usec.
      Thus the DA Fifo Output Frequency is (1/2.56 usec) or 390.625 kHz.

      The number of data points is determined by:
            NumFifoDataPoints = DA Fifo Output Freq/Requested Frequency
         For example, for a 1kHz wave:
            NumFifoDataPoints = 390.625 kHz/1.0 kHz = 390

      The actual frequency of the waveform is determined as follows:
            ActualFreq = 1/(DA Fifo Output Data Rate * NumFifoDataPoints)
         For example, for a 1kHz wave:
            ActualFreq = 1/(2.56 usec * 390) = 1.0016 kHz

      FOR THE DA1
      -----------
      Fifo Output Frequency = 400 Khz
      The Fifo Output Data rate is 2.5 usec
   */
   unsigned int unNumOfFifoSamples;
   float64_t outputFrequency;
   float64_t outputDateRate;
   if (modid == NAI_MODULE_ID_DA1)
   {
      outputFrequency = DA_FIFO_GEN5_OUTPUT_FREQUENCY;
      outputDateRate = DA_FIFO_GEN5_OUTPUT_DATARATE;
   }
   else
   {
      outputFrequency = DA_FIFO_GEN3_OUTPUT_FREQUENCY;
      outputDateRate = DA_FIFO_GEN3_OUTPUT_DATARATE;
   }
   unNumOfFifoSamples = (unsigned int)(outputFrequency / dReqFreq);
   if (unNumOfFifoSamples > DA_MAX_FIFO_SAMPLES)
   {
      unNumOfFifoSamples = DA_MAX_FIFO_SAMPLES;
   }
   *punNumFifoDataPoints = unNumOfFifoSamples;
   *pdActualFrequency = (double)(1.0 / ((double)outputDateRate * (double)unNumOfFifoSamples));
}

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

   switch (moduleID)
   {
   case NAI_MODULE_ID_F1:
   case NAI_MODULE_ID_F3:
   case NAI_MODULE_ID_F5:
   case NAI_MODULE_ID_J3:
   case NAI_MODULE_ID_J5:
   case NAI_MODULE_ID_J8:
   case NAI_MODULE_ID_DA1:
   case NAI_MODULE_ID_DA2:
      bSupportDAFunc = TRUE;
      break;
   default:
      bSupportDAFunc = FALSE;
      break;
   }

   return bSupportDAFunc;
}

Help Bot

X