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

AD BasicOps

AD BasicOps Sample Application (SSK 2.x)

Overview

The AD BasicOps sample application demonstrates how to configure and read analog-to-digital channels using the NAI Software Support Kit (SSK 2.x). It covers the core AD operations you will need in your own application: setting range and polarity, configuring filter break frequency, enabling channel status and latch modes, reading channel data, managing saturation thresholds, and controlling module power reset.

This sample supports the following AD module types: AD1 through AD6, ADE through ADG, CF1, and IF1. It also works with combination modules that include AD functionality: CME, CMF, and CMG. It serves as a practical API reference — each menu command maps directly to one or more naibrd_AD_*() API calls that you can lift into your own code.

For the SSK 1.x version, see AD BasicOps (SSK 1.x).

Prerequisites

Before running this sample, make sure you have:

  • An NAI board with an AD module installed (AD1-AD6, ADE-ADG, CF1, or IF1).

  • SSK 2.x installed on your development host.

  • The sample applications built. Refer to the SSK 2.x Software Development Guide for platform-specific build instructions.

How to Run

Launch the ad_basic_ops executable from your build output directory. On startup the application looks for a configuration file (default_AD_BasicOps.txt). On the first run, this file will not exist — the application will present an interactive board menu where you configure a board connection, card index, and module slot. You can save this configuration so that subsequent runs skip the menu and connect automatically. Once connected, a command menu lets you exercise each AD operation.

Note
If a CF1 module is detected at the selected slot, the application enters a simplified read-only display mode that shows DC and RMS voltage for each channel. The full command menu described in this guide applies to all other supported AD module types.

Board Connection and Module Selection

Note
This startup sequence is common to all NAI sample applications. The board connection and module selection code shown here is not specific to AD.

The main() function follows a standard SSK 2.x startup flow:

  1. Call naiapp_RunBoardMenu() to load a saved configuration file (if one exists) or present the interactive board menu. The configuration file (default_AD_BasicOps.txt) is not included with the SSK — it is created when the user saves their connection settings from the board menu. On the first run, the menu will always appear.

  2. Query the user for a card index with naiapp_query_CardIndex().

  3. Query for a module slot with naiapp_query_ModuleNumber().

  4. Retrieve the module ID with naibrd_GetModuleName() so downstream code can adapt to the specific AD variant installed.

#if defined (NAIBSP_CONFIG_SOFTWARE_OS_VXWORKS)
int32_t AD_BasicOps(void)
#else
int32_t main(void)
#endif
{
   bool_t bQuit = NAI_FALSE;
   int32_t cardIndex = -1;
   int32_t module = 0;
   int32_t moduleCount = 0;
   uint32_t modId = 0u;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   if (naiapp_RunBoardMenu(CONFIG_FILE) == NAI_TRUE)
   {
      while (!bQuit)
      {
         naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
         naibrd_GetModuleCount(cardIndex, &moduleCount);
         naiapp_query_ModuleNumber(moduleCount, 1, &module);
         naibrd_GetModuleName(cardIndex, module, &modId);
         if (NAIBRD_MODULE_ID_CF1 == modId)
         {
            bQuit = CF1ADBasicOps_run(cardIndex, module, modId);
         }
         else
         {
            bQuit = ADBasicOps_run(cardIndex, module, modId);
         }
      }

      naiif_printf("Type the Enter key to exit the program: ");
      naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR,
         inputBuffer, &inputResponseCnt);
   }

   naiapp_access_CloseAllOpenCards();

   return 0;
}

Note the SSK 2.x differences from SSK 1.x in this startup sequence:

  • The VxWorks preprocessor guard uses NAIBSP_CONFIG_SOFTWARE_OS_VXWORKS (SSK 1.x uses __VXWORKS__).

  • The module identifier is retrieved with naibrd_GetModuleName() (SSK 1.x uses naibrd_GetModuleID()).

  • Boolean constants are NAI_TRUE / NAI_FALSE (SSK 1.x uses TRUE / FALSE).

  • Console output uses naiif_printf() from the platform abstraction layer (SSK 1.x uses printf() directly).

Important

Common connection errors you may encounter at this stage:

  • No board found — verify that the board is powered on and physically connected. Check that the configuration file lists the correct interface and address.

  • Connection timeout — confirm network settings (for Ethernet connections) or bus configuration (for PCI/PCIe). Firewalls and IP mismatches are frequent causes.

  • Invalid card or module index — indices are zero-based for cards and one-based for modules. Ensure the values you pass match your hardware setup.

  • Module not present at selected slot — the slot you selected does not contain an AD module. Use the board menu to verify which slots are populated.

Program Structure

Entry Point

On standard platforms (Petalinux, DEOS) the entry point is main(). On VxWorks the entry point is AD_BasicOps() — the SSK 2.x build system selects the correct variant via a preprocessor guard:

#if defined (NAIBSP_CONFIG_SOFTWARE_OS_VXWORKS)
int32_t AD_BasicOps(void)
#else
int32_t main(void)
#endif

The startup flow is the same in both cases:

  1. Attempt to load the saved configuration file via naiapp_RunBoardMenu(CONFIG_FILE). If the file does not yet exist, the interactive board menu is presented instead.

  2. Enter a loop that queries for card index and module slot.

  3. If the detected module is a CF1, call CF1ADBasicOps_run() for the simplified display mode. Otherwise, call ADBasicOps_run() to enter the interactive command loop.

  4. On exit, close all open board connections with naiapp_access_CloseAllOpenCards().

Application Parameters

The ADBasicOps_run() function populates an naiapp_AppParameters_t struct that is passed to every command handler. Your application will need to track these same values to identify which board, module, and channel you are targeting:

naiapp_AppParameters_t  ad_basicops_params;
p_naiapp_AppParameters_t ad_basicOps_params = &ad_basicops_params;

ad_basicOps_params->cardIndex = cardIndex;
ad_basicOps_params->module = module;
ad_basicOps_params->channel = DEFAULT_CHANNEL;
ad_basicOps_params->maxChannels = naibrd_AD_GetChannelCount(modId);
ad_basicOps_params->modId = modId;
ad_basicOps_params->displayHex = NAI_FALSE;
  • cardIndex — identifies which board in a multi-board system.

  • module — the slot number where the AD module is installed.

  • channel — the currently selected channel (defaults to 1).

  • maxChannels — total channel count for the detected module, retrieved by calling naibrd_AD_GetChannelCount() with the module ID.

  • modId — the module identifier returned by naibrd_GetModuleName(). API functions use this to apply module-specific behavior.

  • displayHex — toggles between hexadecimal and decimal display of register values.

Command Loop

ADBasicOps_run() drives the interactive command loop. On each iteration it displays the current channel configuration, prints the command menu, and dispatches the user’s selection to the matching handler function:

do
{
   naiapp_utils_LoadParamMenuCommands(AD_BASICOPS_CMD_COUNT, AD_BasicOpsCmds);
   ADBasicOps_displayConfigurations(cardIndex, module, modId,
      ad_basicOps_params->maxChannels, ad_basicOps_params->displayHex);
   naiapp_display_ParamMenuCommands((int8_t*)SAMPLE_PGM_NAME);
   naiif_printf("\r\n\r\nPlease enter a command or 'q' to quit:");
   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)
         {
            AD_BasicOpsCmds[cmd].func(APP_PARAM_COUNT,
               (int32_t*)ad_basicOps_params);
         }
         else
         {
            naiif_printf("Invalid command entered\r\n");
         }
      }
   }
} while (!bQuit);

The available commands are registered in the AD_BasicOpsCmds[] table:

Command Description

PR

Set AD polarity and range

BRKFRQ

Set AD filter break frequency

M

Set AD voltage/current mode (AD4 only)

L

Set AD latch/unlatch status

AC

Set AD channel active/inactive (AD4 only)

SAT

Open the saturation submenu

D0

Enable, configure, or disable D0 internal test

FP_MODE

Enable/disable hardware floating-point conversion mode

OFFSET

Set hardware floating-point conversion offset

SCALE

Set hardware floating-point conversion scale factor

CHANSTAT

Channel status enable/disable

PBIT

Check power-on BIT

THRESH

Set BIT error threshold

PWRRESET

Open the module power reset submenu

TND

Toggle numeric display (hex/decimal)

The menu-driven structure is a convenience of the sample application. In your own application, you would call the same underlying naibrd_AD_*() API functions directly — for example, calling naibrd_AD_SetRangePolarity() instead of navigating to the "PR" menu command.

Reading and Configuration

This section covers the API calls used to configure AD channel behavior: setting the input range and polarity, switching between voltage and current mode, latching channel readings, adjusting the low-pass filter break frequency, and enabling or disabling individual channels.

Set Range and Polarity

To configure the input range and polarity on a channel in your own application, call naibrd_AD_SetRangePolarity() with the desired polarity and range values.

The sample first retrieves the channel’s current mode (voltage or current) with naibrd_AD_GetMode(), then uses the utility function ADUtils_GetRangePolarity() (defined in ad_common_utils.h) to prompt for and validate polarity and range values against the module’s supported settings. In your own code, you can skip the utility and pass valid polarity and range values directly.

When the display is in hex mode, the sample writes the raw range register directly using naibrd_AD_SetChannelRaw() instead of the engineering-unit API.

naibrd_ad_polarity_t polarity = NAIBRD_AD_POLARITY_UNIPOLAR;
float64_t range = 0.0;
naibrd_ad_mode_t mode = NAIBRD_AD_MODE_VOLTAGE;

/* Retrieve the current mode so the correct range table is used */
naibrd_AD_GetMode(cardIndex, module, channel, &mode);

/* Set the polarity and range for the specified channel */
naibrd_AD_SetRangePolarity(cardIndex, module, channel, polarity, range);

For raw register access (hex mode):

uint32_t rawRange = 0u;

/* Write the range/polarity register directly */
naibrd_AD_SetChannelRaw(cardIndex, module, channel,
   NAIBRD_AD_CHAN_RAW_RANGE, rawRange);
  • cardIndex — identifies the board.

  • module — the slot containing the AD module.

  • channel — the channel to configure.

  • polarity — NAIBRD_AD_POLARITY_UNIPOLAR or NAIBRD_AD_POLARITY_BIPOLAR. The set of valid values depends on the module type.

  • range — the full-scale input range as a floating-point value. Refer to your module’s manual for the list of supported range values per polarity setting: AD1-AD3 Manual, AD4-AD6 Manual, ADE-ADF Manual.

Note
The valid combinations of polarity and range differ across AD module types. Always consult the module manual for your specific hardware.

Set Mode (Voltage or Current)

To switch a channel between voltage and current measurement mode in your own application, call naibrd_AD_SetMode(). This feature is exclusive to the AD4 module — calling it on any other module type returns NAI_ERROR_NOT_SUPPORTED.

nai_status_t status;

/* Set a single channel to voltage mode */
status = naibrd_AD_SetMode(cardIndex, module, channel, NAIBRD_AD_MODE_VOLTAGE);

/* Set a single channel to current mode */
status = naibrd_AD_SetMode(cardIndex, module, channel, NAIBRD_AD_MODE_CURRENT);

To apply the same mode to every channel on the module, loop over all channels:

for (channel = 1; channel <= maxChannels; channel++)
   status = naibrd_AD_SetMode(cardIndex, module, channel, NAIBRD_AD_MODE_VOLTAGE);
  • cardIndex — identifies the board.

  • module — the slot containing the AD module.

  • channel — the channel to configure.

  • The fourth parameter selects the mode: NAIBRD_AD_MODE_VOLTAGE or NAIBRD_AD_MODE_CURRENT.

Note
This function is AD4 only. On all other AD modules the API returns NAI_ERROR_NOT_SUPPORTED.

Set Latch

To latch all channel readings simultaneously in your own application, call naibrd_AD_SetLatchChannel(). When latching is enabled, every channel’s reading is captured at the same instant, which is useful when you need a coherent snapshot across channels. Pass channel 0 to apply the latch setting module-wide.

/* Latch all channel readings on the module */
naibrd_AD_SetLatchChannel(cardIndex, module, 0, NAI_TRUE);

/* Unlatch (return to free-running mode) */
naibrd_AD_SetLatchChannel(cardIndex, module, 0, NAI_FALSE);
  • cardIndex — identifies the board.

  • module — the slot containing the AD module.

  • The third parameter — channel 0 applies the latch to all channels.

  • The fourth parameter — NAI_TRUE to latch (freeze) all channel readings simultaneously, NAI_FALSE to return to free-running mode.

Set Break Frequency

To configure the low-pass filter break frequency on a channel in your own application, call naibrd_AD_SetFilterBreakFrequency(). This controls the cutoff frequency of the per-channel input filter, which determines how much high-frequency noise is attenuated before the signal is digitized.

uint32_t filterBreakFrequency = 100u;

/* Set the filter break frequency for the specified channel */
naibrd_AD_SetFilterBreakFrequency(cardIndex, module, channel,
   filterBreakFrequency);
  • cardIndex — identifies the board.

  • module — the slot containing the AD module.

  • channel — the channel to configure.

  • filterBreakFrequency — the desired cutoff frequency in Hz. Refer to your module’s manual for the set of supported frequency values.

Note
The available break frequency settings vary by module type. Consult the module manual for supported values.

Set Active Channel

To enable or disable individual channels in your own application, call naibrd_AD_SetActiveChannel(). Disabling a channel powers it down, which can reduce module power consumption. This feature is exclusive to the AD4 module — calling it on any other module type returns NAI_ERROR_NOT_SUPPORTED.

nai_status_t status;

/* Enable a single channel */
status = naibrd_AD_SetActiveChannel(cardIndex, module, channel, NAI_TRUE);

/* Disable a single channel */
status = naibrd_AD_SetActiveChannel(cardIndex, module, channel, NAI_FALSE);

To enable or disable all channels at once, loop over every channel on the module:

for (channel = 1; channel <= maxChannels; channel++)
   status = naibrd_AD_SetActiveChannel(cardIndex, module, channel, NAI_TRUE);
  • cardIndex — identifies the board.

  • module — the slot containing the AD module.

  • channel — the channel to enable or disable.

  • The fourth parameter — NAI_TRUE to activate the channel, NAI_FALSE to deactivate it.

Note
This function is AD4 only. On all other AD modules the API returns NAI_ERROR_NOT_SUPPORTED.
Important

Common Errors

  • NAI_ERROR_NOT_SUPPORTED — Returned when attempting to set mode or active channel state on a non-AD4 module. These features are exclusive to the AD4.

  • Invalid range or polarity — Passing a range or polarity value that the module does not support. Consult your module’s manual for the list of valid range and polarity settings.

Self-Test and Diagnostics

This section covers the built-in self-test and diagnostic features available in the AD BasicOps sample: the D0 test signal, power-on BIT verification, BIT error thresholds, and per-channel status enable control. These features help you verify that the AD conversion path is functioning correctly and detect hardware faults early.

D0 Test Enable and Configuration

To inject a known test signal into the AD conversion path in your own application, call naibrd_AD_SetModuleBITEnable() to turn the D0 test on or off, and naibrd_AD_SetD0TestParams() to set the test parameters.

The D0 test drives a known voltage (or current) into the converter so you can verify the digitization path end-to-end. The D0 range is fixed to the highest bipolar range, but the polarity is configurable as unipolar or bipolar. You must also specify a test level — the voltage the D0 source will output.

/* Enable the D0 test */
naibrd_AD_SetModuleBITEnable(cardIndex, module, NAIBRD_AD_D0_TEST, NAI_TRUE);

/* Configure D0 test: set polarity, range, and test level */
naibrd_ad_polarity_t polarity = NAIBRD_AD_POLARITY_BIPOLAR;
float64_t D0Range = 10.0;
float64_t testLevel = 5.0;
naibrd_AD_SetD0TestParams(cardIndex, module, polarity, D0Range, testLevel);

To disable the D0 test when you are finished:

naibrd_AD_SetModuleBITEnable(cardIndex, module, NAIBRD_AD_D0_TEST, NAI_FALSE);

The sample uses naibrd_AD_ConvertToRange() to translate raw polarity values into the correct range and polarity pair before calling naibrd_AD_SetD0TestParams(). In your own code, you can pass the polarity and range values directly.

  • cardIndex — identifies the board.

  • module — the slot containing the AD module.

  • NAIBRD_AD_D0_TEST — selects the D0 test type.

  • polarity — NAIBRD_AD_POLARITY_UNIPOLAR or NAIBRD_AD_POLARITY_BIPOLAR.

  • D0Range — the full-scale range for the D0 test.

  • testLevel — the voltage level the D0 source will output.

Note
Channels that are not set to the same range and polarity as D0 will not be scaled the same, and will show unexpected readings. On AD3 and ADG modules (and CMG combination modules), the D0 test operates in current mode rather than voltage mode. Consult your module’s manual for hardware-specific D0 test behavior.

Power-On BIT Check

To verify that the module passed its power-on built-in test (PBIT) in your own application, call naibrd_AD_CheckPowerOnBITComplete() to check whether PBIT has run, then iterate over all channels calling naibrd_AD_GetChanMappedStatus() with NAIBRD_AD_STATUS_BIT_LATCHED to read each channel’s BIT result.

PBIT only executes once, at power-on. If the module has not been power-cycled since it was installed, PBIT may not have completed — this is normal and does not indicate a hardware failure.

bool_t pbitComplete;
nai_status_bit_t bitFailed;
int32_t channelCount = naibrd_AD_GetChannelCount(modId);

/* Step 1: Check whether PBIT has completed */
naibrd_AD_CheckPowerOnBITComplete(cardIndex, module, &pbitComplete);

if (pbitComplete)
{
   /* Step 2: Read BIT status for each channel */
   for (channel = 1; channel <= channelCount; channel++)
   {
      naibrd_AD_GetChanMappedStatus(cardIndex, module, channel,
         NAIBRD_AD_STATUS_BIT_LATCHED, &bitFailed);
      if (bitFailed)
         naiif_printf("Channel %d: BIT FAILED\r\n", channel);
      else
         naiif_printf("Channel %d: BIT Passed\r\n", channel);
   }
}
  • cardIndex — identifies the board.

  • module — the slot containing the AD module.

  • pbitComplete — set to NAI_TRUE if PBIT has finished, NAI_FALSE otherwise.

  • NAIBRD_AD_STATUS_BIT_LATCHED — reads the latched BIT status for a channel.

  • bitFailed — non-zero if the channel failed its BIT.

BIT Error Thresholds

To configure how many BIT errors the module tolerates before flagging a failure in your own application, call naibrd_AD_SetModuleBITErrorThreshold(). To read the current threshold, call naibrd_AD_GetModuleBITErrorThreshold(). To reset BIT counters on a per-channel basis, call naibrd_AD_ClearModuleBITLogic().

The default BIT error threshold is 5. This means the module must accumulate more than 5 BIT errors on a channel before it reports a BIT failure for that channel. You can raise or lower this threshold depending on your application’s sensitivity requirements.

This feature is supported on ADE, ADF, ADG, IF1, and the corresponding combination modules (CME, CMF, CMG). On other AD module types, calling this function returns NAI_ERROR_NOT_SUPPORTED.

uint32_t bitThreshold = 0u;

/* Set BIT error threshold */
naibrd_AD_SetModuleBITErrorThreshold(cardIndex, module, 10);

/* Read back the current threshold */
naibrd_AD_GetModuleBITErrorThreshold(cardIndex, module, &bitThreshold);

/* Clear BIT counters on all channels */
int32_t channelCount = naibrd_AD_GetChannelCount(modId);
for (int32_t ch = 1; ch <= channelCount; ch++)
   naibrd_AD_ClearModuleBITLogic(cardIndex, module, ch);
  • cardIndex — identifies the board.

  • module — the slot containing the AD module.

  • bitThreshold — the number of BIT errors before a failure is reported. Default is 5.

  • naibrd_AD_ClearModuleBITLogic() resets the BIT error counter for a single channel.

Channel Status Enable

To enable or disable status reporting on a per-channel basis in your own application, call naibrd_AD_SetChanStatusEnable(). When channel status is disabled, the module will not report status conditions for that channel and status-based interrupts will not assert.

/* Enable status reporting on a channel */
naibrd_AD_SetChanStatusEnable(cardIndex, module, channel, NAI_TRUE);

/* Disable status reporting on a channel */
naibrd_AD_SetChanStatusEnable(cardIndex, module, channel, NAI_FALSE);
  • cardIndex — identifies the board.

  • module — the slot containing the AD module.

  • channel — the channel to enable or disable status reporting on.

  • The fourth parameter — NAI_TRUE to enable status reporting, NAI_FALSE to disable it.

Note
Disabling channel status also suppresses any interrupts that would be triggered by status conditions on that channel. Re-enable channel status before relying on status-based interrupt handling.
Important

Common Errors

  • PBIT not complete — The power-on BIT test only runs when the module is first powered on. If the module has not been power-cycled, naibrd_AD_CheckPowerOnBITComplete() will report that PBIT has not completed. This is not a hardware failure.

  • D0 test shows unexpected readings — The D0 test requires that polarity, range, and test level all be configured. Missing any one of these will produce inaccurate results. Additionally, channels not set to the same range and polarity as D0 will show unexpected readings.

  • BIT failure on a channel — A BIT failure can indicate an open input, a hardware fault, or an incorrect range setting. Consult your module’s manual for diagnostic procedures.

  • NAI_ERROR_NOT_SUPPORTED from THRESH command — BIT error threshold control is only available on ADE, ADF, ADG, IF1, CME, CMF, and CMG modules.

Floating-Point Conversion

Some AD modules support hardware floating-point conversion, which applies an offset and scale factor to raw ADC values directly in hardware. If your application needs engineering-unit readings with a custom offset or gain applied, enabling floating-point mode lets the hardware handle this rather than doing it in software. The three functions in this section work together: first verify that the module supports the feature, then configure the offset and scale factor, and finally enable the mode.

Enable Floating-Point Mode

To enable or disable hardware floating-point conversion on a module, call naibrd_SetFloatingPointModeEnable(). Before doing so, always check whether the module supports the feature by calling naibrd_GetFloatingPointModeCapability(). Not all AD modules have floating-point conversion hardware, and calling the enable function on an unsupported module will fail.

bool_t fpCapable = NAI_FALSE;
nai_status_t status;

/* Step 1: Check whether the module supports floating-point conversion */
naibrd_GetFloatingPointModeCapability(cardIndex, module, &fpCapable);

if (fpCapable)
{
   /* Step 2: Enable floating-point mode on the module */
   status = naibrd_SetFloatingPointModeEnable(cardIndex, module, 0x1);
}
  • cardIndex — identifies the board.

  • module — the slot containing the AD module.

  • fpCapable — set to NAI_TRUE if the module supports floating-point conversion, NAI_FALSE otherwise.

  • The third parameter to naibrd_SetFloatingPointModeEnable() — 0x1 to enable, 0x0 to disable.

When enabled, the module applies the configured offset and scale factor to every raw ADC value before it is returned, so subsequent reads produce a calibrated or scaled result directly.

Set Floating-Point Offset

To set the floating-point offset on a per-channel basis, call naibrd_AD_SetFloatingPointAttribute() with the NAIBRD_AD_ATTRIBUTE_OFFSET selector. The offset is added to each raw ADC reading when floating-point mode is enabled. As with enabling the mode itself, always verify floating-point capability first.

bool_t fpCapable = NAI_FALSE;
float64_t offset = 1.25;
nai_status_t status;

naibrd_GetFloatingPointModeCapability(cardIndex, module, &fpCapable);

if (fpCapable)
{
   /* Set the floating-point offset for a specific channel */
   status = naibrd_AD_SetFloatingPointAttribute(cardIndex, module, channel,
      NAIBRD_AD_ATTRIBUTE_OFFSET, offset);
}
  • cardIndex — identifies the board.

  • module — the slot containing the AD module.

  • channel — the channel to configure.

  • NAIBRD_AD_ATTRIBUTE_OFFSET — selects the offset attribute.

  • offset — the offset value to apply. This is a float64_t and can be positive or negative.

Set Floating-Point Scale Factor

To set the floating-point scale factor on a per-channel basis, call naibrd_AD_SetFloatingPointAttribute() with the NAIBRD_AD_ATTRIBUTE_SCALE_FACTOR selector. The scale factor is multiplied against each raw ADC reading when floating-point mode is enabled. As with the other floating-point functions, always verify capability first.

bool_t fpCapable = NAI_FALSE;
float64_t scale = 2.0;
nai_status_t status;

naibrd_GetFloatingPointModeCapability(cardIndex, module, &fpCapable);

if (fpCapable)
{
   /* Set the floating-point scale factor for a specific channel */
   status = naibrd_AD_SetFloatingPointAttribute(cardIndex, module, channel,
      NAIBRD_AD_ATTRIBUTE_SCALE_FACTOR, scale);
}
  • cardIndex — identifies the board.

  • module — the slot containing the AD module.

  • channel — the channel to configure.

  • NAIBRD_AD_ATTRIBUTE_SCALE_FACTOR — selects the scale factor attribute.

  • scale — the scale factor to apply. This is a float64_t.

Note
In SSK 2.x, both offset and scale factor are set through the unified naibrd_AD_SetFloatingPointAttribute() API with an attribute selector, rather than through separate functions as in SSK 1.x.
Important

Common Errors

  • Unexpected readings after enabling floating-point mode — The offset and scale factor must be set to the desired values before enabling floating-point mode. If the mode is enabled without configuring these parameters, the default values may not match your expectations.

  • Offset and scale factor have no effect — These parameters are stored but only applied when floating-point mode is enabled. Verify that naibrd_SetFloatingPointModeEnable() has been called with a nonzero value.

  • "This feature is not supported by this module" — The module does not have floating-point conversion capability. Call naibrd_GetFloatingPointModeCapability() to check before attempting to enable it.

Saturation Control

Saturation control lets you define low and high voltage thresholds on a per-channel basis. When a channel reading exceeds either bound, the hardware flags the condition. This is useful for monitoring whether input signals stay within an expected operating window — for example, detecting an over-voltage or under-voltage condition without polling channel readings in software.

Checking Saturation Availability

Saturation control is not available on all FPGA revisions. Before entering the saturation submenu, the sample calls naibrd_GenModuleRevRaw() to retrieve the module’s FPGA revision and compares it against a minimum threshold that varies by module family:

  • AD1-AD3: FPGA revision >= 0x00020001

  • AD4-AD6: FPGA revision >= 0x0007000C

  • ADE-ADG: FPGA revision >= 0x00010007

  • CME, CMF, CMG, IF1: always available (no minimum revision)

uint32_t fpgaRev = 0u;
bool_t satAvailable = NAI_FALSE;

/* Retrieve the module's FPGA revision */
naibrd_GenModuleRevRaw(cardIndex, module, NULL, &fpgaRev, NULL, NULL, NULL, NULL);

/* Compare fpgaRev against the minimum revision for your module family */
if (fpgaRev >= minimumSupportedRev)
   satAvailable = NAI_TRUE;
  • cardIndex — identifies the board.

  • module — the slot containing the AD module.

  • fpgaRev — the FPGA revision reported by the module.

  • The minimum supported revision differs by module family. Consult your module’s manual for the specific FPGA revision required to enable saturation control.

If the FPGA revision does not meet the minimum, the sample reports "Saturation is not supported by this module" and does not enter the saturation submenu.

Set Saturation Levels

To define the low and high saturation thresholds on a channel, call naibrd_AD_SetSaturationLevel() with the appropriate control selector. Each channel has independent low and high threshold settings.

float64_t lowThreshold = -5.0;
float64_t highThreshold = 5.0;

/* Set the low saturation threshold for a channel */
naibrd_AD_SetSaturationLevel(cardIndex, module, channel,
   NAIBRD_AD_SATURATION_CONTROL_LOW, lowThreshold);

/* Set the high saturation threshold for a channel */
naibrd_AD_SetSaturationLevel(cardIndex, module, channel,
   NAIBRD_AD_SATURATION_CONTROL_HIGH, highThreshold);
  • cardIndex — identifies the board.

  • module — the slot containing the AD module.

  • channel — the channel to configure.

  • The fourth parameter selects which threshold to set: NAIBRD_AD_SATURATION_CONTROL_LOW or NAIBRD_AD_SATURATION_CONTROL_HIGH.

  • The fifth parameter is the threshold voltage as a float64_t.

Enable Saturation Detection

Setting a threshold level alone does not activate saturation detection. You must also enable detection for each threshold independently by calling naibrd_AD_SetSaturationControl(). Both the threshold level and the enable flag must be configured for detection to work.

/* Enable low-level saturation detection on a channel */
naibrd_AD_SetSaturationControl(cardIndex, module, channel,
   NAIBRD_AD_SATURATION_CONTROL_LOW, NAI_TRUE);

/* Enable high-level saturation detection on a channel */
naibrd_AD_SetSaturationControl(cardIndex, module, channel,
   NAIBRD_AD_SATURATION_CONTROL_HIGH, NAI_TRUE);

To disable detection, pass NAI_FALSE instead of NAI_TRUE:

/* Disable low-level saturation detection */
naibrd_AD_SetSaturationControl(cardIndex, module, channel,
   NAIBRD_AD_SATURATION_CONTROL_LOW, NAI_FALSE);

/* Disable high-level saturation detection */
naibrd_AD_SetSaturationControl(cardIndex, module, channel,
   NAIBRD_AD_SATURATION_CONTROL_HIGH, NAI_FALSE);
  • cardIndex — identifies the board.

  • module — the slot containing the AD module.

  • channel — the channel to configure.

  • The fourth parameter selects which threshold to enable or disable: NAIBRD_AD_SATURATION_CONTROL_LOW or NAIBRD_AD_SATURATION_CONTROL_HIGH.

  • The fifth parameter — NAI_TRUE to enable detection, NAI_FALSE to disable it.

Reading Saturation Configuration

To read back the current saturation configuration for a channel, call naibrd_AD_GetSaturationLevel() and naibrd_AD_GetSaturationControl() for both the low and high thresholds. This lets you verify the configured thresholds and whether detection is active.

float64_t satLowLevel = 0.0;
float64_t satHighLevel = 0.0;
bool_t satLowEnable = NAI_FALSE;
bool_t satHighEnable = NAI_FALSE;

/* Read saturation threshold levels */
naibrd_AD_GetSaturationLevel(cardIndex, module, channel,
   NAIBRD_AD_SATURATION_CONTROL_LOW, &satLowLevel);
naibrd_AD_GetSaturationLevel(cardIndex, module, channel,
   NAIBRD_AD_SATURATION_CONTROL_HIGH, &satHighLevel);

/* Read saturation enable states */
naibrd_AD_GetSaturationControl(cardIndex, module, channel,
   NAIBRD_AD_SATURATION_CONTROL_LOW, &satLowEnable);
naibrd_AD_GetSaturationControl(cardIndex, module, channel,
   NAIBRD_AD_SATURATION_CONTROL_HIGH, &satHighEnable);
  • satLowLevel / satHighLevel — the configured threshold voltages.

  • satLowEnable / satHighEnable — NAI_TRUE if detection is active for that threshold, NAI_FALSE otherwise.

To display the saturation configuration for all channels on a module, loop over each channel and call these four functions, as the sample does in ADBasicOps_displaySaturationConfig().

Important

Common Errors

  • Saturation commands unavailable — Saturation control requires a minimum FPGA revision that varies by module family. If the feature is not available, the sample will report "Saturation is not supported by this module." Consult your module’s manual for the required FPGA revision.

  • Thresholds set but detection not working — Both the threshold level and the enable flag must be configured. Setting a threshold without enabling detection (or vice versa) will not produce the expected behavior.

Module Power Reset

The module power reset submenu lets you monitor module power status and issue reset, power-down, or power-up requests. This is useful for recovering a module from an error state or performing a controlled power cycle without restarting the entire board.

Reading Module Power Reset Status

To check the current power status of a module, call naibrd_AD_GetModulePowerResetStatus() with each status type. The sample displays five status flags:

bool_t poweredDownStatus = NAI_FALSE;
bool_t notDetectedStatus = NAI_FALSE;
bool_t notLinkInitStatus = NAI_FALSE;
bool_t notFWNotStatus = NAI_FALSE;
bool_t commErrorStatus = NAI_FALSE;

naibrd_AD_GetModulePowerResetStatus(cardIndex, module,
   NAIBRD_AD_MODULE_POWER_RESET_STATUS_POWERED_DOWN, &poweredDownStatus);
naibrd_AD_GetModulePowerResetStatus(cardIndex, module,
   NAIBRD_AD_MODULE_POWER_RESET_STATUS_NOT_DETECTED, &notDetectedStatus);
naibrd_AD_GetModulePowerResetStatus(cardIndex, module,
   NAIBRD_AD_MODULE_POWER_RESET_STATUS_NOT_LINK_INIT, &notLinkInitStatus);
naibrd_AD_GetModulePowerResetStatus(cardIndex, module,
   NAIBRD_AD_MODULE_POWER_RESET_STATUS_FW_NOT_READY, &notFWNotStatus);
naibrd_AD_GetModulePowerResetStatus(cardIndex, module,
   NAIBRD_AD_MODULE_POWER_RESET_STATUS_COMM_ERROR, &commErrorStatus);
  • Powered Down — the module is in a powered-down state.

  • Not Detected — the module was not detected during initialization.

  • Not Link Init — the communication link to the module has not been initialized.

  • FW Not Ready — the module firmware is not ready.

  • Comm Error — a communication error has occurred with the module.

Requesting Module Power Reset

To issue a power reset request, call naibrd_AD_SetModulePowerReset() with the desired request type:

/* Issue a module reset request */
naibrd_AD_SetModulePowerReset(cardIndex, module,
   NAIBRD_AD_MODULE_POWER_RESET_REQUEST_RESET, NAI_TRUE);

/* Issue a module power-down request */
naibrd_AD_SetModulePowerReset(cardIndex, module,
   NAIBRD_AD_MODULE_POWER_RESET_REQUEST_POWER_DOWN, NAI_TRUE);

/* Issue a module power-up request */
naibrd_AD_SetModulePowerReset(cardIndex, module,
   NAIBRD_AD_MODULE_POWER_RESET_REQUEST_POWER_UP, NAI_TRUE);

To read back the current request state, call naibrd_AD_GetModulePowerReset():

bool_t resetRequest = NAI_FALSE;
naibrd_AD_GetModulePowerReset(cardIndex, module,
   NAIBRD_AD_MODULE_POWER_RESET_REQUEST_RESET, &resetRequest);

Clearing Module Power Reset Status

To clear a module power reset status flag, first read whether the status bit is set, then call naibrd_AD_ClearModulePowerResetStatus():

bool_t statusRead = NAI_FALSE;

naibrd_AD_GetModulePowerResetStatus(cardIndex, module,
   NAIBRD_AD_MODULE_POWER_RESET_STATUS_POWERED_DOWN, &statusRead);
if (statusRead)
{
   naibrd_AD_ClearModulePowerResetStatus(cardIndex, module,
      NAIBRD_AD_MODULE_POWER_RESET_STATUS_POWERED_DOWN);
}
Important

Common Errors

  • Module unresponsive after power-down — After issuing a power-down request, the module will not respond to API calls until a power-up request is issued and the module completes its initialization sequence.

  • Status flags not clearing — A status flag can only be cleared if it is currently set. The sample reads the status before attempting to clear it.

Display Functions

The display functions in this sample demonstrate the full set of naibrd_AD_Get* read-back APIs. These are the same calls you would use in your own application to retrieve channel data, configuration, and status. The sample calls them on every iteration of the command loop to show a live view of the module state, but in your own code you can call them whenever you need to read back a value.

Reading Channel Data

To read back channel voltages in your own application, call naibrd_AD_GetData(). To read raw register values instead, call naibrd_AD_GetChannelRaw(). The ADBasicOps_displayConfigurations() function demonstrates these calls along with the other per-channel read-back APIs. For each channel it retrieves the current reading, range and polarity, filter break frequency, and measurement mode:

float64_t data = 0;
uint32_t rawData = 0u;
float64_t range = 0;
naibrd_ad_polarity_t polarity = NAIBRD_AD_POLARITY_UNIPOLAR;
uint32_t filterBreakFreq = 0u;
naibrd_ad_mode_t data_mode = NAIBRD_AD_MODE_VOLTAGE;

for (channel = 1; channel <= maxChannels; channel++)
{
   naibrd_AD_GetData(cardIndex, module, channel, data_mode, &data);
   naibrd_AD_GetChannelRaw(cardIndex, module, channel,
      NAIBRD_AD_CHAN_RAW_DATA, &rawData);
   naibrd_AD_GetRangePolarity(cardIndex, module, channel, &polarity, &range);
   naibrd_AD_GetFilterBreakFrequency(cardIndex, module, channel, &filterBreakFreq);
   naibrd_AD_GetMode(cardIndex, module, channel, &data_mode);
}

On AD4 modules, the display function also retrieves the channel active/inactive state:

bool_t channelActive = NAI_TRUE;
naibrd_AD_GetActiveChannel(cardIndex, module, channel, &channelActive);

If the module supports hardware floating-point conversion, the function reads back the per-channel offset and scale factor:

float64_t offset = 0.0;
float64_t scale = 0.0;
naibrd_AD_GetFloatingPointAttribute(cardIndex, module, channel,
   NAIBRD_AD_ATTRIBUTE_OFFSET, &offset);
naibrd_AD_GetFloatingPointAttribute(cardIndex, module, channel,
   NAIBRD_AD_ATTRIBUTE_SCALE_FACTOR, &scale);
  • naibrd_AD_GetData() — returns the channel reading in engineering units (volts or amps depending on the mode).

  • naibrd_AD_GetChannelRaw() — returns the raw register value as an unsigned integer.

  • naibrd_AD_GetRangePolarity() — returns both the polarity and the full-scale range for the channel.

  • naibrd_AD_GetFilterBreakFrequency() — returns the configured low-pass filter cutoff frequency in Hz.

  • naibrd_AD_GetMode() — returns the measurement mode (voltage or current).

  • naibrd_AD_GetActiveChannel() — returns the channel active/inactive state (AD4 only).

  • naibrd_AD_GetFloatingPointAttribute() — returns the hardware floating-point offset or scale factor for the channel, depending on the attribute selector.

Reading Channel Status

To read channel status in your own application, call naibrd_AD_GetChanStatusEnable() to check whether status reporting is active, then call naibrd_AD_GetChanMappedStatus() with the appropriate status type to retrieve real-time values. The ADBasicOps_displayConfigurations() function demonstrates the complete set of status read-back calls:

nai_status_bit_t BitStatus = NAI_STATUS_BIT_LO;
nai_status_bit_t OpenStatus = NAI_STATUS_BIT_LO;
nai_status_bit_t PBitStatus = NAI_STATUS_BIT_LO;
nai_status_bit_t AntiAliasingFilterStatus = NAI_STATUS_BIT_LO;
nai_status_bit_t VoltageRdgAccStatus = NAI_STATUS_BIT_LO;
bool_t chanStatusEnabled = NAI_TRUE;

naibrd_AD_GetChanStatusEnable(cardIndex, module, channel, &chanStatusEnabled);
naibrd_AD_GetChanMappedStatus(cardIndex, module, channel,
   NAIBRD_AD_STATUS_BIT_REALTIME, &BitStatus);
naibrd_AD_GetChanMappedStatus(cardIndex, module, channel,
   NAIBRD_AD_STATUS_OPEN_OVERVOLT_REALTIME, &OpenStatus);

On ADE and ADF modules, the display function retrieves three additional status types:

naibrd_AD_GetChanMappedStatus(cardIndex, module, channel,
   NAIBRD_AD_STATUS_POWER_ON_BIT_REALTIME, &PBitStatus);
naibrd_AD_GetChanMappedStatus(cardIndex, module, channel,
   NAIBRD_AD_STATUS_ANTI_ALIASING_FILTER_REALTIME, &AntiAliasingFilterStatus);
naibrd_AD_GetChanMappedStatus(cardIndex, module, channel,
   NAIBRD_AD_STATUS_VOLTAGE_READING_ACCURACY_REALTIME, &VoltageRdgAccStatus);

Here is how to interpret the status values:

  • BIT status — tests the AD conversion path. A NAI_STATUS_BIT_HI value indicates the converter is not producing expected results for a known reference input.

  • Open/overvoltage — detects open-circuit or overvoltage conditions on the channel input. A NAI_STATUS_BIT_HI value typically means the input is disconnected or exceeds the configured range. Not available on IF1 modules.

  • PBIT status (ADE/ADF only) — power-on BIT result for the channel.

  • Anti-aliasing filter status (ADE/ADF only) — indicates a problem with the per-channel anti-aliasing filter.

  • Voltage reading accuracy status (ADE/ADF only) — flags reduced reading accuracy.

CF1 Module Display

When a CF1 module is detected, the application enters a simplified display loop that reads DC voltage and RMS voltage for each channel:

for (channel = 1; channel <= numChannels; channel++)
{
   naibrd_AD_GetData(cardIndex, module, channel, NAIBRD_AD_MODE_VOLTAGE, &Vdc);
   naibrd_AD_GetData(cardIndex, module, channel, NAIBRD_AD_MODE_RMS_VOLTAGE, &Vrms);
   naiif_printf("  %2d     %10.6fV     %10.6fV\r\n", channel, Vdc, Vrms);
}

The CF1 display mode does not provide a command menu — it simply refreshes the channel data table each time you press a key.

Hex vs. Decimal Toggle

The ADBasicOps_toggleNumDisplay() function switches the displayHex flag, which controls whether the display functions call naibrd_AD_GetData() or naibrd_AD_GetChannelRaw():

if (displayHex)
{
   naibrd_AD_GetChannelRaw(cardIndex, module, channel,
      NAIBRD_AD_CHAN_RAW_DATA, &rawData);
   /* Display as hex: 0x00000000 */
}
else
{
   naibrd_AD_GetData(cardIndex, module, channel, data_mode, &data);
   /* Display in engineering units: voltage or current */
}

Both calls read the same underlying channel data, but present it differently:

  • naibrd_AD_GetData() returns a float64_t in engineering units (volts or amps). Use this in your application logic when you need calibrated measurements — for example, comparing a reading against a threshold or logging sensor data.

  • naibrd_AD_GetChannelRaw() returns the raw register value as a uint32_t displayed in hexadecimal. Use this for register-level debugging — for example, verifying that a specific bit pattern is present in the data register or diagnosing a calibration issue where the scaled value looks wrong.

Troubleshooting Reference

This table summarizes common errors and symptoms covered in the sections above. For detailed context on each entry, refer to the relevant section. Consult your module’s manual for hardware-specific diagnostic procedures.

Error / Symptom Possible Causes Suggested Resolution

No board found or connection timeout

Board not powered, incorrect or missing configuration file, network issue

Verify hardware is powered and connected. If default_AD_BasicOps.txt exists, check that it lists the correct interface and address. If it does not exist, the board menu will appear — configure and save your connection settings.

Module not detected at selected slot

No module installed at the specified slot, incorrect module number entered

Verify hardware configuration and module slot assignment

NAI_ERROR_NOT_SUPPORTED

Feature not available for this module type (e.g., mode switching on non-AD4, BIT thresholds on AD1-AD3) or FPGA revision too old for the requested feature

Check your module type. Consult your module’s manual for supported features and required FPGA revisions.

NAI_ERROR_INVALID_VALUE

Invalid parameter passed to an API call (e.g., out-of-range value, unsupported polarity)

Verify input values against your module’s manual specifications

NAI_ERROR_UNKNOWN

Generic failure during an API call

Check board connection, verify module is powered and responsive

PBIT not complete

Module has not been power-cycled since last boot

Power-cycle the module and re-run the PBIT check

Unexpected voltage readings

Range or polarity misconfigured, floating-point offset/scale incorrect, D0 test still enabled

Verify channel configuration. Disable D0 test if not needed. Check floating-point parameters.

BIT failure on a channel

Open input, hardware fault, or incorrect range setting

Check input wiring. Consult your module’s manual for diagnostic procedures.

Saturation commands unavailable

FPGA revision below the minimum required for saturation support

Consult your module’s manual for the required FPGA revision

D0 test produces unexpected results

Polarity, range, or test level not fully configured — all three must be set

Ensure naibrd_AD_SetModuleBITEnable() and naibrd_AD_SetD0TestParams() are both called with valid parameters

Floating-point mode readings incorrect

Offset/scale set but mode not enabled, or mode enabled without setting offset/scale

Enable floating-point mode AND set both offset and scale factor parameters

Module unresponsive after power reset

Power-down request issued without subsequent power-up, or module still initializing

Issue a power-up request and wait for the module firmware to report ready

Full Source

The complete source for this sample is provided below for reference. The sections above explain each part in detail.

Full Source — ad_basic_ops.c (SSK 2.x)
/* nailib include files */
#include "nai_libs/nailib/include/naitypes.h"
#include "nai_libs/nailib/include/nailib.h"
#include "nai_libs/nailib/include/nailib_utils.h"

/* naibrd include files */
#include "nai_libs/naibrd/include/naibrd.h"
#include "nai_libs/naibrd/include/functions/naibrd_ad.h"

/* naiif include files */
#include "nai_libs/naiif/include/naiif_stdio.h"

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

/* AD Sample App include files */
#include "nai_sample_apps/naiapp_src/board_modules/ad/ad_common_utils/ad_common_utils.h"

static const int8_t *SAMPLE_PGM_NAME = (const int8_t *)"AD Module Basic Operation Program";
static const int8_t *CONFIG_FILE = (const int8_t *)"default_AD_BasicOps.txt";

#define NAIAPPS_AD123_SATURATION_SUPPORT_FPGA_REV 0x00020001u
#define NAIAPPS_AD456_SATURATION_SUPPORT_FPGA_REV 0x0007000Cu
#define NAIAPPS_ADEFG_SATURATION_SUPPORT_FPGA_REV 0x00010007u
static const int8_t *SATURATION_MENU = (const int8_t *)"AD Module Saturation Menu";

#define DEFAULT_CHANNEL 1

/* Function prototypes */
static bool_t ADBasicOps_run(int32_t cardIndex, int32_t module, uint32_t modid);
static bool_t CF1ADBasicOps_run(int32_t cardIndex, int32_t module, uint32_t modid);
static void ADBasicOps_displayConfigurations(int32_t cardIndex, int32_t module, uint32_t modId, int32_t maxChannels, bool_t displayHex);
static void ADBasicOps_displaySaturationConfig(int32_t cardIndex, int32_t module, uint32_t modId, int32_t maxChannels, bool_t displayHex);

/* AD Basic Ops Command Functions */
static nai_status_t ADBasicOps_setRangePolarity(int32_t paramCount, int32_t* p_params);
static nai_status_t ADBasicOps_setLatch(int32_t paramCount, int32_t* p_params);
static nai_status_t ADBasicOps_setMode(int32_t paramCount, int32_t* p_params);
static nai_status_t ADBasicOps_setBreakFreq(int32_t paramCount, int32_t* p_params);
static nai_status_t ADBasicOps_setActiveChannel(int32_t paramCount, int32_t* p_params);
static nai_status_t ADBasicOps_saturationMenu(int32_t paramCount, int32_t* p_params);
static nai_status_t ADBasicOps_setD0TestEnable(int32_t paramCount, int32_t* p_params);
static nai_status_t ADBasicOps_FloatingPointMode(int32_t paramCount, int32_t* p_params);
static nai_status_t ADBasicOps_FloatingPointOffset(int32_t paramCount, int32_t* p_params);
static nai_status_t ADBasicOps_FloatingPointScaleFactor(int32_t paramCount, int32_t* p_params);
static nai_status_t ADBasicOps_ChannelStatusEnable(int32_t paramCount, int32_t* p_params);
static nai_status_t ADBasicOps_CheckPowerOnBIT(int32_t paramCount, int32_t* p_params);
static nai_status_t ADBasicOps_BITThresholds(int32_t paramCount, int32_t* p_paramas);
static nai_status_t ADBasicOps_toggleNumDisplay(int32_t paramCount, int32_t* p_params);
static nai_status_t ADBasicOps_setSaturationLow(int32_t paramCount, int32_t* p_params);
static nai_status_t ADBasicOps_setSaturationHigh(int32_t paramCount, int32_t* p_params);
static nai_status_t ADBasicOps_enableSaturationLow(int32_t paramCount, int32_t* p_params);
static nai_status_t ADBasicOps_enableSaturationHigh(int32_t paramCount, int32_t* p_params);
static bool_t ADBasicOps_SaturationAvailable(int32_t paramCount, int32_t* p_params);

static nai_status_t ADBasicOps_ModulePowerResetMenu(int32_t paramCount, int32_t* p_params);
static nai_status_t ADBasicOps_ClearModulePowerResetStatus(int32_t paramCount, int32_t* p_params);
static nai_status_t ADBasicOps_SetModulePowerReset(int32_t paramCount, int32_t* p_params);

/* Additional Helper Functions */
static void ADBasicOps_displayStatus_subBITStatuses(nai_status_bit_t BitStatus, nai_status_bit_t OpenStatus, nai_status_bit_t pBitStatus,
                                                    nai_status_bit_t antiAliasingFilterStatus, nai_status_bit_t voltageRdgAccuracyStatus);

/****** Command Table *******/
/* Invariant: enumeration of cmd table starts from 0 and increments by 1 */
enum ad_basicOps_commands
{
   AD_BASICOPS_CMD_SET_POL_RNG,
   AD_BASICOPS_CMD_SET_BREAK_FREQ,
   AD_BASICOPS_CMD_SET_LATCH,
   AD_BASICOPS_CMD_SET_MODE,
   AD_BASICOPS_CMD_SET_CHANNEL_ACTIVE,
   AD_BASICOPS_CMD_SATURATION_MENU,
   AD_BASICOPS_CMD_SET_D0_TEST_ENABLE,
   AD_BASICOPS_CMD_FLOATING_POINT_MODE,
   AD_BASICOPS_CMD_FLOATING_POINT_OFFSET,
   AD_BASICOPS_CMD_FLOATING_POINT_SCALE_FACTOR,
   AD_BASICOPS_CMD_CHANNEL_STATUS_ENABLE,
   AD_BASICOPS_CMD_PBIT,
   AD_BASICOPS_CMD_BIT_THRESHOLD,
   AD_BASICOPS_CMD_MODULE_POWER_RESET_MENU,
   AD_BASICOPS_CMD_TOGGLE_NUMERIC_DISPLAY,
   AD_BASICOPS_CMD_COUNT
};

enum ad_basicOps_Saturation_commands
{
   AD_BASICOPS_SATURATION_CMD_SET_LOW,
   AD_BASICOPS_SATURATION_CMD_SET_HIGH,
   AD_BASICOPS_SATURATION_CMD_ENABLE_LOW,
   AD_BASICOPS_SATURATION_CMD_ENABLE_HIGH,
   AD_BASICOPS_SATURATION_CMD_COUNT
};

enum ad_basicOps_module_power_reset_commands
{
   AD_BASICOPS_MODULE_POWER_RESET_CMD_BACK,
   AD_BASICOPS_MODULE_POWER_RESET_CMD_CLEAR_MODULE_POWER_RESET_STATUS,
   AD_BASICOPS_MODULE_POWER_RESET_CMD_SET_MODULE_POWER_RESET,
   AD_BASICOPS_MODULE_POWER_RESET_CMD_COUNT
};

naiapp_cmdtbl_params_t AD_BasicOpsCmds[] =
{
   {"PR",      "Set AD Polarity and Range",                   AD_BASICOPS_CMD_SET_POL_RNG,                              ADBasicOps_setRangePolarity },
   {"BRKFRQ",  "Set AD Filter Break Frequency",               AD_BASICOPS_CMD_SET_BREAK_FREQ,                           ADBasicOps_setBreakFreq     },
   {"M",       "Set AD Voltage/Current Mode (AD4 ONLY)",      AD_BASICOPS_CMD_SET_MODE,                                 ADBasicOps_setMode          },
   {"L",       "Set AD Latch/Unlatch Status",                 AD_BASICOPS_CMD_SET_LATCH,                                ADBasicOps_setLatch         },
   {"AC",      "Set AD Channel Active/Inactive (AD4 ONLY)",   AD_BASICOPS_CMD_SET_CHANNEL_ACTIVE,                       ADBasicOps_setActiveChannel },
   {"SAT",     "Saturation Menu",                             AD_BASICOPS_CMD_SATURATION_MENU,                          ADBasicOps_saturationMenu   },
   {"D0",      "Enable/Configure/Disable D0 Test",            AD_BASICOPS_CMD_SET_D0_TEST_ENABLE,                       ADBasicOps_setD0TestEnable  },
   {"FP_MODE", "Enable/Disable Hardware Floating-Point Conversion Mode",   AD_BASICOPS_CMD_FLOATING_POINT_MODE,         ADBasicOps_FloatingPointMode},
   {"OFFSET",  "Set Hardware Floating-Point Conversion Mode Offset",       AD_BASICOPS_CMD_FLOATING_POINT_OFFSET,       ADBasicOps_FloatingPointOffset},
   {"SCALE",   "Set Hardware Floating-Point Conversion Mode Scale Factor", AD_BASICOPS_CMD_FLOATING_POINT_SCALE_FACTOR, ADBasicOps_FloatingPointScaleFactor},
   {"CHANSTAT","Channel Status Enable/Disable",                            AD_BASICOPS_CMD_CHANNEL_STATUS_ENABLE,       ADBasicOps_ChannelStatusEnable},
   {"PBIT",    "Check Power-On BIT",                          AD_BASICOPS_CMD_PBIT,                                     ADBasicOps_CheckPowerOnBIT  },
   {"THRESH",  "Set BIT Error Threshold",                     AD_BASICOPS_CMD_BIT_THRESHOLD,                            ADBasicOps_BITThresholds    },
   {"PWRRESET","Show Module Power Reset Menu Options",        AD_BASICOPS_CMD_MODULE_POWER_RESET_MENU,                  ADBasicOps_ModulePowerResetMenu},
   {"TND",     "Toggle Numeric Display",                      AD_BASICOPS_CMD_TOGGLE_NUMERIC_DISPLAY,                   ADBasicOps_toggleNumDisplay }};

naiapp_cmdtbl_params_t AD_BasicOps_SaturationCmds[] =
{
   {"SL",    "Set Saturation Low value",                    AD_BASICOPS_SATURATION_CMD_SET_LOW,        ADBasicOps_setSaturationLow },
   {"SH",    "Set Saturation High value",                   AD_BASICOPS_SATURATION_CMD_SET_HIGH,       ADBasicOps_setSaturationHigh },
   {"EL",    "Enable/Disable Saturation Low",               AD_BASICOPS_SATURATION_CMD_ENABLE_LOW,     ADBasicOps_enableSaturationLow },
   {"EH",    "Enable/Disable Saturation High",              AD_BASICOPS_SATURATION_CMD_ENABLE_LOW,     ADBasicOps_enableSaturationHigh },
};

naiapp_cmdtbl_params_t AD_BasicOps_ModulePowerResetMenuCmds[AD_BASICOPS_MODULE_POWER_RESET_CMD_COUNT] =
{
   {"BACK",  "Back to Main Menu",               AD_BASICOPS_MODULE_POWER_RESET_CMD_BACK,                            NULL},
   {"CLEAR", "Clear Module Power Reset Status", AD_BASICOPS_MODULE_POWER_RESET_CMD_CLEAR_MODULE_POWER_RESET_STATUS, ADBasicOps_ClearModulePowerResetStatus},
   {"SET",   "Set Module Power Reset Request",  AD_BASICOPS_MODULE_POWER_RESET_CMD_SET_MODULE_POWER_RESET,          ADBasicOps_SetModulePowerReset}
};

/**************************************************************************************************************/
/** \defgroup ADBasicOps

\brief This sample application demonstrates how to use an A/D module to read voltage/current data.

This sample application illustrates how to perform some basic A/D operations using the `naibrd` library. It is
intended to help users understand how to use the library API's to access the basic features of the A/D.

The main steps include actions such as:
- Querying the user for the card index and module number
- Configuring the module for Range and Polarity
- Reading and displaying A/D data
- Demonstrating BIT, Internal tests and Saturation features.

The features are broken up into 3 separate menus:
- Main Menu: Configure, Read and Display A/D channels and data.
- Saturation Menu: Demonstrate the Saturation feature of the A/D.
- Module Power Reset: Demonstrate the Module Power Reset feature of the A/D.

*/
/**************************************************************************************************************/
#if defined (NAIBSP_CONFIG_SOFTWARE_OS_VXWORKS)
int32_t AD_BasicOps(void)
#else
int32_t main(void)
#endif
{
   bool_t bQuit = NAI_FALSE;
   int32_t cardIndex = -1;
   int32_t module = 0;
   int32_t moduleCount = 0;
   uint32_t modId = 0u;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   if (naiapp_RunBoardMenu(CONFIG_FILE) == NAI_TRUE)
   {
      while (!bQuit)
      {
         naiapp_query_CardIndex(naiapp_GetBoardCnt(), 0, &cardIndex);
         naibrd_GetModuleCount(cardIndex, &moduleCount);
         naiapp_query_ModuleNumber(moduleCount, 1, &module);
         naibrd_GetModuleName(cardIndex, module, &modId);
         if (NAIBRD_MODULE_ID_CF1 == modId)
         {
            bQuit = CF1ADBasicOps_run(cardIndex, module, modId);
         }
         else
         {
            bQuit = ADBasicOps_run(cardIndex, module, modId);
         }
      }

      naiif_printf("Type 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 ADBasicOps_run(int32_t cardIndex, int32_t module, uint32_t modId)
{
   bool_t bQuit = NAI_FALSE;
   bool_t bCmdFound = NAI_FALSE;
   int32_t cmd;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;
   naiapp_AppParameters_t  ad_basicops_params;
   p_naiapp_AppParameters_t ad_basicOps_params = &ad_basicops_params;
   ad_basicOps_params->cardIndex = cardIndex;
   ad_basicOps_params->module = module;
   ad_basicOps_params->channel = DEFAULT_CHANNEL;
   ad_basicOps_params->maxChannels = naibrd_AD_GetChannelCount(modId);
   ad_basicOps_params->modId = modId;
   ad_basicOps_params->displayHex = NAI_FALSE;

   do
   {
      naiapp_utils_LoadParamMenuCommands(AD_BASICOPS_CMD_COUNT, AD_BasicOpsCmds);
      ADBasicOps_displayConfigurations(cardIndex, module, modId, ad_basicOps_params->maxChannels, ad_basicOps_params->displayHex);
      naiapp_display_ParamMenuCommands((int8_t*)SAMPLE_PGM_NAME);
      naiif_printf("\r\n\r\nPlease enter a command or 'q' to quit:");
      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)
            {
               AD_BasicOpsCmds[cmd].func(APP_PARAM_COUNT, (int32_t*)ad_basicOps_params);
            }
            else
            {
               naiif_printf("Invalid command entered\r\n");
            }
         }
      }
   } while (!bQuit);
   return bQuit;
}

static void ADBasicOps_displayConfigurations(int32_t cardIndex, int32_t module, uint32_t modId, int32_t maxChannels, bool_t displayHex)
{
   int32_t channel;
   float64_t data = 0;
   float64_t range = 0;
   uint32_t rawData = 0u;
   naibrd_ad_polarity_t polarity = NAIBRD_AD_POLARITY_UNIPOLAR;
   nai_status_bit_t BitStatus = NAI_STATUS_BIT_LO;
   nai_status_bit_t OpenStatus = NAI_STATUS_BIT_LO;
   nai_status_bit_t PBitStatus = NAI_STATUS_BIT_LO;
   nai_status_bit_t AntiAliasingFilterStatus = NAI_STATUS_BIT_LO;
   nai_status_bit_t VoltageRdgAccStatus = NAI_STATUS_BIT_LO;
   naibrd_ad_mode_t data_mode = NAIBRD_AD_MODE_VOLTAGE;
   bool_t channelActive = NAI_TRUE;
   char* sChannelState = "";
   bool_t latched = NAI_FALSE;
   bool_t d0TestEnable = NAI_FALSE;
   naibrd_ad_polarity_t d0Polarity = NAIBRD_AD_POLARITY_UNIPOLAR;
   uint32_t filterBreakFreq = 0u;
   float64_t d0Range = 0.0;
   float64_t d0TestLevel = 0.0;
   uint32_t rawD0TestEnable = 0u;
   uint32_t rawD0Polarity = 0u;
   uint32_t rawD0TestLevel = 0u;
   float64_t offset = 0.0;
   float64_t scale = 0.0;
   bool_t fpCapable = NAI_FALSE;
   bool_t floatMode = NAI_FALSE;
   bool_t chanStatusEnabled = NAI_TRUE;
   const char* chanStatus = NULL;

   if ((modId == NAIBRD_MODULE_ID_ADE) || (modId == NAIBRD_MODULE_ID_ADF))
   {
      naiif_printf("\r\n\r\n =====================================================================================================================================================================================================================\r\n");
   }
   else
   {
      naiif_printf("\r\n\r\n ===============================================================================================================================================\r\n");
   }
   if (modId == NAIBRD_MODULE_ID_AD4)
      naiif_printf(" Chan     Chan State Mode       Volt/Curr   Range    Polarity     BreakFreq   Chan Status Enabled   BIT Status   Open Status");
   else if ((modId == NAIBRD_MODULE_ID_ADE) || (modId == NAIBRD_MODULE_ID_ADF))
      naiif_printf(" Chan     Chan State    Voltage       Range     Polarity     BreakFreq   Chan Status Enabled   BIT Status   Open Status   PBIT Status   Anti-Aliasing Filter Status   Voltage Rdg Acc Status");
   else
      naiif_printf(" Chan     Chan State    Voltage       Range     Polarity     BreakFreq   Chan Status Enabled   BIT Status   Open Status");

   check_status(naibrd_GetFloatingPointModeCapability(cardIndex, module, &fpCapable));
   if (fpCapable == NAI_TRUE)
   {
      naiif_printf("   FP Offset   FP Scale");
   }
   naiif_printf("\r\n");

   if ((modId == NAIBRD_MODULE_ID_ADE) || (modId == NAIBRD_MODULE_ID_ADF))
   {
      naiif_printf(" ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------\r\n");
   }
   else
   {
      naiif_printf(" -----------------------------------------------------------------------------------------------------------------------------------------------\r\n");
   }
   for (channel = 1; channel <= maxChannels; channel++)
   {
      /*** Acquire values stored in selected channel ***/
      check_status(naibrd_AD_GetActiveChannel(cardIndex, module, channel, &channelActive));
      check_status(naibrd_AD_GetMode(cardIndex, module, channel, &data_mode));
      if (modId != NAIBRD_MODULE_ID_IF1)
      {
         check_status(naibrd_AD_GetChanMappedStatus(cardIndex, module, channel, NAIBRD_AD_STATUS_OPEN_OVERVOLT_REALTIME, &OpenStatus));
      }
      check_status(naibrd_AD_GetChanMappedStatus(cardIndex, module, channel, NAIBRD_AD_STATUS_BIT_REALTIME, &BitStatus));
      if ((modId == NAIBRD_MODULE_ID_ADE) || (modId == NAIBRD_MODULE_ID_ADF))
      {
         check_status(naibrd_AD_GetChanMappedStatus(cardIndex, module, channel, NAIBRD_AD_STATUS_POWER_ON_BIT_REALTIME, &PBitStatus));
         check_status(naibrd_AD_GetChanMappedStatus(cardIndex, module, channel, NAIBRD_AD_STATUS_ANTI_ALIASING_FILTER_REALTIME, &AntiAliasingFilterStatus));
         check_status(naibrd_AD_GetChanMappedStatus(cardIndex, module, channel, NAIBRD_AD_STATUS_VOLTAGE_READING_ACCURACY_REALTIME, &VoltageRdgAccStatus));
      }
      check_status(naibrd_AD_GetChanStatusEnable(cardIndex, module, channel, &chanStatusEnabled));
      chanStatus = (chanStatusEnabled == NAI_FALSE) ? "NO " : "YES";

      naiif_printf("  %2d     ", channel);

      if (modId == NAIBRD_MODULE_ID_AD4)
      {
         check_status(naibrd_AD_GetActiveChannel(cardIndex, module, channel, &channelActive));
      }

      if (NAI_FALSE == channelActive)
      {
         sChannelState = "  INACTIVE  ";
      }
      else
      {
         sChannelState = "   ACTIVE   ";
      }
      naiif_printf("%12s", sChannelState);

      if (displayHex)
      {
         check_status(naibrd_AD_GetChannelRaw(cardIndex, module, channel, NAIBRD_AD_CHAN_RAW_DATA, &rawData));
         if (modId == NAIBRD_MODULE_ID_AD4 && data_mode == NAIBRD_AD_MODE_CURRENT)
         {
            naiif_printf("Current   0x%08X ", rawData);
         }
         else if (modId == NAIBRD_MODULE_ID_AD4 && data_mode == NAIBRD_AD_MODE_VOLTAGE)
         {
            naiif_printf("Voltage   0x%08X ", rawData);
         }
         else
         {
            naiif_printf("0x%08X ", rawData);
         }
      }
      else
      {
         check_status(naibrd_AD_GetData(cardIndex, module, channel, data_mode, &data));
         if (modId == NAIBRD_MODULE_ID_AD4 && data_mode == NAIBRD_AD_MODE_CURRENT)
         {
            naiif_printf("Current  %10.6fA ", data);
         }
         else
         {
            if (modId == NAIBRD_MODULE_ID_AD4 && data_mode == NAIBRD_AD_MODE_VOLTAGE)
               naiif_printf("Voltage  %10.6fV ", data);
            else
               naiif_printf("%10.6fV     ", data);
         }
      }

      check_status(naibrd_AD_GetRangePolarity(cardIndex, module, channel, &polarity, &range));
      naiif_printf("%7.3f     ", range);

      if (polarity == NAIBRD_AD_POLARITY_UNIPOLAR)
         naiif_printf("UNIPOLAR     ");
      else if (polarity == NAIBRD_AD_POLARITY_BIPOLAR)
         naiif_printf("BIPOLAR      ");
      else
         naiif_printf("ERROR        ");

      check_status(naibrd_AD_GetFilterBreakFrequency(cardIndex, module, channel, &filterBreakFreq));
      naiif_printf("%6u       ", filterBreakFreq);

      naiif_printf("      %s              ", chanStatus);
      if ((modId == NAIBRD_MODULE_ID_ADE) || (modId == NAIBRD_MODULE_ID_ADF))
      {
         ADBasicOps_displayStatus_subBITStatuses(BitStatus, OpenStatus, PBitStatus, AntiAliasingFilterStatus, VoltageRdgAccStatus);
      }
      else
      {
         if (BitStatus == NAI_STATUS_BIT_HI)
            naiif_printf("BIT FAILURE       ");
         else if (BitStatus == NAI_STATUS_BIT_LO)
            naiif_printf("Normal       ");
         else
            naiif_printf("Error        ");

         if (modId == NAIBRD_MODULE_ID_IF1)
            naiif_printf(" N/A  " );
         else if (OpenStatus == NAI_STATUS_BIT_HI)
            naiif_printf(" OPEN ");
         else if (OpenStatus == NAI_STATUS_BIT_LO)
            naiif_printf("Normal");
         else
            naiif_printf("ERR NOT SUPPORTED");
      }

      if (fpCapable == NAI_TRUE)
      {
         check_status(naibrd_AD_GetFloatingPointAttribute(cardIndex, module, channel, NAIBRD_AD_ATTRIBUTE_OFFSET, &offset));
         check_status(naibrd_AD_GetFloatingPointAttribute(cardIndex, module, channel, NAIBRD_AD_ATTRIBUTE_SCALE_FACTOR, &scale));
         naiif_printf("      %7.3f    %7.3f", offset, scale);
      }
      naiif_printf("\r\n");
   }

   naiif_printf("\r\n\r\nLatch Status (all channels): ");
   check_status(naibrd_AD_GetLatchChannel(cardIndex, module, 0, &latched));
   if (NAI_FALSE == latched)
   {
      naiif_printf("UNLATCHED\r\n");
   }
   else
   {
      naiif_printf("LATCHED\r\n");
   }

   if (fpCapable == NAI_TRUE)
   {
      check_status(naibrd_GetRunningInFloatingPointMode(cardIndex, module, &floatMode));
      if (floatMode == NAI_TRUE)
      {
         naiif_printf("Floating-Point Mode: ENABLED\r\n");
      }
      else
      {
         naiif_printf("Floating-Point Mode: DISABLED\r\n");
      }
   }

   if (displayHex)
   {
      naiif_printf("D0 Test (all channels): Internal Test Enable: ");
      check_status(naibrd_AD_GetRaw(cardIndex, module, NAIBRD_AD_RAW_TEST_ENABLE, &rawD0TestEnable));
      check_status(naibrd_AD_GetRaw(cardIndex, module, NAIBRD_AD_RAW_D0_RANGE_POLARITY, &rawD0Polarity));
      check_status(naibrd_AD_GetRaw(cardIndex, module, NAIBRD_AD_RAW_D0_TEST_VALUE, &rawD0TestLevel));
      naiif_printf("0x%02X, Range/Polarity: 0x%02X, ", rawD0TestEnable, rawD0Polarity);
      naiif_printf("Voltage Level: 0x%08X\r\n", rawD0TestLevel);
   }
   else
   {
      naiif_printf("D0 Test (all channels): ");
      check_status(naibrd_AD_GetModuleBITEnable(cardIndex, module, NAIBRD_AD_D0_TEST, &d0TestEnable));
      if (NAI_FALSE == d0TestEnable)
      {
         naiif_printf("DISABLED\r\n");
      }
      else
      {
         check_status(naibrd_AD_GetD0TestParams(cardIndex, module, &d0Polarity, &d0Range, &d0TestLevel));
         naiif_printf("ENABLED, Range:%6.2lfV, Mode: ", d0Range);
         if (NAIBRD_AD_POLARITY_UNIPOLAR == d0Polarity)
         {
            naiif_printf("UNIPOLAR");
         }
         else
         {
            naiif_printf("BIPOLAR");
         }
         naiif_printf(", Voltage Level:%10.6lfV\r\n", d0TestLevel);
      }
   }
}

static nai_status_t ADBasicOps_setRangePolarity(int32_t paramCount, int32_t* p_params)
{
   p_naiapp_AppParameters_t p_ad_params = (p_naiapp_AppParameters_t)p_params;
   float64_t range = 0.0;
   uint32_t rawRange = 0u;
   naibrd_ad_polarity_t polarity = NAIBRD_AD_POLARITY_UNIPOLAR;
   naibrd_ad_mode_t mode = NAIBRD_AD_MODE_VOLTAGE;
   nai_status_t status = NAI_ERROR_UNKNOWN;

   if (APP_PARAM_COUNT == paramCount)
   {
      naiapp_query_ChannelNumber(p_ad_params->maxChannels, p_ad_params->channel, &(p_ad_params->channel));

      naibrd_AD_GetMode(p_ad_params->cardIndex, p_ad_params->module, p_ad_params->channel, &mode);

      if (NAI_FALSE == p_ad_params->displayHex)
      {
         ADUtils_GetRangePolarity(p_ad_params->cardIndex, p_ad_params->module, mode, &polarity, &range);
         naibrd_AD_SetRangePolarity(p_ad_params->cardIndex, p_ad_params->module, p_ad_params->channel, polarity, range);
      }
      else
      {
         ADUtils_GetRangePolarityHex(p_ad_params->cardIndex, p_ad_params->module, mode, &rawRange);
         naibrd_AD_SetChannelRaw(p_ad_params->cardIndex, p_ad_params->module, p_ad_params->channel, NAIBRD_AD_CHAN_RAW_RANGE, rawRange);
      }

      status = NAI_SUCCESS;
   }
   else
   {
      status = NAI_ERROR_INVALID_VALUE;
   }

   return status;
}

static nai_status_t ADBasicOps_setLatch(int32_t paramCount, int32_t* p_params)
{
   p_naiapp_AppParameters_t p_ad_params = (p_naiapp_AppParameters_t)p_params;
   bool_t latched = NAI_FALSE;
   bool_t bQuit = NAI_FALSE;
   nai_status_t status = NAI_ERROR_UNKNOWN;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   if (APP_PARAM_COUNT == paramCount)
   {
      naiif_printf("Type 'L' to LATCH, or press any other key to UNLATCH all channels:\r\n>>");
      bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
      if (!bQuit)
      {
         if (toupper(inputBuffer[0]) == 'L')
            latched = NAI_TRUE;
         else
            latched = NAI_FALSE;

         check_status(naibrd_AD_SetLatchChannel(p_ad_params->cardIndex, p_ad_params->module, 0, latched));
      }
      status = NAI_SUCCESS;
   }
   else
   {
      status = NAI_ERROR_INVALID_VALUE;
   }

   return status;
}

static nai_status_t ADBasicOps_setMode(int32_t paramCount, int32_t* p_params)
{
   p_naiapp_AppParameters_t p_ad_params = (p_naiapp_AppParameters_t)p_params;
   bool_t bQuit = NAI_FALSE;
   uint32_t modId;
   int channel;
   nai_status_t status = naibrd_GetModuleName(p_ad_params->cardIndex, p_ad_params->module, &modId);
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   if (APP_PARAM_COUNT == paramCount)
   {
      if (modId == NAIBRD_MODULE_ID_AD4)
      {
         naiif_printf("\r\nType   'V' for voltage mode\r\n");
         naiif_printf("       'C' for current mode\r\n");
         naiif_printf("       'VA' to set all chan to voltage mode\r\n");
         naiif_printf("       'CA' to set all chan to current mode\r\n>>");

         bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
         if (!bQuit)
         {
            if (toupper(inputBuffer[0]) == 'V')
            {
               if (toupper(inputBuffer[1]) == 'A')
               {
                  for (channel = 1; channel <= p_ad_params->maxChannels; channel++)
                     status = naibrd_AD_SetMode(p_ad_params->cardIndex, p_ad_params->module, channel, NAIBRD_AD_MODE_VOLTAGE);
               }
               else
               {
                  bQuit = naiapp_query_ChannelNumber(p_ad_params->maxChannels, p_ad_params->channel, &(p_ad_params->channel));
                  if (!bQuit)
                  {
                     status = naibrd_AD_SetMode(p_ad_params->cardIndex, p_ad_params->module, p_ad_params->channel, NAIBRD_AD_MODE_VOLTAGE);
                  }
               }
            }
            else if (toupper(inputBuffer[0]) == 'C')
            {
               if (toupper(inputBuffer[1]) == 'A')
               {
                  for (channel = 1; channel <= p_ad_params->maxChannels; channel++)
                     status = naibrd_AD_SetMode(p_ad_params->cardIndex, p_ad_params->module, channel, NAIBRD_AD_MODE_CURRENT);
               }
               else
               {
                  bQuit = naiapp_query_ChannelNumber(p_ad_params->maxChannels, p_ad_params->channel, &(p_ad_params->channel));
                  if (!bQuit)
                  {
                     status = naibrd_AD_SetMode(p_ad_params->cardIndex, p_ad_params->module, p_ad_params->channel, NAIBRD_AD_MODE_CURRENT);
                  }
               }
            }
            naiif_printf("Returned status %s\r\n", naibrd_GetStatusString(status));
         }
      }
      else
      {
         naiif_printf("Mode selection only available for AD4\r\n");
         status = NAI_ERROR_NOT_SUPPORTED;
      }
   }
   else
   {
      status = NAI_ERROR_INVALID_VALUE;
   }

   return status;
}

static nai_status_t ADBasicOps_setBreakFreq(int32_t paramCount, int32_t* p_params)
{
   p_naiapp_AppParameters_t p_ad_params = (p_naiapp_AppParameters_t)p_params;
   uint32_t filterBreakFrequency = 0u;
   bool_t bQuit = NAI_FALSE;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   if (APP_PARAM_COUNT == paramCount)
   {
      bQuit = naiapp_query_ChannelNumber(p_ad_params->maxChannels, p_ad_params->channel, &(p_ad_params->channel));

      naiif_printf("Enter new Filter Break Frequency: ");
      bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
      if (!bQuit)
      {
         sscanf((const char*)inputBuffer, "%u", &filterBreakFrequency);
         check_status(naibrd_AD_SetFilterBreakFrequency(p_ad_params->cardIndex, p_ad_params->module, p_ad_params->channel,
            filterBreakFrequency));
      }
   }

   return NAI_SUCCESS;
}

static nai_status_t ADBasicOps_setActiveChannel(int32_t paramCount, int32_t* p_params)
{
   p_naiapp_AppParameters_t p_ad_params = (p_naiapp_AppParameters_t)p_params;
   bool_t bQuit = NAI_FALSE;
   int32_t channel = 0;
   uint32_t modId = 0u;
   nai_status_t status = naibrd_GetModuleName(p_ad_params->cardIndex, p_ad_params->module, &modId);
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   if (APP_PARAM_COUNT == paramCount)
   {
      naiif_printf("\r\nType 'A' to set channel to ACTIVE\r\n");
      naiif_printf("Type 'I' to set channel to INACTIVE\r\n");
      naiif_printf("Type 'CA' to set all channels to ACTIVE\r\n");
      naiif_printf("Type 'CI' to set all channels to INACTIVE\r\n");
      bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
      if ((!bQuit) && (inputResponseCnt > 0))
      {
         if (toupper(inputBuffer[0]) == 'A')
         {
            bQuit = naiapp_query_ChannelNumber(p_ad_params->maxChannels, p_ad_params->channel, &(p_ad_params->channel));
            if (!bQuit)
            {
               status = naibrd_AD_SetActiveChannel(p_ad_params->cardIndex, p_ad_params->module, p_ad_params->channel, NAI_TRUE);
            }
         }
         else if (toupper(inputBuffer[0]) == 'I')
         {
            bQuit = naiapp_query_ChannelNumber(p_ad_params->maxChannels, p_ad_params->channel, &(p_ad_params->channel));
            if (!bQuit)
            {
               status = naibrd_AD_SetActiveChannel(p_ad_params->cardIndex, p_ad_params->module, p_ad_params->channel, NAI_FALSE);
            }
         }
         else if (toupper(inputBuffer[0]) == 'C')
         {
            if (toupper(inputBuffer[1]) == 'A')
            {
               for (channel = 1; channel <= p_ad_params->maxChannels; channel++)
               {
                  if (status == NAI_SUCCESS)
                  {
                     status = naibrd_AD_SetActiveChannel(p_ad_params->cardIndex, p_ad_params->module, channel, NAI_TRUE);
                  }
                  else
                  {
                     naibrd_AD_SetActiveChannel(p_ad_params->cardIndex, p_ad_params->module, channel, NAI_TRUE);
                  }
               }
            }
            else if (toupper(inputBuffer[1]) == 'I')
            {
               for (channel = 1; channel <= p_ad_params->maxChannels; channel++)
               {
                  if (status == NAI_SUCCESS)
                  {
                     status = naibrd_AD_SetActiveChannel(p_ad_params->cardIndex, p_ad_params->module, channel, NAI_FALSE);
                  }
                  else
                  {
                     naibrd_AD_SetActiveChannel(p_ad_params->cardIndex, p_ad_params->module, channel, NAI_FALSE);
                  }
               }
            }
            else
            {
               status = NAI_ERROR_INVALID_VALUE;
            }
         }
         else
         {
            status = NAI_ERROR_INVALID_VALUE;
         }
         naiif_printf("Returned status %s\r\n", naibrd_GetStatusString(status));
      }
   }
   else
   {
      status = NAI_ERROR_INVALID_VALUE;
   }

   return status;
}

static nai_status_t ADBasicOps_setD0TestEnable(int32_t paramCount, int32_t* p_params)
{
   p_naiapp_AppParameters_t p_ad_params = (p_naiapp_AppParameters_t)p_params;
   bool_t bQuit = NAI_FALSE;
   naibrd_ad_polarity_t polarity = NAIBRD_AD_POLARITY_UNIPOLAR;
   naibrd_ad_mode_t D0mode;
   float64_t testLevel = 0.0;
   float64_t D0Range = 0.0;
   uint32_t rawD0RangePolarity = 0u;
   uint32_t rawD0TestLevel = 0u;
   nai_status_t status = NAI_ERROR_UNKNOWN;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   if (APP_PARAM_COUNT == paramCount)
   {
      naiif_printf("Type 'D' to DISABLE the D0 Test, or 'E' to ENABLE the D0 Test:\r\n>>");
      bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
      if ((!bQuit) && (inputResponseCnt > 0))
      {
         if (toupper(inputBuffer[0]) == 'D')
         {
            check_status(naibrd_AD_SetModuleBITEnable(p_ad_params->cardIndex, p_ad_params->module, NAIBRD_AD_D0_TEST, NAI_FALSE));
         }
         else
         {
            check_status(naibrd_AD_SetModuleBITEnable(p_ad_params->cardIndex, p_ad_params->module, NAIBRD_AD_D0_TEST, NAI_TRUE));
            naiif_printf("\r\n\r\nConfigure the D0 test Polarity and Voltage level.\r\n");
            naiif_printf("**NOTE: Channels that are not set to the same Range and Polarity as D0 will not be scaled the same,\r\n");
            naiif_printf("  and will show unexpected readings.\r\n");
            naiif_printf("D0 is fix to the highest bipolar range, but the Polarity is configurable.\r\n");

            if (p_ad_params->displayHex)
            {
               naiif_printf("\r\nType Raw D0 Test Range/Polarity Mode to set:\r\n>>");
               bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
               if ((!bQuit) && (inputResponseCnt > 0))
               {
                  sscanf((const char*)inputBuffer, "%X", &rawD0RangePolarity);
                  check_status(naibrd_AD_SetRaw(p_ad_params->cardIndex, p_ad_params->module, NAIBRD_AD_RAW_D0_RANGE_POLARITY,
                     rawD0RangePolarity));
                  naiif_printf("\r\nType Raw D0 Test Voltage Level to set:\r\n>>");
                  bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
                  if ((!bQuit) && (inputResponseCnt > 0))
                  {
                     sscanf((const char*)inputBuffer, "%X", &rawD0TestLevel);
                     check_status(naibrd_AD_SetRaw(p_ad_params->cardIndex, p_ad_params->module, NAIBRD_AD_RAW_D0_TEST_VALUE,
                        rawD0TestLevel));
                  }
               }
            }
            else
            {
               naiif_printf("Type 'U' to set the D0 Test Polarity to UNIPOLAR, or press any other key for BIPOLAR:\r\n>>");
               bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
               if ((!bQuit) && (inputResponseCnt > 0))
               {
                  if (toupper(inputBuffer[0]) == 'U')
                  {
                     polarity = NAIBRD_AD_POLARITY_UNIPOLAR;
                  }
                  else
                  {
                     polarity = NAIBRD_AD_POLARITY_BIPOLAR;
                  }
                  naiif_printf("Type the D0 Test Voltage Level you want to set:\r\n>>");
                  bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
                  if ((!bQuit) && (inputResponseCnt > 0))
                  {
                     sscanf((const char*)inputBuffer, "%lf", &testLevel);
                     rawD0RangePolarity = 0x10u & (uint32_t)polarity;
                     if ((p_ad_params->modId == NAIBRD_MODULE_ID_AD3) || (p_ad_params->modId == NAIBRD_MODULE_ID_ADG) ||
                        (p_ad_params->modId == NAIBRD_MODULE_ID_CMG))
                     {
                        D0mode = NAIBRD_AD_MODE_CURRENT;
                     }
                     else
                     {
                        D0mode = NAIBRD_AD_MODE_VOLTAGE;
                     }
                     naibrd_AD_ConvertToRange(p_ad_params->modId, D0mode, rawD0RangePolarity, &polarity, &D0Range);
                     check_status(naibrd_AD_SetD0TestParams(p_ad_params->cardIndex, p_ad_params->module, polarity, D0Range, testLevel));
                  }
               }
            }
         }
      }

      status = NAI_SUCCESS;
   }
   else
   {
      status = NAI_ERROR_INVALID_VALUE;
   }

   return status;
}

static void ADBasicOps_displayStatus_subBITStatuses(nai_status_bit_t BitStatus, nai_status_bit_t OpenStatus, nai_status_bit_t pBitStatus,
                                                    nai_status_bit_t antiAliasingFilterStatus, nai_status_bit_t voltageRdgAccuracyStatus)
{
   if (BitStatus == NAI_STATUS_BIT_HI)
      naiif_printf("BIT FAILURE  ");
   else if (BitStatus == NAI_STATUS_BIT_LO)
      naiif_printf("Normal       ");
   else
      naiif_printf("Error        ");

   if (OpenStatus == NAI_STATUS_BIT_HI)
      naiif_printf(" OPEN    ");
   else if (OpenStatus == NAI_STATUS_BIT_LO)
      naiif_printf("Normal   ");
   else
      naiif_printf("Error    ");

   if (pBitStatus == NAI_STATUS_BIT_HI)
      naiif_printf("     BIT FAILURE  ");
   else if (pBitStatus == NAI_STATUS_BIT_LO)
      naiif_printf("     Normal       ");
   else
      naiif_printf("     Error        ");

   if (antiAliasingFilterStatus == NAI_STATUS_BIT_HI)
      naiif_printf("         BIT FAILURE  ");
   else if (antiAliasingFilterStatus == NAI_STATUS_BIT_LO)
      naiif_printf("         Normal       ");
   else
      naiif_printf("         Error        ");

   if (voltageRdgAccuracyStatus == NAI_STATUS_BIT_HI)
      naiif_printf("            BIT FAILURE   ");
   else if (voltageRdgAccuracyStatus == NAI_STATUS_BIT_LO)
      naiif_printf("               Normal     ");
   else
      naiif_printf("               Error      ");
}

static nai_status_t ADBasicOps_toggleNumDisplay(int32_t paramCount, int32_t* p_params)
{
   p_naiapp_AppParameters_t p_ad_params = (p_naiapp_AppParameters_t)p_params;
   nai_status_t status = NAI_ERROR_UNKNOWN;

   if (APP_PARAM_COUNT == paramCount)
   {
      if (NAI_FALSE == p_ad_params->displayHex)
      {
         p_ad_params->displayHex = NAI_TRUE;
      }
      else
      {
         p_ad_params->displayHex = NAI_FALSE;
      }

      status = NAI_SUCCESS;
   }
   else
   {
      status = NAI_ERROR_INVALID_VALUE;
   }

   return status;
}

static nai_status_t ADBasicOps_CheckPowerOnBIT(int32_t paramCount, int32_t* p_params)
{
   nai_status_t status = NAI_ERROR_UNKNOWN;
   p_naiapp_AppParameters_t p_ad_params = (p_naiapp_AppParameters_t)p_params;
   int32_t channelCount = 0, channel = 0;
   bool_t pbitComplete;
   nai_status_bit_t bitFailed;

   if (APP_PARAM_COUNT == paramCount)
   {
      channelCount = naibrd_AD_GetChannelCount(p_ad_params->modId);

      /* Check to see if PBIT ran for the module. */
      naiif_printf("Checking if the Power-On BIT test has run...\r\n");
      status = naibrd_AD_CheckPowerOnBITComplete(p_ad_params->cardIndex, p_ad_params->module, &pbitComplete);
      naiif_printf("PBIT Complete: %s", (pbitComplete) ? "COMPLETED\r\n" : "NOT COMPLETED\r\n");

      if (pbitComplete)
      {
         /* Read the BIT status */
         naiif_printf("Checking the result of the Power-on BIT test...\r\n");
         for (channel = 1; channel <= channelCount; channel++)
         {
            status = naibrd_AD_GetChanMappedStatus(p_ad_params->cardIndex, p_ad_params->module, channel, NAIBRD_AD_STATUS_BIT_LATCHED,
               &bitFailed);
            naiif_printf("Ch. %d: %s", channel, bitFailed ? "BIT FAILED\r\n" : "BIT Passed\r\n");
         }
      }
   }
   else
   {
      status = NAI_ERROR_INVALID_VALUE;
   }

   return status;
}

static nai_status_t ADBasicOps_BITThresholds(int32_t paramCount, int32_t* p_params)
{
   p_naiapp_AppParameters_t p_ad_params = (p_naiapp_AppParameters_t)p_params;
   nai_status_t status = NAI_ERROR_UNKNOWN;
   uint32_t bitThreshold = 0u;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   if (APP_PARAM_COUNT == paramCount)
   {
      switch (p_ad_params->modId)
      {
         case NAIBRD_MODULE_ID_ADE:
         case NAIBRD_MODULE_ID_ADF:
         case NAIBRD_MODULE_ID_ADG:
         case NAIBRD_MODULE_ID_CME:
         case NAIBRD_MODULE_ID_CMF:
         case NAIBRD_MODULE_ID_CMG:
         case NAIBRD_MODULE_ID_IF1:
         {
            naiif_printf("Set or Get BIT Error Threshold? ('S' = Set, 'G' = Get, 'C' = Clear BIT Counter): ");
            naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);

            if (inputBuffer[0] == 'S')
            {
               naiif_printf("\r\nType the desired BIT Error Threshold (Default = 5): ");
               naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
               naiif_printf("\r\n");
               bitThreshold = atoi((const char*)inputBuffer);
               status = naibrd_AD_SetModuleBITErrorThreshold(p_ad_params->cardIndex, p_ad_params->module, bitThreshold);
            }
            else if (inputBuffer[0] == 'G')
            {
               status = naibrd_AD_GetModuleBITErrorThreshold(p_ad_params->cardIndex, p_ad_params->module, &bitThreshold);
               naiif_printf("\r\nBIT Error threshold: %d", bitThreshold);
            }
            else if (inputBuffer[0] == 'C')
            {
               int32_t ch;
               int32_t channels = naibrd_AD_GetChannelCount(p_ad_params->modId);

               naiif_printf("\r\nClearing BIT counters on all channels.\r\n");
               for (ch = 1; ch <= channels; ch++)
                  status = naibrd_AD_ClearModuleBITLogic(p_ad_params->cardIndex, p_ad_params->module, ch);
            }
            else
            {
               naiif_printf("\r\nSelection not recognized.\r\n");
            }
         }
         break;
         default:
            naiif_printf("\r\n\r\n*** This feature is not supported by this module.***\r\n");
            status = NAI_ERROR_NOT_SUPPORTED;
            break;
      }
   }
   else
   {
      status = NAI_ERROR_INVALID_VALUE;
   }

   return status;
}

static nai_status_t ADBasicOps_FloatingPointMode(int32_t paramCount, int32_t* p_params)
{
   p_naiapp_AppParameters_t p_ad_params = (p_naiapp_AppParameters_t)p_params;
   bool_t bQuit = NAI_FALSE;
   bool_t fpCapable = NAI_FALSE;
   nai_status_t status = NAI_ERROR_UNKNOWN;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   if (APP_PARAM_COUNT == paramCount)
   {
      naibrd_GetFloatingPointModeCapability(p_ad_params->cardIndex, p_ad_params->module, &fpCapable);
      if (fpCapable == NAI_TRUE)
      {
         naiif_printf("Select Floating-Point Mode to set ('0' for DISABLED, '1' for ENABLED)(default:DISABLED): ");
         bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
         if ((!bQuit) && (inputResponseCnt > 0))
         {
            if (inputBuffer[0] == '0')
            {
               status = check_status(naibrd_SetFloatingPointModeEnable(p_ad_params->cardIndex, p_ad_params->module, 0x0));
            }
            else if (inputBuffer[0] == '1')
            {
               status = check_status(naibrd_SetFloatingPointModeEnable(p_ad_params->cardIndex, p_ad_params->module, 0x1));
            }
         }
      }
      else
      {
         naiif_printf("\r\n\r\n*** This feature is not supported by this module.***\r\n");
      }
   }
   else
   {
      status = NAI_ERROR_INVALID_VALUE;
   }
   return status;
}

static nai_status_t ADBasicOps_FloatingPointOffset(int32_t paramCount, int32_t* p_params)
{
   p_naiapp_AppParameters_t p_ad_params = (p_naiapp_AppParameters_t)p_params;
   bool_t bQuit = NAI_FALSE;
   float64_t offset = 0.0;
   bool_t fpCapable = NAI_FALSE;
   nai_status_t status = NAI_ERROR_UNKNOWN;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   if (APP_PARAM_COUNT == paramCount)
   {
      naibrd_GetFloatingPointModeCapability(p_ad_params->cardIndex, p_ad_params->module, &fpCapable);
      if (fpCapable == NAI_TRUE)
      {
         bQuit = naiapp_query_ChannelNumber(p_ad_params->maxChannels, p_ad_params->channel, &(p_ad_params->channel));
         if (!bQuit)
         {
            naiif_printf("Type Hardware Floating-Point Conversion Mode Offset setting to set: ");
            bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
            if ((!bQuit) && (inputResponseCnt > 0))
            {
               sscanf((const char*)inputBuffer, "%lf", &offset);
               status = check_status(naibrd_AD_SetFloatingPointAttribute(p_ad_params->cardIndex, p_ad_params->module, p_ad_params->channel,
                  NAIBRD_AD_ATTRIBUTE_OFFSET, offset));
            }
         }
      }
      else
      {
         naiif_printf("\r\n\r\n*** This feature is not supported by this module.***\r\n");
      }
   }
   else
   {
      status = NAI_ERROR_INVALID_VALUE;
   }

   return status;
}

static nai_status_t ADBasicOps_FloatingPointScaleFactor(int32_t paramCount, int32_t* p_params)
{
   p_naiapp_AppParameters_t p_ad_params = (p_naiapp_AppParameters_t)p_params;
   bool_t bQuit = NAI_FALSE;
   float64_t scale = 0.0;
   bool_t fpCapable = NAI_FALSE;
   nai_status_t status = NAI_ERROR_UNKNOWN;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   if (APP_PARAM_COUNT == paramCount)
   {
      naibrd_GetFloatingPointModeCapability(p_ad_params->cardIndex, p_ad_params->module, &fpCapable);
      if (fpCapable == NAI_TRUE)
      {
         bQuit = naiapp_query_ChannelNumber(p_ad_params->maxChannels, p_ad_params->channel, &(p_ad_params->channel));
         if (!bQuit)
         {
            naiif_printf("Type Hardware Floating-Point Conversion Mode Scale Factor setting to set: ");
            bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
            if ((!bQuit) && (inputResponseCnt > 0))
            {
               sscanf((const char*)inputBuffer, "%lf", &scale);
               status = check_status(naibrd_AD_SetFloatingPointAttribute(p_ad_params->cardIndex, p_ad_params->module, p_ad_params->channel,
                  NAIBRD_AD_ATTRIBUTE_SCALE_FACTOR, scale));
            }
         }
      }
      else
      {
         naiif_printf("\r\n\r\n*** This feature is not supported by this module.***\r\n");
      }
   }
   else
   {
      status = NAI_ERROR_INVALID_VALUE;
   }

   return status;
}

static nai_status_t ADBasicOps_ChannelStatusEnable(int32_t paramCount, int32_t* p_params)
{
   p_naiapp_AppParameters_t ad_params = (p_naiapp_AppParameters_t)p_params;
   bool_t bQuit = NAI_FALSE;
   nai_status_t status = NAI_ERROR_UNKNOWN;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   if (APP_PARAM_COUNT == paramCount)
   {
      bQuit = naiapp_query_ChannelNumber(ad_params->maxChannels, ad_params->channel, &(ad_params->channel));
      if (!bQuit)
      {
         naiif_printf("Enable Channel Status (Y = YES, [any other key] = NO: ");
         bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
         if (!bQuit)
         {
            status = check_status(naibrd_AD_SetChanStatusEnable(ad_params->cardIndex, ad_params->module, ad_params->channel,
               ((inputResponseCnt > 0) && (inputBuffer[0] == 'Y' || inputBuffer[0] == 'y')) ? NAI_TRUE : NAI_FALSE));
         }
      }
   }

   return status;
}

static void ADBasicOps_displaySaturationConfig(int32_t cardIndex, int32_t module, uint32_t modId, int32_t maxChannels, bool_t displayHex)
{
   int32_t channel;
   float64_t satLowLevel = 0.0;
   float64_t satHighLevel = 0.0;
   bool_t satLowEnable = NAI_FALSE;
   bool_t satHighEnable = NAI_FALSE;
   char* sChannelState = "";

   /* Unused params */
   modId = 0;
   displayHex = 0;

   naiif_printf("\r\n\r\n ============================================================================\r\n");
   naiif_printf(" Chan     Saturation Low   Low Enabled |   Saturation High   High Enabled\r\n");
   naiif_printf(" --------------------------------------------------------------------------------\r\n");

   for (channel = 1; channel <= maxChannels; channel++)
   {
      /*** Acquire values stored in selected channel ***/
      check_status(naibrd_AD_GetSaturationLevel(cardIndex, module, channel, NAIBRD_AD_SATURATION_CONTROL_LOW, &satLowLevel));
      check_status(naibrd_AD_GetSaturationLevel(cardIndex, module, channel, NAIBRD_AD_SATURATION_CONTROL_HIGH, &satHighLevel));
      check_status(naibrd_AD_GetSaturationControl(cardIndex, module, channel, NAIBRD_AD_SATURATION_CONTROL_LOW, &satLowEnable));
      check_status(naibrd_AD_GetSaturationControl(cardIndex, module, channel, NAIBRD_AD_SATURATION_CONTROL_HIGH, &satHighEnable));

      naiif_printf("  %2d     ", channel);

      naiif_printf("%10.6fV       ", satLowLevel);
      if (NAI_FALSE == satLowEnable)
      {
         sChannelState = "  INACTIVE  ";
      }
      else
      {
         sChannelState = "   ACTIVE   ";
      }
      naiif_printf("%12s", sChannelState);

      naiif_printf("|  %10.6fV       ", satHighLevel);
      if (NAI_FALSE == satHighEnable)
      {
         sChannelState = "  INACTIVE  ";
      }
      else
      {
         sChannelState = "   ACTIVE   ";
      }
      naiif_printf("%12s\r\n", sChannelState);
   }
}

static nai_status_t ADBasicOps_saturationMenu(int32_t paramCount, int32_t* p_params)
{
   p_naiapp_AppParameters_t p_ad_params = (p_naiapp_AppParameters_t)p_params;
   bool_t bQuit = NAI_FALSE;
   bool_t bCmdFound = NAI_FALSE;
   int32_t cmd = 0;
   nai_status_t status = NAI_ERROR_UNKNOWN;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   if (NAI_TRUE == ADBasicOps_SaturationAvailable(paramCount, p_params))
   {
      if (APP_PARAM_COUNT == paramCount)
      {
         naiapp_utils_LoadParamMenuCommands(AD_BASICOPS_SATURATION_CMD_COUNT, AD_BasicOps_SaturationCmds);
         do
         {
            ADBasicOps_displaySaturationConfig(p_ad_params->cardIndex, p_ad_params->module, p_ad_params->modId, p_ad_params->maxChannels, p_ad_params->displayHex);
            naiapp_display_ParamMenuCommands((int8_t*)SATURATION_MENU);
            naiif_printf("\r\n\r\nPlease enter a command or 'q' to quit:");
            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)
                  {
                     AD_BasicOps_SaturationCmds[cmd].func(APP_PARAM_COUNT, p_params);
                  }
                  else
                  {
                     naiif_printf("Invalid command entered\r\n");
                  }
               }
            }
         } while (!bQuit);
         status = NAI_SUCCESS;
      }
      else
      {
         status = NAI_ERROR_INVALID_VALUE;
      }
   }
   else
   {
      naiif_printf("\r\n\r\n***Saturation is not supported by this module.***\r\n");
   }

   return status;
}

static nai_status_t ADBasicOps_setSaturationLow(int32_t paramCount, int32_t* p_params)
{
   p_naiapp_AppParameters_t p_ad_params = (p_naiapp_AppParameters_t)p_params;
   bool_t bQuit;
   int8_t userInput[15];
   float64_t satLevel = 0.0;
   nai_status_t status = NAI_ERROR_UNKNOWN;

   if (APP_PARAM_COUNT == paramCount)
   {
      bQuit = naiapp_query_ChannelNumber(p_ad_params->maxChannels, p_ad_params->channel, &(p_ad_params->channel));
      if (!bQuit)
      {
         naiif_printf("Enter Saturation Low value:");

         memset(userInput, 0x00, sizeof(userInput));
         naiapp_fgets_stdin(userInput, sizeof(userInput));

         sscanf((const char*)userInput, "%lf", &satLevel);

         status = naibrd_AD_SetSaturationLevel(p_ad_params->cardIndex, p_ad_params->module, p_ad_params->channel, NAIBRD_AD_SATURATION_CONTROL_LOW,
            satLevel);
      }
   }
   else
   {
      status = NAI_ERROR_INVALID_VALUE;
   }

   return status;
}

static nai_status_t ADBasicOps_setSaturationHigh(int32_t paramCount, int32_t* p_params)
{
   p_naiapp_AppParameters_t p_ad_params = (p_naiapp_AppParameters_t)p_params;
   bool_t bQuit;
   int8_t userInput[15];
   float64_t satLevel = 0.0;
   nai_status_t status = NAI_ERROR_UNKNOWN;

   if (APP_PARAM_COUNT == paramCount)
   {
      bQuit = naiapp_query_ChannelNumber(p_ad_params->maxChannels, p_ad_params->channel, &(p_ad_params->channel));
      if (!bQuit)
      {
         naiif_printf("Enter Saturation High value:");

         memset(userInput, 0x00, sizeof(userInput));
         naiapp_fgets_stdin(userInput, sizeof(userInput));

         sscanf((const char*)userInput, "%lf", &satLevel);

         status = naibrd_AD_SetSaturationLevel(p_ad_params->cardIndex, p_ad_params->module, p_ad_params->channel, NAIBRD_AD_SATURATION_CONTROL_HIGH,
            satLevel);
      }
   }
   else
   {
      status = NAI_ERROR_INVALID_VALUE;
   }

   return status;
}

static nai_status_t ADBasicOps_enableSaturationLow(int32_t paramCount, int32_t* p_params)
{
   p_naiapp_AppParameters_t p_ad_params = (p_naiapp_AppParameters_t)p_params;
   bool_t bQuit = NAI_FALSE;
   nai_status_t status = NAI_ERROR_UNKNOWN;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   if (APP_PARAM_COUNT == paramCount)
   {
      bQuit = naiapp_query_ChannelNumber(p_ad_params->maxChannels, p_ad_params->channel, &(p_ad_params->channel));
      if (!bQuit)
      {
         naiif_printf("Type 'E' to ENABLE Low-Level Saturation, or press any other key to DISABLE it:\r\n>>");
         bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
         if ((!bQuit) && (inputResponseCnt > 0))
         {
            if (toupper(inputBuffer[0]) == 'E')
            {
               check_status(naibrd_AD_SetSaturationControl(p_ad_params->cardIndex, p_ad_params->module, p_ad_params->channel,
                  NAIBRD_AD_SATURATION_CONTROL_LOW, NAI_TRUE));
            }
            else
            {
               check_status(naibrd_AD_SetSaturationControl(p_ad_params->cardIndex, p_ad_params->module, p_ad_params->channel,
                  NAIBRD_AD_SATURATION_CONTROL_LOW, NAI_FALSE));
            }
         }
      }
      status = NAI_SUCCESS;
   }
   else
   {
      status = NAI_ERROR_INVALID_VALUE;
   }

   return status;
}

static nai_status_t ADBasicOps_enableSaturationHigh(int32_t paramCount, int32_t* p_params)
{
   p_naiapp_AppParameters_t p_ad_params = (p_naiapp_AppParameters_t)p_params;
   bool_t bQuit = NAI_FALSE;
   nai_status_t status = NAI_ERROR_UNKNOWN;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   if (APP_PARAM_COUNT == paramCount)
   {
      bQuit = naiapp_query_ChannelNumber(p_ad_params->maxChannels, p_ad_params->channel, &(p_ad_params->channel));
      if (!bQuit)
      {
         naiif_printf("Type 'E' to ENABLE High-Level Saturation, or press any other key to DISABLE it:\r\n>>");
         bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
         if ((!bQuit) && (inputResponseCnt > 0))
         {
            if (toupper(inputBuffer[0]) == 'E')
            {
               check_status(naibrd_AD_SetSaturationControl(p_ad_params->cardIndex, p_ad_params->module, p_ad_params->channel,
                  NAIBRD_AD_SATURATION_CONTROL_HIGH, NAI_TRUE));
            }
            else
            {
               check_status(naibrd_AD_SetSaturationControl(p_ad_params->cardIndex, p_ad_params->module, p_ad_params->channel,
                  NAIBRD_AD_SATURATION_CONTROL_HIGH, NAI_FALSE));
            }
         }
      }
      status = NAI_SUCCESS;
   }
   else
   {
      status = NAI_ERROR_INVALID_VALUE;
   }

   return status;
}

static bool_t ADBasicOps_SaturationAvailable(int32_t paramCount, int32_t* p_params)
{
   p_naiapp_AppParameters_t p_ad_params = (p_naiapp_AppParameters_t)p_params;
   uint32_t fpgaRev = 0u;
   uint32_t supportedRev = 0xFFFFFFFFu;
   bool_t retVal = NAI_FALSE;

   check_status(naibrd_GenModuleRevRaw(p_ad_params->cardIndex, p_ad_params->module, NULL, &fpgaRev, NULL, NULL, NULL, NULL));

   /* Unused params */
   paramCount = 0;

   switch (p_ad_params->modId)
   {
      case NAIBRD_MODULE_ID_AD1:
      case NAIBRD_MODULE_ID_AD2:
      case NAIBRD_MODULE_ID_AD3:
         supportedRev = NAIAPPS_AD123_SATURATION_SUPPORT_FPGA_REV;
         retVal = NAI_TRUE;
         break;
      case NAIBRD_MODULE_ID_AD4:
      case NAIBRD_MODULE_ID_AD5:
      case NAIBRD_MODULE_ID_AD6:
         supportedRev = NAIAPPS_AD456_SATURATION_SUPPORT_FPGA_REV;
         retVal = NAI_TRUE;
         break;
      case NAIBRD_MODULE_ID_ADE:
      case NAIBRD_MODULE_ID_ADF:
      case NAIBRD_MODULE_ID_ADG:
         supportedRev = NAIAPPS_ADEFG_SATURATION_SUPPORT_FPGA_REV;
         retVal = NAI_TRUE;
         break;
      case NAIBRD_MODULE_ID_CME:
      case NAIBRD_MODULE_ID_CMF:
      case NAIBRD_MODULE_ID_CMG:
      case NAIBRD_MODULE_ID_IF1:
         supportedRev = 0;
         retVal = NAI_TRUE;
         break;
      default:
         retVal = NAI_FALSE;
         break;
   }

   if ((retVal == NAI_TRUE) && (fpgaRev < supportedRev))
   {
      retVal = NAI_FALSE;
   }

   return retVal;
}

static nai_status_t ADBasicOps_ModulePowerResetMenu(int32_t paramCount, int32_t* p_params)
{
   bool_t bQuit = NAI_FALSE;
   bool_t bContinue = NAI_TRUE;
   bool_t bCmdFound = NAI_FALSE;
   int32_t cmd = 0;
   int32_t numMenuCmds = 0;
   bool_t poweredDownStatus = NAI_FALSE;
   bool_t notDetectedStatus = NAI_FALSE;
   bool_t notLinkInitStatus = NAI_FALSE;
   bool_t notFWNotStatus = NAI_FALSE;
   bool_t commErrorStatus = NAI_FALSE;
   bool_t resetRequest = NAI_FALSE;
   bool_t powerDownRequest = NAI_FALSE;
   bool_t powerUpRequest = NAI_FALSE;
   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;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   numMenuCmds = AD_BASICOPS_MODULE_POWER_RESET_CMD_COUNT;
   naiapp_utils_LoadParamMenuCommands(numMenuCmds, AD_BasicOps_ModulePowerResetMenuCmds);
   while (bContinue)
   {
      naiif_printf("\r\n\r\n\r\n");
      naiif_printf(" -----------------------------Status------------------------------    ----------Request----------\r\n");
      naiif_printf(" Powered Down  Not Detected  Not Link Init  Not FW Not  Comm Error    Reset  Power Down  Power Up\r\n");
      naiif_printf(" ------------  ------------  -------------  ----------  ----------    -----  ----------  --------\r\n");
      check_status(naibrd_AD_GetModulePowerResetStatus(cardIndex, module, NAIBRD_AD_MODULE_POWER_RESET_STATUS_POWERED_DOWN, &poweredDownStatus));
      check_status(naibrd_AD_GetModulePowerResetStatus(cardIndex, module, NAIBRD_AD_MODULE_POWER_RESET_STATUS_NOT_DETECTED, &notDetectedStatus));
      check_status(naibrd_AD_GetModulePowerResetStatus(cardIndex, module, NAIBRD_AD_MODULE_POWER_RESET_STATUS_NOT_LINK_INIT, &notLinkInitStatus));
      check_status(naibrd_AD_GetModulePowerResetStatus(cardIndex, module, NAIBRD_AD_MODULE_POWER_RESET_STATUS_FW_NOT_READY, &notFWNotStatus));
      check_status(naibrd_AD_GetModulePowerResetStatus(cardIndex, module, NAIBRD_AD_MODULE_POWER_RESET_STATUS_COMM_ERROR, &commErrorStatus));
      check_status(naibrd_AD_GetModulePowerReset(cardIndex, module, NAIBRD_AD_MODULE_POWER_RESET_REQUEST_RESET, &resetRequest));
      check_status(naibrd_AD_GetModulePowerReset(cardIndex, module, NAIBRD_AD_MODULE_POWER_RESET_REQUEST_POWER_DOWN, &powerDownRequest));
      check_status(naibrd_AD_GetModulePowerReset(cardIndex, module, NAIBRD_AD_MODULE_POWER_RESET_REQUEST_POWER_UP, &powerUpRequest));
      naiif_printf("      %1d             %1d              %1d            %1d           %1d           %1d        %1d          %1d\r\n",
         poweredDownStatus, notDetectedStatus, notLinkInitStatus, notFWNotStatus, commErrorStatus, resetRequest, powerDownRequest, powerUpRequest);
      naiapp_display_ParamMenuCommands((int8_t*)"DT Power Reset Operation Menu");
      naiif_printf("\r\nType AD Module Power Reset command or %c to quit : main > module power reset >", NAI_QUIT_CHAR);
      bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
      if (!bQuit)
      {
         if (inputResponseCnt > 0)
         {
            if ((inputBuffer[0] == 'B') || (inputBuffer[0] == 'b'))
            {
               bContinue = NAI_FALSE;
            }
            else
            {
               bCmdFound = naiapp_utils_GetParamMenuCmdNum(inputResponseCnt, inputBuffer, &cmd);
               if (bCmdFound)
               {
                  AD_BasicOps_ModulePowerResetMenuCmds[cmd].func(paramCount, p_params);
               }
               else
               {
                  naiif_printf("\r\nInvalid command entered\r\n");
               }
            }
         }
      }
      else
         bContinue = NAI_FALSE;
   }
   numMenuCmds = AD_BASICOPS_CMD_COUNT;
   naiapp_utils_LoadParamMenuCommands(numMenuCmds, AD_BasicOpsCmds);
   return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}

static nai_status_t ADBasicOps_ClearModulePowerResetStatus(int32_t paramCount, int32_t* p_params)
{
   bool_t bQuit = NAI_FALSE;
   naibrd_ad_module_power_reset_status_type_t statusTypeToClear = (naibrd_ad_module_power_reset_status_type_t)0u;
   bool_t modulePowerResetStatusRead = 0u;
   char statusTypeStr[14] = "";
   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;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   NAIBSP_UNREFERENCED_PARAMETER(paramCount);

   naiif_printf("\r\nSelect Module Power Reset Status type to clear: (0 for Powered Down, 1 for Not Detected, 2 for Not Link Init, 3 for Not FW Not, 4 for Comm Error, q for quit): ");
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if ((!bQuit) && (inputResponseCnt > 0))
   {
      switch (inputBuffer[0])
      {
      case '0':
         statusTypeToClear = NAIBRD_AD_MODULE_POWER_RESET_STATUS_POWERED_DOWN;
         sprintf(statusTypeStr, "Powered Down");
         break;
      case '1':
         statusTypeToClear = NAIBRD_AD_MODULE_POWER_RESET_STATUS_NOT_DETECTED;
         sprintf(statusTypeStr, "Not Detected");
         break;
      case '2':
         statusTypeToClear = NAIBRD_AD_MODULE_POWER_RESET_STATUS_NOT_LINK_INIT;
         sprintf(statusTypeStr, "Not Link Init");
         break;
      case '3':
         statusTypeToClear = NAIBRD_AD_MODULE_POWER_RESET_STATUS_FW_NOT_READY;
         sprintf(statusTypeStr, "Not FW Not");
         break;
      case '4':
         statusTypeToClear = NAIBRD_AD_MODULE_POWER_RESET_STATUS_COMM_ERROR;
         sprintf(statusTypeStr, "Comm Error");
         break;
      case 'q':
      case 'Q':
         bQuit = NAI_TRUE;
         break;
      default:
         bQuit = NAI_TRUE;
         naiif_printf("\r\nInvalid module power reset status type entered\r\n");
         break;
      }

      if (!bQuit)
      {
         naiif_printf("\r\nAre you sure you want to clear the %s status? (Y for Yes or N for No): ", statusTypeStr);
         bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
         if ((!bQuit) && (inputResponseCnt > 0) && (toupper(inputBuffer[0]) == 'Y'))
         {
            check_status(naibrd_AD_GetModulePowerResetStatus(cardIndex, module, statusTypeToClear, &modulePowerResetStatusRead));
            if (modulePowerResetStatusRead == 1u)
            {
               check_status(naibrd_AD_ClearModulePowerResetStatus(cardIndex, module, statusTypeToClear));
            }
         }
      }
   }

   return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}

static nai_status_t ADBasicOps_SetModulePowerReset(int32_t paramCount, int32_t* p_params)
{
   bool_t bQuit = NAI_FALSE;
   naibrd_ad_module_power_reset_type_t resetTypeToSet = (naibrd_ad_module_power_reset_type_t)0u;
   char resetTypeStr[11] = "";
   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;
   int8_t inputBuffer[80];
   int32_t inputResponseCnt;

   NAIBSP_UNREFERENCED_PARAMETER(paramCount);

   naiif_printf("\r\nSelect Module Power Reset Request type to set: (0 for Reset, 1 for Power Down, 2 for Power Up, q for quit): ");
   bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
   if ((!bQuit) && (inputResponseCnt > 0))
   {
      switch (inputBuffer[0])
      {
      case '0':
         resetTypeToSet = NAIBRD_AD_MODULE_POWER_RESET_REQUEST_RESET;
         sprintf(resetTypeStr, "Reset");
         break;
      case '1':
         resetTypeToSet = NAIBRD_AD_MODULE_POWER_RESET_REQUEST_POWER_DOWN;
         sprintf(resetTypeStr, "Power Down");
         break;
      case '2':
         resetTypeToSet = NAIBRD_AD_MODULE_POWER_RESET_REQUEST_POWER_UP;
         sprintf(resetTypeStr, "Power Up");
         break;
      case 'q':
      case 'Q':
         bQuit = NAI_TRUE;
         break;
      default:
         bQuit = NAI_TRUE;
         naiif_printf("\r\nInvalid module power reset request type entered\r\n");
         break;
      }

      if (!bQuit)
      {
         naiif_printf("\r\nDo you want to set or reset the %s request? (1 to set, 0 to reset): ", resetTypeStr);
         bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);
         if ((!bQuit) && (inputResponseCnt > 0))
         {
            if (inputBuffer[0] == '0')
            {
               check_status(naibrd_AD_SetModulePowerReset(cardIndex, module, resetTypeToSet, (bool_t)NAI_FALSE));
            }
            else if (inputBuffer[0] == '1')
            {
               check_status(naibrd_AD_SetModulePowerReset(cardIndex, module, resetTypeToSet, (bool_t)NAI_TRUE));
            }
            else
            {
               naiif_printf("\r\nInvalid selection entered\r\n");
            }
         }
      }
   }

   return (bQuit) ? NAI_ERROR_UNKNOWN : NAI_SUCCESS;
}

static bool_t CF1ADBasicOps_run(int32_t cardIndex, int32_t module, uint32_t modid)
{
   bool_t bQuit = NAI_FALSE;
   float64_t Vdc = 0.0;
   float64_t Vrms = 0.0;
   int32_t channel = 0;
   int32_t numChannels = naibrd_AD_GetChannelCount(modid);
   int8_t inputBuffer[3];
   int32_t inputResponseCnt = 0;

   do
   {
       naiif_printf(" Chan        Vdc            Vrms\r\n");
       naiif_printf("-------------------------------------\r\n");

       for (channel = 1; channel <= numChannels; channel++)
       {
          check_status(naibrd_AD_GetData(cardIndex, module, channel, NAIBRD_AD_MODE_VOLTAGE, &Vdc));
          check_status(naibrd_AD_GetData(cardIndex, module, channel, NAIBRD_AD_MODE_RMS_VOLTAGE, &Vrms));

          naiif_printf("  %2d     %10.6fV     %10.6fV\r\n", channel, Vdc, Vrms);
       }

       naiif_printf("\r\n\r\n'Q' to quit, any other key to refresh\r\n");
       bQuit = naiapp_query_ForQuitResponse(sizeof(inputBuffer), NAI_QUIT_CHAR, inputBuffer, &inputResponseCnt);

   } while (!bQuit);

   return bQuit;
}

Help Bot

X